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