@unicitylabs/sphere-sdk 0.3.9 → 0.4.2
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 +79 -3
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.cts +16 -0
- package/dist/connect/index.d.ts +16 -0
- package/dist/connect/index.js +79 -3
- package/dist/connect/index.js.map +1 -1
- package/dist/core/index.cjs +2686 -56
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +228 -3
- package/dist/core/index.d.ts +228 -3
- package/dist/core/index.js +2682 -52
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/connect/index.cjs +11 -2
- package/dist/impl/browser/connect/index.cjs.map +1 -1
- package/dist/impl/browser/connect/index.js +11 -2
- package/dist/impl/browser/connect/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +467 -47
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +468 -47
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/nodejs/connect/index.cjs +11 -2
- package/dist/impl/nodejs/connect/index.cjs.map +1 -1
- package/dist/impl/nodejs/connect/index.js +11 -2
- package/dist/impl/nodejs/connect/index.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +152 -8
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +47 -0
- package/dist/impl/nodejs/index.d.ts +47 -0
- package/dist/impl/nodejs/index.js +153 -8
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +2703 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +326 -5
- package/dist/index.d.ts +326 -5
- package/dist/index.js +2692 -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 +1 -1
|
@@ -46,6 +46,11 @@ interface Identity {
|
|
|
46
46
|
interface FullIdentity extends Identity {
|
|
47
47
|
readonly privateKey: string;
|
|
48
48
|
}
|
|
49
|
+
interface ComposingIndicator {
|
|
50
|
+
readonly senderPubkey: string;
|
|
51
|
+
readonly senderNametag?: string;
|
|
52
|
+
readonly expiresIn: number;
|
|
53
|
+
}
|
|
49
54
|
/**
|
|
50
55
|
* Minimal data stored in persistent storage for a tracked address.
|
|
51
56
|
* Only contains user state — derived fields are computed on load.
|
|
@@ -443,6 +448,17 @@ interface TransportProvider extends BaseProvider {
|
|
|
443
448
|
* @returns Unsubscribe function
|
|
444
449
|
*/
|
|
445
450
|
onTypingIndicator?(handler: TypingIndicatorHandler): () => void;
|
|
451
|
+
/**
|
|
452
|
+
* Send composing indicator to a recipient using NIP-44 encrypted gift wrap
|
|
453
|
+
* @param recipientTransportPubkey - Transport pubkey of the conversation partner
|
|
454
|
+
* @param content - JSON payload with senderNametag and expiresIn
|
|
455
|
+
*/
|
|
456
|
+
sendComposingIndicator?(recipientTransportPubkey: string, content: string): Promise<void>;
|
|
457
|
+
/**
|
|
458
|
+
* Subscribe to incoming composing indicators
|
|
459
|
+
* @returns Unsubscribe function
|
|
460
|
+
*/
|
|
461
|
+
onComposing?(handler: ComposingHandler): () => void;
|
|
446
462
|
/**
|
|
447
463
|
* Get list of configured relay URLs
|
|
448
464
|
*/
|
|
@@ -675,6 +691,7 @@ interface IncomingTypingIndicator {
|
|
|
675
691
|
timestamp: number;
|
|
676
692
|
}
|
|
677
693
|
type TypingIndicatorHandler = (indicator: IncomingTypingIndicator) => void;
|
|
694
|
+
type ComposingHandler = (indicator: ComposingIndicator) => void;
|
|
678
695
|
|
|
679
696
|
/**
|
|
680
697
|
* WebSocket Abstraction
|
|
@@ -769,6 +786,8 @@ declare class NostrTransportProvider implements TransportProvider {
|
|
|
769
786
|
private paymentRequestResponseHandlers;
|
|
770
787
|
private readReceiptHandlers;
|
|
771
788
|
private typingIndicatorHandlers;
|
|
789
|
+
private composingHandlers;
|
|
790
|
+
private pendingMessages;
|
|
772
791
|
private broadcastHandlers;
|
|
773
792
|
private eventCallbacks;
|
|
774
793
|
constructor(config: NostrTransportProviderConfig);
|
|
@@ -822,6 +841,8 @@ declare class NostrTransportProvider implements TransportProvider {
|
|
|
822
841
|
onReadReceipt(handler: ReadReceiptHandler): () => void;
|
|
823
842
|
sendTypingIndicator(recipientTransportPubkey: string): Promise<void>;
|
|
824
843
|
onTypingIndicator(handler: TypingIndicatorHandler): () => void;
|
|
844
|
+
onComposing(handler: ComposingHandler): () => void;
|
|
845
|
+
sendComposingIndicator(recipientPubkey: string, content: string): Promise<void>;
|
|
825
846
|
/**
|
|
826
847
|
* Resolve any identifier to full peer information.
|
|
827
848
|
* Routes to the appropriate specific resolve method based on identifier format.
|
|
@@ -895,6 +916,12 @@ declare class NostrTransportProvider implements TransportProvider {
|
|
|
895
916
|
private ensureConnected;
|
|
896
917
|
private ensureReady;
|
|
897
918
|
private emitEvent;
|
|
919
|
+
/**
|
|
920
|
+
* Create a NIP-17 gift wrap with a custom inner rumor kind.
|
|
921
|
+
* Replicates the three-layer NIP-59 envelope (rumor → seal → gift wrap)
|
|
922
|
+
* because NIP17.createGiftWrap hardcodes kind 14 for the inner rumor.
|
|
923
|
+
*/
|
|
924
|
+
private createCustomKindGiftWrap;
|
|
898
925
|
private log;
|
|
899
926
|
}
|
|
900
927
|
|
|
@@ -1365,6 +1392,15 @@ interface BasePriceConfig {
|
|
|
1365
1392
|
/** Enable debug logging */
|
|
1366
1393
|
debug?: boolean;
|
|
1367
1394
|
}
|
|
1395
|
+
/**
|
|
1396
|
+
* Base market module configuration
|
|
1397
|
+
*/
|
|
1398
|
+
interface BaseMarketConfig {
|
|
1399
|
+
/** Market API base URL (default: https://market-api.unicity.network) */
|
|
1400
|
+
apiUrl?: string;
|
|
1401
|
+
/** Request timeout in ms (default: 30000) */
|
|
1402
|
+
timeout?: number;
|
|
1403
|
+
}
|
|
1368
1404
|
/**
|
|
1369
1405
|
* Base providers result
|
|
1370
1406
|
* Common structure for all platforms
|
|
@@ -1380,6 +1416,13 @@ interface BaseProviders {
|
|
|
1380
1416
|
price?: PriceProvider;
|
|
1381
1417
|
}
|
|
1382
1418
|
|
|
1419
|
+
interface MarketModuleConfig {
|
|
1420
|
+
/** Market API base URL (default: https://market-api.unicity.network) */
|
|
1421
|
+
apiUrl?: string;
|
|
1422
|
+
/** Request timeout in ms (default: 30000) */
|
|
1423
|
+
timeout?: number;
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1383
1426
|
/** IPFS storage provider configuration */
|
|
1384
1427
|
interface IpfsStorageConfig {
|
|
1385
1428
|
/** Gateway URLs for HTTP API (defaults to Unicity dedicated nodes) */
|
|
@@ -1472,6 +1515,8 @@ interface NodeProvidersConfig {
|
|
|
1472
1515
|
enabled?: boolean;
|
|
1473
1516
|
relays?: string[];
|
|
1474
1517
|
} | boolean;
|
|
1518
|
+
/** Market module configuration. true = enable with defaults, object = custom config */
|
|
1519
|
+
market?: BaseMarketConfig | boolean;
|
|
1475
1520
|
}
|
|
1476
1521
|
interface NodeProviders {
|
|
1477
1522
|
storage: StorageProvider;
|
|
@@ -1486,6 +1531,8 @@ interface NodeProviders {
|
|
|
1486
1531
|
ipfsTokenStorage?: TokenStorageProvider<TxfStorageDataBase>;
|
|
1487
1532
|
/** Group chat config (resolved, for passing to Sphere.init) */
|
|
1488
1533
|
groupChat?: GroupChatModuleConfig | boolean;
|
|
1534
|
+
/** Market module config (resolved, for passing to Sphere.init) */
|
|
1535
|
+
market?: MarketModuleConfig | boolean;
|
|
1489
1536
|
}
|
|
1490
1537
|
/**
|
|
1491
1538
|
* Create all Node.js providers with default configuration
|
|
@@ -46,6 +46,11 @@ interface Identity {
|
|
|
46
46
|
interface FullIdentity extends Identity {
|
|
47
47
|
readonly privateKey: string;
|
|
48
48
|
}
|
|
49
|
+
interface ComposingIndicator {
|
|
50
|
+
readonly senderPubkey: string;
|
|
51
|
+
readonly senderNametag?: string;
|
|
52
|
+
readonly expiresIn: number;
|
|
53
|
+
}
|
|
49
54
|
/**
|
|
50
55
|
* Minimal data stored in persistent storage for a tracked address.
|
|
51
56
|
* Only contains user state — derived fields are computed on load.
|
|
@@ -443,6 +448,17 @@ interface TransportProvider extends BaseProvider {
|
|
|
443
448
|
* @returns Unsubscribe function
|
|
444
449
|
*/
|
|
445
450
|
onTypingIndicator?(handler: TypingIndicatorHandler): () => void;
|
|
451
|
+
/**
|
|
452
|
+
* Send composing indicator to a recipient using NIP-44 encrypted gift wrap
|
|
453
|
+
* @param recipientTransportPubkey - Transport pubkey of the conversation partner
|
|
454
|
+
* @param content - JSON payload with senderNametag and expiresIn
|
|
455
|
+
*/
|
|
456
|
+
sendComposingIndicator?(recipientTransportPubkey: string, content: string): Promise<void>;
|
|
457
|
+
/**
|
|
458
|
+
* Subscribe to incoming composing indicators
|
|
459
|
+
* @returns Unsubscribe function
|
|
460
|
+
*/
|
|
461
|
+
onComposing?(handler: ComposingHandler): () => void;
|
|
446
462
|
/**
|
|
447
463
|
* Get list of configured relay URLs
|
|
448
464
|
*/
|
|
@@ -675,6 +691,7 @@ interface IncomingTypingIndicator {
|
|
|
675
691
|
timestamp: number;
|
|
676
692
|
}
|
|
677
693
|
type TypingIndicatorHandler = (indicator: IncomingTypingIndicator) => void;
|
|
694
|
+
type ComposingHandler = (indicator: ComposingIndicator) => void;
|
|
678
695
|
|
|
679
696
|
/**
|
|
680
697
|
* WebSocket Abstraction
|
|
@@ -769,6 +786,8 @@ declare class NostrTransportProvider implements TransportProvider {
|
|
|
769
786
|
private paymentRequestResponseHandlers;
|
|
770
787
|
private readReceiptHandlers;
|
|
771
788
|
private typingIndicatorHandlers;
|
|
789
|
+
private composingHandlers;
|
|
790
|
+
private pendingMessages;
|
|
772
791
|
private broadcastHandlers;
|
|
773
792
|
private eventCallbacks;
|
|
774
793
|
constructor(config: NostrTransportProviderConfig);
|
|
@@ -822,6 +841,8 @@ declare class NostrTransportProvider implements TransportProvider {
|
|
|
822
841
|
onReadReceipt(handler: ReadReceiptHandler): () => void;
|
|
823
842
|
sendTypingIndicator(recipientTransportPubkey: string): Promise<void>;
|
|
824
843
|
onTypingIndicator(handler: TypingIndicatorHandler): () => void;
|
|
844
|
+
onComposing(handler: ComposingHandler): () => void;
|
|
845
|
+
sendComposingIndicator(recipientPubkey: string, content: string): Promise<void>;
|
|
825
846
|
/**
|
|
826
847
|
* Resolve any identifier to full peer information.
|
|
827
848
|
* Routes to the appropriate specific resolve method based on identifier format.
|
|
@@ -895,6 +916,12 @@ declare class NostrTransportProvider implements TransportProvider {
|
|
|
895
916
|
private ensureConnected;
|
|
896
917
|
private ensureReady;
|
|
897
918
|
private emitEvent;
|
|
919
|
+
/**
|
|
920
|
+
* Create a NIP-17 gift wrap with a custom inner rumor kind.
|
|
921
|
+
* Replicates the three-layer NIP-59 envelope (rumor → seal → gift wrap)
|
|
922
|
+
* because NIP17.createGiftWrap hardcodes kind 14 for the inner rumor.
|
|
923
|
+
*/
|
|
924
|
+
private createCustomKindGiftWrap;
|
|
898
925
|
private log;
|
|
899
926
|
}
|
|
900
927
|
|
|
@@ -1365,6 +1392,15 @@ interface BasePriceConfig {
|
|
|
1365
1392
|
/** Enable debug logging */
|
|
1366
1393
|
debug?: boolean;
|
|
1367
1394
|
}
|
|
1395
|
+
/**
|
|
1396
|
+
* Base market module configuration
|
|
1397
|
+
*/
|
|
1398
|
+
interface BaseMarketConfig {
|
|
1399
|
+
/** Market API base URL (default: https://market-api.unicity.network) */
|
|
1400
|
+
apiUrl?: string;
|
|
1401
|
+
/** Request timeout in ms (default: 30000) */
|
|
1402
|
+
timeout?: number;
|
|
1403
|
+
}
|
|
1368
1404
|
/**
|
|
1369
1405
|
* Base providers result
|
|
1370
1406
|
* Common structure for all platforms
|
|
@@ -1380,6 +1416,13 @@ interface BaseProviders {
|
|
|
1380
1416
|
price?: PriceProvider;
|
|
1381
1417
|
}
|
|
1382
1418
|
|
|
1419
|
+
interface MarketModuleConfig {
|
|
1420
|
+
/** Market API base URL (default: https://market-api.unicity.network) */
|
|
1421
|
+
apiUrl?: string;
|
|
1422
|
+
/** Request timeout in ms (default: 30000) */
|
|
1423
|
+
timeout?: number;
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1383
1426
|
/** IPFS storage provider configuration */
|
|
1384
1427
|
interface IpfsStorageConfig {
|
|
1385
1428
|
/** Gateway URLs for HTTP API (defaults to Unicity dedicated nodes) */
|
|
@@ -1472,6 +1515,8 @@ interface NodeProvidersConfig {
|
|
|
1472
1515
|
enabled?: boolean;
|
|
1473
1516
|
relays?: string[];
|
|
1474
1517
|
} | boolean;
|
|
1518
|
+
/** Market module configuration. true = enable with defaults, object = custom config */
|
|
1519
|
+
market?: BaseMarketConfig | boolean;
|
|
1475
1520
|
}
|
|
1476
1521
|
interface NodeProviders {
|
|
1477
1522
|
storage: StorageProvider;
|
|
@@ -1486,6 +1531,8 @@ interface NodeProviders {
|
|
|
1486
1531
|
ipfsTokenStorage?: TokenStorageProvider<TxfStorageDataBase>;
|
|
1487
1532
|
/** Group chat config (resolved, for passing to Sphere.init) */
|
|
1488
1533
|
groupChat?: GroupChatModuleConfig | boolean;
|
|
1534
|
+
/** Market module config (resolved, for passing to Sphere.init) */
|
|
1535
|
+
market?: MarketModuleConfig | boolean;
|
|
1489
1536
|
}
|
|
1490
1537
|
/**
|
|
1491
1538
|
* Create all Node.js providers with default configuration
|
|
@@ -548,6 +548,52 @@ function createView(arr) {
|
|
|
548
548
|
function rotr(word, shift) {
|
|
549
549
|
return word << 32 - shift | word >>> shift;
|
|
550
550
|
}
|
|
551
|
+
var hasHexBuiltin = /* @__PURE__ */ (() => (
|
|
552
|
+
// @ts-ignore
|
|
553
|
+
typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function"
|
|
554
|
+
))();
|
|
555
|
+
var hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
|
|
556
|
+
function bytesToHex(bytes) {
|
|
557
|
+
abytes(bytes);
|
|
558
|
+
if (hasHexBuiltin)
|
|
559
|
+
return bytes.toHex();
|
|
560
|
+
let hex = "";
|
|
561
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
562
|
+
hex += hexes[bytes[i]];
|
|
563
|
+
}
|
|
564
|
+
return hex;
|
|
565
|
+
}
|
|
566
|
+
var asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
|
|
567
|
+
function asciiToBase16(ch) {
|
|
568
|
+
if (ch >= asciis._0 && ch <= asciis._9)
|
|
569
|
+
return ch - asciis._0;
|
|
570
|
+
if (ch >= asciis.A && ch <= asciis.F)
|
|
571
|
+
return ch - (asciis.A - 10);
|
|
572
|
+
if (ch >= asciis.a && ch <= asciis.f)
|
|
573
|
+
return ch - (asciis.a - 10);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
function hexToBytes(hex) {
|
|
577
|
+
if (typeof hex !== "string")
|
|
578
|
+
throw new Error("hex string expected, got " + typeof hex);
|
|
579
|
+
if (hasHexBuiltin)
|
|
580
|
+
return Uint8Array.fromHex(hex);
|
|
581
|
+
const hl = hex.length;
|
|
582
|
+
const al = hl / 2;
|
|
583
|
+
if (hl % 2)
|
|
584
|
+
throw new Error("hex string expected, got unpadded hex of length " + hl);
|
|
585
|
+
const array = new Uint8Array(al);
|
|
586
|
+
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
|
|
587
|
+
const n1 = asciiToBase16(hex.charCodeAt(hi));
|
|
588
|
+
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
|
|
589
|
+
if (n1 === void 0 || n2 === void 0) {
|
|
590
|
+
const char = hex[hi] + hex[hi + 1];
|
|
591
|
+
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
|
|
592
|
+
}
|
|
593
|
+
array[ai] = n1 * 16 + n2;
|
|
594
|
+
}
|
|
595
|
+
return array;
|
|
596
|
+
}
|
|
551
597
|
function createHasher(hashCons, info = {}) {
|
|
552
598
|
const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
|
|
553
599
|
const tmp = hashCons(void 0);
|
|
@@ -937,6 +983,7 @@ import {
|
|
|
937
983
|
NostrKeyManager,
|
|
938
984
|
NIP04,
|
|
939
985
|
NIP17,
|
|
986
|
+
NIP44,
|
|
940
987
|
Event as NostrEventClass,
|
|
941
988
|
EventKinds,
|
|
942
989
|
hashNametag,
|
|
@@ -1054,7 +1101,7 @@ function publicKeyToAddress(publicKey, prefix = "alpha", witnessVersion = 0) {
|
|
|
1054
1101
|
const programBytes = hash160ToBytes(pubKeyHash);
|
|
1055
1102
|
return encodeBech32(prefix, witnessVersion, programBytes);
|
|
1056
1103
|
}
|
|
1057
|
-
function
|
|
1104
|
+
function hexToBytes2(hex) {
|
|
1058
1105
|
const matches = hex.match(/../g);
|
|
1059
1106
|
if (!matches) {
|
|
1060
1107
|
return new Uint8Array(0);
|
|
@@ -1081,6 +1128,8 @@ function defaultUUIDGenerator() {
|
|
|
1081
1128
|
}
|
|
1082
1129
|
|
|
1083
1130
|
// transport/NostrTransportProvider.ts
|
|
1131
|
+
var COMPOSING_INDICATOR_KIND = 25050;
|
|
1132
|
+
var TIMESTAMP_RANDOMIZATION = 2 * 24 * 60 * 60;
|
|
1084
1133
|
var EVENT_KINDS = NOSTR_EVENT_KINDS;
|
|
1085
1134
|
function hashAddressForTag(address) {
|
|
1086
1135
|
const bytes = new TextEncoder().encode("unicity:address:" + address);
|
|
@@ -1163,6 +1212,8 @@ var NostrTransportProvider = class {
|
|
|
1163
1212
|
paymentRequestResponseHandlers = /* @__PURE__ */ new Set();
|
|
1164
1213
|
readReceiptHandlers = /* @__PURE__ */ new Set();
|
|
1165
1214
|
typingIndicatorHandlers = /* @__PURE__ */ new Set();
|
|
1215
|
+
composingHandlers = /* @__PURE__ */ new Set();
|
|
1216
|
+
pendingMessages = [];
|
|
1166
1217
|
broadcastHandlers = /* @__PURE__ */ new Map();
|
|
1167
1218
|
eventCallbacks = /* @__PURE__ */ new Set();
|
|
1168
1219
|
constructor(config) {
|
|
@@ -1435,6 +1486,18 @@ var NostrTransportProvider = class {
|
|
|
1435
1486
|
}
|
|
1436
1487
|
onMessage(handler) {
|
|
1437
1488
|
this.messageHandlers.add(handler);
|
|
1489
|
+
if (this.pendingMessages.length > 0) {
|
|
1490
|
+
const pending = this.pendingMessages;
|
|
1491
|
+
this.pendingMessages = [];
|
|
1492
|
+
this.log("Flushing", pending.length, "buffered messages to new handler");
|
|
1493
|
+
for (const message of pending) {
|
|
1494
|
+
try {
|
|
1495
|
+
handler(message);
|
|
1496
|
+
} catch (error) {
|
|
1497
|
+
this.log("Message handler error (buffered):", error);
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1438
1501
|
return () => this.messageHandlers.delete(handler);
|
|
1439
1502
|
}
|
|
1440
1503
|
async sendTokenTransfer(recipientPubkey, payload) {
|
|
@@ -1555,6 +1618,19 @@ var NostrTransportProvider = class {
|
|
|
1555
1618
|
this.typingIndicatorHandlers.add(handler);
|
|
1556
1619
|
return () => this.typingIndicatorHandlers.delete(handler);
|
|
1557
1620
|
}
|
|
1621
|
+
// ===========================================================================
|
|
1622
|
+
// Composing Indicators (NIP-59 kind 25050)
|
|
1623
|
+
// ===========================================================================
|
|
1624
|
+
onComposing(handler) {
|
|
1625
|
+
this.composingHandlers.add(handler);
|
|
1626
|
+
return () => this.composingHandlers.delete(handler);
|
|
1627
|
+
}
|
|
1628
|
+
async sendComposingIndicator(recipientPubkey, content) {
|
|
1629
|
+
this.ensureReady();
|
|
1630
|
+
const nostrRecipient = recipientPubkey.length === 66 && (recipientPubkey.startsWith("02") || recipientPubkey.startsWith("03")) ? recipientPubkey.slice(2) : recipientPubkey;
|
|
1631
|
+
const giftWrap = this.createCustomKindGiftWrap(nostrRecipient, content, COMPOSING_INDICATOR_KIND);
|
|
1632
|
+
await this.publishEvent(giftWrap);
|
|
1633
|
+
}
|
|
1558
1634
|
/**
|
|
1559
1635
|
* Resolve any identifier to full peer information.
|
|
1560
1636
|
* Routes to the appropriate specific resolve method based on identifier format.
|
|
@@ -2054,6 +2130,30 @@ var NostrTransportProvider = class {
|
|
|
2054
2130
|
}
|
|
2055
2131
|
return;
|
|
2056
2132
|
}
|
|
2133
|
+
if (pm.kind === COMPOSING_INDICATOR_KIND) {
|
|
2134
|
+
let senderNametag2;
|
|
2135
|
+
let expiresIn = 3e4;
|
|
2136
|
+
try {
|
|
2137
|
+
const parsed = JSON.parse(pm.content);
|
|
2138
|
+
senderNametag2 = parsed.senderNametag || void 0;
|
|
2139
|
+
expiresIn = parsed.expiresIn ?? 3e4;
|
|
2140
|
+
} catch {
|
|
2141
|
+
}
|
|
2142
|
+
const indicator = {
|
|
2143
|
+
senderPubkey: pm.senderPubkey,
|
|
2144
|
+
senderNametag: senderNametag2,
|
|
2145
|
+
expiresIn
|
|
2146
|
+
};
|
|
2147
|
+
this.log("Composing indicator from:", indicator.senderNametag || pm.senderPubkey?.slice(0, 16));
|
|
2148
|
+
for (const handler of this.composingHandlers) {
|
|
2149
|
+
try {
|
|
2150
|
+
handler(indicator);
|
|
2151
|
+
} catch (e) {
|
|
2152
|
+
this.log("Composing handler error:", e);
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
return;
|
|
2156
|
+
}
|
|
2057
2157
|
try {
|
|
2058
2158
|
const parsed = JSON.parse(pm.content);
|
|
2059
2159
|
if (parsed?.type === "typing") {
|
|
@@ -2100,12 +2200,17 @@ var NostrTransportProvider = class {
|
|
|
2100
2200
|
encrypted: true
|
|
2101
2201
|
};
|
|
2102
2202
|
this.emitEvent({ type: "message:received", timestamp: Date.now() });
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2203
|
+
if (this.messageHandlers.size === 0) {
|
|
2204
|
+
this.log("No message handlers registered, buffering message for later delivery");
|
|
2205
|
+
this.pendingMessages.push(message);
|
|
2206
|
+
} else {
|
|
2207
|
+
this.log("Dispatching to", this.messageHandlers.size, "handlers");
|
|
2208
|
+
for (const handler of this.messageHandlers) {
|
|
2209
|
+
try {
|
|
2210
|
+
handler(message);
|
|
2211
|
+
} catch (error) {
|
|
2212
|
+
this.log("Message handler error:", error);
|
|
2213
|
+
}
|
|
2109
2214
|
}
|
|
2110
2215
|
}
|
|
2111
2216
|
} catch (err) {
|
|
@@ -2509,6 +2614,39 @@ var NostrTransportProvider = class {
|
|
|
2509
2614
|
}
|
|
2510
2615
|
}
|
|
2511
2616
|
}
|
|
2617
|
+
/**
|
|
2618
|
+
* Create a NIP-17 gift wrap with a custom inner rumor kind.
|
|
2619
|
+
* Replicates the three-layer NIP-59 envelope (rumor → seal → gift wrap)
|
|
2620
|
+
* because NIP17.createGiftWrap hardcodes kind 14 for the inner rumor.
|
|
2621
|
+
*/
|
|
2622
|
+
createCustomKindGiftWrap(recipientPubkeyHex, content, rumorKind) {
|
|
2623
|
+
const senderPubkey = this.keyManager.getPublicKeyHex();
|
|
2624
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
2625
|
+
const rumorTags = [["p", recipientPubkeyHex]];
|
|
2626
|
+
const rumorSerialized = JSON.stringify([0, senderPubkey, now, rumorKind, rumorTags, content]);
|
|
2627
|
+
const rumorId = bytesToHex(sha256(new TextEncoder().encode(rumorSerialized)));
|
|
2628
|
+
const rumor = { id: rumorId, pubkey: senderPubkey, created_at: now, kind: rumorKind, tags: rumorTags, content };
|
|
2629
|
+
const recipientPubkeyBytes = hexToBytes(recipientPubkeyHex);
|
|
2630
|
+
const encryptedRumor = NIP44.encrypt(JSON.stringify(rumor), this.keyManager.getPrivateKey(), recipientPubkeyBytes);
|
|
2631
|
+
const sealTimestamp = now + Math.floor(Math.random() * 2 * TIMESTAMP_RANDOMIZATION) - TIMESTAMP_RANDOMIZATION;
|
|
2632
|
+
const seal = NostrEventClass.create(this.keyManager, {
|
|
2633
|
+
kind: EventKinds.SEAL,
|
|
2634
|
+
tags: [],
|
|
2635
|
+
content: encryptedRumor,
|
|
2636
|
+
created_at: sealTimestamp
|
|
2637
|
+
});
|
|
2638
|
+
const ephemeralKeys = NostrKeyManager.generate();
|
|
2639
|
+
const encryptedSeal = NIP44.encrypt(JSON.stringify(seal.toJSON()), ephemeralKeys.getPrivateKey(), recipientPubkeyBytes);
|
|
2640
|
+
const wrapTimestamp = now + Math.floor(Math.random() * 2 * TIMESTAMP_RANDOMIZATION) - TIMESTAMP_RANDOMIZATION;
|
|
2641
|
+
const giftWrap = NostrEventClass.create(ephemeralKeys, {
|
|
2642
|
+
kind: EventKinds.GIFT_WRAP,
|
|
2643
|
+
tags: [["p", recipientPubkeyHex]],
|
|
2644
|
+
content: encryptedSeal,
|
|
2645
|
+
created_at: wrapTimestamp
|
|
2646
|
+
});
|
|
2647
|
+
ephemeralKeys.clear();
|
|
2648
|
+
return giftWrap;
|
|
2649
|
+
}
|
|
2512
2650
|
log(...args) {
|
|
2513
2651
|
if (this.config.debug) {
|
|
2514
2652
|
console.log("[NostrTransportProvider]", ...args);
|
|
@@ -3085,7 +3223,7 @@ async function loadLibp2pModules() {
|
|
|
3085
3223
|
};
|
|
3086
3224
|
}
|
|
3087
3225
|
function deriveEd25519KeyMaterial(privateKeyHex, info = IPNS_HKDF_INFO) {
|
|
3088
|
-
const walletSecret =
|
|
3226
|
+
const walletSecret = hexToBytes2(privateKeyHex);
|
|
3089
3227
|
const infoBytes = new TextEncoder().encode(info);
|
|
3090
3228
|
return hkdf(sha256, walletSecret, void 0, infoBytes, 32);
|
|
3091
3229
|
}
|
|
@@ -5570,6 +5708,11 @@ function resolveGroupChatConfig(network, config) {
|
|
|
5570
5708
|
relays: config.relays ?? [...netConfig.groupRelays]
|
|
5571
5709
|
};
|
|
5572
5710
|
}
|
|
5711
|
+
function resolveMarketConfig(config) {
|
|
5712
|
+
if (!config) return void 0;
|
|
5713
|
+
if (config === true) return {};
|
|
5714
|
+
return { apiUrl: config.apiUrl, timeout: config.timeout };
|
|
5715
|
+
}
|
|
5573
5716
|
|
|
5574
5717
|
// impl/nodejs/index.ts
|
|
5575
5718
|
function createNodeProviders(config) {
|
|
@@ -5585,11 +5728,13 @@ function createNodeProviders(config) {
|
|
|
5585
5728
|
const ipfsSync = config?.tokenSync?.ipfs;
|
|
5586
5729
|
const ipfsTokenStorage = ipfsSync?.enabled ? createNodeIpfsStorageProvider(ipfsSync.config, storage) : void 0;
|
|
5587
5730
|
const groupChat = resolveGroupChatConfig(network, config?.groupChat);
|
|
5731
|
+
const market = resolveMarketConfig(config?.market);
|
|
5588
5732
|
const networkConfig = getNetworkConfig(network);
|
|
5589
5733
|
TokenRegistry.configure({ remoteUrl: networkConfig.tokenRegistryUrl, storage });
|
|
5590
5734
|
return {
|
|
5591
5735
|
storage,
|
|
5592
5736
|
groupChat,
|
|
5737
|
+
market,
|
|
5593
5738
|
tokenStorage: createFileTokenStorageProvider({
|
|
5594
5739
|
tokensDir: config?.tokensDir ?? "./sphere-tokens"
|
|
5595
5740
|
}),
|