@unicitylabs/sphere-sdk 0.5.3 → 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 (50) hide show
  1. package/README.md +2 -0
  2. package/dist/connect/index.cjs +145 -23
  3. package/dist/connect/index.cjs.map +1 -1
  4. package/dist/connect/index.d.cts +15 -2
  5. package/dist/connect/index.d.ts +15 -2
  6. package/dist/connect/index.js +145 -23
  7. package/dist/connect/index.js.map +1 -1
  8. package/dist/core/index.cjs +670 -473
  9. package/dist/core/index.cjs.map +1 -1
  10. package/dist/core/index.d.cts +123 -2
  11. package/dist/core/index.d.ts +123 -2
  12. package/dist/core/index.js +667 -473
  13. package/dist/core/index.js.map +1 -1
  14. package/dist/impl/browser/connect/index.cjs +119 -1
  15. package/dist/impl/browser/connect/index.cjs.map +1 -1
  16. package/dist/impl/browser/connect/index.d.cts +53 -1
  17. package/dist/impl/browser/connect/index.d.ts +53 -1
  18. package/dist/impl/browser/connect/index.js +119 -1
  19. package/dist/impl/browser/connect/index.js.map +1 -1
  20. package/dist/impl/browser/index.cjs +306 -193
  21. package/dist/impl/browser/index.cjs.map +1 -1
  22. package/dist/impl/browser/index.js +306 -193
  23. package/dist/impl/browser/index.js.map +1 -1
  24. package/dist/impl/browser/ipfs.cjs +134 -19
  25. package/dist/impl/browser/ipfs.cjs.map +1 -1
  26. package/dist/impl/browser/ipfs.js +134 -19
  27. package/dist/impl/browser/ipfs.js.map +1 -1
  28. package/dist/impl/nodejs/connect/index.cjs +101 -6
  29. package/dist/impl/nodejs/connect/index.cjs.map +1 -1
  30. package/dist/impl/nodejs/connect/index.d.cts +2 -0
  31. package/dist/impl/nodejs/connect/index.d.ts +2 -0
  32. package/dist/impl/nodejs/connect/index.js +101 -6
  33. package/dist/impl/nodejs/connect/index.js.map +1 -1
  34. package/dist/impl/nodejs/index.cjs +267 -152
  35. package/dist/impl/nodejs/index.cjs.map +1 -1
  36. package/dist/impl/nodejs/index.d.cts +2 -1
  37. package/dist/impl/nodejs/index.d.ts +2 -1
  38. package/dist/impl/nodejs/index.js +267 -152
  39. package/dist/impl/nodejs/index.js.map +1 -1
  40. package/dist/index.cjs +682 -493
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.d.cts +124 -8
  43. package/dist/index.d.ts +124 -8
  44. package/dist/index.js +680 -493
  45. package/dist/index.js.map +1 -1
  46. package/dist/l1/index.cjs +139 -32
  47. package/dist/l1/index.cjs.map +1 -1
  48. package/dist/l1/index.js +139 -32
  49. package/dist/l1/index.js.map +1 -1
  50. package/package.json +1 -16
