@unicitylabs/sphere-sdk 0.6.3 → 0.6.4

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.
@@ -1115,7 +1115,7 @@ function defaultUUIDGenerator() {
1115
1115
  var COMPOSING_INDICATOR_KIND = 25050;
1116
1116
  var TIMESTAMP_RANDOMIZATION = 2 * 24 * 60 * 60;
1117
1117
  var EVENT_KINDS = NOSTR_EVENT_KINDS;
1118
- var NostrTransportProvider = class {
1118
+ var NostrTransportProvider = class _NostrTransportProvider {
1119
1119
  id = "nostr";
1120
1120
  name = "Nostr Transport";
1121
1121
  type = "p2p";
@@ -1646,11 +1646,11 @@ var NostrTransportProvider = class {
1646
1646
  return this.resolveNametagInfo(identifier);
1647
1647
  }
1648
1648
  async resolveNametag(nametag) {
1649
- this.ensureConnected();
1649
+ await this.ensureConnectedForResolve();
1650
1650
  return this.nostrClient.queryPubkeyByNametag(nametag);
1651
1651
  }
1652
1652
  async resolveNametagInfo(nametag) {
1653
- this.ensureConnected();
1653
+ await this.ensureConnectedForResolve();
1654
1654
  const binding = await this.nostrClient.queryBindingByNametag(nametag);
1655
1655
  if (!binding) {
1656
1656
  logger.debug("Nostr", `resolveNametagInfo: no binding events found for Unicity ID "${nametag}"`);
@@ -1663,7 +1663,7 @@ var NostrTransportProvider = class {
1663
1663
  * Performs reverse lookup via nostr-js-sdk with first-seen-wins anti-hijacking.
1664
1664
  */
1665
1665
  async resolveAddressInfo(address) {
1666
- this.ensureConnected();
1666
+ await this.ensureConnectedForResolve();
1667
1667
  const binding = await this.nostrClient.queryBindingByAddress(address);
1668
1668
  if (!binding) return null;
1669
1669
  return this.bindingInfoToPeerInfo(binding);
@@ -1698,7 +1698,7 @@ var NostrTransportProvider = class {
1698
1698
  * Queries binding events authored by the given pubkey.
1699
1699
  */
1700
1700
  async resolveTransportPubkeyInfo(transportPubkey) {
1701
- this.ensureConnected();
1701
+ await this.ensureConnectedForResolve();
1702
1702
  const events = await this.queryEvents({
1703
1703
  kinds: [EVENT_KINDS.NAMETAG_BINDING],
1704
1704
  authors: [transportPubkey],
@@ -1733,7 +1733,7 @@ var NostrTransportProvider = class {
1733
1733
  * Used for HD address discovery — single relay query with multi-author filter.
1734
1734
  */
1735
1735
  async discoverAddresses(transportPubkeys) {
1736
- this.ensureConnected();
1736
+ await this.ensureConnectedForResolve();
1737
1737
  if (transportPubkeys.length === 0) return [];
1738
1738
  const events = await this.queryEvents({
1739
1739
  kinds: [EVENT_KINDS.NAMETAG_BINDING],
@@ -1772,7 +1772,10 @@ var NostrTransportProvider = class {
1772
1772
  * @returns Decrypted nametag or null if none found
1773
1773
  */
1774
1774
  async recoverNametag() {
1775
- this.ensureReady();
1775
+ await this.ensureConnectedForResolve();
1776
+ if (!this.identity) {
1777
+ throw new SphereError("Identity not set", "NOT_INITIALIZED");
1778
+ }
1776
1779
  if (!this.identity || !this.keyManager) {
1777
1780
  throw new SphereError("Identity not set", "NOT_INITIALIZED");
1778
1781
  }
@@ -2508,6 +2511,31 @@ var NostrTransportProvider = class {
2508
2511
  throw new SphereError("NostrTransportProvider not connected", "TRANSPORT_ERROR");
2509
2512
  }
2510
2513
  }
2514
+ /**
2515
+ * Async version of ensureConnected — reconnects if the original transport
2516
+ * lost its WebSocket while subscriptions are suppressed (mux handles events).
2517
+ * Used by resolve methods which are always async.
2518
+ */
2519
+ async ensureConnectedForResolve() {
2520
+ if (this.isConnected()) return;
2521
+ if (this._subscriptionsSuppressed && this.nostrClient) {
2522
+ logger.debug("Nostr", "Suppressed transport disconnected \u2014 reconnecting for resolve");
2523
+ try {
2524
+ await Promise.race([
2525
+ this.nostrClient.connect(...this.config.relays),
2526
+ new Promise(
2527
+ (_, reject) => setTimeout(() => reject(new Error("reconnect timeout")), 5e3)
2528
+ )
2529
+ ]);
2530
+ if (this.nostrClient.isConnected()) {
2531
+ this.status = "connected";
2532
+ return;
2533
+ }
2534
+ } catch {
2535
+ }
2536
+ }
2537
+ throw new SphereError("NostrTransportProvider not connected", "TRANSPORT_ERROR");
2538
+ }
2511
2539
  ensureReady() {
2512
2540
  this.ensureConnected();
2513
2541
  if (!this.identity) {
@@ -2529,16 +2557,23 @@ var NostrTransportProvider = class {
2529
2557
  * because NIP17.createGiftWrap hardcodes kind 14 for the inner rumor.
2530
2558
  */
2531
2559
  createCustomKindGiftWrap(recipientPubkeyHex, content, rumorKind) {
2532
- const senderPubkey = this.keyManager.getPublicKeyHex();
2560
+ return _NostrTransportProvider.createCustomKindGiftWrap(this.keyManager, recipientPubkeyHex, content, rumorKind);
2561
+ }
2562
+ /**
2563
+ * Create a NIP-17 gift wrap with a custom rumor kind.
2564
+ * Shared between NostrTransportProvider and MultiAddressTransportMux.
2565
+ */
2566
+ static createCustomKindGiftWrap(keyManager, recipientPubkeyHex, content, rumorKind) {
2567
+ const senderPubkey = keyManager.getPublicKeyHex();
2533
2568
  const now = Math.floor(Date.now() / 1e3);
2534
2569
  const rumorTags = [["p", recipientPubkeyHex]];
2535
2570
  const rumorSerialized = JSON.stringify([0, senderPubkey, now, rumorKind, rumorTags, content]);
2536
2571
  const rumorId = bytesToHex(sha256(new TextEncoder().encode(rumorSerialized)));
2537
2572
  const rumor = { id: rumorId, pubkey: senderPubkey, created_at: now, kind: rumorKind, tags: rumorTags, content };
2538
2573
  const recipientPubkeyBytes = hexToBytes(recipientPubkeyHex);
2539
- const encryptedRumor = import_nostr_js_sdk.NIP44.encrypt(JSON.stringify(rumor), this.keyManager.getPrivateKey(), recipientPubkeyBytes);
2574
+ const encryptedRumor = import_nostr_js_sdk.NIP44.encrypt(JSON.stringify(rumor), keyManager.getPrivateKey(), recipientPubkeyBytes);
2540
2575
  const sealTimestamp = now + Math.floor(Math.random() * 2 * TIMESTAMP_RANDOMIZATION) - TIMESTAMP_RANDOMIZATION;
2541
- const seal = import_nostr_js_sdk.Event.create(this.keyManager, {
2576
+ const seal = import_nostr_js_sdk.Event.create(keyManager, {
2542
2577
  kind: import_nostr_js_sdk.EventKinds.SEAL,
2543
2578
  tags: [],
2544
2579
  content: encryptedRumor,