@unicitylabs/sphere-sdk 0.3.6 → 0.3.7

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.
@@ -1196,6 +1196,8 @@ var NostrTransportProvider = class {
1196
1196
  transferHandlers = /* @__PURE__ */ new Set();
1197
1197
  paymentRequestHandlers = /* @__PURE__ */ new Set();
1198
1198
  paymentRequestResponseHandlers = /* @__PURE__ */ new Set();
1199
+ readReceiptHandlers = /* @__PURE__ */ new Set();
1200
+ typingIndicatorHandlers = /* @__PURE__ */ new Set();
1199
1201
  broadcastHandlers = /* @__PURE__ */ new Map();
1200
1202
  eventCallbacks = /* @__PURE__ */ new Set();
1201
1203
  constructor(config) {
@@ -1447,6 +1449,18 @@ var NostrTransportProvider = class {
1447
1449
  const wrappedContent = senderNametag ? JSON.stringify({ senderNametag, text: content }) : content;
1448
1450
  const giftWrap = import_nostr_js_sdk.NIP17.createGiftWrap(this.keyManager, nostrRecipient, wrappedContent);
1449
1451
  await this.publishEvent(giftWrap);
1452
+ const selfWrapContent = JSON.stringify({
1453
+ selfWrap: true,
1454
+ originalId: giftWrap.id,
1455
+ recipientPubkey,
1456
+ senderNametag,
1457
+ text: content
1458
+ });
1459
+ const selfPubkey = this.keyManager.getPublicKeyHex();
1460
+ const selfGiftWrap = import_nostr_js_sdk.NIP17.createGiftWrap(this.keyManager, selfPubkey, selfWrapContent);
1461
+ this.publishEvent(selfGiftWrap).catch((err) => {
1462
+ this.log("Self-wrap publish failed:", err);
1463
+ });
1450
1464
  this.emitEvent({
1451
1465
  type: "message:sent",
1452
1466
  timestamp: Date.now(),
@@ -1545,6 +1559,37 @@ var NostrTransportProvider = class {
1545
1559
  this.paymentRequestResponseHandlers.add(handler);
1546
1560
  return () => this.paymentRequestResponseHandlers.delete(handler);
1547
1561
  }
1562
+ // ===========================================================================
1563
+ // Read Receipts
1564
+ // ===========================================================================
1565
+ async sendReadReceipt(recipientTransportPubkey, messageEventId) {
1566
+ if (!this.keyManager) throw new Error("Not initialized");
1567
+ const nostrRecipient = recipientTransportPubkey.length === 66 ? recipientTransportPubkey.slice(2) : recipientTransportPubkey;
1568
+ const event = import_nostr_js_sdk.NIP17.createReadReceipt(this.keyManager, nostrRecipient, messageEventId);
1569
+ await this.publishEvent(event);
1570
+ this.log("Sent read receipt for:", messageEventId, "to:", nostrRecipient.slice(0, 16));
1571
+ }
1572
+ onReadReceipt(handler) {
1573
+ this.readReceiptHandlers.add(handler);
1574
+ return () => this.readReceiptHandlers.delete(handler);
1575
+ }
1576
+ // ===========================================================================
1577
+ // Typing Indicators
1578
+ // ===========================================================================
1579
+ async sendTypingIndicator(recipientTransportPubkey) {
1580
+ if (!this.keyManager) throw new Error("Not initialized");
1581
+ const nostrRecipient = recipientTransportPubkey.length === 66 ? recipientTransportPubkey.slice(2) : recipientTransportPubkey;
1582
+ const content = JSON.stringify({
1583
+ type: "typing",
1584
+ senderNametag: this.identity?.nametag
1585
+ });
1586
+ const event = import_nostr_js_sdk.NIP17.createGiftWrap(this.keyManager, nostrRecipient, content);
1587
+ await this.publishEvent(event);
1588
+ }
1589
+ onTypingIndicator(handler) {
1590
+ this.typingIndicatorHandlers.add(handler);
1591
+ return () => this.typingIndicatorHandlers.delete(handler);
1592
+ }
1548
1593
  /**
1549
1594
  * Resolve any identifier to full peer information.
1550
1595
  * Routes to the appropriate specific resolve method based on identifier format.
@@ -1998,11 +2043,74 @@ var NostrTransportProvider = class {
1998
2043
  const pm = import_nostr_js_sdk.NIP17.unwrap(event, this.keyManager);
1999
2044
  this.log("Gift wrap unwrapped, sender:", pm.senderPubkey?.slice(0, 16), "kind:", pm.kind);
2000
2045
  if (pm.senderPubkey === this.keyManager.getPublicKeyHex()) {
2001
- this.log("Skipping own message");
2046
+ try {
2047
+ const parsed = JSON.parse(pm.content);
2048
+ if (parsed?.selfWrap && parsed.recipientPubkey) {
2049
+ this.log("Self-wrap replay for recipient:", parsed.recipientPubkey?.slice(0, 16));
2050
+ const message2 = {
2051
+ id: parsed.originalId || pm.eventId,
2052
+ senderTransportPubkey: pm.senderPubkey,
2053
+ senderNametag: parsed.senderNametag,
2054
+ recipientTransportPubkey: parsed.recipientPubkey,
2055
+ content: parsed.text ?? "",
2056
+ timestamp: pm.timestamp * 1e3,
2057
+ encrypted: true,
2058
+ isSelfWrap: true
2059
+ };
2060
+ for (const handler of this.messageHandlers) {
2061
+ try {
2062
+ handler(message2);
2063
+ } catch (e) {
2064
+ this.log("Self-wrap handler error:", e);
2065
+ }
2066
+ }
2067
+ return;
2068
+ }
2069
+ } catch {
2070
+ }
2071
+ this.log("Skipping own non-self-wrap message");
2002
2072
  return;
2003
2073
  }
2004
- if (pm.kind !== import_nostr_js_sdk.EventKinds.CHAT_MESSAGE) {
2005
- this.log("Skipping non-chat message, kind:", pm.kind);
2074
+ if ((0, import_nostr_js_sdk.isReadReceipt)(pm)) {
2075
+ this.log("Read receipt from:", pm.senderPubkey?.slice(0, 16), "for:", pm.replyToEventId);
2076
+ if (pm.replyToEventId) {
2077
+ const receipt = {
2078
+ senderTransportPubkey: pm.senderPubkey,
2079
+ messageEventId: pm.replyToEventId,
2080
+ timestamp: pm.timestamp * 1e3
2081
+ };
2082
+ for (const handler of this.readReceiptHandlers) {
2083
+ try {
2084
+ handler(receipt);
2085
+ } catch (e) {
2086
+ this.log("Read receipt handler error:", e);
2087
+ }
2088
+ }
2089
+ }
2090
+ return;
2091
+ }
2092
+ try {
2093
+ const parsed = JSON.parse(pm.content);
2094
+ if (parsed?.type === "typing") {
2095
+ this.log("Typing indicator from:", pm.senderPubkey?.slice(0, 16));
2096
+ const indicator = {
2097
+ senderTransportPubkey: pm.senderPubkey,
2098
+ senderNametag: parsed.senderNametag,
2099
+ timestamp: pm.timestamp * 1e3
2100
+ };
2101
+ for (const handler of this.typingIndicatorHandlers) {
2102
+ try {
2103
+ handler(indicator);
2104
+ } catch (e) {
2105
+ this.log("Typing handler error:", e);
2106
+ }
2107
+ }
2108
+ return;
2109
+ }
2110
+ } catch {
2111
+ }
2112
+ if (!(0, import_nostr_js_sdk.isChatMessage)(pm)) {
2113
+ this.log("Skipping unknown message kind:", pm.kind);
2006
2114
  return;
2007
2115
  }
2008
2116
  let content = pm.content;
@@ -2017,7 +2125,9 @@ var NostrTransportProvider = class {
2017
2125
  }
2018
2126
  this.log("DM received from:", senderNametag || pm.senderPubkey?.slice(0, 16), "content:", content?.slice(0, 50));
2019
2127
  const message = {
2020
- id: pm.eventId,
2128
+ // Use outer gift wrap event.id so it matches the sender's stored giftWrap.id.
2129
+ // This ensures read receipts reference an ID the sender recognizes.
2130
+ id: event.id,
2021
2131
  senderTransportPubkey: pm.senderPubkey,
2022
2132
  senderNametag,
2023
2133
  content,