@xmtp/node-sdk 1.2.1 → 2.0.1

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.js CHANGED
@@ -126,6 +126,26 @@ function nsToDate(ns) {
126
126
  return new Date(ns / 1_000_000);
127
127
  }
128
128
 
129
+ /**
130
+ * Represents a decoded XMTP message
131
+ *
132
+ * This class transforms network messages into a structured format with
133
+ * content decoding.
134
+ *
135
+ * @class
136
+ * @property {any} content - The decoded content of the message
137
+ * @property {ContentTypeId} contentType - The content type of the message content
138
+ * @property {string} conversationId - Unique identifier for the conversation
139
+ * @property {MessageDeliveryStatus} deliveryStatus - Current delivery status of the message ("unpublished" | "published" | "failed")
140
+ * @property {string} [fallback] - Optional fallback text for the message
141
+ * @property {number} [compression] - Optional compression level applied to the message
142
+ * @property {string} id - Unique identifier for the message
143
+ * @property {MessageKind} kind - Type of message ("application" | "membership_change")
144
+ * @property {Record<string, string>} parameters - Additional parameters associated with the message
145
+ * @property {string} senderInboxId - Identifier for the sender's inbox
146
+ * @property {Date} sentAt - Timestamp when the message was sent
147
+ * @property {number} sentAtNs - Timestamp when the message was sent (in nanoseconds)
148
+ */
129
149
  class DecodedMessage {
130
150
  #client;
131
151
  content;
@@ -174,10 +194,15 @@ class DecodedMessage {
174
194
  this.parameters = message.content.parameters;
175
195
  this.fallback = message.content.fallback;
176
196
  this.compression = message.content.compression;
177
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
178
- this.content = this.contentType
179
- ? this.#client.decodeContent(message, this.contentType)
180
- : undefined;
197
+ this.content = undefined;
198
+ if (this.contentType) {
199
+ try {
200
+ this.content = this.#client.decodeContent(message, this.contentType);
201
+ }
202
+ catch {
203
+ this.content = undefined;
204
+ }
205
+ }
181
206
  }
182
207
  }
183
208
 
@@ -229,11 +254,33 @@ class MissingContentTypeError extends Error {
229
254
  super("Content type is required when sending content other than text");
230
255
  }
231
256
  }
257
+ class SignerUnavailableError extends Error {
258
+ constructor() {
259
+ super("Signer unavailable, use Client.create to create a client with a signer");
260
+ }
261
+ }
262
+ class ClientNotInitializedError extends Error {
263
+ constructor() {
264
+ super("Client not initialized, use Client.create or Client.build to create a client");
265
+ }
266
+ }
232
267
 