@@ -61,6 +61,110 @@ __export(browser_exports, {
61
61
  module.exports = __toCommonJS(browser_exports);
62
62
  var import_buffer2 = require("buffer");
63
63
 
64
+ // core/logger.ts
65
+ var LOGGER_KEY = "__sphere_sdk_logger__";
66
+ function getState() {
67
+ const g = globalThis;
68
+ if (!g[LOGGER_KEY]) {
69
+ g[LOGGER_KEY] = { debug: false, tags: {}, handler: null };
70
+ }
71
+ return g[LOGGER_KEY];
72
+ }
73
+ function isEnabled(tag) {
74
+ const state = getState();
75
+ if (tag in state.tags) return state.tags[tag];
76
+ return state.debug;
77
+ }
78
+ var logger = {
79
+ /**
80
+ * Configure the logger. Can be called multiple times (last write wins).
81
+ * Typically called by createBrowserProviders(), createNodeProviders(), or Sphere.init().
82
+ */
83
+ configure(config) {
84
+ const state = getState();
85
+ if (config.debug !== void 0) state.debug = config.debug;
86
+ if (config.handler !== void 0) state.handler = config.handler;
87
+ },
88
+ /**
89
+ * Enable/disable debug logging for a specific tag.
90
+ * Per-tag setting overrides the global debug flag.
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * logger.setTagDebug('Nostr', true); // enable only Nostr logs
95
+ * logger.setTagDebug('Nostr', false); // disable Nostr logs even if global debug=true
96
+ * ```
97
+ */
98
+ setTagDebug(tag, enabled) {
99
+ getState().tags[tag] = enabled;
100
+ },
101
+ /**
102
+ * Clear per-tag override, falling back to global debug flag.
103
+ */
104
+ clearTagDebug(tag) {
105
+ delete getState().tags[tag];
106
+ },
107
+ /** Returns true if debug mode is enabled for the given tag (or globally). */
108
+ isDebugEnabled(tag) {
109
+ if (tag) return isEnabled(tag);
110
+ return getState().debug;
111
+ },
112
+ /**
113
+ * Debug-level log. Only shown when debug is enabled (globally or for this tag).
114
+ * Use for detailed operational information.
115
+ */
116
+ debug(tag, message, ...args) {
117
+ if (!isEnabled(tag)) return;
118
+ const state = getState();
119
+ if (state.handler) {
120
+ state.handler("debug", tag, message, ...args);
121
+ } else {
122
+ console.log(`[${tag}]`, message, ...args);
123
+ }
124
+ },
125
+ /**
126
+ * Warning-level log. ALWAYS shown regardless of debug flag.
127
+ * Use for important but non-critical issues (timeouts, retries, degraded state).
128
+ */
129
+ warn(tag, message, ...args) {
130
+ const state = getState();
131
+ if (state.handler) {
132
+ state.handler("warn", tag, message, ...args);
133
+ } else {
134
+ console.warn(`[${tag}]`, message, ...args);
135
+ }
136
+ },
137
+ /**
138
+ * Error-level log. ALWAYS shown regardless of debug flag.
139
+ * Use for critical failures that should never be silenced.
140
+ */
141
+ error(tag, message, ...args) {
142
+ const state = getState();
143
+ if (state.handler) {
144
+ state.handler("error", tag, message, ...args);
145
+ } else {
146
+ console.error(`[${tag}]`, message, ...args);
147
+ }
148
+ },
149
+ /** Reset all logger state (debug flag, tags, handler). Primarily for tests. */
150
+ reset() {
151
+ const g = globalThis;
152
+ delete g[LOGGER_KEY];
153
+ }
154
+ };
155
+
156
+ // core/errors.ts
157
+ var SphereError = class extends Error {
158
+ code;
159
+ cause;
160
+ constructor(message, code, cause) {
161
+ super(message);
162
+ this.name = "SphereError";
163
+ this.code = code;
164
+ this.cause = cause;
165
+ }
166
+ };
167
+
64
168
  // constants.ts
65
169
  var STORAGE_KEYS_GLOBAL = {
66
170
  /** Encrypted BIP39 mnemonic */
@@ -265,7 +369,7 @@ var LocalStorageProvider = class {
265
369
  this.log("Connected to localStorage");
266
370
  } catch (error) {
267
371
  this.status = "error";
268
- throw new Error(`LocalStorage not available: ${error}`);
372
+ throw new SphereError(`LocalStorage not available: ${error}`, "STORAGE_ERROR");
269
373
  }
270
374
  }
271
375
  async disconnect() {
@@ -372,7 +476,7 @@ var LocalStorageProvider = class {
372
476
  }
373
477
  ensureConnected() {
374
478
  if (this.status !== "connected") {
375
- throw new Error("LocalStorageProvider not connected");
479
+ throw new SphereError("LocalStorageProvider not connected", "STORAGE_ERROR");
376
480
  }
377
481
  }
378
482
  getStorageSafe() {
@@ -381,10 +485,8 @@ var LocalStorageProvider = class {
381
485
  }
382
486
  return createInMemoryStorage();
383
487
  }
384
- log(...args) {
385
- if (this.config.debug) {
386
- console.log("[LocalStorageProvider]", ...args);
387
- }
488
+ log(message, ...args) {
489
+ logger.debug("LocalStorage", message, ...args);
388
490
  }
389
491
  };
390
492
  function createInMemoryStorage() {
@@ -445,7 +547,7 @@ var IndexedDBStorageProvider = class {
445
547
  for (let attempt = 0; attempt < 2; attempt++) {
446
548
  this.status = "connecting";
447
549
  const t0 = Date.now();
448
- console.log(`[IndexedDBStorage] connect: opening db=${this.dbName}, attempt=${attempt + 1}/2`);
550
+ logger.debug("IndexedDB", ` connect: opening db=${this.dbName}, attempt=${attempt + 1}/2`);
449
551
  try {
450
552
  this.db = await Promise.race([
451
553
  this.openDatabase(),
@@ -454,23 +556,23 @@ var IndexedDBStorageProvider = class {
454
556
  )
455
557
  ]);
456
558
  this.status = "connected";
457
- console.log(`[IndexedDBStorage] connect: connected db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
559
+ logger.debug("IndexedDB", ` connect: connected db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
458
560
  return;
459
561
  } catch (error) {
460
- console.warn(`[IndexedDBStorage] connect: open failed db=${this.dbName} attempt=${attempt + 1} (${Date.now() - t0}ms):`, error);
562
+ logger.warn("IndexedDB", ` connect: open failed db=${this.dbName} attempt=${attempt + 1} (${Date.now() - t0}ms):`, error);
461
563
  if (attempt === 0) {
462
564
  this.status = "disconnected";
463
565
  await new Promise((r) => setTimeout(r, 1e3));
464
566
  continue;
465
567
  }
466
568
  this.status = "error";
467
- throw new Error(`IndexedDB not available: ${error}`);
569
+ throw new SphereError(`IndexedDB not available: ${error}`, "STORAGE_ERROR");
468
570
  }
469
571
  }
470
572
  }
471
573
  async disconnect() {
472
574
  const cid = this.connId;
473
- console.log(`[IndexedDBStorage] disconnect: db=${this.dbName} connId=${cid} wasConnected=${!!this.db}`);
575
+ logger.debug("IndexedDB", ` disconnect: db=${this.dbName} connId=${cid} wasConnected=${!!this.db}`);
474
576
  if (this.db) {
475
577
  this.db.close();
476
578
  this.db = null;
@@ -529,15 +631,15 @@ var IndexedDBStorageProvider = class {
529
631
  if (!prefix) {
530
632
  const t0 = Date.now();
531
633
  const prevConnId = this.connId;
532
- console.log(`[IndexedDBStorage] clear: starting db=${this.dbName} connId=${prevConnId} status=${this.status} hasDb=${!!this.db}`);
634
+ logger.debug("IndexedDB", ` clear: starting db=${this.dbName} connId=${prevConnId} status=${this.status} hasDb=${!!this.db}`);
533
635
  try {
534
636
  if (!this.db || this.status !== "connected") {
535
637
  if (this.db) {
536
- console.log(`[IndexedDBStorage] clear: closing stale handle connId=${prevConnId}`);
638
+ logger.debug("IndexedDB", ` clear: closing stale handle connId=${prevConnId}`);
537
639
  this.db.close();
538
640
  this.db = null;
539
641
  }
540
- console.log(`[IndexedDBStorage] clear: opening fresh connection for wipe`);
642
+ logger.debug("IndexedDB", ` clear: opening fresh connection for wipe`);
541
643
  this.db = await Promise.race([
542
644
  this.openDatabase(),
543
645
  new Promise(
@@ -547,9 +649,9 @@ var IndexedDBStorageProvider = class {
547
649
  this.status = "connected";
548
650
  }
549
651
  await this.idbClear();
550
- console.log(`[IndexedDBStorage] clear: store cleared db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
652
+ logger.debug("IndexedDB", ` clear: store cleared db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
551
653
  } catch (err) {
552
- console.warn(`[IndexedDBStorage] clear: failed db=${this.dbName} (${Date.now() - t0}ms)`, err);
654
+ logger.warn("IndexedDB", ` clear: failed db=${this.dbName} (${Date.now() - t0}ms)`, err);
553
655
  } finally {
554
656
  if (this.db) {
555
657
  this.db.close();
@@ -612,7 +714,7 @@ var IndexedDBStorageProvider = class {
612
714
  }
613
715
  ensureConnected() {
614
716
  if (this.status !== "connected" || !this.db) {
615
- throw new Error("IndexedDBStorageProvider not connected");
717
+ throw new SphereError("IndexedDBStorageProvider not connected", "STORAGE_ERROR");
616
718
  }
617
719
  }
618
720
  // ===========================================================================
@@ -627,7 +729,7 @@ var IndexedDBStorageProvider = class {
627
729
  const cid = ++connectionSeq;
628
730
  this.connId = cid;
629
731
  db.onversionchange = () => {
630
- console.log(`[IndexedDBStorage] onversionchange: auto-closing db=${this.dbName} connId=${cid}`);
732
+ logger.debug("IndexedDB", ` onversionchange: auto-closing db=${this.dbName} connId=${cid}`);
631
733
  db.close();
632
734
  if (this.db === db) {
633
735
  this.db = null;
@@ -637,7 +739,7 @@ var IndexedDBStorageProvider = class {
637
739
  resolve(db);
638
740
  };
639
741
  request.onblocked = () => {
640
- console.warn(`[IndexedDBStorage] open blocked by another connection, db=${this.dbName}`);
742
+ logger.warn("IndexedDB", ` open blocked by another connection, db=${this.dbName}`);
641
743
  };
642
744
  request.onupgradeneeded = (event) => {
643
745
  const db = event.target.result;
@@ -701,10 +803,8 @@ var IndexedDBStorageProvider = class {
701
803
  request.onsuccess = () => resolve();
702
804
  });
703
805
  }
704
- log(...args) {
705
- if (this.debug) {
706
- console.log("[IndexedDBStorageProvider]", ...args);
707
- }
806
+ log(message, ...args) {
807
+ logger.debug("IndexedDB", message, ...args);
708
808
  }
709
809
  };
710
810
  function createIndexedDBStorageProvider(config) {
@@ -741,31 +841,31 @@ var IndexedDBTokenStorageProvider = class {
741
841
  const addressId = getAddressId(identity.directAddress);
742
842
  this.dbName = `${this.dbNamePrefix}-${addressId}`;
743
843
  }
744
- console.log(`[IndexedDBTokenStorage] setIdentity: db=${this.dbName}`);
844
+ logger.debug("IndexedDBToken", `setIdentity: db=${this.dbName}`);
745
845
  }
746
846
  async initialize() {
747
847
  const prevConnId = this.connId;
748
848
  const t0 = Date.now();
749
849
  try {
750
850
  if (this.db) {
751
- console.log(`[IndexedDBTokenStorage] initialize: closing existing connId=${prevConnId} before re-open (db=${this.dbName})`);
851
+ logger.debug("IndexedDBToken", `initialize: closing existing connId=${prevConnId} before re-open (db=${this.dbName})`);
752
852
  this.db.close();
753
853
  this.db = null;
754
854
  }
755
- console.log(`[IndexedDBTokenStorage] initialize: opening db=${this.dbName}`);
855
+ logger.debug("IndexedDBToken", `initialize: opening db=${this.dbName}`);
756
856
  this.db = await this.openDatabase();
757
857
  this.status = "connected";
758
- console.log(`[IndexedDBTokenStorage] initialize: connected db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
858
+ logger.debug("IndexedDBToken", `initialize: connected db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
759
859
  return true;
760
860
  } catch (error) {
761
- console.error(`[IndexedDBTokenStorage] initialize: failed db=${this.dbName} (${Date.now() - t0}ms):`, error);
861
+ logger.error("IndexedDBToken", `initialize: failed db=${this.dbName} (${Date.now() - t0}ms):`, error);
762
862
  this.status = "error";
763
863
  return false;
764
864
  }
765
865
  }
766
866
  async shutdown() {
767
867
  const cid = this.connId;
768
- console.log(`[IndexedDBTokenStorage] shutdown: db=${this.dbName} connId=${cid} wasConnected=${!!this.db}`);
868
+ logger.debug("IndexedDBToken", `shutdown: db=${this.dbName} connId=${cid} wasConnected=${!!this.db}`);
769
869
  if (this.db) {
770
870
  this.db.close();
771
871
  this.db = null;
@@ -786,7 +886,7 @@ var IndexedDBTokenStorageProvider = class {
786
886
  }
787
887
  async load() {
788
888
  if (!this.db) {
789
- console.warn(`[IndexedDBTokenStorage] load: db not initialized (db=${this.dbName})`);
889
+ logger.warn("IndexedDBToken", `load: db not initialized (db=${this.dbName})`);
790
890
  return {
791
891
  success: false,
792
892
  error: "Database not initialized",
@@ -836,7 +936,7 @@ var IndexedDBTokenStorageProvider = class {
836
936
  data._invalid = invalid;
837
937
  }
838
938
  const tokenKeys = Object.keys(data).filter((k) => k.startsWith("_") && !["_meta", "_tombstones", "_outbox", "_sent", "_invalid"].includes(k));
839
- console.log(`[IndexedDBTokenStorage] load: db=${this.dbName}, tokens=${tokenKeys.length}`);
939
+ logger.debug("IndexedDBToken", `load: db=${this.dbName}, tokens=${tokenKeys.length}`);
840
940
  return {
841
941
  success: true,
842
942
  data,
@@ -844,7 +944,7 @@ var IndexedDBTokenStorageProvider = class {
844
944
  timestamp: Date.now()
845
945
  };
846
946
  } catch (error) {
847
- console.error(`[IndexedDBTokenStorage] load failed: db=${this.dbName}`, error);
947
+ logger.error("IndexedDBToken", `load failed: db=${this.dbName}`, error);
848
948
  return {
849
949
  success: false,
850
950
  error: error instanceof Error ? error.message : "Unknown error",
@@ -855,7 +955,7 @@ var IndexedDBTokenStorageProvider = class {
855
955
  }
856
956
  async save(data) {
857
957
  if (!this.db) {
858
- console.warn(`[IndexedDBTokenStorage] save: db not initialized (db=${this.dbName})`);
958
+ logger.warn("IndexedDBToken", `save: db not initialized (db=${this.dbName})`);
859
959
  return {
860
960
  success: false,
861
961
  error: "Database not initialized",
@@ -865,7 +965,7 @@ var IndexedDBTokenStorageProvider = class {
865
965
  try {
866
966
  const tokenKeys = Object.keys(data).filter((k) => k.startsWith("_") && !["_meta", "_tombstones", "_outbox", "_sent", "_invalid"].includes(k));
867
967
  const archivedKeys = Object.keys(data).filter((k) => k.startsWith("archived-"));
868
- console.log(`[IndexedDBTokenStorage] save: db=${this.dbName}, tokens=${tokenKeys.length}, archived=${archivedKeys.length}, tombstones=${data._tombstones?.length ?? 0}`);
968
+ logger.debug("IndexedDBToken", `save: db=${this.dbName}, tokens=${tokenKeys.length}, archived=${archivedKeys.length}, tombstones=${data._tombstones?.length ?? 0}`);
869
969
  await this.putToStore(STORE_META, "meta", data._meta);
870
970
  if (data._tombstones) {
871
971
  await this.putToStore(STORE_META, "tombstones", data._tombstones);
@@ -934,21 +1034,22 @@ var IndexedDBTokenStorageProvider = class {
934
1034
  for (const name of await this.findPrefixedDatabases()) {
935
1035
  dbNames.add(name);
936
1036
  }
937
- console.log(`[IndexedDBTokenStorage] clear: clearing ${dbNames.size} database(s) (${[...dbNames].join(", ")})`);
1037
+ logger.debug("IndexedDBToken", `clear: clearing ${dbNames.size} database(s) (${[...dbNames].join(", ")})`);
938
1038
  const results = await Promise.allSettled(
939
1039
  [...dbNames].map((name) => this.clearDatabaseStores(name))
940
1040
  );
941
1041
  const failed = results.filter((r) => r.status === "rejected");
942
1042
  if (failed.length > 0) {
943
- console.warn(
944
- `[IndexedDBTokenStorage] clear: ${failed.length}/${dbNames.size} failed (${Date.now() - t0}ms)`,
1043
+ logger.warn(
1044
+ "IndexedDBToken",
1045
+ `clear: ${failed.length}/${dbNames.size} failed (${Date.now() - t0}ms)`,
945
1046
  failed.map((r) => r.reason)
946
1047
  );
947
1048
  }
948
- console.log(`[IndexedDBTokenStorage] clear: done ${dbNames.size} database(s) (${Date.now() - t0}ms)`);
1049
+ logger.debug("IndexedDBToken", `clear: done ${dbNames.size} database(s) (${Date.now() - t0}ms)`);
949
1050
  return failed.length === 0;
950
1051
  } catch (err) {
951
- console.warn(`[IndexedDBTokenStorage] clear: failed (${Date.now() - t0}ms)`, err);
1052
+ logger.warn("IndexedDBToken", `clear: failed (${Date.now() - t0}ms)`, err);
952
1053
  return false;
953
1054
  }
954
1055
  }
@@ -964,7 +1065,7 @@ var IndexedDBTokenStorageProvider = class {
964
1065
  const cid = ++connectionSeq2;
965
1066
  this.connId = cid;
966
1067
  db.onversionchange = () => {
967
- console.log(`[IndexedDBTokenStorage] onversionchange: auto-closing db=${this.dbName} connId=${cid}`);
1068
+ logger.debug("IndexedDBToken", `onversionchange: auto-closing db=${this.dbName} connId=${cid}`);
968
1069
  db.close();
969
1070
  if (this.db === db) {
970
1071
  this.db = null;
@@ -974,7 +1075,7 @@ var IndexedDBTokenStorageProvider = class {
974
1075
  resolve(db);
975
1076
  };
976
1077
  request.onblocked = () => {
977
- console.warn(`[IndexedDBTokenStorage] open blocked by another connection, db=${this.dbName}`);
1078
+ logger.warn("IndexedDBToken", `open blocked by another connection, db=${this.dbName}`);
978
1079
  };
979
1080
  request.onupgradeneeded = (event) => {
980
1081
  const db = event.target.result;
@@ -1719,11 +1820,11 @@ function bech32Checksum(hrp, data) {
1719
1820
  }
1720
1821
  function encodeBech32(hrp, version, program) {
1721
1822
  if (version < 0 || version > 16) {
1722
- throw new Error("Invalid witness version");
1823
+ throw new SphereError("Invalid witness version", "VALIDATION_ERROR");
1723
1824
  }
1724
1825
  const converted = convertBits(Array.from(program), 8, 5, true);
1725
1826
  if (!converted) {
1726
- throw new Error("Failed to convert bits");
1827
+ throw new SphereError("Failed to convert bits", "VALIDATION_ERROR");
1727
1828
  }
1728
1829
  const data = [version].concat(converted);
1729
1830
  const checksum = bech32Checksum(hrp, data);
@@ -1916,18 +2017,18 @@ var NostrTransportProvider = class {
1916
2017
  });
1917
2018
  this.nostrClient.addConnectionListener({
1918
2019
  onConnect: (url) => {
1919
- this.log("NostrClient connected to relay:", url);
2020
+ logger.debug("Nostr", "NostrClient connected to relay:", url);
1920
2021
  this.emitEvent({ type: "transport:connected", timestamp: Date.now() });
1921
2022
  },
1922
2023
  onDisconnect: (url, reason) => {
1923
- this.log("NostrClient disconnected from relay:", url, "reason:", reason);
2024
+ logger.debug("Nostr", "NostrClient disconnected from relay:", url, "reason:", reason);
1924
2025
  },
1925
2026
  onReconnecting: (url, attempt) => {
1926
- this.log("NostrClient reconnecting to relay:", url, "attempt:", attempt);
2027
+ logger.debug("Nostr", "NostrClient reconnecting to relay:", url, "attempt:", attempt);
1927
2028
  this.emitEvent({ type: "transport:reconnecting", timestamp: Date.now() });
1928
2029
  },
1929
2030
  onReconnected: (url) => {
1930
- this.log("NostrClient reconnected to relay:", url);
2031
+ logger.debug("Nostr", "NostrClient reconnected to relay:", url);
1931
2032
  this.emitEvent({ type: "transport:connected", timestamp: Date.now() });
1932
2033
  }
1933
2034
  });
@@ -1940,11 +2041,11 @@ var NostrTransportProvider = class {
1940
2041
  )
1941
2042
  ]);
1942
2043
  if (!this.nostrClient.isConnected()) {
1943
- throw new Error("Failed to connect to any relay");
2044
+ throw new SphereError("Failed to connect to any relay", "TRANSPORT_ERROR");
1944
2045
  }
1945
2046
  this.status = "connected";
1946
2047
  this.emitEvent({ type: "transport:connected", timestamp: Date.now() });
1947
- this.log("Connected to", this.nostrClient.getConnectedRelays().size, "relays");
2048
+ logger.debug("Nostr", "Connected to", this.nostrClient.getConnectedRelays().size, "relays");
1948
2049
  if (this.identity) {
1949
2050
  await this.subscribeToEvents();
1950
2051
  }
@@ -1963,7 +2064,7 @@ var NostrTransportProvider = class {
1963
2064
  this.chatSubscriptionId = null;
1964
2065
  this.status = "disconnected";
1965
2066
  this.emitEvent({ type: "transport:disconnected", timestamp: Date.now() });
1966
- this.log("Disconnected from all relays");
2067
+ logger.debug("Nostr", "Disconnected from all relays");
1967
2068
  }
1968
2069
  isConnected() {
1969
2070
  return this.status === "connected" && this.nostrClient?.isConnected() === true;
@@ -1993,14 +2094,14 @@ var NostrTransportProvider = class {
1993
2094
  */
1994
2095
  async addRelay(relayUrl) {
1995
2096
  if (this.config.relays.includes(relayUrl)) {
1996
- this.log("Relay already configured:", relayUrl);
2097
+ logger.debug("Nostr", "Relay already configured:", relayUrl);
1997
2098
  return false;
1998
2099
  }
1999
2100
  this.config.relays.push(relayUrl);
2000
2101
  if (this.status === "connected" && this.nostrClient) {
2001
2102
  try {
2002
2103
  await this.nostrClient.connect(relayUrl);
2003
- this.log("Added and connected to relay:", relayUrl);
2104
+ logger.debug("Nostr", "Added and connected to relay:", relayUrl);
2004
2105
  this.emitEvent({
2005
2106
  type: "transport:relay_added",
2006
2107
  timestamp: Date.now(),
@@ -2008,7 +2109,7 @@ var NostrTransportProvider = class {
2008
2109
  });
2009
2110
  return true;
2010
2111
  } catch (error) {
2011
- this.log("Failed to connect to new relay:", relayUrl, error);
2112
+ logger.debug("Nostr", "Failed to connect to new relay:", relayUrl, error);
2012
2113
  this.emitEvent({
2013
2114
  type: "transport:relay_added",
2014
2115
  timestamp: Date.now(),
@@ -2033,11 +2134,11 @@ var NostrTransportProvider = class {
2033
2134
  async removeRelay(relayUrl) {
2034
2135
  const index = this.config.relays.indexOf(relayUrl);
2035
2136
  if (index === -1) {
2036
- this.log("Relay not found:", relayUrl);
2137
+ logger.debug("Nostr", "Relay not found:", relayUrl);
2037
2138
  return false;
2038
2139
  }
2039
2140
  this.config.relays.splice(index, 1);
2040
- this.log("Removed relay from config:", relayUrl);
2141
+ logger.debug("Nostr", "Removed relay from config:", relayUrl);
2041
2142
  this.emitEvent({
2042
2143
  type: "transport:relay_removed",
2043
2144
  timestamp: Date.now(),
@@ -2074,9 +2175,9 @@ var NostrTransportProvider = class {
2074
2175
  const secretKey = import_buffer.Buffer.from(identity.privateKey, "hex");
2075
2176
  this.keyManager = import_nostr_js_sdk.NostrKeyManager.fromPrivateKey(secretKey);
2076
2177
  const nostrPubkey = this.keyManager.getPublicKeyHex();
2077
- this.log("Identity set, Nostr pubkey:", nostrPubkey.slice(0, 16) + "...");
2178
+ logger.debug("Nostr", "Identity set, Nostr pubkey:", nostrPubkey.slice(0, 16) + "...");
2078
2179
  if (this.nostrClient && this.status === "connected") {
2079
- this.log("Identity changed while connected - recreating NostrClient");
2180
+ logger.debug("Nostr", "Identity changed while connected - recreating NostrClient");
2080
2181
  const oldClient = this.nostrClient;
2081
2182
  this.nostrClient = new import_nostr_js_sdk.NostrClient(this.keyManager, {
2082
2183
  autoReconnect: this.config.autoReconnect,
@@ -2087,16 +2188,16 @@ var NostrTransportProvider = class {
2087
2188
  });
2088
2189
  this.nostrClient.addConnectionListener({
2089
2190
  onConnect: (url) => {
2090
- this.log("NostrClient connected to relay:", url);
2191
+ logger.debug("Nostr", "NostrClient connected to relay:", url);
2091
2192
  },
2092
2193
  onDisconnect: (url, reason) => {
2093
- this.log("NostrClient disconnected from relay:", url, "reason:", reason);
2194
+ logger.debug("Nostr", "NostrClient disconnected from relay:", url, "reason:", reason);
2094
2195
  },
2095
2196
  onReconnecting: (url, attempt) => {
2096
- this.log("NostrClient reconnecting to relay:", url, "attempt:", attempt);
2197
+ logger.debug("Nostr", "NostrClient reconnecting to relay:", url, "attempt:", attempt);
2097
2198
  },
2098
2199
  onReconnected: (url) => {
2099
- this.log("NostrClient reconnected to relay:", url);
2200
+ logger.debug("Nostr", "NostrClient reconnected to relay:", url);
2100
2201
  }
2101
2202
  });
2102
2203
  await Promise.race([
@@ -2119,7 +2220,7 @@ var NostrTransportProvider = class {
2119
2220
  */
2120
2221
  getNostrPubkey() {
2121
2222
  if (!this.keyManager) {
2122
- throw new Error("KeyManager not initialized - call setIdentity first");
2223
+ throw new SphereError("KeyManager not initialized - call setIdentity first", "NOT_INITIALIZED");
2123
2224
  }
2124
2225
  return this.keyManager.getPublicKeyHex();
2125
2226
  }
@@ -2140,7 +2241,7 @@ var NostrTransportProvider = class {
2140
2241
  const selfPubkey = this.keyManager.getPublicKeyHex();
2141
2242
  const selfGiftWrap = import_nostr_js_sdk.NIP17.createGiftWrap(this.keyManager, selfPubkey, selfWrapContent);
2142
2243
  this.publishEvent(selfGiftWrap).catch((err) => {
2143
- this.log("Self-wrap publish failed:", err);
2244
+ logger.debug("Nostr", "Self-wrap publish failed:", err);
2144
2245
  });
2145
2246
  this.emitEvent({
2146
2247
  type: "message:sent",
@@ -2154,12 +2255,12 @@ var NostrTransportProvider = class {
2154
2255
  if (this.pendingMessages.length > 0) {
2155
2256
  const pending = this.pendingMessages;
2156
2257
  this.pendingMessages = [];
2157
- this.log("Flushing", pending.length, "buffered messages to new handler");
2258
+ logger.debug("Nostr", "Flushing", pending.length, "buffered messages to new handler");
2158
2259
  for (const message of pending) {
2159
2260
  try {
2160
2261
  handler(message);
2161
2262
  } catch (error) {
2162
- this.log("Message handler error (buffered):", error);
2263
+ logger.debug("Nostr", "Message handler error (buffered):", error);
2163
2264
  }
2164
2265
  }
2165
2266
  }
@@ -2218,7 +2319,7 @@ var NostrTransportProvider = class {
2218
2319
  tags
2219
2320
  );
2220
2321
  await this.publishEvent(event);
2221
- this.log("Sent payment request:", event.id);
2322
+ logger.debug("Nostr", "Sent payment request:", event.id);
2222
2323
  return event.id;
2223
2324
  }
2224
2325
  onPaymentRequest(handler) {
@@ -2246,7 +2347,7 @@ var NostrTransportProvider = class {
2246
2347
  ]
2247
2348
  );
2248
2349
  await this.publishEvent(event);
2249
- this.log("Sent payment request response:", event.id, "type:", payload.responseType);
2350
+ logger.debug("Nostr", "Sent payment request response:", event.id, "type:", payload.responseType);
2250
2351
  return event.id;
2251
2352
  }
2252
2353
  onPaymentRequestResponse(handler) {
@@ -2257,11 +2358,11 @@ var NostrTransportProvider = class {
2257
2358
  // Read Receipts
2258
2359
  // ===========================================================================
2259
2360
  async sendReadReceipt(recipientTransportPubkey, messageEventId) {
2260
- if (!this.keyManager) throw new Error("Not initialized");
2361
+ if (!this.keyManager) throw new SphereError("Not initialized", "NOT_INITIALIZED");
2261
2362
  const nostrRecipient = recipientTransportPubkey.length === 66 ? recipientTransportPubkey.slice(2) : recipientTransportPubkey;
2262
2363
  const event = import_nostr_js_sdk.NIP17.createReadReceipt(this.keyManager, nostrRecipient, messageEventId);
2263
2364
  await this.publishEvent(event);
2264
- this.log("Sent read receipt for:", messageEventId, "to:", nostrRecipient.slice(0, 16));
2365
+ logger.debug("Nostr", "Sent read receipt for:", messageEventId, "to:", nostrRecipient.slice(0, 16));
2265
2366
  }
2266
2367
  onReadReceipt(handler) {
2267
2368
  this.readReceiptHandlers.add(handler);
@@ -2271,7 +2372,7 @@ var NostrTransportProvider = class {
2271
2372
  // Typing Indicators
2272
2373
  // ===========================================================================
2273
2374
  async sendTypingIndicator(recipientTransportPubkey) {
2274
- if (!this.keyManager) throw new Error("Not initialized");
2375
+ if (!this.keyManager) throw new SphereError("Not initialized", "NOT_INITIALIZED");
2275
2376
  const nostrRecipient = recipientTransportPubkey.length === 66 ? recipientTransportPubkey.slice(2) : recipientTransportPubkey;
2276
2377
  const content = JSON.stringify({
2277
2378
  type: "typing",
@@ -2358,7 +2459,10 @@ var NostrTransportProvider = class {
2358
2459
  limit: 1
2359
2460
  });
2360
2461
  }
2361
- if (events.length === 0) return null;
2462
+ if (events.length === 0) {
2463
+ logger.debug("Nostr", `resolveNametagInfo: no binding events found for nametag "${nametag}"`);
2464
+ return null;
2465
+ }
2362
2466
  const bindingEvent = events[0];
2363
2467
  try {
2364
2468
  const content = JSON.parse(bindingEvent.content);
@@ -2376,7 +2480,7 @@ var NostrTransportProvider = class {
2376
2480
  timestamp: bindingEvent.created_at * 1e3
2377
2481
  };
2378
2482
  }
2379
- this.log("Legacy nametag event without extended fields:", nametag);
2483
+ logger.debug("Nostr", "Legacy nametag event without extended fields:", nametag);
2380
2484
  const pubkeyTag = bindingEvent.tags.find((t) => t[0] === "pubkey");
2381
2485
  const l1Tag = bindingEvent.tags.find((t) => t[0] === "l1");
2382
2486
  if (pubkeyTag?.[1] && l1Tag?.[1]) {
@@ -2532,10 +2636,10 @@ var NostrTransportProvider = class {
2532
2636
  async recoverNametag() {
2533
2637
  this.ensureReady();
2534
2638
  if (!this.identity || !this.keyManager) {
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
- this.log("Searching for nametag events for pubkey:", nostrPubkey.slice(0, 16) + "...");
2642
+ logger.debug("Nostr", "Searching for nametag events for pubkey:", nostrPubkey.slice(0, 16) + "...");
2539
2643
  const events = await this.queryEvents({
2540
2644
  kinds: [EVENT_KINDS.NAMETAG_BINDING],
2541
2645
  authors: [nostrPubkey],
@@ -2543,7 +2647,7 @@ var NostrTransportProvider = class {
2543
2647
  // Get recent events in case of updates
2544
2648
  });
2545
2649
  if (events.length === 0) {
2546
- this.log("No nametag events found for this pubkey");
2650
+ logger.debug("Nostr", "No nametag events found for this pubkey");
2547
2651
  return null;
2548
2652
  }
2549
2653
  events.sort((a, b) => b.created_at - a.created_at);
@@ -2556,7 +2660,7 @@ var NostrTransportProvider = class {
2556
2660
  this.identity.privateKey
2557
2661
  );
2558
2662
  if (decrypted) {
2559
- this.log("Recovered nametag:", decrypted);
2663
+ logger.debug("Nostr", "Recovered nametag:", decrypted);
2560
2664
  return decrypted;
2561
2665
  }
2562
2666
  }
@@ -2564,7 +2668,7 @@ var NostrTransportProvider = class {
2564
2668
  continue;
2565
2669
  }
2566
2670
  }
2567
- this.log("Could not decrypt nametag from any event");
2671
+ logger.debug("Nostr", "Could not decrypt nametag from any event");
2568
2672
  return null;
2569
2673
  }
2570
2674
  /**
@@ -2580,7 +2684,7 @@ var NostrTransportProvider = class {
2580
2684
  async publishIdentityBinding(chainPubkey, l1Address, directAddress, nametag) {
2581
2685
  this.ensureReady();
2582
2686
  if (!this.identity) {
2583
- throw new Error("Identity not set");
2687
+ throw new SphereError("Identity not set", "NOT_INITIALIZED");
2584
2688
  }
2585
2689
  const nostrPubkey = this.getNostrPubkey();
2586
2690
  const dTagBytes = new TextEncoder().encode("unicity:identity:" + nostrPubkey);
@@ -2599,7 +2703,7 @@ var NostrTransportProvider = class {
2599
2703
  if (nametag) {
2600
2704
  const existing = await this.resolveNametag(nametag);
2601
2705
  if (existing && existing !== nostrPubkey) {
2602
- this.log("Nametag already taken:", nametag, "- owner:", existing);
2706
+ logger.debug("Nostr", "Nametag already taken:", nametag, "- owner:", existing);
2603
2707
  return false;
2604
2708
  }
2605
2709
  const { ProxyAddress } = await import("@unicitylabs/state-transition-sdk/lib/address/ProxyAddress");
@@ -2617,9 +2721,9 @@ var NostrTransportProvider = class {
2617
2721
  const event = await this.createEvent(EVENT_KINDS.NAMETAG_BINDING, content, tags);
2618
2722
  await this.publishEvent(event);
2619
2723
  if (nametag) {
2620
- this.log("Published identity binding with nametag:", nametag, "for pubkey:", nostrPubkey.slice(0, 16) + "...");
2724
+ logger.debug("Nostr", "Published identity binding with nametag:", nametag, "for pubkey:", nostrPubkey.slice(0, 16) + "...");
2621
2725
  } else {
2622
- this.log("Published identity binding (no nametag) for pubkey:", nostrPubkey.slice(0, 16) + "...");
2726
+ logger.debug("Nostr", "Published identity binding (no nametag) for pubkey:", nostrPubkey.slice(0, 16) + "...");
2623
2727
  }
2624
2728
  return true;
2625
2729
  }
@@ -2632,18 +2736,18 @@ var NostrTransportProvider = class {
2632
2736
  ["a", address]
2633
2737
  ]);
2634
2738
  await this.publishEvent(event);
2635
- this.log("Published nametag binding:", nametag);
2739
+ logger.debug("Nostr", "Published nametag binding:", nametag);
2636
2740
  }
2637
2741
  async registerNametag(nametag, _publicKey, directAddress = "") {
2638
2742
  this.ensureReady();
2639
2743
  if (!this.identity) {
2640
- throw new Error("Identity not set");
2744
+ throw new SphereError("Identity not set", "NOT_INITIALIZED");
2641
2745
  }
2642
2746
  const nostrPubkey = this.getNostrPubkey();
2643
2747
  const existing = await this.resolveNametag(nametag);
2644
- this.log("registerNametag:", nametag, "existing:", existing, "myPubkey:", nostrPubkey);
2748
+ logger.debug("Nostr", "registerNametag:", nametag, "existing:", existing, "myPubkey:", nostrPubkey);
2645
2749
  if (existing && existing !== nostrPubkey) {
2646
- this.log("Nametag already taken:", nametag, "- owner:", existing);
2750
+ logger.debug("Nostr", "Nametag already taken:", nametag, "- owner:", existing);
2647
2751
  return false;
2648
2752
  }
2649
2753
  const privateKeyHex = this.identity.privateKey;
@@ -2677,7 +2781,7 @@ var NostrTransportProvider = class {
2677
2781
  ];
2678
2782
  const event = await this.createEvent(EVENT_KINDS.NAMETAG_BINDING, content, tags);
2679
2783
  await this.publishEvent(event);
2680
- this.log("Registered nametag:", nametag, "for pubkey:", nostrPubkey.slice(0, 16) + "...", "l1:", l1Address.slice(0, 12) + "...");
2784
+ logger.debug("Nostr", "Registered nametag:", nametag, "for pubkey:", nostrPubkey.slice(0, 16) + "...", "l1:", l1Address.slice(0, 12) + "...");
2681
2785
  return true;
2682
2786
  }
2683
2787
  // Track broadcast subscriptions
@@ -2728,14 +2832,14 @@ var NostrTransportProvider = class {
2728
2832
  if (event.id) {
2729
2833
  this.processedEventIds.add(event.id);
2730
2834
  }
2731
- this.log("Processing event kind:", event.kind, "id:", event.id?.slice(0, 12));
2835
+ logger.debug("Nostr", "Processing event kind:", event.kind, "id:", event.id?.slice(0, 12));
2732
2836
  try {
2733
2837
  switch (event.kind) {
2734
2838
  case EVENT_KINDS.DIRECT_MESSAGE:
2735
2839
  await this.handleDirectMessage(event);
2736
2840
  break;
2737
2841
  case import_nostr_js_sdk.EventKinds.GIFT_WRAP:
2738
- this.log("Handling gift wrap (NIP-17 DM)");
2842
+ logger.debug("Nostr", "Handling gift wrap (NIP-17 DM)");
2739
2843
  await this.handleGiftWrap(event);
2740
2844
  break;
2741
2845
  case EVENT_KINDS.TOKEN_TRANSFER:
@@ -2758,7 +2862,7 @@ var NostrTransportProvider = class {
2758
2862
  }
2759
2863
  }
2760
2864
  } catch (error) {
2761
- this.log("Failed to handle event:", error);
2865
+ logger.debug("Nostr", "Failed to handle event:", error);
2762
2866
  }
2763
2867
  }
2764
2868
  /**
@@ -2773,25 +2877,25 @@ var NostrTransportProvider = class {
2773
2877
  const pubkey = this.keyManager.getPublicKeyHex();
2774
2878
  const storageKey = `${STORAGE_KEYS_GLOBAL.LAST_WALLET_EVENT_TS}_${pubkey.slice(0, 16)}`;
2775
2879
  this.storage.set(storageKey, createdAt.toString()).catch((err) => {
2776
- this.log("Failed to save last event timestamp:", err);
2880
+ logger.debug("Nostr", "Failed to save last event timestamp:", err);
2777
2881
  });
2778
2882
  }
2779
2883
  async handleDirectMessage(event) {
2780
- this.log("Ignoring NIP-04 kind 4 event (DMs use NIP-17):", event.id?.slice(0, 12));
2884
+ logger.debug("Nostr", "Ignoring NIP-04 kind 4 event (DMs use NIP-17):", event.id?.slice(0, 12));
2781
2885
  }
2782
2886
  async handleGiftWrap(event) {
2783
2887
  if (!this.identity || !this.keyManager) {
2784
- this.log("handleGiftWrap: no identity/keyManager");
2888
+ logger.debug("Nostr", "handleGiftWrap: no identity/keyManager");
2785
2889
  return;
2786
2890
  }
2787
2891
  try {
2788
2892
  const pm = import_nostr_js_sdk.NIP17.unwrap(event, this.keyManager);
2789
- this.log("Gift wrap unwrapped, sender:", pm.senderPubkey?.slice(0, 16), "kind:", pm.kind);
2893
+ logger.debug("Nostr", "Gift wrap unwrapped, sender:", pm.senderPubkey?.slice(0, 16), "kind:", pm.kind);
2790
2894
  if (pm.senderPubkey === this.keyManager.getPublicKeyHex()) {
2791
2895
  try {
2792
2896
  const parsed = JSON.parse(pm.content);
2793
2897
  if (parsed?.selfWrap && parsed.recipientPubkey) {
2794
- this.log("Self-wrap replay for recipient:", parsed.recipientPubkey?.slice(0, 16));
2898
+ logger.debug("Nostr", "Self-wrap replay for recipient:", parsed.recipientPubkey?.slice(0, 16));
2795
2899
  const message2 = {
2796
2900
  id: parsed.originalId || pm.eventId,
2797
2901
  senderTransportPubkey: pm.senderPubkey,
@@ -2806,18 +2910,18 @@ var NostrTransportProvider = class {
2806
2910
  try {
2807
2911
  handler(message2);
2808
2912
  } catch (e) {
2809
- this.log("Self-wrap handler error:", e);
2913
+ logger.debug("Nostr", "Self-wrap handler error:", e);
2810
2914
  }
2811
2915
  }
2812
2916
  return;
2813
2917
  }
2814
2918
  } catch {
2815
2919
  }
2816
- this.log("Skipping own non-self-wrap message");
2920
+ logger.debug("Nostr", "Skipping own non-self-wrap message");
2817
2921
  return;
2818
2922
  }
2819
2923
  if ((0, import_nostr_js_sdk.isReadReceipt)(pm)) {
2820
- this.log("Read receipt from:", pm.senderPubkey?.slice(0, 16), "for:", pm.replyToEventId);
2924
+ logger.debug("Nostr", "Read receipt from:", pm.senderPubkey?.slice(0, 16), "for:", pm.replyToEventId);
2821
2925
  if (pm.replyToEventId) {
2822
2926
  const receipt = {
2823
2927
  senderTransportPubkey: pm.senderPubkey,
@@ -2828,7 +2932,7 @@ var NostrTransportProvider = class {
2828
2932
  try {
2829
2933
  handler(receipt);
2830
2934
  } catch (e) {
2831
- this.log("Read receipt handler error:", e);
2935
+ logger.debug("Nostr", "Read receipt handler error:", e);
2832
2936
  }
2833
2937
  }
2834
2938
  }
@@ -2848,12 +2952,12 @@ var NostrTransportProvider = class {
2848
2952
  senderNametag: senderNametag2,
2849
2953
  expiresIn
2850
2954
  };
2851
- this.log("Composing indicator from:", indicator.senderNametag || pm.senderPubkey?.slice(0, 16));
2955
+ logger.debug("Nostr", "Composing indicator from:", indicator.senderNametag || pm.senderPubkey?.slice(0, 16));
2852
2956
  for (const handler of this.composingHandlers) {
2853
2957
  try {
2854
2958
  handler(indicator);
2855
2959
  } catch (e) {
2856
- this.log("Composing handler error:", e);
2960
+ logger.debug("Nostr", "Composing handler error:", e);
2857
2961
  }
2858
2962
  }
2859
2963
  return;
@@ -2861,7 +2965,7 @@ var NostrTransportProvider = class {
2861
2965
  try {
2862
2966
  const parsed = JSON.parse(pm.content);
2863
2967
  if (parsed?.type === "typing") {
2864
- this.log("Typing indicator from:", pm.senderPubkey?.slice(0, 16));
2968
+ logger.debug("Nostr", "Typing indicator from:", pm.senderPubkey?.slice(0, 16));
2865
2969
  const indicator = {
2866
2970
  senderTransportPubkey: pm.senderPubkey,
2867
2971
  senderNametag: parsed.senderNametag,
@@ -2871,7 +2975,7 @@ var NostrTransportProvider = class {
2871
2975
  try {
2872
2976
  handler(indicator);
2873
2977
  } catch (e) {
2874
- this.log("Typing handler error:", e);
2978
+ logger.debug("Nostr", "Typing handler error:", e);
2875
2979
  }
2876
2980
  }
2877
2981
  return;
@@ -2879,7 +2983,7 @@ var NostrTransportProvider = class {
2879
2983
  } catch {
2880
2984
  }
2881
2985
  if (!(0, import_nostr_js_sdk.isChatMessage)(pm)) {
2882
- this.log("Skipping unknown message kind:", pm.kind);
2986
+ logger.debug("Nostr", "Skipping unknown message kind:", pm.kind);
2883
2987
  return;
2884
2988
  }
2885
2989
  let content = pm.content;
@@ -2892,7 +2996,7 @@ var NostrTransportProvider = class {
2892
2996
  }
2893
2997
  } catch {
2894
2998
  }
2895
- this.log("DM received from:", senderNametag || pm.senderPubkey?.slice(0, 16), "content:", content?.slice(0, 50));
2999
+ logger.debug("Nostr", "DM received from:", senderNametag || pm.senderPubkey?.slice(0, 16), "content:", content?.slice(0, 50));
2896
3000
  const message = {
2897
3001
  // Use outer gift wrap event.id so it matches the sender's stored giftWrap.id.
2898
3002
  // This ensures read receipts reference an ID the sender recognizes.
@@ -2905,20 +3009,20 @@ var NostrTransportProvider = class {
2905
3009
  };
2906
3010
  this.emitEvent({ type: "message:received", timestamp: Date.now() });
2907
3011
  if (this.messageHandlers.size === 0) {
2908
- this.log("No message handlers registered, buffering message for later delivery");
3012
+ logger.debug("Nostr", "No message handlers registered, buffering message for later delivery");
2909
3013
  this.pendingMessages.push(message);
2910
3014
  } else {
2911
- this.log("Dispatching to", this.messageHandlers.size, "handlers");
3015
+ logger.debug("Nostr", "Dispatching to", this.messageHandlers.size, "handlers");
2912
3016
  for (const handler of this.messageHandlers) {
2913
3017
  try {
2914
3018
  handler(message);
2915
3019
  } catch (error) {
2916
- this.log("Message handler error:", error);
3020
+ logger.debug("Nostr", "Message handler error:", error);
2917
3021
  }
2918
3022
  }
2919
3023
  }
2920
3024
  } catch (err) {
2921
- this.log("Gift wrap decrypt failed (expected if not for us):", err?.message?.slice(0, 50));
3025
+ logger.debug("Nostr", "Gift wrap decrypt failed (expected if not for us):", err?.message?.slice(0, 50));
2922
3026
  }
2923
3027
  }
2924
3028
  async handleTokenTransfer(event) {
@@ -2936,7 +3040,7 @@ var NostrTransportProvider = class {
2936
3040
  try {
2937
3041
  await handler(transfer);
2938
3042
  } catch (error) {
2939
- this.log("Transfer handler error:", error);
3043
+ logger.debug("Nostr", "Transfer handler error:", error);
2940
3044
  }
2941
3045
  }
2942
3046
  }
@@ -2959,16 +3063,16 @@ var NostrTransportProvider = class {
2959
3063
  },
2960
3064
  timestamp: event.created_at * 1e3
2961
3065
  };
2962
- this.log("Received payment request:", request.id);
3066
+ logger.debug("Nostr", "Received payment request:", request.id);
2963
3067
  for (const handler of this.paymentRequestHandlers) {
2964
3068
  try {
2965
3069
  handler(request);
2966
3070
  } catch (error) {
2967
- this.log("Payment request handler error:", error);
3071
+ logger.debug("Nostr", "Payment request handler error:", error);
2968
3072
  }
2969
3073
  }
2970
3074
  } catch (error) {
2971
- this.log("Failed to handle payment request:", error);
3075
+ logger.debug("Nostr", "Failed to handle payment request:", error);
2972
3076
  }
2973
3077
  }
2974
3078
  async handlePaymentRequestResponse(event) {
@@ -2987,16 +3091,16 @@ var NostrTransportProvider = class {
2987
3091
  },
2988
3092
  timestamp: event.created_at * 1e3
2989
3093
  };
2990
- this.log("Received payment request response:", response.id, "type:", responseData.responseType);
3094
+ logger.debug("Nostr", "Received payment request response:", response.id, "type:", responseData.responseType);
2991
3095
  for (const handler of this.paymentRequestResponseHandlers) {
2992
3096
  try {
2993
3097
  handler(response);
2994
3098
  } catch (error) {
2995
- this.log("Payment request response handler error:", error);
3099
+ logger.debug("Nostr", "Payment request response handler error:", error);
2996
3100
  }
2997
3101
  }
2998
3102
  } catch (error) {
2999
- this.log("Failed to handle payment request response:", error);
3103
+ logger.debug("Nostr", "Failed to handle payment request response:", error);
3000
3104
  }
3001
3105
  }
3002
3106
  handleBroadcast(event) {
@@ -3015,7 +3119,7 @@ var NostrTransportProvider = class {
3015
3119
  try {
3016
3120
  handler(broadcast);
3017
3121
  } catch (error) {
3018
- this.log("Broadcast handler error:", error);
3122
+ logger.debug("Nostr", "Broadcast handler error:", error);
3019
3123
  }
3020
3124
  }
3021
3125
  }
@@ -3025,8 +3129,8 @@ var NostrTransportProvider = class {
3025
3129
  // Private: Event Creation & Publishing
3026
3130
  // ===========================================================================
3027
3131
  async createEvent(kind, content, tags) {
3028
- if (!this.identity) throw new Error("Identity not set");
3029
- if (!this.keyManager) throw new Error("KeyManager not initialized");
3132
+ if (!this.identity) throw new SphereError("Identity not set", "NOT_INITIALIZED");
3133
+ if (!this.keyManager) throw new SphereError("KeyManager not initialized", "NOT_INITIALIZED");
3030
3134
  const signedEvent = import_nostr_js_sdk.Event.create(this.keyManager, {
3031
3135
  kind,
3032
3136
  content,
@@ -3044,10 +3148,10 @@ var NostrTransportProvider = class {
3044
3148
  return event;
3045
3149
  }
3046
3150
  async createEncryptedEvent(kind, content, tags) {
3047
- if (!this.keyManager) throw new Error("KeyManager not initialized");
3151
+ if (!this.keyManager) throw new SphereError("KeyManager not initialized", "NOT_INITIALIZED");
3048
3152
  const recipientTag = tags.find((t) => t[0] === "p");
3049
3153
  if (!recipientTag || !recipientTag[1]) {
3050
- throw new Error("No recipient pubkey in tags for encryption");
3154
+ throw new SphereError("No recipient pubkey in tags for encryption", "VALIDATION_ERROR");
3051
3155
  }
3052
3156
  const recipientPubkey = recipientTag[1];
3053
3157
  const encrypted = await import_nostr_js_sdk.NIP04.encryptHex(
@@ -3059,14 +3163,14 @@ var NostrTransportProvider = class {
3059
3163
  }
3060
3164
  async publishEvent(event) {
3061
3165
  if (!this.nostrClient) {
3062
- throw new Error("NostrClient not initialized");
3166
+ throw new SphereError("NostrClient not initialized", "NOT_INITIALIZED");
3063
3167
  }
3064
3168
  const sdkEvent = import_nostr_js_sdk.Event.fromJSON(event);
3065
3169
  await this.nostrClient.publishEvent(sdkEvent);
3066
3170
  }
3067
3171
  async fetchPendingEvents() {
3068
3172
  if (!this.nostrClient?.isConnected() || !this.keyManager) {
3069
- throw new Error("Transport not connected");
3173
+ throw new SphereError("Transport not connected", "TRANSPORT_ERROR");
3070
3174
  }
3071
3175
  const nostrPubkey = this.keyManager.getPublicKeyHex();
3072
3176
  const walletFilter = new import_nostr_js_sdk.Filter();
@@ -3109,7 +3213,7 @@ var NostrTransportProvider = class {
3109
3213
  }
3110
3214
  async queryEvents(filterObj) {
3111
3215
  if (!this.nostrClient || !this.nostrClient.isConnected()) {
3112
- throw new Error("No connected relays");
3216
+ throw new SphereError("No connected relays", "TRANSPORT_ERROR");
3113
3217
  }
3114
3218
  const events = [];
3115
3219
  const filter = new import_nostr_js_sdk.Filter(filterObj);
@@ -3118,6 +3222,7 @@ var NostrTransportProvider = class {
3118
3222
  if (subId) {
3119
3223
  this.nostrClient?.unsubscribe(subId);
3120
3224
  }
3225
+ logger.warn("Nostr", `queryEvents timed out after 5s, returning ${events.length} event(s)`, { kinds: filterObj.kinds, limit: filterObj.limit });
3121
3226
  resolve(events);
3122
3227
  }, 5e3);
3123
3228
  const subId = this.nostrClient.subscribe(filter, {
@@ -3147,9 +3252,9 @@ var NostrTransportProvider = class {
3147
3252
  walletSubscriptionId = null;
3148
3253
  chatSubscriptionId = null;
3149
3254
  async subscribeToEvents() {
3150
- this.log("subscribeToEvents called, identity:", !!this.identity, "keyManager:", !!this.keyManager, "nostrClient:", !!this.nostrClient);
3255
+ logger.debug("Nostr", "subscribeToEvents called, identity:", !!this.identity, "keyManager:", !!this.keyManager, "nostrClient:", !!this.nostrClient);
3151
3256
  if (!this.identity || !this.keyManager || !this.nostrClient) {
3152
- this.log("subscribeToEvents: skipped - no identity, keyManager, or nostrClient");
3257
+ logger.debug("Nostr", "subscribeToEvents: skipped - no identity, keyManager, or nostrClient");
3153
3258
  return;
3154
3259
  }
3155
3260
  if (this.walletSubscriptionId) {
@@ -3165,7 +3270,7 @@ var NostrTransportProvider = class {
3165
3270
  this.mainSubscriptionId = null;
3166
3271
  }
3167
3272
  const nostrPubkey = this.keyManager.getPublicKeyHex();
3168
- this.log("Subscribing with Nostr pubkey:", nostrPubkey);
3273
+ logger.debug("Nostr", "Subscribing with Nostr pubkey:", nostrPubkey);
3169
3274
  let since;
3170
3275
  if (this.storage) {
3171
3276
  const storageKey = `${STORAGE_KEYS_GLOBAL.LAST_WALLET_EVENT_TS}_${nostrPubkey.slice(0, 16)}`;
@@ -3174,18 +3279,18 @@ var NostrTransportProvider = class {
3174
3279
  if (stored) {
3175
3280
  since = parseInt(stored, 10);
3176
3281
  this.lastEventTs = since;
3177
- this.log("Resuming from stored event timestamp:", since);
3282
+ logger.debug("Nostr", "Resuming from stored event timestamp:", since);
3178
3283
  } else {
3179
3284
  since = Math.floor(Date.now() / 1e3);
3180
- this.log("No stored timestamp, starting from now:", since);
3285
+ logger.debug("Nostr", "No stored timestamp, starting from now:", since);
3181
3286
  }
3182
3287
  } catch (err) {
3183
- this.log("Failed to read last event timestamp, falling back to now:", err);
3288
+ logger.debug("Nostr", "Failed to read last event timestamp, falling back to now:", err);
3184
3289
  since = Math.floor(Date.now() / 1e3);
3185
3290
  }
3186
3291
  } else {
3187
3292
  since = Math.floor(Date.now() / 1e3) - 86400;
3188
- this.log("No storage adapter, using 24h fallback");
3293
+ logger.debug("Nostr", "No storage adapter, using 24h fallback");
3189
3294
  }
3190
3295
  const walletFilter = new import_nostr_js_sdk.Filter();
3191
3296
  walletFilter.kinds = [
@@ -3198,7 +3303,7 @@ var NostrTransportProvider = class {
3198
3303
  walletFilter.since = since;
3199
3304
  this.walletSubscriptionId = this.nostrClient.subscribe(walletFilter, {
3200
3305
  onEvent: (event) => {
3201
- this.log("Received wallet event kind:", event.kind, "id:", event.id?.slice(0, 12));
3306
+ logger.debug("Nostr", "Received wallet event kind:", event.kind, "id:", event.id?.slice(0, 12));
3202
3307
  this.handleEvent({
3203
3308
  id: event.id,
3204
3309
  kind: event.kind,
@@ -3210,19 +3315,19 @@ var NostrTransportProvider = class {
3210
3315
  });
3211
3316
  },
3212
3317
  onEndOfStoredEvents: () => {
3213
- this.log("Wallet subscription ready (EOSE)");
3318
+ logger.debug("Nostr", "Wallet subscription ready (EOSE)");
3214
3319
  },
3215
3320
  onError: (_subId, error) => {
3216
- this.log("Wallet subscription error:", error);
3321
+ logger.debug("Nostr", "Wallet subscription error:", error);
3217
3322
  }
3218
3323
  });
3219
- this.log("Wallet subscription created, subId:", this.walletSubscriptionId);
3324
+ logger.debug("Nostr", "Wallet subscription created, subId:", this.walletSubscriptionId);
3220
3325
  const chatFilter = new import_nostr_js_sdk.Filter();
3221
3326
  chatFilter.kinds = [import_nostr_js_sdk.EventKinds.GIFT_WRAP];
3222
3327
  chatFilter["#p"] = [nostrPubkey];
3223
3328
  this.chatSubscriptionId = this.nostrClient.subscribe(chatFilter, {
3224
3329
  onEvent: (event) => {
3225
- this.log("Received chat event kind:", event.kind, "id:", event.id?.slice(0, 12));
3330
+ logger.debug("Nostr", "Received chat event kind:", event.kind, "id:", event.id?.slice(0, 12));
3226
3331
  this.handleEvent({
3227
3332
  id: event.id,
3228
3333
  kind: event.kind,
@@ -3234,13 +3339,13 @@ var NostrTransportProvider = class {
3234
3339
  });
3235
3340
  },
3236
3341
  onEndOfStoredEvents: () => {
3237
- this.log("Chat subscription ready (EOSE)");
3342
+ logger.debug("Nostr", "Chat subscription ready (EOSE)");
3238
3343
  },
3239
3344
  onError: (_subId, error) => {
3240
- this.log("Chat subscription error:", error);
3345
+ logger.debug("Nostr", "Chat subscription error:", error);
3241
3346
  }
3242
3347
  });
3243
- this.log("Chat subscription created, subId:", this.chatSubscriptionId);
3348
+ logger.debug("Nostr", "Chat subscription created, subId:", this.chatSubscriptionId);
3244
3349
  }
3245
3350
  subscribeToTags(tags) {
3246
3351
  if (!this.nostrClient) return;
@@ -3270,7 +3375,7 @@ var NostrTransportProvider = class {
3270
3375
  // Private: Encryption
3271
3376
  // ===========================================================================
3272
3377
  async decryptContent(content, senderPubkey) {
3273
- if (!this.keyManager) throw new Error("KeyManager not initialized");
3378
+ if (!this.keyManager) throw new SphereError("KeyManager not initialized", "NOT_INITIALIZED");
3274
3379
  const decrypted = await import_nostr_js_sdk.NIP04.decryptHex(
3275
3380
  content,
3276
3381
  this.keyManager.getPrivateKeyHex(),
@@ -3300,13 +3405,13 @@ var NostrTransportProvider = class {
3300
3405
  // ===========================================================================
3301
3406
  ensureConnected() {
3302
3407
  if (!this.isConnected()) {
3303
- throw new Error("NostrTransportProvider not connected");
3408
+ throw new SphereError("NostrTransportProvider not connected", "TRANSPORT_ERROR");
3304
3409
  }
3305
3410
  }
3306
3411
  ensureReady() {
3307
3412
  this.ensureConnected();
3308
3413
  if (!this.identity) {
3309
- throw new Error("Identity not set");
3414
+ throw new SphereError("Identity not set", "NOT_INITIALIZED");
3310
3415
  }
3311
3416
  }
3312
3417
  emitEvent(event) {
@@ -3314,7 +3419,7 @@ var NostrTransportProvider = class {
3314
3419
  try {
3315
3420
  callback(event);
3316
3421
  } catch (error) {
3317
- this.log("Event callback error:", error);
3422
+ logger.debug("Nostr", "Event callback error:", error);
3318
3423
  }
3319
3424
  }
3320
3425
  }
@@ -3351,11 +3456,6 @@ var NostrTransportProvider = class {
3351
3456
  ephemeralKeys.clear();
3352
3457
  return giftWrap;
3353
3458
  }
3354
- log(...args) {
3355
- if (this.config.debug) {
3356
- console.log("[NostrTransportProvider]", ...args);
3357
- }
3358
- }
3359
3459
  };
3360
3460
 
3361
3461
  // impl/browser/transport/index.ts
@@ -3539,7 +3639,8 @@ var UnicityAggregatorProvider = class {
3539
3639
  proof: response.proof,
3540
3640
  timestamp: Date.now()
3541
3641
  };
3542
- } catch {
3642
+ } catch (error) {
3643
+ logger.warn("Aggregator", "getProof failed", error);
3543
3644
  return null;
3544
3645
  }
3545
3646
  }
@@ -3561,7 +3662,7 @@ var UnicityAggregatorProvider = class {
3561
3662
  }
3562
3663
  await new Promise((resolve) => setTimeout(resolve, pollInterval));
3563
3664
  }
3564
- throw new Error(`Timeout waiting for proof: ${requestId}`);
3665
+ throw new SphereError(`Timeout waiting for proof: ${requestId}`, "TIMEOUT");
3565
3666
  }
3566
3667
  async validateToken(tokenData) {
3567
3668
  this.ensureConnected();
@@ -3620,7 +3721,7 @@ var UnicityAggregatorProvider = class {
3620
3721
  async waitForProofSdk(commitment, signal) {
3621
3722
  this.ensureConnected();
3622
3723
  if (!this.trustBase) {
3623
- throw new Error("Trust base not initialized");
3724
+ throw new SphereError("Trust base not initialized", "NOT_INITIALIZED");
3624
3725
  }
3625
3726
  return await (0, import_InclusionProofUtils.waitInclusionProof)(
3626
3727
  this.trustBase,
@@ -3642,7 +3743,8 @@ var UnicityAggregatorProvider = class {
3642
3743
  this.spentCache.set(stateHash, true);
3643
3744
  }
3644
3745
  return spent;
3645
- } catch {
3746
+ } catch (error) {
3747
+ logger.warn("Aggregator", "isSpent check failed, assuming unspent", error);
3646
3748
  return false;
3647
3749
  }
3648
3750
  }
@@ -3660,7 +3762,8 @@ var UnicityAggregatorProvider = class {
3660
3762
  roundNumber: response.state.roundNumber,
3661
3763
  lastUpdated: Date.now()
3662
3764
  };
3663
- } catch {
3765
+ } catch (error) {
3766
+ logger.warn("Aggregator", "getTokenState failed", error);
3664
3767
  return null;
3665
3768
  }
3666
3769
  }
@@ -3720,11 +3823,11 @@ var UnicityAggregatorProvider = class {
3720
3823
  signal: controller.signal
3721
3824
  });
3722
3825
  if (!response.ok) {
3723
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
3826
+ throw new SphereError(`HTTP ${response.status}: ${response.statusText}`, "AGGREGATOR_ERROR");
3724
3827
  }
3725
3828
  const result = await response.json();
3726
3829
  if (result.error) {
3727
- throw new Error(result.error.message ?? "RPC error");
3830
+ throw new SphereError(result.error.message ?? "RPC error", "AGGREGATOR_ERROR");
3728
3831
  }
3729
3832
  return result.result ?? {};
3730
3833
  } finally {
@@ -3736,7 +3839,7 @@ var UnicityAggregatorProvider = class {
3736
3839
  // ===========================================================================
3737
3840
  ensureConnected() {
3738
3841
  if (this.status !== "connected") {
3739
- throw new Error("UnicityAggregatorProvider not connected");
3842
+ throw new SphereError("UnicityAggregatorProvider not connected", "NOT_INITIALIZED");
3740
3843
  }
3741
3844
  }
3742
3845
  emitEvent(event) {
@@ -3748,10 +3851,8 @@ var UnicityAggregatorProvider = class {
3748
3851
  }
3749
3852
  }
3750
3853
  }
3751
- log(...args) {
3752
- if (this.config.debug) {
3753
- console.log("[UnicityAggregatorProvider]", ...args);
3754
- }
3854
+ log(message, ...args) {
3855
+ logger.debug("Aggregator", message, ...args);
3755
3856
  }
3756
3857
  };
3757
3858
  var UnicityOracleProvider = UnicityAggregatorProvider;
@@ -4340,7 +4441,10 @@ var IpfsHttpClient = class {
4340
4441
  { headers: { Accept: "application/octet-stream" } }
4341
4442
  );
4342
4443
  if (!response.ok) {
4343
- const body = await response.text().catch(() => "");
4444
+ const body = await response.text().catch((err) => {
4445
+ logger.debug("IPFS-HTTP", "Failed to read error response body", err);
4446
+ return "";
4447
+ });
4344
4448
  throw new IpfsError(
4345
4449
  `Fetch failed: HTTP ${response.status}`,
4346
4450
  classifyHttpStatus(response.status, body),
@@ -4386,7 +4490,10 @@ var IpfsHttpClient = class {
4386
4490
  { method: "POST" }
4387
4491
  );
4388
4492
  if (!response.ok) {
4389
- const body = await response.text().catch(() => "");
4493
+ const body = await response.text().catch((err) => {
4494
+ logger.debug("IPFS-HTTP", "Failed to read error response body", err);
4495
+ return "";
4496
+ });
4390
4497
  const category = classifyHttpStatus(response.status, body);
4391
4498
  if (category === "NOT_FOUND") return null;
4392
4499
  throw new IpfsError(`Routing API: HTTP ${response.status}`, category, gateway);
@@ -4432,7 +4539,8 @@ var IpfsHttpClient = class {
4432
4539
  }
4433
4540
  }
4434
4541
  return { cid: "", content };
4435
- } catch {
4542
+ } catch (err) {
4543
+ logger.debug("IPFS-HTTP", "IPNS gateway resolution failed", err);
4436
4544
  return null;
4437
4545
  }
4438
4546
  }
@@ -4497,7 +4605,10 @@ var IpfsHttpClient = class {
4497
4605
  { method: "POST", body: formData }
4498
4606
  );
4499
4607
  if (!response.ok) {
4500
- const errorText = await response.text().catch(() => "");
4608
+ const errorText = await response.text().catch((err) => {
4609
+ logger.debug("IPFS-HTTP", "Failed to read error response body", err);
4610
+ return "";
4611
+ });
4501
4612
  throw new IpfsError(
4502
4613
  `IPNS publish: HTTP ${response.status}: ${errorText.slice(0, 100)}`,
4503
4614
  classifyHttpStatus(response.status, errorText),
@@ -4574,9 +4685,7 @@ var IpfsHttpClient = class {
4574
4685
  }
4575
4686
  }
4576
4687
  log(message) {
4577
- if (this.debug) {
4578
- console.log(`[IPFS-HTTP] ${message}`);
4579
- }
4688
+ logger.debug("IPFS-HTTP", message);
4580
4689
  }
4581
4690
  };
4582
4691
 
@@ -5020,10 +5129,12 @@ var IpnsSubscriptionClient = class {
5020
5129
  startFallbackPolling() {
5021
5130
  if (this.fallbackPollInterval || !this.fallbackPollFn || this.destroyed) return;
5022
5131
  this.log(`Starting fallback polling (${this.fallbackPollIntervalMs / 1e3}s interval)`);
5023
- this.fallbackPollFn().catch(() => {
5132
+ this.fallbackPollFn().catch((err) => {
5133
+ logger.warn("IPNS-WS", "Fallback poll error:", err);
5024
5134
  });
5025
5135
  this.fallbackPollInterval = setInterval(() => {
5026
- this.fallbackPollFn?.().catch(() => {
5136
+ this.fallbackPollFn?.().catch((err) => {
5137
+ logger.warn("IPNS-WS", "Fallback poll error:", err);
5027
5138
  });
5028
5139
  }, this.fallbackPollIntervalMs);
5029
5140
  }
@@ -5037,9 +5148,7 @@ var IpnsSubscriptionClient = class {
5037
5148
  // Internal: Logging
5038
5149
  // ---------------------------------------------------------------------------
5039
5150
  log(message) {
5040
- if (this.debugEnabled) {
5041
- console.log(`[IPNS-WS] ${message}`);
5042
- }
5151
+ logger.debug("IPNS-WS", message);
5043
5152
  }
5044
5153
  };
5045
5154
 
@@ -5228,7 +5337,8 @@ var IpfsStorageProvider = class {
5228
5337
  } else {
5229
5338
  this.log("Warning: no healthy gateways found");
5230
5339
  }
5231
- }).catch(() => {
5340
+ }).catch((err) => {
5341
+ logger.warn("IPFS-Storage", "Gateway health check failed (non-fatal):", err);
5232
5342
  });
5233
5343
  this.isShuttingDown = false;
5234
5344
  this.status = "connected";
@@ -5392,7 +5502,7 @@ var IpfsStorageProvider = class {
5392
5502
  };
5393
5503
  const result = await this._doSave(baseData);
5394
5504
  if (!result.success) {
5395
- throw new Error(result.error ?? "Save failed");
5505
+ throw new SphereError(result.error ?? "Save failed", "STORAGE_ERROR");
5396
5506
  }
5397
5507
  this.log(`Flushed successfully: CID=${result.cid}`);
5398
5508
  } catch (error) {
@@ -5632,10 +5742,12 @@ var IpfsStorageProvider = class {
5632
5742
  if (this.flushTimer) {
5633
5743
  clearTimeout(this.flushTimer);
5634
5744
  this.flushTimer = null;
5635
- await this.flushQueue.enqueue(() => this.executeFlush()).catch(() => {
5745
+ await this.flushQueue.enqueue(() => this.executeFlush()).catch((err) => {
5746
+ logger.warn("IPFS-Storage", "Flush on shutdown failed:", err);
5636
5747
  });
5637
5748
  } else if (!this.pendingBuffer.isEmpty) {
5638
- await this.flushQueue.enqueue(() => this.executeFlush()).catch(() => {
5749
+ await this.flushQueue.enqueue(() => this.executeFlush()).catch((err) => {
5750
+ logger.warn("IPFS-Storage", "Flush on shutdown failed:", err);
5639
5751
  });
5640
5752
  } else {
5641
5753
  await this.flushQueue.enqueue(async () => {
@@ -5689,9 +5801,7 @@ var IpfsStorageProvider = class {
5689
5801
  }
5690
5802
  }
5691
5803
  log(message) {
5692
- if (this.debug) {
5693
- console.log(`[IPFS-Storage] ${message}`);
5694
- }
5804
+ logger.debug("IPFS-Storage", message);
5695
5805
  }
5696
5806
  };
5697
5807
 
@@ -5804,7 +5914,7 @@ var CoinGeckoPriceProvider = class {
5804
5914
  const allCovered = uncachedNames.every((n) => this.fetchNames.has(n));
5805
5915
  if (allCovered) {
5806
5916
  if (this.debug) {
5807
- console.log(`[CoinGecko] Deduplicating request, reusing in-flight fetch`);
5917
+ logger.debug("CoinGecko", "Deduplicating request, reusing in-flight fetch");
5808
5918
  }
5809
5919
  const fetched = await this.fetchPromise;
5810
5920
  for (const name of uncachedNames) {
@@ -5843,7 +5953,7 @@ var CoinGeckoPriceProvider = class {
5843
5953
  headers["x-cg-pro-api-key"] = this.apiKey;
5844
5954
  }
5845
5955
  if (this.debug) {
5846
- console.log(`[CoinGecko] Fetching prices for: ${uncachedNames.join(", ")}`);
5956
+ logger.debug("CoinGecko", `Fetching prices for: ${uncachedNames.join(", ")}`);
5847
5957
  }
5848
5958
  const response = await fetch(url, {
5849
5959
  headers,
@@ -5853,7 +5963,7 @@ var CoinGeckoPriceProvider = class {
5853
5963
  if (response.status === 429) {
5854
5964
  this.extendCacheOnRateLimit(uncachedNames);
5855
5965
  }
5856
- throw new Error(`CoinGecko API error: ${response.status} ${response.statusText}`);
5966
+ throw new SphereError(`CoinGecko API error: ${response.status} ${response.statusText}`, "NETWORK_ERROR");
5857
5967
  }
5858
5968
  const data = await response.json();
5859
5969
  for (const [name, values] of Object.entries(data)) {
@@ -5883,12 +5993,12 @@ var CoinGeckoPriceProvider = class {
5883
5993
  }
5884
5994
  }
5885
5995
  if (this.debug) {
5886
- console.log(`[CoinGecko] Fetched ${result.size} prices`);
5996
+ logger.debug("CoinGecko", `Fetched ${result.size} prices`);
5887
5997
  }
5888
5998
  this.saveToStorage();
5889
5999
  } catch (error) {
5890
6000
  if (this.debug) {
5891
- console.warn("[CoinGecko] Fetch failed, using stale cache:", error);
6001
+ logger.warn("CoinGecko", "Fetch failed, using stale cache:", error);
5892
6002
  }
5893
6003
  for (const name of uncachedNames) {
5894
6004
  const stale = this.cache.get(name);
@@ -5938,7 +6048,7 @@ var CoinGeckoPriceProvider = class {
5938
6048
  }
5939
6049
  }
5940
6050
  if (this.debug) {
5941
- console.log(`[CoinGecko] Loaded ${Object.keys(data).length} prices from persistent cache`);
6051
+ logger.debug("CoinGecko", `Loaded ${Object.keys(data).length} prices from persistent cache`);
5942
6052
  }
5943
6053
  } catch {
5944
6054
  }
@@ -5955,8 +6065,7 @@ var CoinGeckoPriceProvider = class {
5955
6065
  Promise.all([
5956
6066
  this.storage.set(STORAGE_KEYS_GLOBAL.PRICE_CACHE, JSON.stringify(data)),
5957
6067
  this.storage.set(STORAGE_KEYS_GLOBAL.PRICE_CACHE_TS, String(Date.now()))
5958
- ]).catch(() => {
5959
- });
6068
+ ]).catch((err) => logger.debug("Price", "Cache save failed (non-critical)", err));
5960
6069
  }
5961
6070
  // ===========================================================================
5962
6071
  // Rate-limit handling
@@ -5975,7 +6084,7 @@ var CoinGeckoPriceProvider = class {
5975
6084
  }
5976
6085
  }
5977
6086
  if (this.debug) {
5978
- console.warn(`[CoinGecko] Rate-limited (429), extended cache TTL by ${backoffMs / 1e3}s`);
6087
+ logger.warn("CoinGecko", `Rate-limited (429), extended cache TTL by ${backoffMs / 1e3}s`);
5979
6088
  }
5980
6089
  }
5981
6090
  async getPrice(tokenName) {
@@ -5993,7 +6102,7 @@ function createPriceProvider(config) {
5993
6102
  case "coingecko":
5994
6103
  return new CoinGeckoPriceProvider(config);
5995
6104
  default:
5996
- throw new Error(`Unsupported price platform: ${String(config.platform)}`);
6105
+ throw new SphereError(`Unsupported price platform: ${String(config.platform)}`, "INVALID_CONFIG");
5997
6106
  }
5998
6107
  }
5999
6108
 
@@ -6218,14 +6327,12 @@ var TokenRegistry = class _TokenRegistry {
6218
6327
  clearTimeout(timer);
6219
6328
  }
6220
6329
  if (!response.ok) {
6221
- console.warn(
6222
- `[TokenRegistry] Remote fetch failed: HTTP ${response.status} ${response.statusText}`
6223
- );
6330
+ logger.warn("TokenRegistry", `Remote fetch failed: HTTP ${response.status} ${response.statusText}`);
6224
6331
  return false;
6225
6332
  }
6226
6333
  const data = await response.json();
6227
6334
  if (!this.isValidDefinitionsArray(data)) {
6228
- console.warn("[TokenRegistry] Remote data is not a valid token definitions array");
6335
+ logger.warn("TokenRegistry", "Remote data is not a valid token definitions array");
6229
6336
  return false;
6230
6337
  }
6231
6338
  const definitions = data;
@@ -6235,7 +6342,7 @@ var TokenRegistry = class _TokenRegistry {
6235
6342
  return true;
6236
6343
  } catch (error) {
6237
6344
  const message = error instanceof Error ? error.message : String(error);
6238
- console.warn(`[TokenRegistry] Remote refresh failed: ${message}`);
6345
+ logger.warn("TokenRegistry", `Remote refresh failed: ${message}`);
6239
6346
  return false;
6240
6347
  }
6241
6348
  }
@@ -6541,6 +6648,12 @@ function resolveTokenSyncConfig(network, config) {
6541
6648
  }
6542
6649
  function createBrowserProviders(config) {
6543
6650
  const network = config?.network ?? "mainnet";
6651
+ if (config?.debug !== void 0) {
6652
+ logger.configure({ debug: config.debug });
6653
+ }
6654
+ if (config?.transport?.debug) logger.setTagDebug("Nostr", true);
6655
+ if (config?.oracle?.debug) logger.setTagDebug("Aggregator", true);
6656
+ if (config?.price?.debug) logger.setTagDebug("Price", true);
6544
6657
  const transportConfig = resolveTransportConfig(network, config?.transport);
6545
6658
  const oracleConfig = resolveOracleConfig(network, config?.oracle);
6546
6659
  const l1Config = resolveL1Config(network, config?.l1);