@unicitylabs/sphere-sdk 0.4.6 → 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.d.cts CHANGED
@@ -3446,6 +3446,12 @@ declare class GroupChatModule {
3446
3446
  onMessage(handler: (message: GroupMessageData) => void): () => void;
3447
3447
  getRelayUrls(): string[];
3448
3448
  getMyPublicKey(): string | null;
3449
+ /**
3450
+ * Returns the latest message timestamp (in Nostr seconds) across the given groups,
3451
+ * or 0 if no messages exist. Used to set `since` on subscriptions so the relay
3452
+ * only sends events we don't already have.
3453
+ */
3454
+ private getLatestMessageTimestamp;
3449
3455
  private fetchRelayAdmins;
3450
3456
  private doFetchRelayAdmins;
3451
3457
  private fetchGroupMetadataInternal;
@@ -4466,14 +4472,9 @@ declare class Sphere {
4466
4472
  * });
4467
4473
  * ```
4468
4474
  */
4469
- static importFromJSON(options: {
4475
+ static importFromJSON(options: Omit<SphereImportOptions, 'mnemonic' | 'masterKey' | 'chainCode' | 'derivationPath' | 'basePath' | 'derivationMode'> & {
4470
4476
  jsonContent: string;
4471
4477
  password?: string;
4472
- storage: StorageProvider;
4473
- transport: TransportProvider;
4474
- oracle: OracleProvider;
4475
- tokenStorage?: TokenStorageProvider<TxfStorageDataBase>;
4476
- l1?: L1Config;
4477
4478
  }): Promise<{
4478
4479
  success: boolean;
4479
4480
  mnemonic?: string;
@@ -4509,7 +4510,7 @@ declare class Sphere {
4509
4510
  * });
4510
4511
  * ```
4511
4512
  */
