@unicitylabs/sphere-sdk 0.3.8 → 0.4.0
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/dist/connect/index.cjs +770 -0
- package/dist/connect/index.cjs.map +1 -0
- package/dist/connect/index.d.cts +312 -0
- package/dist/connect/index.d.ts +312 -0
- package/dist/connect/index.js +747 -0
- package/dist/connect/index.js.map +1 -0
- package/dist/core/index.cjs +2744 -56
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +277 -3
- package/dist/core/index.d.ts +277 -3
- package/dist/core/index.js +2740 -52
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/connect/index.cjs +271 -0
- package/dist/impl/browser/connect/index.cjs.map +1 -0
- package/dist/impl/browser/connect/index.d.cts +137 -0
- package/dist/impl/browser/connect/index.d.ts +137 -0
- package/dist/impl/browser/connect/index.js +248 -0
- package/dist/impl/browser/connect/index.js.map +1 -0
- package/dist/impl/browser/index.cjs +583 -45
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +587 -46
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/browser/ipfs.cjs.map +1 -1
- package/dist/impl/browser/ipfs.js.map +1 -1
- package/dist/impl/nodejs/connect/index.cjs +372 -0
- package/dist/impl/nodejs/connect/index.cjs.map +1 -0
- package/dist/impl/nodejs/connect/index.d.cts +178 -0
- package/dist/impl/nodejs/connect/index.d.ts +178 -0
- package/dist/impl/nodejs/connect/index.js +333 -0
- package/dist/impl/nodejs/connect/index.js.map +1 -0
- package/dist/impl/nodejs/index.cjs +266 -12
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +96 -0
- package/dist/impl/nodejs/index.d.ts +96 -0
- package/dist/impl/nodejs/index.js +270 -13
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +2761 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +375 -5
- package/dist/index.d.ts +375 -5
- package/dist/index.js +2750 -52
- package/dist/index.js.map +1 -1
- package/dist/l1/index.cjs +5 -1
- package/dist/l1/index.cjs.map +1 -1
- package/dist/l1/index.d.cts +2 -1
- package/dist/l1/index.d.ts +2 -1
- package/dist/l1/index.js +5 -1
- package/dist/l1/index.js.map +1 -1
- package/package.json +31 -1
|
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var browser_exports = {};
|
|
32
32
|
__export(browser_exports, {
|
|
33
33
|
BrowserTrustBaseLoader: () => BrowserTrustBaseLoader,
|
|
34
|
+
IndexedDBStorageProvider: () => IndexedDBStorageProvider,
|
|
34
35
|
IndexedDBTokenStorageProvider: () => IndexedDBTokenStorageProvider,
|
|
35
36
|
LocalStorageProvider: () => LocalStorageProvider,
|
|
36
37
|
NostrTransportProvider: () => NostrTransportProvider,
|
|
@@ -40,6 +41,7 @@ __export(browser_exports, {
|
|
|
40
41
|
createBrowserProviders: () => createBrowserProviders,
|
|
41
42
|
createBrowserTrustBaseLoader: () => createBrowserTrustBaseLoader,
|
|
42
43
|
createBrowserWebSocket: () => createBrowserWebSocket,
|
|
44
|
+
createIndexedDBStorageProvider: () => createIndexedDBStorageProvider,
|
|
43
45
|
createIndexedDBTokenStorageProvider: () => createIndexedDBTokenStorageProvider,
|
|
44
46
|
createLocalStorageProvider: () => createLocalStorageProvider,
|
|
45
47
|
createNostrTransportProvider: () => createNostrTransportProvider,
|
|
@@ -408,9 +410,264 @@ function createLocalStorageProvider(config) {
|
|
|
408
410
|
return new LocalStorageProvider(config);
|
|
409
411
|
}
|
|
410
412
|
|
|
411
|
-
// impl/browser/storage/
|
|
412
|
-
var DB_NAME = "sphere-
|
|
413
|
+
// impl/browser/storage/IndexedDBStorageProvider.ts
|
|
414
|
+
var DB_NAME = "sphere-storage";
|
|
413
415
|
var DB_VERSION = 1;
|
|
416
|
+
var STORE_NAME = "kv";
|
|
417
|
+
var IndexedDBStorageProvider = class {
|
|
418
|
+
id = "indexeddb-storage";
|
|
419
|
+
name = "IndexedDB Storage";
|
|
420
|
+
type = "local";
|
|
421
|
+
description = "Browser IndexedDB for large-capacity persistence";
|
|
422
|
+
prefix;
|
|
423
|
+
dbName;
|
|
424
|
+
debug;
|
|
425
|
+
identity = null;
|
|
426
|
+
status = "disconnected";
|
|
427
|
+
db = null;
|
|
428
|
+
constructor(config) {
|
|
429
|
+
this.prefix = config?.prefix ?? "sphere_";
|
|
430
|
+
this.dbName = config?.dbName ?? DB_NAME;
|
|
431
|
+
this.debug = config?.debug ?? false;
|
|
432
|
+
}
|
|
433
|
+
// ===========================================================================
|
|
434
|
+
// BaseProvider Implementation
|
|
435
|
+
// ===========================================================================
|
|
436
|
+
async connect() {
|
|
437
|
+
if (this.status === "connected" && this.db) return;
|
|
438
|
+
this.status = "connecting";
|
|
439
|
+
try {
|
|
440
|
+
this.db = await Promise.race([
|
|
441
|
+
this.openDatabase(),
|
|
442
|
+
new Promise(
|
|
443
|
+
(_, reject) => setTimeout(() => reject(new Error("IndexedDB open timed out after 5s")), 5e3)
|
|
444
|
+
)
|
|
445
|
+
]);
|
|
446
|
+
this.status = "connected";
|
|
447
|
+
this.log("Connected to IndexedDB");
|
|
448
|
+
} catch (error) {
|
|
449
|
+
this.status = "error";
|
|
450
|
+
throw new Error(`IndexedDB not available: ${error}`);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
async disconnect() {
|
|
454
|
+
if (this.db) {
|
|
455
|
+
this.db.close();
|
|
456
|
+
this.db = null;
|
|
457
|
+
}
|
|
458
|
+
this.status = "disconnected";
|
|
459
|
+
this.log("Disconnected from IndexedDB");
|
|
460
|
+
}
|
|
461
|
+
isConnected() {
|
|
462
|
+
return this.status === "connected" && this.db !== null;
|
|
463
|
+
}
|
|
464
|
+
getStatus() {
|
|
465
|
+
return this.status;
|
|
466
|
+
}
|
|
467
|
+
// ===========================================================================
|
|
468
|
+
// StorageProvider Implementation
|
|
469
|
+
// ===========================================================================
|
|
470
|
+
setIdentity(identity) {
|
|
471
|
+
this.identity = identity;
|
|
472
|
+
this.log("Identity set:", identity.l1Address);
|
|
473
|
+
}
|
|
474
|
+
async get(key) {
|
|
475
|
+
this.ensureConnected();
|
|
476
|
+
const fullKey = this.getFullKey(key);
|
|
477
|
+
const result = await this.idbGet(fullKey);
|
|
478
|
+
return result?.v ?? null;
|
|
479
|
+
}
|
|
480
|
+
async set(key, value) {
|
|
481
|
+
this.ensureConnected();
|
|
482
|
+
const fullKey = this.getFullKey(key);
|
|
483
|
+
await this.idbPut({ k: fullKey, v: value });
|
|
484
|
+
}
|
|
485
|
+
async remove(key) {
|
|
486
|
+
this.ensureConnected();
|
|
487
|
+
const fullKey = this.getFullKey(key);
|
|
488
|
+
await this.idbDelete(fullKey);
|
|
489
|
+
}
|
|
490
|
+
async has(key) {
|
|
491
|
+
this.ensureConnected();
|
|
492
|
+
const fullKey = this.getFullKey(key);
|
|
493
|
+
const count = await this.idbCount(fullKey);
|
|
494
|
+
return count > 0;
|
|
495
|
+
}
|
|
496
|
+
async keys(prefix) {
|
|
497
|
+
this.ensureConnected();
|
|
498
|
+
const basePrefix = this.getFullKey("");
|
|
499
|
+
const searchPrefix = prefix ? this.getFullKey(prefix) : basePrefix;
|
|
500
|
+
const allEntries = await this.idbGetAll();
|
|
501
|
+
const result = [];
|
|
502
|
+
for (const entry of allEntries) {
|
|
503
|
+
if (entry.k.startsWith(searchPrefix)) {
|
|
504
|
+
result.push(entry.k.slice(basePrefix.length));
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return result;
|
|
508
|
+
}
|
|
509
|
+
async clear(prefix) {
|
|
510
|
+
if (!prefix) {
|
|
511
|
+
if (this.db) {
|
|
512
|
+
this.db.close();
|
|
513
|
+
this.db = null;
|
|
514
|
+
}
|
|
515
|
+
this.status = "disconnected";
|
|
516
|
+
await new Promise((resolve) => {
|
|
517
|
+
try {
|
|
518
|
+
const req = indexedDB.deleteDatabase(this.dbName);
|
|
519
|
+
req.onsuccess = () => resolve();
|
|
520
|
+
req.onerror = () => resolve();
|
|
521
|
+
req.onblocked = () => resolve();
|
|
522
|
+
} catch {
|
|
523
|
+
resolve();
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
this.log("Database deleted:", this.dbName);
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
this.ensureConnected();
|
|
530
|
+
const keysToRemove = await this.keys(prefix);
|
|
531
|
+
for (const key of keysToRemove) {
|
|
532
|
+
await this.remove(key);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
async saveTrackedAddresses(entries) {
|
|
536
|
+
await this.set(STORAGE_KEYS_GLOBAL.TRACKED_ADDRESSES, JSON.stringify({ version: 1, addresses: entries }));
|
|
537
|
+
}
|
|
538
|
+
async loadTrackedAddresses() {
|
|
539
|
+
const data = await this.get(STORAGE_KEYS_GLOBAL.TRACKED_ADDRESSES);
|
|
540
|
+
if (!data) return [];
|
|
541
|
+
try {
|
|
542
|
+
const parsed = JSON.parse(data);
|
|
543
|
+
return parsed.addresses ?? [];
|
|
544
|
+
} catch {
|
|
545
|
+
return [];
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
// ===========================================================================
|
|
549
|
+
// Helpers
|
|
550
|
+
// ===========================================================================
|
|
551
|
+
/**
|
|
552
|
+
* Get JSON data
|
|
553
|
+
*/
|
|
554
|
+
async getJSON(key) {
|
|
555
|
+
const value = await this.get(key);
|
|
556
|
+
if (!value) return null;
|
|
557
|
+
try {
|
|
558
|
+
return JSON.parse(value);
|
|
559
|
+
} catch {
|
|
560
|
+
return null;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Set JSON data
|
|
565
|
+
*/
|
|
566
|
+
async setJSON(key, value) {
|
|
567
|
+
await this.set(key, JSON.stringify(value));
|
|
568
|
+
}
|
|
569
|
+
// ===========================================================================
|
|
570
|
+
// Private: Key Scoping
|
|
571
|
+
// ===========================================================================
|
|
572
|
+
getFullKey(key) {
|
|
573
|
+
const isPerAddressKey = Object.values(STORAGE_KEYS_ADDRESS).includes(key);
|
|
574
|
+
if (isPerAddressKey && this.identity?.directAddress) {
|
|
575
|
+
const addressId = getAddressId(this.identity.directAddress);
|
|
576
|
+
return `${this.prefix}${addressId}_${key}`;
|
|
577
|
+
}
|
|
578
|
+
return `${this.prefix}${key}`;
|
|
579
|
+
}
|
|
580
|
+
ensureConnected() {
|
|
581
|
+
if (this.status !== "connected" || !this.db) {
|
|
582
|
+
throw new Error("IndexedDBStorageProvider not connected");
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
// ===========================================================================
|
|
586
|
+
// Private: IndexedDB Operations
|
|
587
|
+
// ===========================================================================
|
|
588
|
+
openDatabase() {
|
|
589
|
+
return new Promise((resolve, reject) => {
|
|
590
|
+
const request = indexedDB.open(this.dbName, DB_VERSION);
|
|
591
|
+
request.onerror = () => reject(request.error);
|
|
592
|
+
request.onsuccess = () => resolve(request.result);
|
|
593
|
+
request.onblocked = () => {
|
|
594
|
+
console.warn("[IndexedDBStorageProvider] open blocked by another connection");
|
|
595
|
+
};
|
|
596
|
+
request.onupgradeneeded = (event) => {
|
|
597
|
+
const db = event.target.result;
|
|
598
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
599
|
+
db.createObjectStore(STORE_NAME, { keyPath: "k" });
|
|
600
|
+
}
|
|
601
|
+
};
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
idbGet(key) {
|
|
605
|
+
return new Promise((resolve, reject) => {
|
|
606
|
+
const tx = this.db.transaction(STORE_NAME, "readonly");
|
|
607
|
+
const store = tx.objectStore(STORE_NAME);
|
|
608
|
+
const request = store.get(key);
|
|
609
|
+
request.onerror = () => reject(request.error);
|
|
610
|
+
request.onsuccess = () => resolve(request.result ?? void 0);
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
idbPut(entry) {
|
|
614
|
+
return new Promise((resolve, reject) => {
|
|
615
|
+
const tx = this.db.transaction(STORE_NAME, "readwrite");
|
|
616
|
+
const store = tx.objectStore(STORE_NAME);
|
|
617
|
+
const request = store.put(entry);
|
|
618
|
+
request.onerror = () => reject(request.error);
|
|
619
|
+
request.onsuccess = () => resolve();
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
idbDelete(key) {
|
|
623
|
+
return new Promise((resolve, reject) => {
|
|
624
|
+
const tx = this.db.transaction(STORE_NAME, "readwrite");
|
|
625
|
+
const store = tx.objectStore(STORE_NAME);
|
|
626
|
+
const request = store.delete(key);
|
|
627
|
+
request.onerror = () => reject(request.error);
|
|
628
|
+
request.onsuccess = () => resolve();
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
idbCount(key) {
|
|
632
|
+
return new Promise((resolve, reject) => {
|
|
633
|
+
const tx = this.db.transaction(STORE_NAME, "readonly");
|
|
634
|
+
const store = tx.objectStore(STORE_NAME);
|
|
635
|
+
const request = store.count(key);
|
|
636
|
+
request.onerror = () => reject(request.error);
|
|
637
|
+
request.onsuccess = () => resolve(request.result);
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
idbGetAll() {
|
|
641
|
+
return new Promise((resolve, reject) => {
|
|
642
|
+
const tx = this.db.transaction(STORE_NAME, "readonly");
|
|
643
|
+
const store = tx.objectStore(STORE_NAME);
|
|
644
|
+
const request = store.getAll();
|
|
645
|
+
request.onerror = () => reject(request.error);
|
|
646
|
+
request.onsuccess = () => resolve(request.result ?? []);
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
idbClear() {
|
|
650
|
+
return new Promise((resolve, reject) => {
|
|
651
|
+
const tx = this.db.transaction(STORE_NAME, "readwrite");
|
|
652
|
+
const store = tx.objectStore(STORE_NAME);
|
|
653
|
+
const request = store.clear();
|
|
654
|
+
request.onerror = () => reject(request.error);
|
|
655
|
+
request.onsuccess = () => resolve();
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
log(...args) {
|
|
659
|
+
if (this.debug) {
|
|
660
|
+
console.log("[IndexedDBStorageProvider]", ...args);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
function createIndexedDBStorageProvider(config) {
|
|
665
|
+
return new IndexedDBStorageProvider(config);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// impl/browser/storage/IndexedDBTokenStorageProvider.ts
|
|
669
|
+
var DB_NAME2 = "sphere-token-storage";
|
|
670
|
+
var DB_VERSION2 = 1;
|
|
414
671
|
var STORE_TOKENS = "tokens";
|
|
415
672
|
var STORE_META = "meta";
|
|
416
673
|
var IndexedDBTokenStorageProvider = class {
|
|
@@ -423,7 +680,7 @@ var IndexedDBTokenStorageProvider = class {
|
|
|
423
680
|
status = "disconnected";
|
|
424
681
|
identity = null;
|
|
425
682
|
constructor(config) {
|
|
426
|
-
this.dbNamePrefix = config?.dbNamePrefix ??
|
|
683
|
+
this.dbNamePrefix = config?.dbNamePrefix ?? DB_NAME2;
|
|
427
684
|
this.dbName = this.dbNamePrefix;
|
|
428
685
|
}
|
|
429
686
|
setIdentity(identity) {
|
|
@@ -437,6 +694,7 @@ var IndexedDBTokenStorageProvider = class {
|
|
|
437
694
|
try {
|
|
438
695
|
this.db = await this.openDatabase();
|
|
439
696
|
this.status = "connected";
|
|
697
|
+
this.cleanupStaleDatabases();
|
|
440
698
|
return true;
|
|
441
699
|
} catch (error) {
|
|
442
700
|
console.error("[IndexedDBTokenStorage] Failed to initialize:", error);
|
|
@@ -594,37 +852,43 @@ var IndexedDBTokenStorageProvider = class {
|
|
|
594
852
|
return meta !== null;
|
|
595
853
|
}
|
|
596
854
|
async clear() {
|
|
597
|
-
if (this.db) {
|
|
598
|
-
this.db.close();
|
|
599
|
-
this.db = null;
|
|
600
|
-
}
|
|
601
|
-
this.status = "disconnected";
|
|
602
|
-
const CLEAR_TIMEOUT = 1500;
|
|
603
|
-
const withTimeout = (promise, ms, label) => Promise.race([
|
|
604
|
-
promise,
|
|
605
|
-
new Promise(
|
|
606
|
-
(_, reject) => setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms)
|
|
607
|
-
)
|
|
608
|
-
]);
|
|
609
|
-
const deleteDb = (name) => new Promise((resolve) => {
|
|
610
|
-
const req = indexedDB.deleteDatabase(name);
|
|
611
|
-
req.onsuccess = () => resolve();
|
|
612
|
-
req.onerror = () => resolve();
|
|
613
|
-
req.onblocked = () => resolve();
|
|
614
|
-
});
|
|
615
855
|
try {
|
|
856
|
+
if (this.db) {
|
|
857
|
+
this.db.close();
|
|
858
|
+
this.db = null;
|
|
859
|
+
}
|
|
860
|
+
this.status = "disconnected";
|
|
861
|
+
const dbNames = [this.dbName];
|
|
616
862
|
if (typeof indexedDB.databases === "function") {
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
863
|
+
try {
|
|
864
|
+
const dbs = await Promise.race([
|
|
865
|
+
indexedDB.databases(),
|
|
866
|
+
new Promise(
|
|
867
|
+
(_, reject) => setTimeout(() => reject(new Error("timeout")), 1500)
|
|
868
|
+
)
|
|
869
|
+
]);
|
|
870
|
+
for (const dbInfo of dbs) {
|
|
871
|
+
if (dbInfo.name && dbInfo.name.startsWith(this.dbNamePrefix) && dbInfo.name !== this.dbName) {
|
|
872
|
+
dbNames.push(dbInfo.name);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
} catch {
|
|
876
|
+
}
|
|
627
877
|
}
|
|
878
|
+
await Promise.all(dbNames.map(
|
|
879
|
+
(name) => new Promise((resolve) => {
|
|
880
|
+
try {
|
|
881
|
+
const req = indexedDB.deleteDatabase(name);
|
|
882
|
+
req.onsuccess = () => resolve();
|
|
883
|
+
req.onerror = () => resolve();
|
|
884
|
+
req.onblocked = () => {
|
|
885
|
+
resolve();
|
|
886
|
+
};
|
|
887
|
+
} catch {
|
|
888
|
+
resolve();
|
|
889
|
+
}
|
|
890
|
+
})
|
|
891
|
+
));
|
|
628
892
|
return true;
|
|
629
893
|
} catch (err) {
|
|
630
894
|
console.warn("[IndexedDBTokenStorage] clear() failed:", err);
|
|
@@ -634,9 +898,29 @@ var IndexedDBTokenStorageProvider = class {
|
|
|
634
898
|
// =========================================================================
|
|
635
899
|
// Private IndexedDB helpers
|
|
636
900
|
// =========================================================================
|
|
901
|
+
/**
|
|
902
|
+
* Delete stale databases from other addresses (fire-and-forget, background).
|
|
903
|
+
* Called after the current database is already open, so deleteDatabase
|
|
904
|
+
* on other databases won't block anything.
|
|
905
|
+
*/
|
|
906
|
+
cleanupStaleDatabases() {
|
|
907
|
+
if (typeof indexedDB.databases !== "function") return;
|
|
908
|
+
indexedDB.databases().then((dbs) => {
|
|
909
|
+
for (const dbInfo of dbs) {
|
|
910
|
+
if (dbInfo.name && dbInfo.name.startsWith(this.dbNamePrefix) && dbInfo.name !== this.dbName) {
|
|
911
|
+
const req = indexedDB.deleteDatabase(dbInfo.name);
|
|
912
|
+
req.onerror = () => {
|
|
913
|
+
};
|
|
914
|
+
req.onblocked = () => {
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
}).catch(() => {
|
|
919
|
+
});
|
|
920
|
+
}
|
|
637
921
|
openDatabase() {
|
|
638
922
|
return new Promise((resolve, reject) => {
|
|
639
|
-
const request = indexedDB.open(this.dbName,
|
|
923
|
+
const request = indexedDB.open(this.dbName, DB_VERSION2);
|
|
640
924
|
request.onerror = () => {
|
|
641
925
|
reject(request.error);
|
|
642
926
|
};
|
|
@@ -779,6 +1063,52 @@ function createView(arr) {
|
|
|
779
1063
|
function rotr(word, shift) {
|
|
780
1064
|
return word << 32 - shift | word >>> shift;
|
|
781
1065
|
}
|
|
1066
|
+
var hasHexBuiltin = /* @__PURE__ */ (() => (
|
|
1067
|
+
// @ts-ignore
|
|
1068
|
+
typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function"
|
|
1069
|
+
))();
|
|
1070
|
+
var hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
|
|
1071
|
+
function bytesToHex(bytes) {
|
|
1072
|
+
abytes(bytes);
|
|
1073
|
+
if (hasHexBuiltin)
|
|
1074
|
+
return bytes.toHex();
|
|
1075
|
+
let hex = "";
|
|
1076
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
1077
|
+
hex += hexes[bytes[i]];
|
|
1078
|
+
}
|
|
1079
|
+
return hex;
|
|
1080
|
+
}
|
|
1081
|
+
var asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
|
|
1082
|
+
function asciiToBase16(ch) {
|
|
1083
|
+
if (ch >= asciis._0 && ch <= asciis._9)
|
|
1084
|
+
return ch - asciis._0;
|
|
1085
|
+
if (ch >= asciis.A && ch <= asciis.F)
|
|
1086
|
+
return ch - (asciis.A - 10);
|
|
1087
|
+
if (ch >= asciis.a && ch <= asciis.f)
|
|
1088
|
+
return ch - (asciis.a - 10);
|
|
1089
|
+
return;
|
|
1090
|
+
}
|
|
1091
|
+
function hexToBytes(hex) {
|
|
1092
|
+
if (typeof hex !== "string")
|
|
1093
|
+
throw new Error("hex string expected, got " + typeof hex);
|
|
1094
|
+
if (hasHexBuiltin)
|
|
1095
|
+
return Uint8Array.fromHex(hex);
|
|
1096
|
+
const hl = hex.length;
|
|
1097
|
+
const al = hl / 2;
|
|
1098
|
+
if (hl % 2)
|
|
1099
|
+
throw new Error("hex string expected, got unpadded hex of length " + hl);
|
|
1100
|
+
const array = new Uint8Array(al);
|
|
1101
|
+
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
|
|
1102
|
+
const n1 = asciiToBase16(hex.charCodeAt(hi));
|
|
1103
|
+
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
|
|
1104
|
+
if (n1 === void 0 || n2 === void 0) {
|
|
1105
|
+
const char = hex[hi] + hex[hi + 1];
|
|
1106
|
+
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
|
|
1107
|
+
}
|
|
1108
|
+
array[ai] = n1 * 16 + n2;
|
|
1109
|
+
}
|
|
1110
|
+
return array;
|
|
1111
|
+
}
|
|
782
1112
|
function createHasher(hashCons, info = {}) {
|
|
783
1113
|
const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
|
|
784
1114
|
const tmp = hashCons(void 0);
|
|
@@ -1274,7 +1604,7 @@ function publicKeyToAddress(publicKey, prefix = "alpha", witnessVersion = 0) {
|
|
|
1274
1604
|
const programBytes = hash160ToBytes(pubKeyHash);
|
|
1275
1605
|
return encodeBech32(prefix, witnessVersion, programBytes);
|
|
1276
1606
|
}
|
|
1277
|
-
function
|
|
1607
|
+
function hexToBytes2(hex) {
|
|
1278
1608
|
const matches = hex.match(/../g);
|
|
1279
1609
|
if (!matches) {
|
|
1280
1610
|
return new Uint8Array(0);
|
|
@@ -1301,6 +1631,8 @@ function defaultUUIDGenerator() {
|
|
|
1301
1631
|
}
|
|
1302
1632
|
|
|
1303
1633
|
// transport/NostrTransportProvider.ts
|
|
1634
|
+
var COMPOSING_INDICATOR_KIND = 25050;
|
|
1635
|
+
var TIMESTAMP_RANDOMIZATION = 2 * 24 * 60 * 60;
|
|
1304
1636
|
var EVENT_KINDS = NOSTR_EVENT_KINDS;
|
|
1305
1637
|
function hashAddressForTag(address) {
|
|
1306
1638
|
const bytes = new TextEncoder().encode("unicity:address:" + address);
|
|
@@ -1381,6 +1713,10 @@ var NostrTransportProvider = class {
|
|
|
1381
1713
|
transferHandlers = /* @__PURE__ */ new Set();
|
|
1382
1714
|
paymentRequestHandlers = /* @__PURE__ */ new Set();
|
|
1383
1715
|
paymentRequestResponseHandlers = /* @__PURE__ */ new Set();
|
|
1716
|
+
readReceiptHandlers = /* @__PURE__ */ new Set();
|
|
1717
|
+
typingIndicatorHandlers = /* @__PURE__ */ new Set();
|
|
1718
|
+
composingHandlers = /* @__PURE__ */ new Set();
|
|
1719
|
+
pendingMessages = [];
|
|
1384
1720
|
broadcastHandlers = /* @__PURE__ */ new Map();
|
|
1385
1721
|
eventCallbacks = /* @__PURE__ */ new Set();
|
|
1386
1722
|
constructor(config) {
|
|
@@ -1632,6 +1968,18 @@ var NostrTransportProvider = class {
|
|
|
1632
1968
|
const wrappedContent = senderNametag ? JSON.stringify({ senderNametag, text: content }) : content;
|
|
1633
1969
|
const giftWrap = import_nostr_js_sdk.NIP17.createGiftWrap(this.keyManager, nostrRecipient, wrappedContent);
|
|
1634
1970
|
await this.publishEvent(giftWrap);
|
|
1971
|
+
const selfWrapContent = JSON.stringify({
|
|
1972
|
+
selfWrap: true,
|
|
1973
|
+
originalId: giftWrap.id,
|
|
1974
|
+
recipientPubkey,
|
|
1975
|
+
senderNametag,
|
|
1976
|
+
text: content
|
|
1977
|
+
});
|
|
1978
|
+
const selfPubkey = this.keyManager.getPublicKeyHex();
|
|
1979
|
+
const selfGiftWrap = import_nostr_js_sdk.NIP17.createGiftWrap(this.keyManager, selfPubkey, selfWrapContent);
|
|
1980
|
+
this.publishEvent(selfGiftWrap).catch((err) => {
|
|
1981
|
+
this.log("Self-wrap publish failed:", err);
|
|
1982
|
+
});
|
|
1635
1983
|
this.emitEvent({
|
|
1636
1984
|
type: "message:sent",
|
|
1637
1985
|
timestamp: Date.now(),
|
|
@@ -1641,6 +1989,18 @@ var NostrTransportProvider = class {
|
|
|
1641
1989
|
}
|
|
1642
1990
|
onMessage(handler) {
|
|
1643
1991
|
this.messageHandlers.add(handler);
|
|
1992
|
+
if (this.pendingMessages.length > 0) {
|
|
1993
|
+
const pending = this.pendingMessages;
|
|
1994
|
+
this.pendingMessages = [];
|
|
1995
|
+
this.log("Flushing", pending.length, "buffered messages to new handler");
|
|
1996
|
+
for (const message of pending) {
|
|
1997
|
+
try {
|
|
1998
|
+
handler(message);
|
|
1999
|
+
} catch (error) {
|
|
2000
|
+
this.log("Message handler error (buffered):", error);
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
1644
2004
|
return () => this.messageHandlers.delete(handler);
|
|
1645
2005
|
}
|
|
1646
2006
|
async sendTokenTransfer(recipientPubkey, payload) {
|
|
@@ -1730,6 +2090,50 @@ var NostrTransportProvider = class {
|
|
|
1730
2090
|
this.paymentRequestResponseHandlers.add(handler);
|
|
1731
2091
|
return () => this.paymentRequestResponseHandlers.delete(handler);
|
|
1732
2092
|
}
|
|
2093
|
+
// ===========================================================================
|
|
2094
|
+
// Read Receipts
|
|
2095
|
+
// ===========================================================================
|
|
2096
|
+
async sendReadReceipt(recipientTransportPubkey, messageEventId) {
|
|
2097
|
+
if (!this.keyManager) throw new Error("Not initialized");
|
|
2098
|
+
const nostrRecipient = recipientTransportPubkey.length === 66 ? recipientTransportPubkey.slice(2) : recipientTransportPubkey;
|
|
2099
|
+
const event = import_nostr_js_sdk.NIP17.createReadReceipt(this.keyManager, nostrRecipient, messageEventId);
|
|
2100
|
+
await this.publishEvent(event);
|
|
2101
|
+
this.log("Sent read receipt for:", messageEventId, "to:", nostrRecipient.slice(0, 16));
|
|
2102
|
+
}
|
|
2103
|
+
onReadReceipt(handler) {
|
|
2104
|
+
this.readReceiptHandlers.add(handler);
|
|
2105
|
+
return () => this.readReceiptHandlers.delete(handler);
|
|
2106
|
+
}
|
|
2107
|
+
// ===========================================================================
|
|
2108
|
+
// Typing Indicators
|
|
2109
|
+
// ===========================================================================
|
|
2110
|
+
async sendTypingIndicator(recipientTransportPubkey) {
|
|
2111
|
+
if (!this.keyManager) throw new Error("Not initialized");
|
|
2112
|
+
const nostrRecipient = recipientTransportPubkey.length === 66 ? recipientTransportPubkey.slice(2) : recipientTransportPubkey;
|
|
2113
|
+
const content = JSON.stringify({
|
|
2114
|
+
type: "typing",
|
|
2115
|
+
senderNametag: this.identity?.nametag
|
|
2116
|
+
});
|
|
2117
|
+
const event = import_nostr_js_sdk.NIP17.createGiftWrap(this.keyManager, nostrRecipient, content);
|
|
2118
|
+
await this.publishEvent(event);
|
|
2119
|
+
}
|
|
2120
|
+
onTypingIndicator(handler) {
|
|
2121
|
+
this.typingIndicatorHandlers.add(handler);
|
|
2122
|
+
return () => this.typingIndicatorHandlers.delete(handler);
|
|
2123
|
+
}
|
|
2124
|
+
// ===========================================================================
|
|
2125
|
+
// Composing Indicators (NIP-59 kind 25050)
|
|
2126
|
+
// ===========================================================================
|
|
2127
|
+
onComposing(handler) {
|
|
2128
|
+
this.composingHandlers.add(handler);
|
|
2129
|
+
return () => this.composingHandlers.delete(handler);
|
|
2130
|
+
}
|
|
2131
|
+
async sendComposingIndicator(recipientPubkey, content) {
|
|
2132
|
+
this.ensureReady();
|
|
2133
|
+
const nostrRecipient = recipientPubkey.length === 66 && (recipientPubkey.startsWith("02") || recipientPubkey.startsWith("03")) ? recipientPubkey.slice(2) : recipientPubkey;
|
|
2134
|
+
const giftWrap = this.createCustomKindGiftWrap(nostrRecipient, content, COMPOSING_INDICATOR_KIND);
|
|
2135
|
+
await this.publishEvent(giftWrap);
|
|
2136
|
+
}
|
|
1733
2137
|
/**
|
|
1734
2138
|
* Resolve any identifier to full peer information.
|
|
1735
2139
|
* Routes to the appropriate specific resolve method based on identifier format.
|
|
@@ -2183,11 +2587,98 @@ var NostrTransportProvider = class {
|
|
|
2183
2587
|
const pm = import_nostr_js_sdk.NIP17.unwrap(event, this.keyManager);
|
|
2184
2588
|
this.log("Gift wrap unwrapped, sender:", pm.senderPubkey?.slice(0, 16), "kind:", pm.kind);
|
|
2185
2589
|
if (pm.senderPubkey === this.keyManager.getPublicKeyHex()) {
|
|
2186
|
-
|
|
2590
|
+
try {
|
|
2591
|
+
const parsed = JSON.parse(pm.content);
|
|
2592
|
+
if (parsed?.selfWrap && parsed.recipientPubkey) {
|
|
2593
|
+
this.log("Self-wrap replay for recipient:", parsed.recipientPubkey?.slice(0, 16));
|
|
2594
|
+
const message2 = {
|
|
2595
|
+
id: parsed.originalId || pm.eventId,
|
|
2596
|
+
senderTransportPubkey: pm.senderPubkey,
|
|
2597
|
+
senderNametag: parsed.senderNametag,
|
|
2598
|
+
recipientTransportPubkey: parsed.recipientPubkey,
|
|
2599
|
+
content: parsed.text ?? "",
|
|
2600
|
+
timestamp: pm.timestamp * 1e3,
|
|
2601
|
+
encrypted: true,
|
|
2602
|
+
isSelfWrap: true
|
|
2603
|
+
};
|
|
2604
|
+
for (const handler of this.messageHandlers) {
|
|
2605
|
+
try {
|
|
2606
|
+
handler(message2);
|
|
2607
|
+
} catch (e) {
|
|
2608
|
+
this.log("Self-wrap handler error:", e);
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
return;
|
|
2612
|
+
}
|
|
2613
|
+
} catch {
|
|
2614
|
+
}
|
|
2615
|
+
this.log("Skipping own non-self-wrap message");
|
|
2187
2616
|
return;
|
|
2188
2617
|
}
|
|
2189
|
-
if (
|
|
2190
|
-
this.log("
|
|
2618
|
+
if ((0, import_nostr_js_sdk.isReadReceipt)(pm)) {
|
|
2619
|
+
this.log("Read receipt from:", pm.senderPubkey?.slice(0, 16), "for:", pm.replyToEventId);
|
|
2620
|
+
if (pm.replyToEventId) {
|
|
2621
|
+
const receipt = {
|
|
2622
|
+
senderTransportPubkey: pm.senderPubkey,
|
|
2623
|
+
messageEventId: pm.replyToEventId,
|
|
2624
|
+
timestamp: pm.timestamp * 1e3
|
|
2625
|
+
};
|
|
2626
|
+
for (const handler of this.readReceiptHandlers) {
|
|
2627
|
+
try {
|
|
2628
|
+
handler(receipt);
|
|
2629
|
+
} catch (e) {
|
|
2630
|
+
this.log("Read receipt handler error:", e);
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
return;
|
|
2635
|
+
}
|
|
2636
|
+
if (pm.kind === COMPOSING_INDICATOR_KIND) {
|
|
2637
|
+
let senderNametag2;
|
|
2638
|
+
let expiresIn = 3e4;
|
|
2639
|
+
try {
|
|
2640
|
+
const parsed = JSON.parse(pm.content);
|
|
2641
|
+
senderNametag2 = parsed.senderNametag || void 0;
|
|
2642
|
+
expiresIn = parsed.expiresIn ?? 3e4;
|
|
2643
|
+
} catch {
|
|
2644
|
+
}
|
|
2645
|
+
const indicator = {
|
|
2646
|
+
senderPubkey: pm.senderPubkey,
|
|
2647
|
+
senderNametag: senderNametag2,
|
|
2648
|
+
expiresIn
|
|
2649
|
+
};
|
|
2650
|
+
this.log("Composing indicator from:", indicator.senderNametag || pm.senderPubkey?.slice(0, 16));
|
|
2651
|
+
for (const handler of this.composingHandlers) {
|
|
2652
|
+
try {
|
|
2653
|
+
handler(indicator);
|
|
2654
|
+
} catch (e) {
|
|
2655
|
+
this.log("Composing handler error:", e);
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
return;
|
|
2659
|
+
}
|
|
2660
|
+
try {
|
|
2661
|
+
const parsed = JSON.parse(pm.content);
|
|
2662
|
+
if (parsed?.type === "typing") {
|
|
2663
|
+
this.log("Typing indicator from:", pm.senderPubkey?.slice(0, 16));
|
|
2664
|
+
const indicator = {
|
|
2665
|
+
senderTransportPubkey: pm.senderPubkey,
|
|
2666
|
+
senderNametag: parsed.senderNametag,
|
|
2667
|
+
timestamp: pm.timestamp * 1e3
|
|
2668
|
+
};
|
|
2669
|
+
for (const handler of this.typingIndicatorHandlers) {
|
|
2670
|
+
try {
|
|
2671
|
+
handler(indicator);
|
|
2672
|
+
} catch (e) {
|
|
2673
|
+
this.log("Typing handler error:", e);
|
|
2674
|
+
}
|
|
2675
|
+
}
|
|
2676
|
+
return;
|
|
2677
|
+
}
|
|
2678
|
+
} catch {
|
|
2679
|
+
}
|
|
2680
|
+
if (!(0, import_nostr_js_sdk.isChatMessage)(pm)) {
|
|
2681
|
+
this.log("Skipping unknown message kind:", pm.kind);
|
|
2191
2682
|
return;
|
|
2192
2683
|
}
|
|
2193
2684
|
let content = pm.content;
|
|
@@ -2202,7 +2693,9 @@ var NostrTransportProvider = class {
|
|
|
2202
2693
|
}
|
|
2203
2694
|
this.log("DM received from:", senderNametag || pm.senderPubkey?.slice(0, 16), "content:", content?.slice(0, 50));
|
|
2204
2695
|
const message = {
|
|
2205
|
-
id
|
|
2696
|
+
// Use outer gift wrap event.id so it matches the sender's stored giftWrap.id.
|
|
2697
|
+
// This ensures read receipts reference an ID the sender recognizes.
|
|
2698
|
+
id: event.id,
|
|
2206
2699
|
senderTransportPubkey: pm.senderPubkey,
|
|
2207
2700
|
senderNametag,
|
|
2208
2701
|
content,
|
|
@@ -2210,12 +2703,17 @@ var NostrTransportProvider = class {
|
|
|
2210
2703
|
encrypted: true
|
|
2211
2704
|
};
|
|
2212
2705
|
this.emitEvent({ type: "message:received", timestamp: Date.now() });
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2706
|
+
if (this.messageHandlers.size === 0) {
|
|
2707
|
+
this.log("No message handlers registered, buffering message for later delivery");
|
|
2708
|
+
this.pendingMessages.push(message);
|
|
2709
|
+
} else {
|
|
2710
|
+
this.log("Dispatching to", this.messageHandlers.size, "handlers");
|
|
2711
|
+
for (const handler of this.messageHandlers) {
|
|
2712
|
+
try {
|
|
2713
|
+
handler(message);
|
|
2714
|
+
} catch (error) {
|
|
2715
|
+
this.log("Message handler error:", error);
|
|
2716
|
+
}
|
|
2219
2717
|
}
|
|
2220
2718
|
}
|
|
2221
2719
|
} catch (err) {
|
|
@@ -2619,6 +3117,39 @@ var NostrTransportProvider = class {
|
|
|
2619
3117
|
}
|
|
2620
3118
|
}
|
|
2621
3119
|
}
|
|
3120
|
+
/**
|
|
3121
|
+
* Create a NIP-17 gift wrap with a custom inner rumor kind.
|
|
3122
|
+
* Replicates the three-layer NIP-59 envelope (rumor → seal → gift wrap)
|
|
3123
|
+
* because NIP17.createGiftWrap hardcodes kind 14 for the inner rumor.
|
|
3124
|
+
*/
|
|
3125
|
+
createCustomKindGiftWrap(recipientPubkeyHex, content, rumorKind) {
|
|
3126
|
+
const senderPubkey = this.keyManager.getPublicKeyHex();
|
|
3127
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
3128
|
+
const rumorTags = [["p", recipientPubkeyHex]];
|
|
3129
|
+
const rumorSerialized = JSON.stringify([0, senderPubkey, now, rumorKind, rumorTags, content]);
|
|
3130
|
+
const rumorId = bytesToHex(sha256(new TextEncoder().encode(rumorSerialized)));
|
|
3131
|
+
const rumor = { id: rumorId, pubkey: senderPubkey, created_at: now, kind: rumorKind, tags: rumorTags, content };
|
|
3132
|
+
const recipientPubkeyBytes = hexToBytes(recipientPubkeyHex);
|
|
3133
|
+
const encryptedRumor = import_nostr_js_sdk.NIP44.encrypt(JSON.stringify(rumor), this.keyManager.getPrivateKey(), recipientPubkeyBytes);
|
|
3134
|
+
const sealTimestamp = now + Math.floor(Math.random() * 2 * TIMESTAMP_RANDOMIZATION) - TIMESTAMP_RANDOMIZATION;
|
|
3135
|
+
const seal = import_nostr_js_sdk.Event.create(this.keyManager, {
|
|
3136
|
+
kind: import_nostr_js_sdk.EventKinds.SEAL,
|
|
3137
|
+
tags: [],
|
|
3138
|
+
content: encryptedRumor,
|
|
3139
|
+
created_at: sealTimestamp
|
|
3140
|
+
});
|
|
3141
|
+
const ephemeralKeys = import_nostr_js_sdk.NostrKeyManager.generate();
|
|
3142
|
+
const encryptedSeal = import_nostr_js_sdk.NIP44.encrypt(JSON.stringify(seal.toJSON()), ephemeralKeys.getPrivateKey(), recipientPubkeyBytes);
|
|
3143
|
+
const wrapTimestamp = now + Math.floor(Math.random() * 2 * TIMESTAMP_RANDOMIZATION) - TIMESTAMP_RANDOMIZATION;
|
|
3144
|
+
const giftWrap = import_nostr_js_sdk.Event.create(ephemeralKeys, {
|
|
3145
|
+
kind: import_nostr_js_sdk.EventKinds.GIFT_WRAP,
|
|
3146
|
+
tags: [["p", recipientPubkeyHex]],
|
|
3147
|
+
content: encryptedSeal,
|
|
3148
|
+
created_at: wrapTimestamp
|
|
3149
|
+
});
|
|
3150
|
+
ephemeralKeys.clear();
|
|
3151
|
+
return giftWrap;
|
|
3152
|
+
}
|
|
2622
3153
|
log(...args) {
|
|
2623
3154
|
if (this.config.debug) {
|
|
2624
3155
|
console.log("[NostrTransportProvider]", ...args);
|
|
@@ -3248,7 +3779,7 @@ async function loadLibp2pModules() {
|
|
|
3248
3779
|
};
|
|
3249
3780
|
}
|
|
3250
3781
|
function deriveEd25519KeyMaterial(privateKeyHex, info = IPNS_HKDF_INFO) {
|
|
3251
|
-
const walletSecret =
|
|
3782
|
+
const walletSecret = hexToBytes2(privateKeyHex);
|
|
3252
3783
|
const infoBytes = new TextEncoder().encode(info);
|
|
3253
3784
|
return hkdf(sha256, walletSecret, void 0, infoBytes, 32);
|
|
3254
3785
|
}
|
|
@@ -5746,6 +6277,11 @@ function resolveGroupChatConfig(network, config) {
|
|
|
5746
6277
|
relays: config.relays ?? [...netConfig.groupRelays]
|
|
5747
6278
|
};
|
|
5748
6279
|
}
|
|
6280
|
+
function resolveMarketConfig(config) {
|
|
6281
|
+
if (!config) return void 0;
|
|
6282
|
+
if (config === true) return {};
|
|
6283
|
+
return { apiUrl: config.apiUrl, timeout: config.timeout };
|
|
6284
|
+
}
|
|
5749
6285
|
|
|
5750
6286
|
// impl/browser/index.ts
|
|
5751
6287
|
if (typeof globalThis.Buffer === "undefined") {
|
|
@@ -5803,7 +6339,7 @@ function createBrowserProviders(config) {
|
|
|
5803
6339
|
const oracleConfig = resolveOracleConfig(network, config?.oracle);
|
|
5804
6340
|
const l1Config = resolveL1Config(network, config?.l1);
|
|
5805
6341
|
const tokenSyncConfig = resolveTokenSyncConfig(network, config?.tokenSync);
|
|
5806
|
-
const storage =
|
|
6342
|
+
const storage = createIndexedDBStorageProvider(config?.storage);
|
|
5807
6343
|
const priceConfig = resolvePriceConfig(config?.price, storage);
|
|
5808
6344
|
const ipfsConfig = tokenSyncConfig?.ipfs;
|
|
5809
6345
|
const ipfsTokenStorage = ipfsConfig?.enabled ? createBrowserIpfsStorageProvider({
|
|
@@ -5812,11 +6348,13 @@ function createBrowserProviders(config) {
|
|
|
5812
6348
|
// reuse debug-like flag
|
|
5813
6349
|
}) : void 0;
|
|
5814
6350
|
const groupChat = resolveGroupChatConfig(network, config?.groupChat);
|
|
6351
|
+
const market = resolveMarketConfig(config?.market);
|
|
5815
6352
|
const networkConfig = getNetworkConfig(network);
|
|
5816
6353
|
TokenRegistry.configure({ remoteUrl: networkConfig.tokenRegistryUrl, storage });
|
|
5817
6354
|
return {
|
|
5818
6355
|
storage,
|
|
5819
6356
|
groupChat,
|
|
6357
|
+
market,
|
|
5820
6358
|
transport: createNostrTransportProvider({
|
|
5821
6359
|
relays: transportConfig.relays,
|
|
5822
6360
|
timeout: transportConfig.timeout,
|