@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.
@@ -1683,7 +1683,7 @@ function defaultUUIDGenerator() {
1683
1683
  var COMPOSING_INDICATOR_KIND = 25050;
1684
1684
  var TIMESTAMP_RANDOMIZATION = 2 * 24 * 60 * 60;
1685
1685
  var EVENT_KINDS = NOSTR_EVENT_KINDS;
1686
- var NostrTransportProvider = class {
1686
+ var NostrTransportProvider = class _NostrTransportProvider {
1687
1687
  id = "nostr";
1688
1688
  name = "Nostr Transport";
1689
1689
  type = "p2p";
@@ -2214,11 +2214,11 @@ var NostrTransportProvider = class {
2214
2214
  return this.resolveNametagInfo(identifier);
2215
2215
  }
2216
2216
  async resolveNametag(nametag) {
2217
- this.ensureConnected();
2217
+ await this.ensureConnectedForResolve();
2218
2218
  return this.nostrClient.queryPubkeyByNametag(nametag);
2219
2219
  }
2220
2220
  async resolveNametagInfo(nametag) {
2221
- this.ensureConnected();
2221
+ await this.ensureConnectedForResolve();
2222
2222
  const binding = await this.nostrClient.queryBindingByNametag(nametag);
2223
2223
  if (!binding) {
2224
2224
  logger.debug("Nostr", `resolveNametagInfo: no binding events found for Unicity ID "${nametag}"`);
@@ -2231,7 +2231,7 @@ var NostrTransportProvider = class {
2231
2231
  * Performs reverse lookup via nostr-js-sdk with first-seen-wins anti-hijacking.
2232
2232
  */
2233
2233
  async resolveAddressInfo(address) {
2234
- this.ensureConnected();
2234
+ await this.ensureConnectedForResolve();
2235
2235
  const binding = await this.nostrClient.queryBindingByAddress(address);
2236
2236
  if (!binding) return null;
2237
2237
  return this.bindingInfoToPeerInfo(binding);
@@ -2266,7 +2266,7 @@ var NostrTransportProvider = class {
2266
2266
  * Queries binding events authored by the given pubkey.
2267
2267
  */
2268
2268
  async resolveTransportPubkeyInfo(transportPubkey) {
2269
- this.ensureConnected();
2269
+ await this.ensureConnectedForResolve();
2270
2270
  const events = await this.queryEvents({
2271
2271
  kinds: [EVENT_KINDS.NAMETAG_BINDING],
2272
2272
  authors: [transportPubkey],
@@ -2301,7 +2301,7 @@ var NostrTransportProvider = class {
2301
2301
  * Used for HD address discovery — single relay query with multi-author filter.
2302
2302
  */
2303
2303
  async discoverAddresses(transportPubkeys) {
2304
- this.ensureConnected();
2304
+ await this.ensureConnectedForResolve();
2305
2305
  if (transportPubkeys.length === 0) return [];
2306
2306
  const events = await this.queryEvents({
2307
2307
  kinds: [EVENT_KINDS.NAMETAG_BINDING],
@@ -2340,7 +2340,10 @@ var NostrTransportProvider = class {
2340
2340
  * @returns Decrypted nametag or null if none found
2341
2341
  */
2342
2342
  async recoverNametag() {
2343
- this.ensureReady();
2343
+ await this.ensureConnectedForResolve();
2344
+ if (!this.identity) {
2345
+ throw new SphereError("Identity not set", "NOT_INITIALIZED");
2346
+ }
2344
2347
  if (!this.identity || !this.keyManager) {
2345
2348
  throw new SphereError("Identity not set", "NOT_INITIALIZED");
2346
2349
  }
@@ -3076,6 +3079,31 @@ var NostrTransportProvider = class {
3076
3079
  throw new SphereError("NostrTransportProvider not connected", "TRANSPORT_ERROR");
3077
3080
  }
3078
3081
  }
3082
+ /**
3083
+ * Async version of ensureConnected — reconnects if the original transport
3084
+ * lost its WebSocket while subscriptions are suppressed (mux handles events).
3085
+ * Used by resolve methods which are always async.
3086
+ */
3087
+ async ensureConnectedForResolve() {
3088
+ if (this.isConnected()) return;
3089
+ if (this._subscriptionsSuppressed && this.nostrClient) {
3090
+ logger.debug("Nostr", "Suppressed transport disconnected \u2014 reconnecting for resolve");
3091
+ try {
3092
+ await Promise.race([
3093
+ this.nostrClient.connect(...this.config.relays),
3094
+ new Promise(
3095
+ (_, reject) => setTimeout(() => reject(new Error("reconnect timeout")), 5e3)
3096
+ )
3097
+ ]);
3098
+ if (this.nostrClient.isConnected()) {
3099
+ this.status = "connected";
3100
+ return;
3101
+ }
3102
+ } catch {
3103
+ }
3104
+ }
3105
+ throw new SphereError("NostrTransportProvider not connected", "TRANSPORT_ERROR");
3106
+ }
3079
3107
  ensureReady() {
3080
3108
  this.ensureConnected();
3081
3109
  if (!this.identity) {
@@ -3097,16 +3125,23 @@ var NostrTransportProvider = class {
3097
3125
  * because NIP17.createGiftWrap hardcodes kind 14 for the inner rumor.
3098
3126
  */
3099
3127
  createCustomKindGiftWrap(recipientPubkeyHex, content, rumorKind) {
3100
- const senderPubkey = this.keyManager.getPublicKeyHex();
3128
+ return _NostrTransportProvider.createCustomKindGiftWrap(this.keyManager, recipientPubkeyHex, content, rumorKind);
3129
+ }
3130
+ /**
3131
+ * Create a NIP-17 gift wrap with a custom rumor kind.
3132
+ * Shared between NostrTransportProvider and MultiAddressTransportMux.
3133
+ */
3134
+ static createCustomKindGiftWrap(keyManager, recipientPubkeyHex, content, rumorKind) {
3135
+ const senderPubkey = keyManager.getPublicKeyHex();
3101
3136
  const now = Math.floor(Date.now() / 1e3);
3102
3137
  const rumorTags = [["p", recipientPubkeyHex]];
3103
3138
  const rumorSerialized = JSON.stringify([0, senderPubkey, now, rumorKind, rumorTags, content]);
3104
3139
  const rumorId = bytesToHex(sha256(new TextEncoder().encode(rumorSerialized)));
3105
3140
  const rumor = { id: rumorId, pubkey: senderPubkey, created_at: now, kind: rumorKind, tags: rumorTags, content };
3106
3141
  const recipientPubkeyBytes = hexToBytes(recipientPubkeyHex);
3107
- const encryptedRumor = import_nostr_js_sdk.NIP44.encrypt(JSON.stringify(rumor), this.keyManager.getPrivateKey(), recipientPubkeyBytes);
3142
+ const encryptedRumor = import_nostr_js_sdk.NIP44.encrypt(JSON.stringify(rumor), keyManager.getPrivateKey(), recipientPubkeyBytes);
3108
3143
  const sealTimestamp = now + Math.floor(Math.random() * 2 * TIMESTAMP_RANDOMIZATION) - TIMESTAMP_RANDOMIZATION;
3109
- const seal = import_nostr_js_sdk.Event.create(this.keyManager, {
3144
+ const seal = import_nostr_js_sdk.Event.create(keyManager, {
3110
3145
  kind: import_nostr_js_sdk.EventKinds.SEAL,
3111
3146
  tags: [],
3112
3147
  content: encryptedRumor,