268
+ /**
269
+ * Represents a conversation
270
+ *
271
+ * This class is not intended to be initialized directly.
272
+ */
233
273
  class Conversation {
234
274
  #client;
235
275
  #conversation;
236
276
  #lastMessage;
277
+ /**
278
+ * Creates a new conversation instance
279
+ *
280
+ * @param client - The client instance managing the conversation
281
+ * @param conversation - The underlying conversation instance
282
+ * @param lastMessage - Optional last message in the conversation
283
+ */
237
284
  constructor(client, conversation, lastMessage) {
238
285
  this.#client = client;
239
286
  this.#conversation = conversation;
@@ -241,21 +288,41 @@ class Conversation {
241
288
  ? new DecodedMessage(client, lastMessage)
242
289
  : undefined;
243
290
  }
291
+ /**
292
+ * Gets the unique identifier for this conversation
293
+ */
244
294
  get id() {
245
295
  return this.#conversation.id();
246
296
  }
297
+ /**
298
+ * Gets whether this conversation is currently active
299
+ */
247
300
  get isActive() {
248
301
  return this.#conversation.isActive();
249
302
  }
303
+ /**
304
+ * Gets the inbox ID that added this client's inbox to the conversation
305
+ */
250
306
  get addedByInboxId() {
251
307
  return this.#conversation.addedByInboxId();
252
308
  }
309
+ /**
310
+ * Gets the timestamp when the conversation was created in nanoseconds
311
+ */
253
312
  get createdAtNs() {
254
313
  return this.#conversation.createdAtNs();
255
314
  }
315
+ /**
316
+ * Gets the date when the conversation was created
317
+ */
256
318
  get createdAt() {
257
319
  return nsToDate(this.createdAtNs);
258
320
  }
321
+ /**
322
+ * Gets the metadata for this conversation
323
+ *
324
+ * @returns Promise that resolves with the conversation metadata
325
+ */
259
326
  async metadata() {
260
327
  const metadata = await this.#conversation.groupMetadata();
261
328
  return {
@@ -263,12 +330,28 @@ class Conversation {
263
330
  conversationType: metadata.conversationType(),
264
331
  };
265
332
  }
333
+ /**
334
+ * Gets the members of this conversation
335
+ *
336
+ * @returns Promise that resolves with the conversation members
337
+ */
266
338
  async members() {
267
339
  return this.#conversation.listMembers();
268
340
  }
341
+ /**
342
+ * Synchronizes conversation data from the network
343
+ *
344
+ * @returns Promise that resolves when synchronization is complete
345
+ */
269
346
  async sync() {
270
347
  return this.#conversation.sync();
271
348
  }
349
+ /**
350
+ * Creates a stream for new messages in this conversation
351
+ *
352
+ * @param callback - Optional callback function for handling new stream values
353
+ * @returns Stream instance for new messages
354
+ */
272
355
  stream(callback) {
273
356
  const asyncStream = new AsyncStream();
274
357
  const stream = this.#conversation.stream((error, value) => {
@@ -288,9 +371,22 @@ class Conversation {
288
371
  asyncStream.onReturn = stream.end.bind(stream);
289
372
  return asyncStream;
290
373
  }
374
+ /**
375
+ * Publishes pending messages that were sent optimistically
376
+ *
377
+ * @returns Promise that resolves when publishing is complete
378
+ */
291
379
  async publishMessages() {
292
380
  return this.#conversation.publishMessages();
293
381
  }
382
+ /**
383
+ * Prepares a message to be published
384
+ *
385
+ * @param content - The content to send
386
+ * @param contentType - Optional content type of the message content
387
+ * @returns Promise that resolves with the message ID
388
+ * @throws {MissingContentTypeError} if content type is required but not provided
389
+ */
294
390
  sendOptimistic(content, contentType) {
295
391
  if (typeof content !== "string" && !contentType) {
296
392
  throw new MissingContentTypeError();
@@ -301,6 +397,14 @@ class Conversation {
301
397
  this.#client.encodeContent(content, contentType);
302
398
  return this.#conversation.sendOptimistic(encodedContent);
303
399
  }
400
+ /**
401
+ * Publishes a new message
402
+ *
403
+ * @param content - The content to send
404
+ * @param contentType - Optional content type of the message content
405
+ * @returns Promise that resolves with the message ID after it has been sent
406
+ * @throws {MissingContentTypeError} if content type is required but not provided
407
+ */
304
408
  async send(content, contentType) {
305
409
  if (typeof content !== "string" && !contentType) {
306
410
  throw new MissingContentTypeError();
@@ -311,80 +415,179 @@ class Conversation {
311
415
  this.#client.encodeContent(content, contentType);
312
416
  return this.#conversation.send(encodedContent);
313
417
  }
418
+ /**
419
+ * Lists messages in this conversation
420
+ *
421
+ * @param options - Optional filtering and pagination options
422
+ * @returns Promise that resolves with an array of decoded messages
423
+ */
314
424
  async messages(options) {
315
425
  const messages = await this.#conversation.findMessages(options);
316
- return (messages
317
- .map((message) => new DecodedMessage(this.#client, message))
318
- // filter out messages without content
319
- .filter((message) => message.content !== undefined));
426
+ return messages.map((message) => new DecodedMessage(this.#client, message));
320
427
  }
428
+ /**
429
+ * Gets the last message in this conversation
430
+ *
431
+ * @returns Promise that resolves with the last message or undefined if none exists
432
+ */
321
433
  async lastMessage() {
322
434
  return this.#lastMessage ?? (await this.messages({ limit: 1 }))[0];
323
435
  }
436
+ /**
437
+ * Gets the consent state for this conversation
438
+ */
324
439
  get consentState() {
325
440
  return this.#conversation.consentState();
326
441
  }
442
+ /**
443
+ * Updates the consent state for this conversation
444
+ *
445
+ * @param consentState - The new consent state to set
446
+ */
327
447
  updateConsentState(consentState) {
328
448
  this.#conversation.updateConsentState(consentState);
329
449
  }
450
+ /**
451
+ * Gets the message disappearing settings for this conversation
452
+ *
453
+ * @returns The current message disappearing settings or undefined if not set
454
+ */
330
455
  messageDisappearingSettings() {
331
456
  return this.#conversation.messageDisappearingSettings() ?? undefined;
332
457
  }
458
+ /**
459
+ * Updates message disappearing settings for this conversation
460
+ *
461
+ * @param fromNs - The timestamp from which messages should start disappearing
462
+ * @param inNs - The duration after which messages should disappear
463
+ * @returns Promise that resolves when the update is complete
464
+ */
333
465
  async updateMessageDisappearingSettings(fromNs, inNs) {
334
466
  return this.#conversation.updateMessageDisappearingSettings({
335
467
  fromNs,
336
468
  inNs,
337
469
  });
338
470
  }
471
+ /**
472
+ * Removes message disappearing settings from this conversation
473
+ *
474
+ * @returns Promise that resolves when the settings are removed
475
+ */
339
476
  async removeMessageDisappearingSettings() {
340
477
  return this.#conversation.removeMessageDisappearingSettings();
341
478
  }
479
+ /**
480
+ * Checks if message disappearing is enabled for this conversation
481
+ *
482
+ * @returns Whether message disappearing is enabled
483
+ */
342
484
  isMessageDisappearingEnabled() {
343
485
  return this.#conversation.isMessageDisappearingEnabled();
344
486
  }
345
487
  pausedForVersion() {
346
488
  return this.#conversation.pausedForVersion() ?? undefined;
347
489
  }
490
+ /**
491
+ * Retrieves HMAC keys for this conversation
492
+ *
493
+ * @returns The HMAC keys for this conversation
494
+ */
348
495
  getHmacKeys() {
349
496
  return this.#conversation.getHmacKeys();
350
497
  }
351
498
  }
352
499
 
500
+ /**
501
+ * Represents a direct message conversation between two inboxes
502
+ *
503
+ * This class is not intended to be initialized directly.
504
+ */
353
505
  class Dm extends Conversation {
354
506
  #conversation;
507
+ /**
508
+ * Creates a new direct message conversation instance
509
+ *
510
+ * @param client - The client instance managing this direct message conversation
511
+ * @param conversation - The underlying conversation instance
512
+ * @param lastMessage - Optional last message in the conversation
513
+ */
355
514
  constructor(client, conversation, lastMessage) {
356
515
  super(client, conversation, lastMessage);
357
516
  this.#conversation = conversation;
358
517
  }
518
+ /**
519
+ * Retrieves the inbox ID of the other participant in the DM
520
+ *
521
+ * @returns Promise that resolves with the peer's inbox ID
522
+ */
359
523
  get peerInboxId() {
360
524
  return this.#conversation.dmPeerInboxId();
361
525
  }
362
526
  }
363
527
 
528
+ /**
529
+ * Represents a group conversation between multiple inboxes
530
+ *
531
+ * This class is not intended to be initialized directly.
532
+ */
364
533
  class Group extends Conversation {
365
534
  #conversation;
535
+ /**
536
+ * Creates a new group conversation instance
537
+ *
538
+ * @param client - The client instance managing this group conversation
539
+ * @param conversation - The underlying conversation object
540
+ * @param lastMessage - Optional last message in the conversation
541
+ */
366
542
  constructor(client, conversation, lastMessage) {
367
543
  super(client, conversation, lastMessage);
368
544
  this.#conversation = conversation;
369
545
  }
546
+ /**
547
+ * The name of the group
548
+ */
370
549
  get name() {
371
550
  return this.#conversation.groupName();
372
551
  }
552
+ /**
553
+ * Updates the group's name
554
+ *
555
+ * @param name The new name for the group
556
+ */
373
557
  async updateName(name) {
374
558
  return this.#conversation.updateGroupName(name);
375
559
  }
560
+ /**
561
+ * The image URL of the group
562
+ */
376
563
  get imageUrl() {
377
564
  return this.#conversation.groupImageUrlSquare();
378
565
  }
566
+ /**
567
+ * Updates the group's image URL
568
+ *
569
+ * @param imageUrl The new image URL for the group
570
+ */
379
571
  async updateImageUrl(imageUrl) {
380
572
  return this.#conversation.updateGroupImageUrlSquare(imageUrl);
381
573
  }
574
+ /**
575
+ * The description of the group
576
+ */
382
577
  get description() {
383
578
  return this.#conversation.groupDescription();
384
579
  }
580
+ /**
581
+ * Updates the group's description
582
+ *
583
+ * @param description The new description for the group
584
+ */
385
585
  async updateDescription(description) {
386
586
  return this.#conversation.updateGroupDescription(description);
387
587
  }
588
+ /**
589
+ * The permissions of the group
590
+ */
388
591
  get permissions() {
389
592
  const permissions = this.#conversation.groupPermissions();
390
593
  return {
@@ -392,54 +595,136 @@ class Group extends Conversation {
392
595
  policySet: permissions.policySet(),
393
596
  };
394
597
  }
598
+ /**
599
+ * Updates a specific permission policy for the group
600
+ *
601
+ * @param permissionType The type of permission to update
602
+ * @param policy The new permission policy
603
+ * @param metadataField Optional metadata field for the permission
604
+ */
395
605
  async updatePermission(permissionType, policy, metadataField) {
396
606
  return this.#conversation.updatePermissionPolicy(permissionType, policy, metadataField);
397
607
  }
608
+ /**
609
+ * The list of admins of the group
610
+ */
398
611
  get admins() {
399
612
  return this.#conversation.adminList();
400
613
  }
614
+ /**
615
+ * The list of super admins of the group
616
+ */
401
617
  get superAdmins() {
402
618
  return this.#conversation.superAdminList();
403
619
  }
620
+ /**
621
+ * Checks if an inbox is an admin of the group
622
+ *
623
+ * @param inboxId The inbox ID to check
624
+ * @returns Boolean indicating if the inbox is an admin
625
+ */
404
626
  isAdmin(inboxId) {
405
627
  return this.#conversation.isAdmin(inboxId);
406
628
  }
629
+ /**
630
+ * Checks if an inbox is a super admin of the group
631
+ *
632
+ * @param inboxId The inbox ID to check
633
+ * @returns Boolean indicating if the inbox is a super admin
634
+ */
407
635
  isSuperAdmin(inboxId) {
408
636
  return this.#conversation.isSuperAdmin(inboxId);
409
637
  }
638
+ /**
639
+ * Adds members to the group using identifiers
640
+ *
641
+ * @param identifiers Array of member identifiers to add
642
+ */
410
643
  async addMembersByIdentifiers(identifiers) {
411
644
  return this.#conversation.addMembers(identifiers);
412
645
  }
646
+ /**
647
+ * Adds members to the group using inbox IDs
648
+ *
649
+ * @param inboxIds Array of inbox IDs to add
650
+ */
413
651
  async addMembers(inboxIds) {
414
652
  return this.#conversation.addMembersByInboxId(inboxIds);
415
653
  }
654
+ /**
655
+ * Removes members from the group using identifiers
656
+ *
657
+ * @param identifiers Array of member identifiers to remove
658
+ */
416
659
  async removeMembersByIdentifiers(identifiers) {
417
660
  return this.#conversation.removeMembers(identifiers);
418
661
  }
662
+ /**
663
+ * Removes members from the group using inbox IDs
664
+ *
665
+ * @param inboxIds Array of inbox IDs to remove
666
+ */
419
667
  async removeMembers(inboxIds) {
420
668
  return this.#conversation.removeMembersByInboxId(inboxIds);
421
669
  }
670
+ /**
671
+ * Promotes a group member to admin status
672
+ *
673
+ * @param inboxId The inbox ID of the member to promote
674
+ */
422
675
  async addAdmin(inboxId) {
423
676
  return this.#conversation.addAdmin(inboxId);
424
677
  }
678
+ /**
679
+ * Removes admin status from a group member
680
+ *
681
+ * @param inboxId The inbox ID of the admin to demote
682
+ */
425
683
  async removeAdmin(inboxId) {
426
684
  return this.#conversation.removeAdmin(inboxId);
427
685
  }
686
+ /**
687
+ * Promotes a group member to super admin status
688
+ *
689
+ * @param inboxId The inbox ID of the member to promote
690
+ */
428
691
  async addSuperAdmin(inboxId) {
429
692
  return this.#conversation.addSuperAdmin(inboxId);
430
693
  }
694
+ /**
695
+ * Removes super admin status from a group member
696
+ *
697
+ * @param inboxId The inbox ID of the super admin to demote
698
+ */
431
699
  async removeSuperAdmin(inboxId) {
432
700
  return this.#conversation.removeSuperAdmin(inboxId);
433
701
  }
434
702
  }
435
703
 
704
+ /**
705
+ * Manages conversations
706
+ *
707
+ * This class is not intended to be initialized directly.
708
+ */
436
709
  class Conversations {
437
710
  #client;
438
711
  #conversations;
712
+ /**
713
+ * Creates a new conversations instance
714
+ *
715
+ * @param client - The client instance managing the conversations
716
+ * @param conversations - The underlying conversations instance
717
+ */
439
718
  constructor(client, conversations) {
440
719
  this.#client = client;
441
720
  this.#conversations = conversations;
442
721
  }
722
+ /**
723
+ * Retrieves a conversation by its ID
724
+ *
725
+ * @param id - The conversation ID to look up
726
+ * @returns The conversation if found, undefined otherwise
727
+ */
443
728
  async getConversationById(id) {
444
729
  try {
445
730
  // findGroupById will throw if group is not found
@@ -453,6 +738,12 @@ class Conversations {
453
738
  return undefined;
454
739
  }
455
740
  }
741
+ /**
742
+ * Retrieves a DM by inbox ID
743
+ *
744
+ * @param inboxId - The inbox ID to look up
745
+ * @returns The DM if found, undefined otherwise
746
+ */
456
747
  getDmByInboxId(inboxId) {
457
748
  try {
458
749
  // findDmByTargetInboxId will throw if group is not found
@@ -463,6 +754,12 @@ class Conversations {
463
754
  return undefined;
464
755
  }
465
756
  }
757
+ /**
758
+ * Retrieves a message by its ID
759
+ *
760
+ * @param id - The message ID to look up
761
+ * @returns The decoded message if found, undefined otherwise
762
+ */
466
763
  getMessageById(id) {
467
764
  try {
468
765
  // findMessageById will throw if message is not found
@@ -473,26 +770,60 @@ class Conversations {
473
770
  return undefined;
474
771
  }
475
772
  }
773
+ /**
774
+ * Creates a new group conversation with the specified identifiers
775
+ *
776
+ * @param identifiers - Array of identifiers for group members
777
+ * @param options - Optional group creation options
778
+ * @returns The new group
779
+ */
476
780
  async newGroupWithIdentifiers(identifiers, options) {
477
781
  const group = await this.#conversations.createGroup(identifiers, options);
478
782
  const conversation = new Group(this.#client, group);
479
783
  return conversation;
480
784
  }
785
+ /**
786
+ * Creates a new group conversation with the specified inbox IDs
787
+ *
788
+ * @param inboxIds - Array of inbox IDs for group members
789
+ * @param options - Optional group creation options
790
+ * @returns The new group
791
+ */
481
792
  async newGroup(inboxIds, options) {
482
793
  const group = await this.#conversations.createGroupByInboxId(inboxIds, options);
483
794
  const conversation = new Group(this.#client, group);
484
795
  return conversation;
485
796
  }
797
+ /**
798
+ * Creates a new DM conversation with the specified identifier
799
+ *
800
+ * @param identifier - Identifier for the DM recipient
801
+ * @param options - Optional DM creation options
802
+ * @returns The new DM
803
+ */
486
804
  async newDmWithIdentifier(identifier, options) {
487
805
  const group = await this.#conversations.createDm(identifier, options);
488
806
  const conversation = new Dm(this.#client, group);
489
807
  return conversation;
490
808
  }
809
+ /**
810
+ * Creates a new DM conversation with the specified inbox ID
811
+ *
812
+ * @param inboxId - Inbox ID for the DM recipient
813
+ * @param options - Optional DM creation options
814
+ * @returns The new DM
815
+ */
491
816
  async newDm(inboxId, options) {
492
817
  const group = await this.#conversations.createDmByInboxId(inboxId, options);
493
818
  const conversation = new Dm(this.#client, group);
494
819
  return conversation;
495
820
  }
821
+ /**
822
+ * Lists all conversations with optional filtering
823
+ *
824
+ * @param options - Optional filtering and pagination options
825
+ * @returns Array of conversations
826
+ */
496
827
  async list(options) {
497
828
  const groups = this.#conversations.list(options);
498
829
  return Promise.all(groups.map(async (item) => {
@@ -502,6 +833,12 @@ class Conversations {
502
833
  : new Group(this.#client, item.conversation, item.lastMessage);
503
834
  }));
504
835
  }
836
+ /**
837
+ * Lists all groups with optional filtering
838
+ *
839
+ * @param options - Optional filtering and pagination options
840
+ * @returns Array of groups
841
+ */
505
842
  listGroups(options) {
506
843
  const groups = this.#conversations.listGroups(options);
507
844
  return groups.map((item) => {
@@ -509,6 +846,12 @@ class Conversations {
509
846
  return conversation;
510
847
  });
511
848
  }
849
+ /**
850
+ * Lists all DMs with optional filtering
851
+ *
852
+ * @param options - Optional filtering and pagination options
853
+ * @returns Array of DMs
854
+ */
512
855
  listDms(options) {
513
856
  const groups = this.#conversations.listDms(options);
514
857
  return groups.map((item) => {
@@ -516,12 +859,30 @@ class Conversations {
516
859
  return conversation;
517
860
  });
518
861
  }
862
+ /**
863
+ * Synchronizes conversations for the current client from the network
864
+ *
865
+ * @returns Promise that resolves when sync is complete
866
+ */
519
867
  async sync() {
520
868
  return this.#conversations.sync();
521
869
  }
870
+ /**
871
+ * Synchronizes all conversations and messages from the network with optional
872
+ * consent state filtering
873
+ *
874
+ * @param consentStates - Optional array of consent states to filter by
875
+ * @returns Promise that resolves when sync is complete
876
+ */
522
877
  async syncAll(consentStates) {
523
878
  return this.#conversations.syncAllConversations(consentStates);
524
879
  }
880
+ /**
881
+ * Creates a stream for new conversations
882
+ *
883
+ * @param callback - Optional callback function for handling new stream value
884
+ * @returns Stream instance for new conversations
885
+ */
525
886
  stream(callback) {
526
887
  const asyncStream = new AsyncStream();
527
888
  const stream = this.#conversations.stream((err, value) => {
@@ -547,6 +908,12 @@ class Conversations {
547
908
  asyncStream.onReturn = stream.end.bind(stream);
548
909
  return asyncStream;
549
910
  }
911
+ /**
912
+ * Creates a stream for new group conversations
913
+ *
914
+ * @param callback - Optional callback function for handling new stream value
915
+ * @returns Stream instance for new group conversations
916
+ */
550
917
  streamGroups(callback) {
551
918
  const asyncStream = new AsyncStream();
552
919
  const stream = this.#conversations.streamGroups((error, value) => {
@@ -566,6 +933,12 @@ class Conversations {
566
933
  asyncStream.onReturn = stream.end.bind(stream);
567
934
  return asyncStream;
568
935
  }
936
+ /**
937
+ * Creates a stream for new DM conversations
938
+ *
939
+ * @param callback - Optional callback function for handling new stream value
940
+ * @returns Stream instance for new DM conversations
941
+ */
569
942
  streamDms(callback) {
570
943
  const asyncStream = new AsyncStream();
571
944
  const stream = this.#conversations.streamDms((error, value) => {
@@ -585,6 +958,12 @@ class Conversations {
585
958
  asyncStream.onReturn = stream.end.bind(stream);
586
959
  return asyncStream;
587
960
  }
961
+ /**
962
+ * Creates a stream for all new messages
963
+ *
964
+ * @param callback - Optional callback function for handling new stream value
965
+ * @returns Stream instance for new messages
966
+ */
588
967
  async streamAllMessages(callback) {
589
968
  // sync conversations first
590
969
  await this.sync();
@@ -606,6 +985,12 @@ class Conversations {
606
985
  asyncStream.onReturn = stream.end.bind(stream);
607
986
  return asyncStream;
608
987
  }
988
+ /**
989
+ * Creates a stream for all new group messages
990
+ *
991
+ * @param callback - Optional callback function for handling new stream value
992
+ * @returns Stream instance for new group messages
993
+ */
609
994
  async streamAllGroupMessages(callback) {
610
995
  // sync conversations first
611
996
  await this.sync();
@@ -627,6 +1012,12 @@ class Conversations {
627
1012
  asyncStream.onReturn = stream.end.bind(stream);
628
1013
  return asyncStream;
629
1014
  }
1015
+ /**
1016
+ * Creates a stream for all new DM messages
1017
+ *
1018
+ * @param callback - Optional callback function for handling new stream value
1019
+ * @returns Stream instance for new DM messages
1020
+ */
630
1021
  async streamAllDmMessages(callback) {
631
1022
  // sync conversations first
632
1023
  await this.sync();
@@ -648,33 +1039,87 @@ class Conversations {
648
1039
  asyncStream.onReturn = stream.end.bind(stream);
649
1040
  return asyncStream;
650
1041
  }
1042
+ /**
1043
+ * Retrieves HMAC keys for all conversations
1044
+ *
1045
+ * @returns The HMAC keys for all conversations
1046
+ */
651
1047
  hmacKeys() {
652
1048
  return this.#conversations.getHmacKeys();
653
1049
  }
654
1050
  }
655
1051
 
1052
+ /**
1053
+ * Manages user preferences and consent states
1054
+ *
1055
+ * This class is not intended to be initialized directly.
1056
+ */
656
1057
  class Preferences {
657
1058
  #client;
658
1059
  #conversations;
1060
+ /**
1061
+ * Creates a new preferences instance
1062
+ *
1063
+ * @param client - The client instance managing preferences
1064
+ * @param conversations - The underlying conversations instance
1065
+ */
659
1066
  constructor(client, conversations) {
660
1067
  this.#client = client;
661
1068
  this.#conversations = conversations;
662
1069
  }
1070
+ /**
1071
+ * Retrieves the current inbox state
1072
+ *
1073
+ * @param refreshFromNetwork - Optional flag to force refresh from network
1074
+ * @returns Promise that resolves with the inbox state
1075
+ */
663
1076
  async inboxState(refreshFromNetwork = false) {
664
1077
  return this.#client.inboxState(refreshFromNetwork);
665
1078
  }
1079
+ /**
1080
+ * Gets the latest inbox state for a specific inbox
1081
+ *
1082
+ * @param inboxId - The inbox ID to get state for
1083
+ * @returns Promise that resolves with the latest inbox state
1084
+ */
666
1085
  async getLatestInboxState(inboxId) {
667
1086
  return this.#client.getLatestInboxState(inboxId);
668
1087
  }
1088
+ /**
1089
+ * Retrieves inbox state for specific inbox IDs
1090
+ *
1091
+ * @param inboxIds - Array of inbox IDs to get state for
1092
+ * @param refreshFromNetwork - Optional flag to force refresh from network
1093
+ * @returns Promise that resolves with the inbox state for the inbox IDs
1094
+ */
669
1095
  async inboxStateFromInboxIds(inboxIds, refreshFromNetwork) {
670
1096
  return this.#client.addressesFromInboxId(refreshFromNetwork ?? false, inboxIds);
671
1097
  }
1098
+ /**
1099
+ * Updates consent states for multiple records
1100
+ *
1101
+ * @param consentStates - Array of consent records to update
1102
+ * @returns Promise that resolves when consent states are updated
1103
+ */
672
1104
  async setConsentStates(consentStates) {
673
1105
  return this.#client.setConsentStates(consentStates);
674
1106
  }
1107
+ /**
1108
+ * Retrieves consent state for a specific entity
1109
+ *
1110
+ * @param entityType - Type of entity to get consent for
1111
+ * @param entity - Entity identifier
1112
+ * @returns Promise that resolves with the consent state
1113
+ */
675
1114
  async getConsentState(entityType, entity) {
676
1115
  return this.#client.getConsentState(entityType, entity);
677
1116
  }
1117
+ /**
1118
+ * Creates a stream of consent state updates
1119
+ *
1120
+ * @param callback - Optional callback function for handling stream updates
1121
+ * @returns Stream instance for consent updates
1122
+ */
678
1123
  streamConsent(callback) {
679
1124
  const asyncStream = new AsyncStream();
680
1125
  const stream = this.#conversations.streamConsent((err, value) => {
@@ -689,6 +1134,12 @@ class Preferences {
689
1134
  asyncStream.onReturn = stream.end.bind(stream);
690
1135
  return asyncStream;
691
1136
  }
1137
+ /**
1138
+ * Creates a stream of user preference updates
1139
+ *
1140
+ * @param callback - Optional callback function for handling stream updates
1141
+ * @returns Stream instance for preference updates
1142
+ */
692
1143
  streamPreferences(callback) {
693
1144
  const asyncStream = new AsyncStream();
694
1145
  const stream = this.#conversations.streamPreferences((err, value) => {
@@ -715,81 +1166,202 @@ const getInboxIdForIdentifier = async (identifier, env = "dev") => {
715
1166
  return getInboxIdForIdentifier$1(host, isSecure, identifier);
716
1167
  };
717
1168
 
718
- const createClient = async (identifier, encryptionKey, options) => {
1169
+ const createClient = async (identifier, options) => {
719
1170
  const env = options?.env || "dev";
720
1171
  const host = options?.apiUrl || ApiUrls[env];
721
1172
  const isSecure = host.startsWith("https");
722
1173
  const inboxId = (await getInboxIdForIdentifier(identifier, env)) ||
723
1174
  generateInboxId(identifier);
724
- const dbPath = options?.dbPath || join(process.cwd(), `xmtp-${env}-${inboxId}.db3`);
1175
+ const dbPath = options?.dbPath === undefined
1176
+ ? join(process.cwd(), `xmtp-${env}-${inboxId}.db3`)
1177
+ : options.dbPath;
725
1178
  const logOptions = {
726
1179
  structured: options?.structuredLogging ?? false,
727
1180
  level: options?.loggingLevel ?? "off" /* LogLevel.off */,
728
1181
  };
729
1182
  const historySyncUrl = options?.historySyncUrl || HistorySyncUrls[env];
730
- return createClient$1(host, isSecure, dbPath, inboxId, identifier, encryptionKey, historySyncUrl, logOptions);
1183
+ return createClient$1(host, isSecure, dbPath, inboxId, identifier, options?.dbEncryptionKey, historySyncUrl, logOptions);
731
1184
  };
732
1185
 
733
1186
  const version = `${bindingsVersion.branch}@${bindingsVersion.version} (${bindingsVersion.date})`;
734
1187
 
1188
+ /**
1189
+ * Client for interacting with the XMTP network
1190
+ */
735
1191
  class Client {
736
- #innerClient;
1192
+ #client;
737
1193
  #conversations;
738
1194
  #preferences;
739
1195
  #signer;
740
1196
  #codecs;
741
- constructor(client, signer, codecs) {
742
- this.#innerClient = client;
743
- const conversations = client.conversations();
744
- this.#conversations = new Conversations(this, conversations);
745
- this.#preferences = new Preferences(client, conversations);
746
- this.#signer = signer;
747
- this.#codecs = new Map(codecs.map((codec) => [codec.contentType.toString(), codec]));
748
- }
749
- static async create(signer, encryptionKey, options) {
750
- const identifier = await signer.getIdentifier();
751
- const client = await createClient(identifier, encryptionKey, options);
752
- const clientInstance = new Client(client, signer, [
1197
+ #identifier;
1198
+ #options;
1199
+ /**
1200
+ * Creates a new XMTP client instance
1201
+ *
1202
+ * This class is not intended to be initialized directly.
1203
+ * Use `Client.create` or `Client.build` instead.
1204
+ *
1205
+ * @param options - Optional configuration for the client
1206
+ */
1207
+ constructor(options) {
1208
+ this.#options = options;
1209
+ const codecs = [
753
1210
  new GroupUpdatedCodec(),
754
1211
  new TextCodec(),
755
1212
  ...(options?.codecs ?? []),
756
- ]);
1213
+ ];
1214
+ this.#codecs = new Map(codecs.map((codec) => [codec.contentType.toString(), codec]));
1215
+ }
1216
+ /**
1217
+ * Initializes the client with the provided identifier
1218
+ *
1219
+ * This is not meant to be called directly.
1220
+ * Use `Client.create` or `Client.build` instead.
1221
+ *
1222
+ * @param identifier - The identifier to initialize the client with
1223
+ */
1224
+ async init(identifier) {
1225
+ if (this.#client) {
1226
+ return;
1227
+ }
1228
+ this.#identifier = identifier;
1229
+ this.#client = await createClient(identifier, this.#options);
1230
+ const conversations = this.#client.conversations();
1231
+ this.#conversations = new Conversations(this, conversations);
1232
+ this.#preferences = new Preferences(this.#client, conversations);
1233
+ }
1234
+ /**
1235
+ * Creates a new client instance with a signer
1236
+ *
1237
+ * @param signer - The signer to use for authentication
1238
+ * @param options - Optional configuration for the client
1239
+ * @returns A new client instance
1240
+ */
1241
+ static async create(signer, options) {
1242
+ const identifier = await signer.getIdentifier();
1243
+ const client = new Client(options);
1244
+ client.#signer = signer;
1245
+ await client.init(identifier);
757
1246
  if (!options?.disableAutoRegister) {
758
- await clientInstance.register();
1247
+ await client.register();
759
1248
  }
760
- return clientInstance;
1249
+ return client;
761
1250
  }
762
- get identifier() {
763
- return this.#innerClient.accountIdentifier;
1251
+ /**
1252
+ * Creates a new client instance with an identifier
1253
+ *
1254
+ * Clients created with this method must already be registered.
1255
+ * Any methods called that require a signer will throw an error.
1256
+ *
1257
+ * @param identifier - The identifier to use
1258
+ * @param options - Optional configuration for the client
1259
+ * @returns A new client instance
1260
+ */
1261
+ static async build(identifier, options) {
1262
+ const client = new Client({
1263
+ ...options,
1264
+ disableAutoRegister: true,
1265
+ });
1266
+ await client.init(identifier);
1267
+ return client;
1268
+ }
1269
+ /**
1270
+ * Gets the client options
1271
+ */
1272
+ get options() {
1273
+ return this.#options;
1274
+ }
1275
+ /**
1276
+ * Gets the signer associated with this client
1277
+ */
1278
+ get signer() {
1279
+ return this.#signer;
1280
+ }
1281
+ /**
1282
+ * Gets the account identifier for this client
1283
+ */
1284
+ get accountIdentifier() {
1285
+ return this.#identifier;
764
1286
  }
1287
+ /**
1288
+ * Gets the inbox ID associated with this client
1289
+ */
765
1290
  get inboxId() {
766
- return this.#innerClient.inboxId();
1291
+ if (!this.#client) {
1292
+ throw new ClientNotInitializedError();
1293
+ }
1294
+ return this.#client.inboxId();
767
1295
  }
1296
+ /**
1297
+ * Gets the installation ID for this client
1298
+ */
768
1299
  get installationId() {
769
- return this.#innerClient.installationId();
1300
+ if (!this.#client) {
1301
+ throw new ClientNotInitializedError();
1302
+ }
1303
+ return this.#client.installationId();
770
1304
  }
1305
+ /**
1306
+ * Gets the installation ID bytes for this client
1307
+ */
771
1308
  get installationIdBytes() {
772
- return this.#innerClient.installationIdBytes();
1309
+ if (!this.#client) {
1310
+ throw new ClientNotInitializedError();
1311
+ }
1312
+ return this.#client.installationIdBytes();
773
1313
  }
1314
+ /**
1315
+ * Gets whether the client is registered with the XMTP network
1316
+ *
1317
+ * @throws {ClientNotInitializedError} if the client is not initialized
1318
+ */
774
1319
  get isRegistered() {
775
- return this.#innerClient.isRegistered();
1320
+ if (!this.#client) {
1321
+ throw new ClientNotInitializedError();
1322
+ }
1323
+ return this.#client.isRegistered();
776
1324
  }
1325
+ /**
1326
+ * Gets the conversations manager for this client
1327
+ *
1328
+ * @throws {ClientNotInitializedError} if the client is not initialized
1329
+ */
777
1330
  get conversations() {
1331
+ if (!this.#conversations) {
1332
+ throw new ClientNotInitializedError();
1333
+ }
778
1334
  return this.#conversations;
779
1335
  }
1336
+ /**
1337
+ * Gets the preferences manager for this client
1338
+ *
1339
+ * @throws {ClientNotInitializedError} if the client is not initialized
1340
+ */
780
1341
  get preferences() {
1342
+ if (!this.#preferences) {
1343
+ throw new ClientNotInitializedError();
1344
+ }
781
1345
  return this.#preferences;
782
1346
  }
783
1347
  /**
1348
+ * Creates signature text for creating a new inbox
1349
+ *
784
1350
  * WARNING: This function should be used with caution. It is only provided
785
1351
  * for use in special cases where the provided workflows do not meet the
786
1352
  * requirements of an application.
787
1353
  *
788
- * It is highly recommended to use the `register` function instead.
1354
+ * It is highly recommended to use the `register` method instead.
1355
+ *
1356
+ * @returns The signature text
1357
+ * @throws {ClientNotInitializedError} if the client is not initialized
789
1358
  */
790
1359
  async unsafe_createInboxSignatureText() {
1360
+ if (!this.#client) {
1361
+ throw new ClientNotInitializedError();
1362
+ }
791
1363
  try {
792
- const signatureText = await this.#innerClient.createInboxSignatureText();
1364
+ const signatureText = await this.#client.createInboxSignatureText();
793
1365
  return signatureText;
794
1366
  }
795
1367
  catch {
@@ -797,21 +1369,31 @@ class Client {
797
1369
  }
798
1370
  }
799
1371
  /**
1372
+ * Creates signature text for adding a new account to the client's inbox
1373
+ *
800
1374
  * WARNING: This function should be used with caution. It is only provided
801
1375
  * for use in special cases where the provided workflows do not meet the
802
1376
  * requirements of an application.
803
1377
  *
804
- * It is highly recommended to use the `unsafe_addAccount` function instead.
1378
+ * It is highly recommended to use the `unsafe_addAccount` method instead.
805
1379
  *
806
1380
  * The `allowInboxReassign` parameter must be true or this function will
807
1381
  * throw an error.
1382
+ *
1383
+ * @param newAccountIdentifier - The identifier of the new account
1384
+ * @param allowInboxReassign - Whether to allow inbox reassignment
1385
+ * @returns The signature text
1386
+ * @throws {ClientNotInitializedError} if the client is not initialized
808
1387
  */
809
1388
  async unsafe_addAccountSignatureText(newAccountIdentifier, allowInboxReassign = false) {
1389
+ if (!this.#client) {
1390
+ throw new ClientNotInitializedError();
1391
+ }
810
1392
  if (!allowInboxReassign) {
811
1393
  throw new InboxReassignError();
812
1394
  }
813
1395
  try {
814
- const signatureText = await this.#innerClient.addIdentifierSignatureText(newAccountIdentifier);
1396
+ const signatureText = await this.#client.addIdentifierSignatureText(newAccountIdentifier);
815
1397
  return signatureText;
816
1398
  }
817
1399
  catch {
@@ -819,15 +1401,24 @@ class Client {
819
1401
  }
820
1402
  }
821
1403
  /**
1404
+ * Creates signature text for removing an account from the client's inbox
1405
+ *
822
1406
  * WARNING: This function should be used with caution. It is only provided
823
1407
  * for use in special cases where the provided workflows do not meet the
824
1408
  * requirements of an application.
825
1409
  *
826
- * It is highly recommended to use the `removeAccount` function instead.
1410
+ * It is highly recommended to use the `removeAccount` method instead.
1411
+ *
1412
+ * @param identifier - The identifier of the account to remove
1413
+ * @returns The signature text
1414
+ * @throws {ClientNotInitializedError} if the client is not initialized
827
1415
  */
828
1416
  async unsafe_removeAccountSignatureText(identifier) {
1417
+ if (!this.#client) {
1418
+ throw new ClientNotInitializedError();
1419
+ }
829
1420
  try {
830
- const signatureText = await this.#innerClient.revokeIdentifierSignatureText(identifier);
1421
+ const signatureText = await this.#client.revokeIdentifierSignatureText(identifier);
831
1422
  return signatureText;
832
1423
  }
833
1424
  catch {
@@ -835,16 +1426,24 @@ class Client {
835
1426
  }
836
1427
  }
837
1428
  /**
1429
+ * Creates signature text for revoking all other installations of the
1430
+ * client's inbox
1431
+ *
838
1432
  * WARNING: This function should be used with caution. It is only provided
839
1433
  * for use in special cases where the provided workflows do not meet the
840
1434
  * requirements of an application.
841
1435
  *
842
- * It is highly recommended to use the `revokeAllOtherInstallations` function
843
- * instead.
1436
+ * It is highly recommended to use the `revokeAllOtherInstallations` method instead.
1437
+ *
1438
+ * @returns The signature text
1439
+ * @throws {ClientNotInitializedError} if the client is not initialized
844
1440
  */
845
1441
  async unsafe_revokeAllOtherInstallationsSignatureText() {
1442
+ if (!this.#client) {
1443
+ throw new ClientNotInitializedError();
1444
+ }
846
1445
  try {
847
- const signatureText = await this.#innerClient.revokeAllOtherInstallationsSignatureText();
1446
+ const signatureText = await this.#client.revokeAllOtherInstallationsSignatureText();
848
1447
  return signatureText;
849
1448
  }
850
1449
  catch {
@@ -852,15 +1451,25 @@ class Client {
852
1451
  }
853
1452
  }
854
1453
  /**
1454
+ * Creates signature text for revoking specific installations of the
1455
+ * client's inbox
1456
+ *
855
1457
  * WARNING: This function should be used with caution. It is only provided
856
1458
  * for use in special cases where the provided workflows do not meet the
857
1459
  * requirements of an application.
858
1460
  *
859
- * It is highly recommended to use the `revokeInstallations` function instead.
1461
+ * It is highly recommended to use the `revokeInstallations` method instead.
1462
+ *
1463
+ * @param installationIds - The installation IDs to revoke
1464
+ * @returns The signature text
1465
+ * @throws {ClientNotInitializedError} if the client is not initialized
860
1466
  */
861
1467
  async unsafe_revokeInstallationsSignatureText(installationIds) {
1468
+ if (!this.#client) {
1469
+ throw new ClientNotInitializedError();
1470
+ }
862
1471
  try {
863
- const signatureText = await this.#innerClient.revokeInstallationsSignatureText(installationIds);
1472
+ const signatureText = await this.#client.revokeInstallationsSignatureText(installationIds);
864
1473
  return signatureText;
865
1474
  }
866
1475
  catch {
@@ -868,15 +1477,25 @@ class Client {
868
1477
  }
869
1478
  }
870
1479
  /**
1480
+ * Creates signature text for changing the recovery identifier for this
1481
+ * client's inbox
1482
+ *
871
1483
  * WARNING: This function should be used with caution. It is only provided
872
1484
  * for use in special cases where the provided workflows do not meet the
873
1485
  * requirements of an application.
874
1486
  *
875
- * It is highly recommended to use the `changeRecoveryIdentifer` function instead.
1487
+ * It is highly recommended to use the `changeRecoveryIdentifier` method instead.
1488
+ *
1489
+ * @param identifier - The new recovery identifier
1490
+ * @returns The signature text
1491
+ * @throws {ClientNotInitializedError} if the client is not initialized
876
1492
  */
877
1493
  async unsafe_changeRecoveryIdentifierSignatureText(identifier) {
1494
+ if (!this.#client) {
1495
+ throw new ClientNotInitializedError();
1496
+ }
878
1497
  try {
879
- const signatureText = await this.#innerClient.changeRecoveryIdentifierSignatureText(identifier);
1498
+ const signatureText = await this.#client.changeRecoveryIdentifierSignatureText(identifier);
880
1499
  return signatureText;
881
1500
  }
882
1501
  catch {
@@ -884,54 +1503,99 @@ class Client {
884
1503
  }
885
1504
  }
886
1505
  /**
1506
+ * Adds a signature for a specific request type
1507
+ *
887
1508
  * WARNING: This function should be used with caution. It is only provided
888
1509
  * for use in special cases where the provided workflows do not meet the
889
1510
  * requirements of an application.
890
1511
  *
891
1512
  * It is highly recommended to use the `register`, `unsafe_addAccount`,
892
1513
  * `removeAccount`, `revokeAllOtherInstallations`, or `revokeInstallations`
893
- * functions instead.
1514
+ * methods instead.
1515
+ *
1516
+ * @param signatureType - The type of signature request
1517
+ * @param signatureText - The text to sign
1518
+ * @param signer - The signer to use
1519
+ * @throws {ClientNotInitializedError} if the client is not initialized
894
1520
  */
895
1521
  async unsafe_addSignature(signatureType, signatureText, signer) {
1522
+ if (!this.#client) {
1523
+ throw new ClientNotInitializedError();
1524
+ }
896
1525
  switch (signer.type) {
897
1526
  case "SCW":
898
- await this.#innerClient.addScwSignature(signatureType, await signer.signMessage(signatureText), signer.getChainId(), signer.getBlockNumber?.());
1527
+ await this.#client.addScwSignature(signatureType, await signer.signMessage(signatureText), signer.getChainId(), signer.getBlockNumber?.());
899
1528
  break;
900
1529
  case "EOA":
901
- await this.#innerClient.addEcdsaSignature(signatureType, await signer.signMessage(signatureText));
1530
+ await this.#client.addEcdsaSignature(signatureType, await signer.signMessage(signatureText));
902
1531
  break;
903
1532
  }
904
1533
  }
905
1534
  /**
1535
+ * Applies all pending signatures
1536
+ *
906
1537
  * WARNING: This function should be used with caution. It is only provided
907
1538
  * for use in special cases where the provided workflows do not meet the
908
1539
  * requirements of an application.
909
1540
  *
910
1541
  * It is highly recommended to use the `register`, `unsafe_addAccount`,
911
1542
  * `removeAccount`, `revokeAllOtherInstallations`, or `revokeInstallations`
912
- * functions instead.
1543
+ * methods instead.
1544
+ *
1545
+ * @throws {ClientNotInitializedError} if the client is not initialized
913
1546
  */
914
1547
  async unsafe_applySignatures() {
915
- return this.#innerClient.applySignatureRequests();
1548
+ if (!this.#client) {
1549
+ throw new ClientNotInitializedError();
1550
+ }
1551
+ return this.#client.applySignatureRequests();
916
1552
  }
1553
+ /**
1554
+ * Registers the client with the XMTP network
1555
+ *
1556
+ * Requires a signer, use `Client.create` to create a client with a signer.
1557
+ *
1558
+ * @throws {ClientNotInitializedError} if the client is not initialized
1559
+ * @throws {SignerUnavailableError} if no signer is available
1560
+ */
917
1561
  async register() {
1562
+ if (!this.#client) {
1563
+ throw new ClientNotInitializedError();
1564
+ }
1565
+ if (!this.#signer) {
1566
+ throw new SignerUnavailableError();
1567
+ }
918
1568
  const signatureText = await this.unsafe_createInboxSignatureText();
919
1569
  // if the signature text is not available, the client is already registered
920
1570
  if (!signatureText) {
921
1571
  return;
922
1572
  }
923
1573
  await this.unsafe_addSignature(1 /* SignatureRequestType.CreateInbox */, signatureText, this.#signer);
924
- return this.#innerClient.registerIdentity();
1574
+ return this.#client.registerIdentity();
925
1575
  }
926
1576
  /**
1577
+ * Adds a new account to the client inbox
1578
+ *
927
1579
  * WARNING: This function should be used with caution. Adding a wallet already
928
- * associated with an inboxId will cause the wallet to lose access to
1580
+ * associated with an inbox ID will cause the wallet to lose access to
929
1581
  * that inbox.
930
1582
  *
931
1583
  * The `allowInboxReassign` parameter must be true to reassign an inbox
932
1584
  * already associated with a different account.
1585
+ *
1586
+ * Requires a signer, use `Client.create` to create a client with a signer.
1587
+ *
1588
+ * @param newAccountSigner - The signer for the new account
1589
+ * @param allowInboxReassign - Whether to allow inbox reassignment
1590
+ * @throws {ClientNotInitializedError} if the client is not initialized
1591
+ * @throws {AccountAlreadyAssociatedError} if the account is already associated with an inbox ID
1592
+ * @throws {GenerateSignatureError} if the signature cannot be generated
1593
+ * @throws {SignerUnavailableError} if no signer is available
933
1594
  */
934
1595
  async unsafe_addAccount(newAccountSigner, allowInboxReassign = false) {
1596
+ if (!this.#client) {
1597
+ throw new ClientNotInitializedError();
1598
+ }
935
1599
  // check for existing inbox id
936
1600
  const identifier = await newAccountSigner.getIdentifier();
937
1601
  const existingInboxId = await this.getInboxIdByIdentifier(identifier);
@@ -945,7 +1609,23 @@ class Client {
945
1609
  await this.unsafe_addSignature(0 /* SignatureRequestType.AddWallet */, signatureText, newAccountSigner);
946
1610
  await this.unsafe_applySignatures();
947
1611
  }
1612
+ /**
1613
+ * Removes an account from the client's inbox
1614
+ *
1615
+ * Requires a signer, use `Client.create` to create a client with a signer.
1616
+ *
1617
+ * @param identifier - The identifier of the account to remove
1618
+ * @throws {ClientNotInitializedError} if the client is not initialized
1619
+ * @throws {GenerateSignatureError} if the signature cannot be generated
1620
+ * @throws {SignerUnavailableError} if no signer is available
1621
+ */
948
1622
  async removeAccount(identifier) {
1623
+ if (!this.#client) {
1624
+ throw new ClientNotInitializedError();
1625
+ }
1626
+ if (!this.#signer) {
1627
+ throw new SignerUnavailableError();
1628
+ }
949
1629
  const signatureText = await this.unsafe_removeAccountSignatureText(identifier);
950
1630
  if (!signatureText) {
951
1631
  throw new GenerateSignatureError(2 /* SignatureRequestType.RevokeWallet */);
@@ -953,7 +1633,22 @@ class Client {
953
1633
  await this.unsafe_addSignature(2 /* SignatureRequestType.RevokeWallet */, signatureText, this.#signer);
954
1634
  await this.unsafe_applySignatures();
955
1635
  }
1636
+ /**
1637
+ * Revokes all other installations of the client's inbox
1638
+ *
1639
+ * Requires a signer, use `Client.create` to create a client with a signer.
1640
+ *
1641
+ * @throws {ClientNotInitializedError} if the client is not initialized
1642
+ * @throws {GenerateSignatureError} if the signature cannot be generated
1643
+ * @throws {SignerUnavailableError} if no signer is available
1644
+ */
956
1645
  async revokeAllOtherInstallations() {
1646
+ if (!this.#client) {
1647
+ throw new ClientNotInitializedError();
1648
+ }
1649
+ if (!this.#signer) {
1650
+ throw new SignerUnavailableError();
1651
+ }
957
1652
  const signatureText = await this.unsafe_revokeAllOtherInstallationsSignatureText();
958
1653
  if (!signatureText) {
959
1654
  throw new GenerateSignatureError(3 /* SignatureRequestType.RevokeInstallations */);
@@ -961,7 +1656,23 @@ class Client {
961
1656
  await this.unsafe_addSignature(3 /* SignatureRequestType.RevokeInstallations */, signatureText, this.#signer);
962
1657
  await this.unsafe_applySignatures();
963
1658
  }
1659
+ /**
1660
+ * Revokes specific installations of the client's inbox
1661
+ *
1662
+ * Requires a signer, use `Client.create` to create a client with a signer.
1663
+ *
1664
+ * @param installationIds - The installation IDs to revoke
1665
+ * @throws {ClientNotInitializedError} if the client is not initialized
1666
+ * @throws {SignerUnavailableError} if no signer is available
1667
+ * @throws {GenerateSignatureError} if the signature cannot be generated
1668
+ */
964
1669
  async revokeInstallations(installationIds) {
1670
+ if (!this.#client) {
1671
+ throw new ClientNotInitializedError();
1672
+ }
1673
+ if (!this.#signer) {
1674
+ throw new SignerUnavailableError();
1675
+ }
965
1676
  const signatureText = await this.unsafe_revokeInstallationsSignatureText(installationIds);
966
1677
  if (!signatureText) {
967
1678
  throw new GenerateSignatureError(3 /* SignatureRequestType.RevokeInstallations */);
@@ -969,7 +1680,23 @@ class Client {
969
1680
  await this.unsafe_addSignature(3 /* SignatureRequestType.RevokeInstallations */, signatureText, this.#signer);
970
1681
  await this.unsafe_applySignatures();
971
1682
  }
1683
+ /**
1684
+ * Changes the recovery identifier for the client's inbox
1685
+ *
1686
+ * Requires a signer, use `Client.create` to create a client with a signer.
1687
+ *
1688
+ * @param identifier - The new recovery identifier
1689
+ * @throws {ClientNotInitializedError} if the client is not initialized
1690
+ * @throws {SignerUnavailableError} if no signer is available
1691
+ * @throws {GenerateSignatureError} if the signature cannot be generated
1692
+ */
972
1693
  async changeRecoveryIdentifier(identifier) {
1694
+ if (!this.#client) {
1695
+ throw new ClientNotInitializedError();
1696
+ }
1697
+ if (!this.#signer) {
1698
+ throw new SignerUnavailableError();
1699
+ }
973
1700
  const signatureText = await this.unsafe_changeRecoveryIdentifierSignatureText(identifier);
974
1701
  if (!signatureText) {
975
1702
  throw new GenerateSignatureError(4 /* SignatureRequestType.ChangeRecoveryIdentifier */);
@@ -977,10 +1704,27 @@ class Client {
977
1704
  await this.unsafe_addSignature(4 /* SignatureRequestType.ChangeRecoveryIdentifier */, signatureText, this.#signer);
978
1705
  await this.unsafe_applySignatures();
979
1706
  }
1707
+ /**
1708
+ * Checks if the client can message the specified identifiers
1709
+ *
1710
+ * @param identifiers - The identifiers to check
1711
+ * @returns Whether the client can message the identifiers
1712
+ * @throws {ClientNotInitializedError} if the client is not initialized
1713
+ */
980
1714
  async canMessage(identifiers) {
981
- const canMessage = await this.#innerClient.canMessage(identifiers);
1715
+ if (!this.#client) {
1716
+ throw new ClientNotInitializedError();
1717
+ }
1718
+ const canMessage = await this.#client.canMessage(identifiers);
982
1719
  return new Map(Object.entries(canMessage));
983
1720
  }
1721
+ /**
1722
+ * Checks if the specified identifiers can be messaged
1723
+ *
1724
+ * @param identifiers - The identifiers to check
1725
+ * @param env - Optional XMTP environment
1726
+ * @returns Map of identifiers to whether they can be messaged
1727
+ */
984
1728
  static async canMessage(identifiers, env) {
985
1729
  const canMessageMap = new Map();
986
1730
  for (const identifier of identifiers) {
@@ -989,12 +1733,36 @@ class Client {
989
1733
  }
990
1734
  return canMessageMap;
991
1735
  }
1736
+ /**
1737
+ * Gets the key package statuses for the specified installation IDs
1738
+ *
1739
+ * @param installationIds - The installation IDs to check
1740
+ * @returns The key package statuses
1741
+ * @throws {ClientNotInitializedError} if the client is not initialized
1742
+ */
992
1743
  async getKeyPackageStatusesForInstallationIds(installationIds) {
993
- return this.#innerClient.getKeyPackageStatusesForInstallationIds(installationIds);
1744
+ if (!this.#client) {
1745
+ throw new ClientNotInitializedError();
1746
+ }
1747
+ return this.#client.getKeyPackageStatusesForInstallationIds(installationIds);
994
1748
  }
1749
+ /**
1750
+ * Gets the codec for a given content type
1751
+ *
1752
+ * @param contentType - The content type to get the codec for
1753
+ * @returns The codec, if found
1754
+ */
995
1755
  codecFor(contentType) {
996
1756
  return this.#codecs.get(contentType.toString());
997
1757
  }
1758
+ /**
1759
+ * Encodes content for a given content type
1760
+ *
1761
+ * @param content - The content to encode
1762
+ * @param contentType - The content type to encode for
1763
+ * @returns The encoded content
1764
+ * @throws {CodecNotFoundError} if no codec is found for the content type
1765
+ */
998
1766
  encodeContent(content, contentType) {
999
1767
  const codec = this.codecFor(contentType);
1000
1768
  if (!codec) {
@@ -1007,6 +1775,15 @@ class Client {
1007
1775
  }
1008
1776
  return encoded;
1009
1777
  }
1778
+ /**
1779
+ * Decodes a message for a given content type
1780
+ *
1781
+ * @param message - The message to decode
1782
+ * @param contentType - The content type to decode for
1783
+ * @returns The decoded content
1784
+ * @throws {CodecNotFoundError} if no codec is found for the content type
1785
+ * @throws {InvalidGroupMembershipChangeError} if the message is an invalid group membership change
1786
+ */
1010
1787
  decodeContent(message, contentType) {
1011
1788
  const codec = this.codecFor(contentType);
1012
1789
  if (!codec) {
@@ -1017,27 +1794,62 @@ class Client {
1017
1794
  message.kind !== 1 /* GroupMessageKind.MembershipChange */) {
1018
1795
  throw new InvalidGroupMembershipChangeError(message.id);
1019
1796
  }
1020
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
1021
1797
  return codec.decode(message.content, this);
1022
1798
  }
1023
- async requestHistorySync() {
1024
- return this.#innerClient.sendHistorySyncRequest();
1025
- }
1799
+ /**
1800
+ * Finds the inbox ID for a given identifier
1801
+ *
1802
+ * @param identifier - The identifier to look up
1803
+ * @returns The inbox ID, if found
1804
+ * @throws {ClientNotInitializedError} if the client is not initialized
1805
+ */
1026
1806
  async getInboxIdByIdentifier(identifier) {
1027
- return this.#innerClient.findInboxIdByIdentifier(identifier);
1807
+ if (!this.#client) {
1808
+ throw new ClientNotInitializedError();
1809
+ }
1810
+ return this.#client.findInboxIdByIdentifier(identifier);
1028
1811
  }
1812
+ /**
1813
+ * Signs a message with the installation key
1814
+ *
1815
+ * @param signatureText - The text to sign
1816
+ * @returns The signature
1817
+ * @throws {ClientNotInitializedError} if the client is not initialized
1818
+ */
1029
1819
  signWithInstallationKey(signatureText) {
1030
- return this.#innerClient.signWithInstallationKey(signatureText);
1820
+ if (!this.#client) {
1821
+ throw new ClientNotInitializedError();
1822
+ }
1823
+ return this.#client.signWithInstallationKey(signatureText);
1031
1824
  }
1825
+ /**
1826
+ * Verifies a signature was made with the installation key
1827
+ *
1828
+ * @param signatureText - The text that was signed
1829
+ * @param signatureBytes - The signature bytes to verify
1830
+ * @returns Whether the signature is valid
1831
+ * @throws {ClientNotInitializedError} if the client is not initialized
1832
+ */
1032
1833
  verifySignedWithInstallationKey(signatureText, signatureBytes) {
1834
+ if (!this.#client) {
1835
+ throw new ClientNotInitializedError();
1836
+ }
1033
1837
  try {
1034
- this.#innerClient.verifySignedWithInstallationKey(signatureText, signatureBytes);
1838
+ this.#client.verifySignedWithInstallationKey(signatureText, signatureBytes);
1035
1839
  return true;
1036
1840
  }
1037
1841
  catch {
1038
1842
  return false;
1039
1843
  }
1040
1844
  }
1845
+ /**
1846
+ * Verifies a signature was made with a public key
1847
+ *
1848
+ * @param signatureText - The text that was signed
1849
+ * @param signatureBytes - The signature bytes to verify
1850
+ * @param publicKey - The public key to verify against
1851
+ * @returns Whether the signature is valid
1852
+ */
1041
1853
  static verifySignedWithPublicKey(signatureText, signatureBytes, publicKey) {
1042
1854
  try {
1043
1855
  verifySignedWithPublicKey(signatureText, signatureBytes, publicKey);
@@ -1047,14 +1859,33 @@ class Client {
1047
1859
  return false;
1048
1860
  }
1049
1861
  }
1862
+ /**
1863
+ * Checks if an address is authorized for an inbox
1864
+ *
1865
+ * @param inboxId - The inbox ID to check
1866
+ * @param address - The address to check
1867
+ * @param options - Optional network options
1868
+ * @returns Whether the address is authorized
1869
+ */
1050
1870
  static async isAddressAuthorized(inboxId, address, options) {
1051
1871
  const host = options?.apiUrl || ApiUrls[options?.env || "dev"];
1052
1872
  return await isAddressAuthorized(host, inboxId, address);
1053
1873
  }
1874
+ /**
1875
+ * Checks if an installation is authorized for an inbox
1876
+ *
1877
+ * @param inboxId - The inbox ID to check
1878
+ * @param installation - The installation to check
1879
+ * @param options - Optional network options
1880
+ * @returns Whether the installation is authorized
1881
+ */
1054
1882
  static async isInstallationAuthorized(inboxId, installation, options) {
1055
1883
  const host = options?.apiUrl || ApiUrls[options?.env || "dev"];
1056
1884
  return await isInstallationAuthorized(host, inboxId, installation);
1057
1885
  }
1886
+ /**
1887
+ * Gets the version of the Node bindings
1888
+ */
1058
1889
  static get version() {
1059
1890
  return version;
1060
1891
  }