@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.
@@ -1635,7 +1635,7 @@ function defaultUUIDGenerator() {
1635
1635
  var COMPOSING_INDICATOR_KIND = 25050;
1636
1636
  var TIMESTAMP_RANDOMIZATION = 2 * 24 * 60 * 60;
1637
1637
  var EVENT_KINDS = NOSTR_EVENT_KINDS;
1638
- var NostrTransportProvider = class {
1638
+ var NostrTransportProvider = class _NostrTransportProvider {
1639
1639
  id = "nostr";
1640
1640
  name = "Nostr Transport";
1641
1641
  type = "p2p";
@@ -2166,11 +2166,11 @@ var NostrTransportProvider = class {
2166
2166
  return this.resolveNametagInfo(identifier);
2167
2167
  }
2168
2168
  async resolveNametag(nametag) {
2169
- this.ensureConnected();
2169
+ await this.ensureConnectedForResolve();
2170
2170
  return this.nostrClient.queryPubkeyByNametag(nametag);
2171
2171
  }
2172
2172
  async resolveNametagInfo(nametag) {
2173
- this.ensureConnected();
2173
+ await this.ensureConnectedForResolve();
2174
2174
  const binding = await this.nostrClient.queryBindingByNametag(nametag);
2175
2175
  if (!binding) {
2176
2176
  logger.debug("Nostr", `resolveNametagInfo: no binding events found for Unicity ID "${nametag}"`);
@@ -2183,7 +2183,7 @@ var NostrTransportProvider = class {
2183
2183
  * Performs reverse lookup via nostr-js-sdk with first-seen-wins anti-hijacking.
2184
2184
  */
2185
2185
  async resolveAddressInfo(address) {
2186
- this.ensureConnected();
2186
+ await this.ensureConnectedForResolve();
2187
2187
  const binding = await this.nostrClient.queryBindingByAddress(address);
2188
2188
  if (!binding) return null;
2189
2189
  return this.bindingInfoToPeerInfo(binding);
@@ -2218,7 +2218,7 @@ var NostrTransportProvider = class {
2218
2218
  * Queries binding events authored by the given pubkey.
2219
2219
  */
2220
2220
  async resolveTransportPubkeyInfo(transportPubkey) {
2221
- this.ensureConnected();
2221
+ await this.ensureConnectedForResolve();
2222
2222
  const events = await this.queryEvents({
2223
2223
  kinds: [EVENT_KINDS.NAMETAG_BINDING],
2224
2224
  authors: [transportPubkey],
@@ -2253,7 +2253,7 @@ var NostrTransportProvider = class {
2253
2253
  * Used for HD address discovery — single relay query with multi-author filter.
2254
2254
  */
2255
2255
  async discoverAddresses(transportPubkeys) {
2256
- this.ensureConnected();
2256
+ await this.ensureConnectedForResolve();
2257
2257
  if (transportPubkeys.length === 0) return [];
2258
2258
  const events = await this.queryEvents({
2259
2259
  kinds: [EVENT_KINDS.NAMETAG_BINDING],
@@ -2292,7 +2292,10 @@ var NostrTransportProvider = class {
2292
2292
  * @returns Decrypted nametag or null if none found
2293
2293
  */
2294
2294
  async recoverNametag() {
2295
- this.ensureReady();
2295
+ await this.ensureConnectedForResolve();
2296
+ if (!this.identity) {
2297
+ throw new SphereError("Identity not set", "NOT_INITIALIZED");
2298
+ }
2296
2299
  if (!this.identity || !this.keyManager) {
2297
2300
  throw new SphereError("Identity not set", "NOT_INITIALIZED");
2298
2301
  }
@@ -3028,6 +3031,31 @@ var NostrTransportProvider = class {
3028
3031
  throw new SphereError("NostrTransportProvider not connected", "TRANSPORT_ERROR");
3029
3032
  }
3030
3033
  }
3034
+ /**
3035
+ * Async version of ensureConnected — reconnects if the original transport
3036
+ * lost its WebSocket while subscriptions are suppressed (mux handles events).
3037
+ * Used by resolve methods which are always async.
3038
+ */
3039
+ async ensureConnectedForResolve() {
3040
+ if (this.isConnected()) return;
3041
+ if (this._subscriptionsSuppressed && this.nostrClient) {
3042
+ logger.debug("Nostr", "Suppressed transport disconnected \u2014 reconnecting for resolve");
3043
+ try {
3044
+ await Promise.race([
3045
+ this.nostrClient.connect(...this.config.relays),
3046
+ new Promise(
3047
+ (_, reject) => setTimeout(() => reject(new Error("reconnect timeout")), 5e3)
3048
+ )
3049
+ ]);
3050
+ if (this.nostrClient.isConnected()) {
3051
+ this.status = "connected";
3052
+ return;
3053
+ }
3054
+ } catch {
3055
+ }
3056
+ }
3057
+ throw new SphereError("NostrTransportProvider not connected", "TRANSPORT_ERROR");
3058
+ }
3031
3059
  ensureReady() {
3032
3060
  this.ensureConnected();
3033
3061
  if (!this.identity) {
@@ -3049,16 +3077,23 @@ var NostrTransportProvider = class {
3049
3077
  * because NIP17.createGiftWrap hardcodes kind 14 for the inner rumor.
3050
3078
  */
3051
3079
  createCustomKindGiftWrap(recipientPubkeyHex, content, rumorKind) {
3052
- const senderPubkey = this.keyManager.getPublicKeyHex();
3080
+ return _NostrTransportProvider.createCustomKindGiftWrap(this.keyManager, recipientPubkeyHex, content, rumorKind);
3081
+ }
3082
+ /**
3083
+ * Create a NIP-17 gift wrap with a custom rumor kind.
3084
+ * Shared between NostrTransportProvider and MultiAddressTransportMux.
3085
+ */
3086
+ static createCustomKindGiftWrap(keyManager, recipientPubkeyHex, content, rumorKind) {
3087
+ const senderPubkey = keyManager.getPublicKeyHex();
3053
3088
  const now = Math.floor(Date.now() / 1e3);
3054
3089
  const rumorTags = [["p", recipientPubkeyHex]];
3055
3090
  const rumorSerialized = JSON.stringify([0, senderPubkey, now, rumorKind, rumorTags, content]);
3056
3091
  const rumorId = bytesToHex(sha256(new TextEncoder().encode(rumorSerialized)));
3057
3092
  const rumor = { id: rumorId, pubkey: senderPubkey, created_at: now, kind: rumorKind, tags: rumorTags, content };
3058
3093
  const recipientPubkeyBytes = hexToBytes(recipientPubkeyHex);
3059
- const encryptedRumor = NIP44.encrypt(JSON.stringify(rumor), this.keyManager.getPrivateKey(), recipientPubkeyBytes);
3094
+ const encryptedRumor = NIP44.encrypt(JSON.stringify(rumor), keyManager.getPrivateKey(), recipientPubkeyBytes);
3060
3095
  const sealTimestamp = now + Math.floor(Math.random() * 2 * TIMESTAMP_RANDOMIZATION) - TIMESTAMP_RANDOMIZATION;
3061
- const seal = NostrEventClass.create(this.keyManager, {
3096
+ const seal = NostrEventClass.create(keyManager, {
3062
3097
  kind: EventKinds.SEAL,
3063
3098
  tags: [],
3064
3099
  content: encryptedRumor,