@unicitylabs/sphere-sdk 0.3.8 → 0.3.9
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 +87 -7
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +57 -1
- package/dist/core/index.d.ts +57 -1
- package/dist/core/index.js +87 -7
- 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 +167 -32
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +170 -33
- 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 +114 -4
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +49 -0
- package/dist/impl/nodejs/index.d.ts +49 -0
- package/dist/impl/nodejs/index.js +117 -5
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +87 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -1
- package/dist/index.d.ts +57 -1
- package/dist/index.js +87 -7
- package/dist/index.js.map +1 -1
- package/package.json +31 -1
|
@@ -422,6 +422,27 @@ interface TransportProvider extends BaseProvider {
|
|
|
422
422
|
* @returns Unsubscribe function
|
|
423
423
|
*/
|
|
424
424
|
onPaymentRequestResponse?(handler: PaymentRequestResponseHandler): () => void;
|
|
425
|
+
/**
|
|
426
|
+
* Send a read receipt for a message
|
|
427
|
+
* @param recipientTransportPubkey - Transport pubkey of the message sender
|
|
428
|
+
* @param messageEventId - Event ID of the message being acknowledged
|
|
429
|
+
*/
|
|
430
|
+
sendReadReceipt?(recipientTransportPubkey: string, messageEventId: string): Promise<void>;
|
|
431
|
+
/**
|
|
432
|
+
* Subscribe to incoming read receipts
|
|
433
|
+
* @returns Unsubscribe function
|
|
434
|
+
*/
|
|
435
|
+
onReadReceipt?(handler: ReadReceiptHandler): () => void;
|
|
436
|
+
/**
|
|
437
|
+
* Send typing indicator to a recipient
|
|
438
|
+
* @param recipientTransportPubkey - Transport pubkey of the conversation partner
|
|
439
|
+
*/
|
|
440
|
+
sendTypingIndicator?(recipientTransportPubkey: string): Promise<void>;
|
|
441
|
+
/**
|
|
442
|
+
* Subscribe to incoming typing indicators
|
|
443
|
+
* @returns Unsubscribe function
|
|
444
|
+
*/
|
|
445
|
+
onTypingIndicator?(handler: TypingIndicatorHandler): () => void;
|
|
425
446
|
/**
|
|
426
447
|
* Get list of configured relay URLs
|
|
427
448
|
*/
|
|
@@ -511,6 +532,10 @@ interface IncomingMessage {
|
|
|
511
532
|
content: string;
|
|
512
533
|
timestamp: number;
|
|
513
534
|
encrypted: boolean;
|
|
535
|
+
/** Set when this is a self-wrap replay (sent message recovered from relay) */
|
|
536
|
+
isSelfWrap?: boolean;
|
|
537
|
+
/** Recipient pubkey — only present on self-wrap replays */
|
|
538
|
+
recipientTransportPubkey?: string;
|
|
514
539
|
}
|
|
515
540
|
type MessageHandler = (message: IncomingMessage) => void;
|
|
516
541
|
interface TokenTransferPayload {
|
|
@@ -632,6 +657,24 @@ interface PeerInfo {
|
|
|
632
657
|
/** Event timestamp */
|
|
633
658
|
timestamp: number;
|
|
634
659
|
}
|
|
660
|
+
interface IncomingReadReceipt {
|
|
661
|
+
/** Transport-specific pubkey of the sender who read the message */
|
|
662
|
+
senderTransportPubkey: string;
|
|
663
|
+
/** Event ID of the message that was read */
|
|
664
|
+
messageEventId: string;
|
|
665
|
+
/** Timestamp */
|
|
666
|
+
timestamp: number;
|
|
667
|
+
}
|
|
668
|
+
type ReadReceiptHandler = (receipt: IncomingReadReceipt) => void;
|
|
669
|
+
interface IncomingTypingIndicator {
|
|
670
|
+
/** Transport-specific pubkey of the sender who is typing */
|
|
671
|
+
senderTransportPubkey: string;
|
|
672
|
+
/** Sender's nametag (if known) */
|
|
673
|
+
senderNametag?: string;
|
|
674
|
+
/** Timestamp */
|
|
675
|
+
timestamp: number;
|
|
676
|
+
}
|
|
677
|
+
type TypingIndicatorHandler = (indicator: IncomingTypingIndicator) => void;
|
|
635
678
|
|
|
636
679
|
/**
|
|
637
680
|
* WebSocket Abstraction
|
|
@@ -724,6 +767,8 @@ declare class NostrTransportProvider implements TransportProvider {
|
|
|
724
767
|
private transferHandlers;
|
|
725
768
|
private paymentRequestHandlers;
|
|
726
769
|
private paymentRequestResponseHandlers;
|
|
770
|
+
private readReceiptHandlers;
|
|
771
|
+
private typingIndicatorHandlers;
|
|
727
772
|
private broadcastHandlers;
|
|
728
773
|
private eventCallbacks;
|
|
729
774
|
constructor(config: NostrTransportProviderConfig);
|
|
@@ -773,6 +818,10 @@ declare class NostrTransportProvider implements TransportProvider {
|
|
|
773
818
|
onPaymentRequest(handler: PaymentRequestHandler): () => void;
|
|
774
819
|
sendPaymentRequestResponse(recipientPubkey: string, payload: PaymentRequestResponsePayload): Promise<string>;
|
|
775
820
|
onPaymentRequestResponse(handler: PaymentRequestResponseHandler): () => void;
|
|
821
|
+
sendReadReceipt(recipientTransportPubkey: string, messageEventId: string): Promise<void>;
|
|
822
|
+
onReadReceipt(handler: ReadReceiptHandler): () => void;
|
|
823
|
+
sendTypingIndicator(recipientTransportPubkey: string): Promise<void>;
|
|
824
|
+
onTypingIndicator(handler: TypingIndicatorHandler): () => void;
|
|
776
825
|
/**
|
|
777
826
|
* Resolve any identifier to full peer information.
|
|
778
827
|
* Routes to the appropriate specific resolve method based on identifier format.
|
|
@@ -422,6 +422,27 @@ interface TransportProvider extends BaseProvider {
|
|
|
422
422
|
* @returns Unsubscribe function
|
|
423
423
|
*/
|
|
424
424
|
onPaymentRequestResponse?(handler: PaymentRequestResponseHandler): () => void;
|
|
425
|
+
/**
|
|
426
|
+
* Send a read receipt for a message
|
|
427
|
+
* @param recipientTransportPubkey - Transport pubkey of the message sender
|
|
428
|
+
* @param messageEventId - Event ID of the message being acknowledged
|
|
429
|
+
*/
|
|
430
|
+
sendReadReceipt?(recipientTransportPubkey: string, messageEventId: string): Promise<void>;
|
|
431
|
+
/**
|
|
432
|
+
* Subscribe to incoming read receipts
|
|
433
|
+
* @returns Unsubscribe function
|
|
434
|
+
*/
|
|
435
|
+
onReadReceipt?(handler: ReadReceiptHandler): () => void;
|
|
436
|
+
/**
|
|
437
|
+
* Send typing indicator to a recipient
|
|
438
|
+
* @param recipientTransportPubkey - Transport pubkey of the conversation partner
|
|
439
|
+
*/
|
|
440
|
+
sendTypingIndicator?(recipientTransportPubkey: string): Promise<void>;
|
|
441
|
+
/**
|
|
442
|
+
* Subscribe to incoming typing indicators
|
|
443
|
+
* @returns Unsubscribe function
|
|
444
|
+
*/
|
|
445
|
+
onTypingIndicator?(handler: TypingIndicatorHandler): () => void;
|
|
425
446
|
/**
|
|
426
447
|
* Get list of configured relay URLs
|
|
427
448
|
*/
|
|
@@ -511,6 +532,10 @@ interface IncomingMessage {
|
|
|
511
532
|
content: string;
|
|
512
533
|
timestamp: number;
|
|
513
534
|
encrypted: boolean;
|
|
535
|
+
/** Set when this is a self-wrap replay (sent message recovered from relay) */
|
|
536
|
+
isSelfWrap?: boolean;
|
|
537
|
+
/** Recipient pubkey — only present on self-wrap replays */
|
|
538
|
+
recipientTransportPubkey?: string;
|
|
514
539
|
}
|
|
515
540
|
type MessageHandler = (message: IncomingMessage) => void;
|
|
516
541
|
interface TokenTransferPayload {
|
|
@@ -632,6 +657,24 @@ interface PeerInfo {
|
|
|
632
657
|
/** Event timestamp */
|
|
633
658
|
timestamp: number;
|
|
634
659
|
}
|
|
660
|
+
interface IncomingReadReceipt {
|
|
661
|
+
/** Transport-specific pubkey of the sender who read the message */
|
|
662
|
+
senderTransportPubkey: string;
|
|
663
|
+
/** Event ID of the message that was read */
|
|
664
|
+
messageEventId: string;
|
|
665
|
+
/** Timestamp */
|
|
666
|
+
timestamp: number;
|
|
667
|
+
}
|
|
668
|
+
type ReadReceiptHandler = (receipt: IncomingReadReceipt) => void;
|
|
669
|
+
interface IncomingTypingIndicator {
|
|
670
|
+
/** Transport-specific pubkey of the sender who is typing */
|
|
671
|
+
senderTransportPubkey: string;
|
|
672
|
+
/** Sender's nametag (if known) */
|
|
673
|
+
senderNametag?: string;
|
|
674
|
+
/** Timestamp */
|
|
675
|
+
timestamp: number;
|
|
676
|
+
}
|
|
677
|
+
type TypingIndicatorHandler = (indicator: IncomingTypingIndicator) => void;
|
|
635
678
|
|
|
636
679
|
/**
|
|
637
680
|
* WebSocket Abstraction
|
|
@@ -724,6 +767,8 @@ declare class NostrTransportProvider implements TransportProvider {
|
|
|
724
767
|
private transferHandlers;
|
|
725
768
|
private paymentRequestHandlers;
|
|
726
769
|
private paymentRequestResponseHandlers;
|
|
770
|
+
private readReceiptHandlers;
|
|
771
|
+
private typingIndicatorHandlers;
|
|
727
772
|
private broadcastHandlers;
|
|
728
773
|
private eventCallbacks;
|
|
729
774
|
constructor(config: NostrTransportProviderConfig);
|
|
@@ -773,6 +818,10 @@ declare class NostrTransportProvider implements TransportProvider {
|
|
|
773
818
|
onPaymentRequest(handler: PaymentRequestHandler): () => void;
|
|
774
819
|
sendPaymentRequestResponse(recipientPubkey: string, payload: PaymentRequestResponsePayload): Promise<string>;
|
|
775
820
|
onPaymentRequestResponse(handler: PaymentRequestResponseHandler): () => void;
|
|
821
|
+
sendReadReceipt(recipientTransportPubkey: string, messageEventId: string): Promise<void>;
|
|
822
|
+
onReadReceipt(handler: ReadReceiptHandler): () => void;
|
|
823
|
+
sendTypingIndicator(recipientTransportPubkey: string): Promise<void>;
|
|
824
|
+
onTypingIndicator(handler: TypingIndicatorHandler): () => void;
|
|
776
825
|
/**
|
|
777
826
|
* Resolve any identifier to full peer information.
|
|
778
827
|
* Routes to the appropriate specific resolve method based on identifier format.
|
|
@@ -941,7 +941,9 @@ import {
|
|
|
941
941
|
EventKinds,
|
|
942
942
|
hashNametag,
|
|
943
943
|
NostrClient,
|
|
944
|
-
Filter
|
|
944
|
+
Filter,
|
|
945
|
+
isChatMessage,
|
|
946
|
+
isReadReceipt
|
|
945
947
|
} from "@unicitylabs/nostr-js-sdk";
|
|
946
948
|
|
|
947
949
|
// core/crypto.ts
|
|
@@ -1159,6 +1161,8 @@ var NostrTransportProvider = class {
|
|
|
1159
1161
|
transferHandlers = /* @__PURE__ */ new Set();
|
|
1160
1162
|
paymentRequestHandlers = /* @__PURE__ */ new Set();
|
|
1161
1163
|
paymentRequestResponseHandlers = /* @__PURE__ */ new Set();
|
|
1164
|
+
readReceiptHandlers = /* @__PURE__ */ new Set();
|
|
1165
|
+
typingIndicatorHandlers = /* @__PURE__ */ new Set();
|
|
1162
1166
|
broadcastHandlers = /* @__PURE__ */ new Map();
|
|
1163
1167
|
eventCallbacks = /* @__PURE__ */ new Set();
|
|
1164
1168
|
constructor(config) {
|
|
@@ -1410,6 +1414,18 @@ var NostrTransportProvider = class {
|
|
|
1410
1414
|
const wrappedContent = senderNametag ? JSON.stringify({ senderNametag, text: content }) : content;
|
|
1411
1415
|
const giftWrap = NIP17.createGiftWrap(this.keyManager, nostrRecipient, wrappedContent);
|
|
1412
1416
|
await this.publishEvent(giftWrap);
|
|
1417
|
+
const selfWrapContent = JSON.stringify({
|
|
1418
|
+
selfWrap: true,
|
|
1419
|
+
originalId: giftWrap.id,
|
|
1420
|
+
recipientPubkey,
|
|
1421
|
+
senderNametag,
|
|
1422
|
+
text: content
|
|
1423
|
+
});
|
|
1424
|
+
const selfPubkey = this.keyManager.getPublicKeyHex();
|
|
1425
|
+
const selfGiftWrap = NIP17.createGiftWrap(this.keyManager, selfPubkey, selfWrapContent);
|
|
1426
|
+
this.publishEvent(selfGiftWrap).catch((err) => {
|
|
1427
|
+
this.log("Self-wrap publish failed:", err);
|
|
1428
|
+
});
|
|
1413
1429
|
this.emitEvent({
|
|
1414
1430
|
type: "message:sent",
|
|
1415
1431
|
timestamp: Date.now(),
|
|
@@ -1508,6 +1524,37 @@ var NostrTransportProvider = class {
|
|
|
1508
1524
|
this.paymentRequestResponseHandlers.add(handler);
|
|
1509
1525
|
return () => this.paymentRequestResponseHandlers.delete(handler);
|
|
1510
1526
|
}
|
|
1527
|
+
// ===========================================================================
|
|
1528
|
+
// Read Receipts
|
|
1529
|
+
// ===========================================================================
|
|
1530
|
+
async sendReadReceipt(recipientTransportPubkey, messageEventId) {
|
|
1531
|
+
if (!this.keyManager) throw new Error("Not initialized");
|
|
1532
|
+
const nostrRecipient = recipientTransportPubkey.length === 66 ? recipientTransportPubkey.slice(2) : recipientTransportPubkey;
|
|
1533
|
+
const event = NIP17.createReadReceipt(this.keyManager, nostrRecipient, messageEventId);
|
|
1534
|
+
await this.publishEvent(event);
|
|
1535
|
+
this.log("Sent read receipt for:", messageEventId, "to:", nostrRecipient.slice(0, 16));
|
|
1536
|
+
}
|
|
1537
|
+
onReadReceipt(handler) {
|
|
1538
|
+
this.readReceiptHandlers.add(handler);
|
|
1539
|
+
return () => this.readReceiptHandlers.delete(handler);
|
|
1540
|
+
}
|
|
1541
|
+
// ===========================================================================
|
|
1542
|
+
// Typing Indicators
|
|
1543
|
+
// ===========================================================================
|
|
1544
|
+
async sendTypingIndicator(recipientTransportPubkey) {
|
|
1545
|
+
if (!this.keyManager) throw new Error("Not initialized");
|
|
1546
|
+
const nostrRecipient = recipientTransportPubkey.length === 66 ? recipientTransportPubkey.slice(2) : recipientTransportPubkey;
|
|
1547
|
+
const content = JSON.stringify({
|
|
1548
|
+
type: "typing",
|
|
1549
|
+
senderNametag: this.identity?.nametag
|
|
1550
|
+
});
|
|
1551
|
+
const event = NIP17.createGiftWrap(this.keyManager, nostrRecipient, content);
|
|
1552
|
+
await this.publishEvent(event);
|
|
1553
|
+
}
|
|
1554
|
+
onTypingIndicator(handler) {
|
|
1555
|
+
this.typingIndicatorHandlers.add(handler);
|
|
1556
|
+
return () => this.typingIndicatorHandlers.delete(handler);
|
|
1557
|
+
}
|
|
1511
1558
|
/**
|
|
1512
1559
|
* Resolve any identifier to full peer information.
|
|
1513
1560
|
* Routes to the appropriate specific resolve method based on identifier format.
|
|
@@ -1961,11 +2008,74 @@ var NostrTransportProvider = class {
|
|
|
1961
2008
|
const pm = NIP17.unwrap(event, this.keyManager);
|
|
1962
2009
|
this.log("Gift wrap unwrapped, sender:", pm.senderPubkey?.slice(0, 16), "kind:", pm.kind);
|
|
1963
2010
|
if (pm.senderPubkey === this.keyManager.getPublicKeyHex()) {
|
|
1964
|
-
|
|
2011
|
+
try {
|
|
2012
|
+
const parsed = JSON.parse(pm.content);
|
|
2013
|
+
if (parsed?.selfWrap && parsed.recipientPubkey) {
|
|
2014
|
+
this.log("Self-wrap replay for recipient:", parsed.recipientPubkey?.slice(0, 16));
|
|
2015
|
+
const message2 = {
|
|
2016
|
+
id: parsed.originalId || pm.eventId,
|
|
2017
|
+
senderTransportPubkey: pm.senderPubkey,
|
|
2018
|
+
senderNametag: parsed.senderNametag,
|
|
2019
|
+
recipientTransportPubkey: parsed.recipientPubkey,
|
|
2020
|
+
content: parsed.text ?? "",
|
|
2021
|
+
timestamp: pm.timestamp * 1e3,
|
|
2022
|
+
encrypted: true,
|
|
2023
|
+
isSelfWrap: true
|
|
2024
|
+
};
|
|
2025
|
+
for (const handler of this.messageHandlers) {
|
|
2026
|
+
try {
|
|
2027
|
+
handler(message2);
|
|
2028
|
+
} catch (e) {
|
|
2029
|
+
this.log("Self-wrap handler error:", e);
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
return;
|
|
2033
|
+
}
|
|
2034
|
+
} catch {
|
|
2035
|
+
}
|
|
2036
|
+
this.log("Skipping own non-self-wrap message");
|
|
1965
2037
|
return;
|
|
1966
2038
|
}
|
|
1967
|
-
if (pm
|
|
1968
|
-
this.log("
|
|
2039
|
+
if (isReadReceipt(pm)) {
|
|
2040
|
+
this.log("Read receipt from:", pm.senderPubkey?.slice(0, 16), "for:", pm.replyToEventId);
|
|
2041
|
+
if (pm.replyToEventId) {
|
|
2042
|
+
const receipt = {
|
|
2043
|
+
senderTransportPubkey: pm.senderPubkey,
|
|
2044
|
+
messageEventId: pm.replyToEventId,
|
|
2045
|
+
timestamp: pm.timestamp * 1e3
|
|
2046
|
+
};
|
|
2047
|
+
for (const handler of this.readReceiptHandlers) {
|
|
2048
|
+
try {
|
|
2049
|
+
handler(receipt);
|
|
2050
|
+
} catch (e) {
|
|
2051
|
+
this.log("Read receipt handler error:", e);
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
return;
|
|
2056
|
+
}
|
|
2057
|
+
try {
|
|
2058
|
+
const parsed = JSON.parse(pm.content);
|
|
2059
|
+
if (parsed?.type === "typing") {
|
|
2060
|
+
this.log("Typing indicator from:", pm.senderPubkey?.slice(0, 16));
|
|
2061
|
+
const indicator = {
|
|
2062
|
+
senderTransportPubkey: pm.senderPubkey,
|
|
2063
|
+
senderNametag: parsed.senderNametag,
|
|
2064
|
+
timestamp: pm.timestamp * 1e3
|
|
2065
|
+
};
|
|
2066
|
+
for (const handler of this.typingIndicatorHandlers) {
|
|
2067
|
+
try {
|
|
2068
|
+
handler(indicator);
|
|
2069
|
+
} catch (e) {
|
|
2070
|
+
this.log("Typing handler error:", e);
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
return;
|
|
2074
|
+
}
|
|
2075
|
+
} catch {
|
|
2076
|
+
}
|
|
2077
|
+
if (!isChatMessage(pm)) {
|
|
2078
|
+
this.log("Skipping unknown message kind:", pm.kind);
|
|
1969
2079
|
return;
|
|
1970
2080
|
}
|
|
1971
2081
|
let content = pm.content;
|
|
@@ -1980,7 +2090,9 @@ var NostrTransportProvider = class {
|
|
|
1980
2090
|
}
|
|
1981
2091
|
this.log("DM received from:", senderNametag || pm.senderPubkey?.slice(0, 16), "content:", content?.slice(0, 50));
|
|
1982
2092
|
const message = {
|
|
1983
|
-
id
|
|
2093
|
+
// Use outer gift wrap event.id so it matches the sender's stored giftWrap.id.
|
|
2094
|
+
// This ensures read receipts reference an ID the sender recognizes.
|
|
2095
|
+
id: event.id,
|
|
1984
2096
|
senderTransportPubkey: pm.senderPubkey,
|
|
1985
2097
|
senderNametag,
|
|
1986
2098
|
content,
|