4512
- static importFromLegacyFile(options: {
4513
+ static importFromLegacyFile(options: Omit<SphereImportOptions, 'mnemonic' | 'masterKey' | 'chainCode' | 'derivationPath' | 'basePath' | 'derivationMode'> & {
4513
4514
  /** File content - Uint8Array for .dat, string for .txt */
4514
4515
  fileContent: string | Uint8Array;
4515
4516
  /** File name (used for type detection) */
@@ -4518,18 +4519,6 @@ declare class Sphere {
4518
4519
  password?: string;
4519
4520
  /** Progress callback for long decryption operations */
4520
4521
  onDecryptProgress?: DecryptionProgressCallback;
4521
- /** Storage provider instance */
4522
- storage: StorageProvider;
4523
- /** Transport provider instance */
4524
- transport: TransportProvider;
4525
- /** Oracle provider instance */
4526
- oracle: OracleProvider;
4527
- /** Optional token storage provider */
4528
- tokenStorage?: TokenStorageProvider<TxfStorageDataBase>;
4529
- /** Optional nametag to register */
4530
- nametag?: string;
4531
- /** L1 (ALPHA blockchain) configuration */
4532
- l1?: L1Config;
4533
4522
  }): Promise<{
4534
4523
  success: boolean;
4535
4524
  sphere?: Sphere;
package/dist/index.d.ts CHANGED
@@ -3446,6 +3446,12 @@ declare class GroupChatModule {
3446
3446
  onMessage(handler: (message: GroupMessageData) => void): () => void;
3447
3447
  getRelayUrls(): string[];
3448
3448
  getMyPublicKey(): string | null;
3449
+ /**
3450
+ * Returns the latest message timestamp (in Nostr seconds) across the given groups,
3451
+ * or 0 if no messages exist. Used to set `since` on subscriptions so the relay
3452
+ * only sends events we don't already have.
3453
+ */
3454
+ private getLatestMessageTimestamp;
3449
3455
  private fetchRelayAdmins;
3450
3456
  private doFetchRelayAdmins;
3451
3457
  private fetchGroupMetadataInternal;
@@ -4466,14 +4472,9 @@ declare class Sphere {
4466
4472
  * });
4467
4473
  * ```
4468
4474
  */
4469
- static importFromJSON(options: {
4475
+ static importFromJSON(options: Omit<SphereImportOptions, 'mnemonic' | 'masterKey' | 'chainCode' | 'derivationPath' | 'basePath' | 'derivationMode'> & {
4470
4476
  jsonContent: string;
4471
4477
  password?: string;
4472
- storage: StorageProvider;
4473
- transport: TransportProvider;
4474
- oracle: OracleProvider;
4475
- tokenStorage?: TokenStorageProvider<TxfStorageDataBase>;
4476
- l1?: L1Config;
4477
4478
  }): Promise<{
4478
4479
  success: boolean;
4479
4480
  mnemonic?: string;
@@ -4509,7 +4510,7 @@ declare class Sphere {
4509
4510
  * });
4510
4511
  * ```
4511
4512
  */
4512
- static importFromLegacyFile(options: {
4513
+ static importFromLegacyFile(options: Omit<SphereImportOptions, 'mnemonic' | 'masterKey' | 'chainCode' | 'derivationPath' | 'basePath' | 'derivationMode'> & {
4513
4514
  /** File content - Uint8Array for .dat, string for .txt */
4514
4515
  fileContent: string | Uint8Array;
4515
4516
  /** File name (used for type detection) */
@@ -4518,18 +4519,6 @@ declare class Sphere {
4518
4519
  password?: string;
4519
4520
  /** Progress callback for long decryption operations */
4520
4521
  onDecryptProgress?: DecryptionProgressCallback;
4521
- /** Storage provider instance */
4522
- storage: StorageProvider;
4523
- /** Transport provider instance */
4524
- transport: TransportProvider;
4525
- /** Oracle provider instance */
4526
- oracle: OracleProvider;
4527
- /** Optional token storage provider */
4528
- tokenStorage?: TokenStorageProvider<TxfStorageDataBase>;
4529
- /** Optional nametag to register */
4530
- nametag?: string;
4531
- /** L1 (ALPHA blockchain) configuration */
4532
- l1?: L1Config;
4533
4522
  }): Promise<{
4534
4523
  success: boolean;
4535
4524
  sphere?: Sphere;
package/dist/index.js CHANGED
@@ -8360,10 +8360,12 @@ var GroupChatModule = class {
8360
8360
  if (!this.client) return;
8361
8361
  const groupIds = Array.from(this.groups.keys());
8362
8362
  if (groupIds.length === 0) return;
8363
+ const latestTimestamp = this.getLatestMessageTimestamp(groupIds);
8363
8364
  this.trackSubscription(
8364
8365
  createNip29Filter({
8365
8366
  kinds: [NIP29_KINDS.CHAT_MESSAGE, NIP29_KINDS.THREAD_ROOT, NIP29_KINDS.THREAD_REPLY],
8366
- "#h": groupIds
8367
+ "#h": groupIds,
8368
+ ...latestTimestamp ? { since: latestTimestamp } : {}
8367
8369
  }),
8368
8370
  { onEvent: (event) => this.handleGroupEvent(event) }
8369
8371
  );
@@ -8384,10 +8386,12 @@ var GroupChatModule = class {
8384
8386
  }
8385
8387
  subscribeToGroup(groupId) {
8386
8388
  if (!this.client) return;
8389
+ const latestTimestamp = this.getLatestMessageTimestamp([groupId]);
8387
8390
  this.trackSubscription(
8388
8391
  createNip29Filter({
8389
8392
  kinds: [NIP29_KINDS.CHAT_MESSAGE, NIP29_KINDS.THREAD_ROOT, NIP29_KINDS.THREAD_REPLY],
8390
- "#h": [groupId]
8393
+ "#h": [groupId],
8394
+ ...latestTimestamp ? { since: latestTimestamp } : {}
8391
8395
  }),
8392
8396
  { onEvent: (event) => this.handleGroupEvent(event) }
8393
8397
  );
@@ -9079,6 +9083,23 @@ var GroupChatModule = class {
9079
9083
  getMyPublicKey() {
9080
9084
  return this.keyManager?.getPublicKeyHex() || null;
9081
9085
  }
9086
+ /**
9087
+ * Returns the latest message timestamp (in Nostr seconds) across the given groups,
9088
+ * or 0 if no messages exist. Used to set `since` on subscriptions so the relay
9089
+ * only sends events we don't already have.
9090
+ */
9091
+ getLatestMessageTimestamp(groupIds) {
9092
+ let latest = 0;
9093
+ for (const gid of groupIds) {
9094
+ const msgs = this.messages.get(gid);
9095
+ if (!msgs) continue;
9096
+ for (const m of msgs) {
9097
+ const ts = Math.floor(m.timestamp / 1e3);
9098
+ if (ts > latest) latest = ts;
9099
+ }
9100
+ }
9101
+ return latest;
9102
+ }
9082
9103
  // ===========================================================================
9083
9104
  // Private — Relay Admin
9084
9105
  // ===========================================================================
@@ -13525,55 +13546,44 @@ var Sphere = class _Sphere {
13525
13546
  * ```
13526
13547
  */
13527
13548
  static async importFromJSON(options) {
13549
+ const { jsonContent, password, ...baseOptions } = options;
13528
13550
  try {
13529
- const data = JSON.parse(options.jsonContent);
13551
+ const data = JSON.parse(jsonContent);
13530
13552
  if (data.version !== "1.0" || data.type !== "sphere-wallet") {
13531
13553
  return { success: false, error: "Invalid wallet format" };
13532
13554
  }
13533
13555
  let mnemonic = data.mnemonic;
13534
13556
  let masterKey = data.wallet.masterPrivateKey;
13535
- if (data.encrypted && options.password) {
13557
+ if (data.encrypted && password) {
13536
13558
  if (mnemonic) {
13537
- const decrypted = decryptSimple(mnemonic, options.password);
13559
+ const decrypted = decryptSimple(mnemonic, password);
13538
13560
  if (!decrypted) {
13539
13561
  return { success: false, error: "Failed to decrypt mnemonic - wrong password?" };
13540
13562
  }
13541
13563
  mnemonic = decrypted;
13542
13564
  }
13543
13565
  if (masterKey) {
13544
- const decrypted = decryptSimple(masterKey, options.password);
13566
+ const decrypted = decryptSimple(masterKey, password);
13545
13567
  if (!decrypted) {
13546
13568
  return { success: false, error: "Failed to decrypt master key - wrong password?" };
13547
13569
  }
13548
13570
  masterKey = decrypted;
13549
13571
  }
13550
- } else if (data.encrypted && !options.password) {
13572
+ } else if (data.encrypted && !password) {
13551
13573
  return { success: false, error: "Password required for encrypted wallet" };
13552
13574
  }
13553
13575
  const basePath = data.wallet.descriptorPath ? `m/${data.wallet.descriptorPath}` : DEFAULT_BASE_PATH;
13554
13576
  if (mnemonic) {
13555
- await _Sphere.import({
13556
- mnemonic,
13557
- basePath,
13558
- storage: options.storage,
13559
- transport: options.transport,
13560
- oracle: options.oracle,
13561
- tokenStorage: options.tokenStorage,
13562
- l1: options.l1
13563
- });
13577
+ await _Sphere.import({ ...baseOptions, mnemonic, basePath });
13564
13578
  return { success: true, mnemonic };
13565
13579
  }
13566
13580
  if (masterKey) {
13567
13581
  await _Sphere.import({
13582
+ ...baseOptions,
13568
13583
  masterKey,
13569
13584
  chainCode: data.wallet.chainCode,
13570
13585
  basePath,
13571
- derivationMode: data.derivationMode || (data.wallet.isBIP32 ? "bip32" : "wif_hmac"),
13572
- storage: options.storage,
13573
- transport: options.transport,
13574
- oracle: options.oracle,
13575
- tokenStorage: options.tokenStorage,
13576
- l1: options.l1
13586
+ derivationMode: data.derivationMode || (data.wallet.isBIP32 ? "bip32" : "wif_hmac")
13577
13587
  });
13578
13588
  return { success: true };
13579
13589
  }
@@ -13616,7 +13626,7 @@ var Sphere = class _Sphere {
13616
13626
  * ```
13617
13627
  */
13618
13628
  static async importFromLegacyFile(options) {
13619
- const { fileContent, fileName, password, onDecryptProgress } = options;
13629
+ const { fileContent, fileName, password, onDecryptProgress, ...baseOptions } = options;
13620
13630
  const fileType = _Sphere.detectLegacyFileType(fileName, fileContent);
13621
13631
  if (fileType === "unknown") {
13622
13632
  return { success: false, error: "Unknown file format" };
@@ -13626,15 +13636,7 @@ var Sphere = class _Sphere {
13626
13636
  if (!_Sphere.validateMnemonic(mnemonic)) {
13627
13637
  return { success: false, error: "Invalid mnemonic phrase" };
13628
13638
  }
13629
- const sphere = await _Sphere.import({
13630
- mnemonic,
13631
- storage: options.storage,
13632
- transport: options.transport,
13633
- oracle: options.oracle,
13634
- tokenStorage: options.tokenStorage,
13635
- nametag: options.nametag,
13636
- l1: options.l1
13637
- });
13639
+ const sphere = await _Sphere.import({ ...baseOptions, mnemonic });
13638
13640
  return { success: true, sphere, mnemonic };
13639
13641
  }
13640
13642
  if (fileType === "dat") {
@@ -13654,16 +13656,11 @@ var Sphere = class _Sphere {
13654
13656
  const { masterKey, chainCode, descriptorPath, derivationMode } = parseResult.data;
13655
13657
  const basePath = descriptorPath ? `m/${descriptorPath}` : DEFAULT_BASE_PATH;
13656
13658
  const sphere = await _Sphere.import({
13659
+ ...baseOptions,
13657
13660
  masterKey,
13658
13661
  chainCode,
13659
13662
  basePath,
13660
- derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac"),
13661
- storage: options.storage,
13662
- transport: options.transport,
13663
- oracle: options.oracle,
13664
- tokenStorage: options.tokenStorage,
13665
- nametag: options.nametag,
13666
- l1: options.l1
13663
+ derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
13667
13664
  });
13668
13665
  return { success: true, sphere };
13669
13666
  }
@@ -13686,16 +13683,11 @@ var Sphere = class _Sphere {
13686
13683
  const { masterKey, chainCode, descriptorPath, derivationMode } = parseResult.data;
13687
13684
  const basePath = descriptorPath ? `m/${descriptorPath}` : DEFAULT_BASE_PATH;
13688
13685
  const sphere = await _Sphere.import({
13686
+ ...baseOptions,
13689
13687
  masterKey,
13690
13688
  chainCode,
13691
13689
  basePath,
13692
- derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac"),
13693
- storage: options.storage,
13694
- transport: options.transport,
13695
- oracle: options.oracle,
13696
- tokenStorage: options.tokenStorage,
13697
- nametag: options.nametag,
13698
- l1: options.l1
13690
+ derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
13699
13691
  });
13700
13692
  return { success: true, sphere };
13701
13693
  }
@@ -13709,13 +13701,9 @@ var Sphere = class _Sphere {
13709
13701
  }
13710
13702
  if (parsed.type === "sphere-wallet") {
13711
13703
  const result = await _Sphere.importFromJSON({
13704
+ ...baseOptions,
13712
13705
  jsonContent: content,
13713
- password,
13714
- storage: options.storage,
13715
- transport: options.transport,
13716
- oracle: options.oracle,
13717
- tokenStorage: options.tokenStorage,
13718
- l1: options.l1
13706
+ password
13719
13707
  });
13720
13708
  if (result.success) {
13721
13709
  const sphere2 = _Sphere.getInstance();
@@ -13757,29 +13745,15 @@ var Sphere = class _Sphere {
13757
13745
  const isBIP32 = derivationMode === "bip32" || !!chainCode;
13758
13746
  const basePath = descriptorPath ? `m/${descriptorPath}` : isBIP32 ? "m/84'/1'/0'" : DEFAULT_BASE_PATH;
13759
13747
  if (mnemonic) {
13760
- const sphere2 = await _Sphere.import({
13761
- mnemonic,
13762
- basePath,
13763
- storage: options.storage,
13764
- transport: options.transport,
13765
- oracle: options.oracle,
13766
- tokenStorage: options.tokenStorage,
13767
- nametag: options.nametag,
13768
- l1: options.l1
13769
- });
13748
+ const sphere2 = await _Sphere.import({ ...baseOptions, mnemonic, basePath });
13770
13749
  return { success: true, sphere: sphere2, mnemonic };
13771
13750
  }
13772
13751
  const sphere = await _Sphere.import({
13752
+ ...baseOptions,
13773
13753
  masterKey,
13774
13754
  chainCode,
13775
13755
  basePath,
13776
- derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac"),
13777
- storage: options.storage,
13778
- transport: options.transport,
13779
- oracle: options.oracle,
13780
- tokenStorage: options.tokenStorage,
13781
- nametag: options.nametag,
13782
- l1: options.l1
13756
+ derivationMode: derivationMode || (chainCode ? "bip32" : "wif_hmac")
13783
13757
  });
13784
13758
  return { success: true, sphere };
13785
13759
  }