@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.
- package/README.md +2 -0
- package/dist/connect/index.cjs +145 -23
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.cts +15 -2
- package/dist/connect/index.d.ts +15 -2
- package/dist/connect/index.js +145 -23
- package/dist/connect/index.js.map +1 -1
- package/dist/core/index.cjs +670 -473
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +123 -2
- package/dist/core/index.d.ts +123 -2
- package/dist/core/index.js +667 -473
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/connect/index.cjs +119 -1
- package/dist/impl/browser/connect/index.cjs.map +1 -1
- package/dist/impl/browser/connect/index.d.cts +53 -1
- package/dist/impl/browser/connect/index.d.ts +53 -1
- package/dist/impl/browser/connect/index.js +119 -1
- package/dist/impl/browser/connect/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +306 -193
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +306 -193
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/browser/ipfs.cjs +134 -19
- package/dist/impl/browser/ipfs.cjs.map +1 -1
- package/dist/impl/browser/ipfs.js +134 -19
- package/dist/impl/browser/ipfs.js.map +1 -1
- package/dist/impl/nodejs/connect/index.cjs +101 -6
- package/dist/impl/nodejs/connect/index.cjs.map +1 -1
- package/dist/impl/nodejs/connect/index.d.cts +2 -0
- package/dist/impl/nodejs/connect/index.d.ts +2 -0
- package/dist/impl/nodejs/connect/index.js +101 -6
- package/dist/impl/nodejs/connect/index.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +267 -152
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +2 -1
- package/dist/impl/nodejs/index.d.ts +2 -1
- package/dist/impl/nodejs/index.js +267 -152
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +682 -493
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +124 -8
- package/dist/index.d.ts +124 -8
- package/dist/index.js +680 -493
- package/dist/index.js.map +1 -1
- package/dist/l1/index.cjs +139 -32
- package/dist/l1/index.cjs.map +1 -1
- package/dist/l1/index.js +139 -32
- package/dist/l1/index.js.map +1 -1
- 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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
559
|
+
logger.debug("IndexedDB", ` connect: connected db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
|
|
458
560
|
return;
|
|
459
561
|
} catch (error) {
|
|
460
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
638
|
+
logger.debug("IndexedDB", ` clear: closing stale handle connId=${prevConnId}`);
|
|
537
639
|
this.db.close();
|
|
538
640
|
this.db = null;
|
|
539
641
|
}
|
|
540
|
-
|
|
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
|
-
|
|
652
|
+
logger.debug("IndexedDB", ` clear: store cleared db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
|
|
551
653
|
} catch (err) {
|
|
552
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
855
|
+
logger.debug("IndexedDBToken", `initialize: opening db=${this.dbName}`);
|
|
756
856
|
this.db = await this.openDatabase();
|
|
757
857
|
this.status = "connected";
|
|
758
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
944
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
2024
|
+
logger.debug("Nostr", "NostrClient disconnected from relay:", url, "reason:", reason);
|
|
1924
2025
|
},
|
|
1925
2026
|
onReconnecting: (url, attempt) => {
|
|
1926
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2137
|
+
logger.debug("Nostr", "Relay not found:", relayUrl);
|
|
2037
2138
|
return false;
|
|
2038
2139
|
}
|
|
2039
2140
|
this.config.relays.splice(index, 1);
|
|
2040
|
-
|
|
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
|
-
|
|
2178
|
+
logger.debug("Nostr", "Identity set, Nostr pubkey:", nostrPubkey.slice(0, 16) + "...");
|
|
2078
2179
|
if (this.nostrClient && this.status === "connected") {
|
|
2079
|
-
|
|
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
|
-
|
|
2191
|
+
logger.debug("Nostr", "NostrClient connected to relay:", url);
|
|
2091
2192
|
},
|
|
2092
2193
|
onDisconnect: (url, reason) => {
|
|
2093
|
-
|
|
2194
|
+
logger.debug("Nostr", "NostrClient disconnected from relay:", url, "reason:", reason);
|
|
2094
2195
|
},
|
|
2095
2196
|
onReconnecting: (url, attempt) => {
|
|
2096
|
-
|
|
2197
|
+
logger.debug("Nostr", "NostrClient reconnecting to relay:", url, "attempt:", attempt);
|
|
2097
2198
|
},
|
|
2098
2199
|
onReconnected: (url) => {
|
|
2099
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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)
|
|
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
|
-
|
|
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
|
|
2639
|
+
throw new SphereError("Identity not set", "NOT_INITIALIZED");
|
|
2536
2640
|
}
|
|
2537
2641
|
const nostrPubkey = this.getNostrPubkey();
|
|
2538
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
2724
|
+
logger.debug("Nostr", "Published identity binding with nametag:", nametag, "for pubkey:", nostrPubkey.slice(0, 16) + "...");
|
|
2621
2725
|
} else {
|
|
2622
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
2748
|
+
logger.debug("Nostr", "registerNametag:", nametag, "existing:", existing, "myPubkey:", nostrPubkey);
|
|
2645
2749
|
if (existing && existing !== nostrPubkey) {
|
|
2646
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2880
|
+
logger.debug("Nostr", "Failed to save last event timestamp:", err);
|
|
2777
2881
|
});
|
|
2778
2882
|
}
|
|
2779
2883
|
async handleDirectMessage(event) {
|
|
2780
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2913
|
+
logger.debug("Nostr", "Self-wrap handler error:", e);
|
|
2810
2914
|
}
|
|
2811
2915
|
}
|
|
2812
2916
|
return;
|
|
2813
2917
|
}
|
|
2814
2918
|
} catch {
|
|
2815
2919
|
}
|
|
2816
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3012
|
+
logger.debug("Nostr", "No message handlers registered, buffering message for later delivery");
|
|
2909
3013
|
this.pendingMessages.push(message);
|
|
2910
3014
|
} else {
|
|
2911
|
-
|
|
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
|
-
|
|
3020
|
+
logger.debug("Nostr", "Message handler error:", error);
|
|
2917
3021
|
}
|
|
2918
3022
|
}
|
|
2919
3023
|
}
|
|
2920
3024
|
} catch (err) {
|
|
2921
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3071
|
+
logger.debug("Nostr", "Payment request handler error:", error);
|
|
2968
3072
|
}
|
|
2969
3073
|
}
|
|
2970
3074
|
} catch (error) {
|
|
2971
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3099
|
+
logger.debug("Nostr", "Payment request response handler error:", error);
|
|
2996
3100
|
}
|
|
2997
3101
|
}
|
|
2998
3102
|
} catch (error) {
|
|
2999
|
-
|
|
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
|
-
|
|
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
|
|
3029
|
-
if (!this.keyManager) throw new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3282
|
+
logger.debug("Nostr", "Resuming from stored event timestamp:", since);
|
|
3178
3283
|
} else {
|
|
3179
3284
|
since = Math.floor(Date.now() / 1e3);
|
|
3180
|
-
|
|
3285
|
+
logger.debug("Nostr", "No stored timestamp, starting from now:", since);
|
|
3181
3286
|
}
|
|
3182
3287
|
} catch (err) {
|
|
3183
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3318
|
+
logger.debug("Nostr", "Wallet subscription ready (EOSE)");
|
|
3214
3319
|
},
|
|
3215
3320
|
onError: (_subId, error) => {
|
|
3216
|
-
|
|
3321
|
+
logger.debug("Nostr", "Wallet subscription error:", error);
|
|
3217
3322
|
}
|
|
3218
3323
|
});
|
|
3219
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3342
|
+
logger.debug("Nostr", "Chat subscription ready (EOSE)");
|
|
3238
3343
|
},
|
|
3239
3344
|
onError: (_subId, error) => {
|
|
3240
|
-
|
|
3345
|
+
logger.debug("Nostr", "Chat subscription error:", error);
|
|
3241
3346
|
}
|
|
3242
3347
|
});
|
|
3243
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
5996
|
+
logger.debug("CoinGecko", `Fetched ${result.size} prices`);
|
|
5887
5997
|
}
|
|
5888
5998
|
this.saveToStorage();
|
|
5889
5999
|
} catch (error) {
|
|
5890
6000
|
if (this.debug) {
|
|
5891
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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);
|