@unicitylabs/sphere-sdk 0.4.5 → 0.4.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.
package/dist/index.cjs CHANGED
@@ -8115,6 +8115,23 @@ var CommunicationsModule = class {
8115
8115
  return () => this.broadcastHandlers.delete(handler);
8116
8116
  }
8117
8117
  // ===========================================================================
8118
+ // Public API - Peer Resolution
8119
+ // ===========================================================================
8120
+ /**
8121
+ * Resolve a peer's nametag by their transport pubkey.
8122
+ * Uses transport.resolveTransportPubkeyInfo() for live lookup from relay binding events.
8123
+ * Returns undefined if transport doesn't support resolution or peer has no nametag.
8124
+ */
8125
+ async resolvePeerNametag(peerPubkey) {
8126
+ if (!this.deps?.transport.resolveTransportPubkeyInfo) return void 0;
8127
+ try {
8128
+ const info = await this.deps.transport.resolveTransportPubkeyInfo(peerPubkey);
8129
+ return info?.nametag;
8130
+ } catch {
8131
+ return void 0;
8132
+ }
8133
+ }
8134
+ // ===========================================================================
8118
8135
  // Private: Message Handling
8119
8136
  // ===========================================================================
8120
8137
  handleIncomingMessage(msg) {
@@ -8500,10 +8517,12 @@ var GroupChatModule = class {
8500
8517
  if (!this.client) return;
8501
8518
  const groupIds = Array.from(this.groups.keys());
8502
8519
  if (groupIds.length === 0) return;
8520
+ const latestTimestamp = this.getLatestMessageTimestamp(groupIds);
8503
8521
  this.trackSubscription(
8504
8522
  createNip29Filter({
8505
8523
  kinds: [NIP29_KINDS.CHAT_MESSAGE, NIP29_KINDS.THREAD_ROOT, NIP29_KINDS.THREAD_REPLY],
8506
- "#h": groupIds
8524
+ "#h": groupIds,
8525
+ ...latestTimestamp ? { since: latestTimestamp } : {}
8507
8526
  }),
8508
8527
  { onEvent: (event) => this.handleGroupEvent(event) }
8509
8528
  );
@@ -8524,10 +8543,12 @@ var GroupChatModule = class {
8524
8543
  }
8525
8544
  subscribeToGroup(groupId) {
8526
8545
  if (!this.client) return;
8546
+ const latestTimestamp = this.getLatestMessageTimestamp([groupId]);
8527
8547
  this.trackSubscription(
8528
8548
  createNip29Filter({
8529
8549
  kinds: [NIP29_KINDS.CHAT_MESSAGE, NIP29_KINDS.THREAD_ROOT, NIP29_KINDS.THREAD_REPLY],
8530
- "#h": [groupId]
8550
+ "#h": [groupId],
8551
+ ...latestTimestamp ? { since: latestTimestamp } : {}
8531
8552
  }),
8532
8553
  { onEvent: (event) => this.handleGroupEvent(event) }
8533
8554
  );
@@ -9219,6 +9240,23 @@ var GroupChatModule = class {
9219
9240
  getMyPublicKey() {
9220
9241
  return this.keyManager?.getPublicKeyHex() || null;
9221
9242
  }
9243
+ /**
9244
+ * Returns the latest message timestamp (in Nostr seconds) across the given groups,
9245
+ * or 0 if no messages exist. Used to set `since` on subscriptions so the relay
9246
+ * only sends events we don't already have.
9247
+ */
9248
+ getLatestMessageTimestamp(groupIds) {
9249
+ let latest = 0;
9250
+ for (const gid of groupIds) {
9251
+ const msgs = this.messages.get(gid);
9252
+ if (!msgs) continue;
9253
+ for (const m of msgs) {
9254
+ const ts = Math.floor(m.timestamp / 1e3);
9255
+ if (ts > latest) latest = ts;
9256
+ }
9257
+ }
9258
+ return latest;
9259
+ }
9222
9260
  // ===========================================================================
9223
9261
  // Private — Relay Admin
9224
9262
  // ===========================================================================
@@ -13665,55 +13703,44 @@ var Sphere = class _Sphere {
13665
13703
  * ```
13666
13704
  */
13667
13705
  static async importFromJSON(options) {
13706
+ const { jsonContent, password, ...baseOptions } = options;
13668
13707
  try {
13669
- const data = JSON.parse(options.jsonContent);
13708
+ const data = JSON.parse(jsonContent);
13670
13709
  if (data.version !== "1.0" || data.type !== "sphere-wallet") {
13671
13710
  return { success: false, error: "Invalid wallet format" };
13672
13711
  }
13673
13712
  let mnemonic = data.mnemonic;
13674
13713
  let masterKey = data.wallet.masterPrivateKey;
13675
- if (data.encrypted && options.password) {
13714
+ if (data.encrypted && password) {
13676
13715
  if (mnemonic) {
13677
- const decrypted = decryptSimple(mnemonic, options.password);
13716
+ const decrypted = decryptSimple(mnemonic, password);
13678
13717
  if (!decrypted) {
13679
13718
  return { success: false, error: "Failed to decrypt mnemonic - wrong password?" };
13680
13719
  }
13681
13720
  mnemonic = decrypted;
13682
13721
  }
13683
13722
  if (masterKey) {
13684
- const decrypted = decryptSimple(masterKey, options.password);
13723
+ const decrypted = decryptSimple(masterKey, password);
13685
13724
  if (!decrypted) {
13686
13725
  return { success: false, error: "Failed to decrypt master key - wrong password?" };
13687
13726
  }
13688
13727
  masterKey = decrypted;
13689
13728
  }
13690
- } else if (data.encrypted && !options.password) {
13729
+ } else if (data.encrypted && !password) {
13691
13730
  return { success: false, error: "Password required for encrypted wallet" };
13692
13731
  }
13693
13732
  const basePath = data.wallet.descriptorPath ? `m/${data.wallet.descriptorPath}` : DEFAULT_BASE_PATH;
13694
13733
  if (mnemonic) {
13695
- await _Sphere.import({
13696
- mnemonic,
13697
- basePath,
13698
- storage: options.storage,
13699
- transport: options.transport,
13700
- oracle: options.oracle,
13701
- tokenStorage: options.tokenStorage,
13702
- l1: options.l1
13703
- });
13734
+ await _Sphere.import({ ...baseOptions, mnemonic, basePath });
13704
13735
  return { success: true, mnemonic };
13705
13736
  }
13706
13737
  if (masterKey) {
13707
13738
  await _Sphere.import({
13739
+ ...baseOptions,
13708
13740
  masterKey,
13709
13741
  chainCode: data.wallet.chainCode,
13710
13742
  basePath,
13711
- derivationMode: data.derivationMode || (data.wallet.isBIP32 ? "bip32" : "wif_hmac"),
13712
- storage: options.storage,
13713
- transport: options.transport,
13714
- oracle: options.oracle,
13715
- tokenStorage: options.tokenStorage,
13716
- l1: options.l1
13743
+ derivationMode: data.derivationMode || (data.wallet.isBIP32 ? "bip32" : "wif_hmac")
13717
13744
  });
13718
13745
  return { success: true };
13719
13746
  }
@@ -13756,7 +13783,7 @@ var Sphere = class _Sphere {
13756
13783
  * ```
13757
13784
  */
13758
13785
  static async importFromLegacyFile(options) {
13759
- const { fileContent, fileName, password, onDecryptProgress } = options;
13786
+ const { fileContent, fileName, password, onDecryptProgress, ...baseOptions } = options;
13760
13787
  const fileType = _Sphere.detectLegacyFileType(fileName, fileContent);
13761
13788
  if (fileType === "unknown") {
13762
13789
  return { success: false, error: "Unknown file format" };
@@ -13766,15 +13793,7 @@ var Sphere = class _Sphere {
13766
13793
  if (!_Sphere.validateMnemonic(mnemonic)) {
13767
13794
  return { success: false, error: "Invalid mnemonic phrase" };
13768
13795
  }
13769
- const sphere = await _Sphere.import({
13770
- mnemonic,
13771
- storage: options.storage,
13772
- transport: options.transport,
13773
- oracle: options.oracle,
13774
- tokenStorage: options.tokenStorage,
13775
- nametag: options.nametag,
13776
- l1: options.l1
13777
- });
13796
+ const sphere = await _Sphere.import({ ...baseOptions, mnemonic });
13778
13797
  return { success: true, sphere, mnemonic };
13779
13798
  }
13780
13799
  if (fileType === "dat") {
@@ -13794,16 +13813,11 @@ var Sphere = class _Sphere {
13794
13813
  const { masterKey, chainCode, descriptorPath, derivationMode } = parseResult.data;
13795
13814
  const basePath = descriptorPath ? `m/${descriptorPath}` : DEFAULT_BASE_PATH;
13796
13815
  const sphere = await _Sphere.import({
13816
+ ...baseOptions,
13797
13817
  masterKey,
13798
13818
  chainCode,
13799
13819
  basePath,
13800
- derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac"),
13801
- storage: options.storage,
13802
- transport: options.transport,
13803
- oracle: options.oracle,
13804
- tokenStorage: options.tokenStorage,
13805
- nametag: options.nametag,
13806
- l1: options.l1
13820
+ derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
13807
13821
  });
13808
13822
  return { success: true, sphere };
13809
13823
  }
@@ -13826,16 +13840,11 @@ var Sphere = class _Sphere {
13826
13840
  const { masterKey, chainCode, descriptorPath, derivationMode } = parseResult.data;
13827
13841
  const basePath = descriptorPath ? `m/${descriptorPath}` : DEFAULT_BASE_PATH;
13828
13842
  const sphere = await _Sphere.import({
13843
+ ...baseOptions,
13829
13844
  masterKey,
13830
13845
  chainCode,
13831
13846
  basePath,
13832
- derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac"),
13833
- storage: options.storage,
13834
- transport: options.transport,
13835
- oracle: options.oracle,
13836
- tokenStorage: options.tokenStorage,
13837
- nametag: options.nametag,
13838
- l1: options.l1
13847
+ derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
13839
13848
  });
13840
13849
  return { success: true, sphere };
13841
13850
  }
@@ -13849,13 +13858,9 @@ var Sphere = class _Sphere {
13849
13858
  }
13850
13859
  if (parsed.type === "sphere-wallet") {
13851
13860
  const result = await _Sphere.importFromJSON({
13861
+ ...baseOptions,
13852
13862
  jsonContent: content,
13853
- password,
13854
- storage: options.storage,
13855
- transport: options.transport,
13856
- oracle: options.oracle,
13857
- tokenStorage: options.tokenStorage,
13858
- l1: options.l1
13863
+ password
13859
13864
  });
13860
13865
  if (result.success) {
13861
13866
  const sphere2 = _Sphere.getInstance();
@@ -13897,29 +13902,15 @@ var Sphere = class _Sphere {
13897
13902
  const isBIP32 = derivationMode === "bip32" || !!chainCode;
13898
13903
  const basePath = descriptorPath ? `m/${descriptorPath}` : isBIP32 ? "m/84'/1'/0'" : DEFAULT_BASE_PATH;
13899
13904
  if (mnemonic) {
13900
- const sphere2 = await _Sphere.import({
13901
- mnemonic,
13902
- basePath,
13903
- storage: options.storage,
13904
- transport: options.transport,
13905
- oracle: options.oracle,
13906
- tokenStorage: options.tokenStorage,
13907
- nametag: options.nametag,
13908
- l1: options.l1
13909
- });
13905
+ const sphere2 = await _Sphere.import({ ...baseOptions, mnemonic, basePath });
13910
13906
  return { success: true, sphere: sphere2, mnemonic };
13911
13907
  }
13912
13908
  const sphere = await _Sphere.import({
13909
+ ...baseOptions,
13913
13910
  masterKey,
13914
13911
  chainCode,
13915
13912
  basePath,
13916
- derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac"),
13917
- storage: options.storage,
13918
- transport: options.transport,
13919
- oracle: options.oracle,
13920
- tokenStorage: options.tokenStorage,
13921
- nametag: options.nametag,
13922
- l1: options.l1
13913
+ derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
13923
13914
  });
13924
13915
  return { success: true, sphere };
13925
13916
  }