@xmtp/node-sdk 5.0.0-rc1 → 5.0.0

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
@@ -1,6 +1,6 @@
1
- import { contentTypeToString, contentTypesAreEqual } from '@xmtp/content-type-primitives';
2
- import { generateInboxId as generateInboxId$1, getInboxIdForIdentifier as getInboxIdForIdentifier$1, createClient as createClient$1, revokeInstallationsSignatureRequest, applySignatureRequest, inboxStateFromInboxIds, groupUpdatedContentType, verifySignedWithPublicKey, isAddressAuthorized, isInstallationAuthorized } from '@xmtp/node-bindings';
3
- export { ConsentEntityType, ConsentState, ConversationType, DeliveryStatus, GroupMember, GroupMembershipState, GroupMessageKind, GroupMetadata, GroupPermissions, GroupPermissionsOptions, IdentifierKind, LogLevel, MetadataField, PermissionLevel, PermissionPolicy, PermissionUpdateType, SignatureRequestHandle, SortDirection } from '@xmtp/node-bindings';
1
+ import { generateInboxId as generateInboxId$1, getInboxIdForIdentifier as getInboxIdForIdentifier$1, createClient as createClient$1, revokeInstallationsSignatureRequest, applySignatureRequest, inboxStateFromInboxIds, verifySignedWithPublicKey, isAddressAuthorized, isInstallationAuthorized } from '@xmtp/node-bindings';
2
+ export { ActionStyle, ConsentEntityType, ConsentState, ContentType, ConversationType, DeliveryStatus, GroupMembershipState, GroupMessageKind, GroupPermissionsOptions, IdentifierKind, ListConversationsOrderBy, LogLevel, MessageSortBy, MetadataField, PermissionLevel, PermissionPolicy, PermissionUpdateType, ReactionAction, ReactionSchema, SortDirection, contentTypeActions, contentTypeAttachment, contentTypeGroupUpdated, contentTypeIntent, contentTypeLeaveRequest, contentTypeMarkdown, contentTypeMultiRemoteAttachment, contentTypeReaction, contentTypeReadReceipt, contentTypeRemoteAttachment, contentTypeReply, contentTypeText, contentTypeTransactionReference, contentTypeWalletSendCalls, decryptAttachment, encodeActions, encodeAttachment, encodeIntent, encodeMarkdown, encodeMultiRemoteAttachment, encodeReaction, encodeReadReceipt, encodeRemoteAttachment, encodeText, encodeTransactionReference, encodeWalletSendCalls, encryptAttachment } from '@xmtp/node-bindings';
3
+ import { contentTypeToString } from '@xmtp/content-type-primitives';
4
4
  import { isPromise } from 'node:util/types';
5
5
  import { join } from 'node:path';
6
6
  import process from 'node:process';
@@ -32,10 +32,134 @@ const HistorySyncUrls = {
32
32
  production: "https://message-history.production.ephemera.network",
33
33
  };
34
34
 
35
+ class InboxReassignError extends Error {
36
+ constructor() {
37
+ super("Unable to create add account signature text, `allowInboxReassign` must be true");
38
+ }
39
+ }
40
+ class AccountAlreadyAssociatedError extends Error {
41
+ constructor(inboxId) {
42
+ super(`Account already associated with inbox ${inboxId}`);
43
+ }
44
+ }
45
+ class MissingContentTypeError extends Error {
46
+ constructor() {
47
+ super("Content type is required when sending encoded content");
48
+ }
49
+ }
50
+ class SignerUnavailableError extends Error {
51
+ constructor() {
52
+ super("Signer unavailable, use Client.create to create a client with a signer");
53
+ }
54
+ }
55
+ class ClientNotInitializedError extends Error {
56
+ constructor() {
57
+ super("Client not initialized, use Client.create or Client.build to create a client");
58
+ }
59
+ }
60
+ class StreamFailedError extends Error {
61
+ constructor(retryAttempts) {
62
+ const times = `time${retryAttempts !== 1 ? "s" : ""}`;
63
+ super(`Stream failed, retried ${retryAttempts} ${times}`);
64
+ }
65
+ }
66
+ class StreamInvalidRetryAttemptsError extends Error {
67
+ constructor() {
68
+ super("Stream retry attempts must be greater than 0");
69
+ }
70
+ }
71
+
72
+ const generateInboxId = (identifier, nonce) => {
73
+ return generateInboxId$1(identifier, nonce);
74
+ };
75
+ const getInboxIdForIdentifier = async (identifier, env = "dev", gatewayHost) => {
76
+ const host = ApiUrls[env];
77
+ const isSecure = host.startsWith("https");
78
+ return getInboxIdForIdentifier$1(host, gatewayHost, isSecure, identifier);
79
+ };
80
+
81
+ function isHexString(value) {
82
+ return typeof value === "string" && /^0x(?:[0-9a-fA-F]{2})+$/.test(value);
83
+ }
84
+ function validHex(value) {
85
+ if (!isHexString(value)) {
86
+ throw new TypeError(`Value is not a hexadecimal string.`);
87
+ }
88
+ return value;
89
+ }
90
+
91
+ class CodecRegistry {
92
+ #codecs;
93
+ constructor(codecs) {
94
+ this.#codecs = new Map(codecs.map((codec) => [contentTypeToString(codec.contentType), codec]));
95
+ }
96
+ /**
97
+ * Gets the codec for a given content type
98
+ *
99
+ * @param contentType - The content type to get the codec for
100
+ * @returns The codec, if found
101
+ */
102
+ getCodec(contentType) {
103
+ return this.#codecs.get(contentTypeToString(contentType));
104
+ }
105
+ }
106
+
35
107
  function nsToDate(ns) {
36
- return new Date(ns / 1_000_000);
108
+ return new Date(Number(ns / 1000000n));
37
109
  }
38
110
 
111
+ const getContentFromDecodedMessageContent = (content) => {
112
+ switch (content.type) {
113
+ case "Text" /* DecodedMessageContentType.Text */: {
114
+ return content.text;
115
+ }
116
+ case "Markdown" /* DecodedMessageContentType.Markdown */: {
117
+ return content.markdown;
118
+ }
119
+ case "Reply" /* DecodedMessageContentType.Reply */: {
120
+ return content.reply;
121
+ }
122
+ case "Reaction" /* DecodedMessageContentType.Reaction */: {
123
+ return content.reaction;
124
+ }
125
+ case "Attachment" /* DecodedMessageContentType.Attachment */: {
126
+ return content.attachment;
127
+ }
128
+ case "RemoteAttachment" /* DecodedMessageContentType.RemoteAttachment */: {
129
+ return content.remoteAttachment;
130
+ }
131
+ case "MultiRemoteAttachment" /* DecodedMessageContentType.MultiRemoteAttachment */: {
132
+ return content.multiRemoteAttachment;
133
+ }
134
+ case "TransactionReference" /* DecodedMessageContentType.TransactionReference */: {
135
+ return content.transactionReference;
136
+ }
137
+ case "GroupUpdated" /* DecodedMessageContentType.GroupUpdated */: {
138
+ return content.groupUpdated;
139
+ }
140
+ case "ReadReceipt" /* DecodedMessageContentType.ReadReceipt */: {
141
+ return content.readReceipt;
142
+ }
143
+ case "LeaveRequest" /* DecodedMessageContentType.LeaveRequest */: {
144
+ return content.leaveRequest;
145
+ }
146
+ case "WalletSendCalls" /* DecodedMessageContentType.WalletSendCalls */: {
147
+ return content.walletSendCalls;
148
+ }
149
+ case "Actions" /* DecodedMessageContentType.Actions */: {
150
+ return content.actions;
151
+ }
152
+ case "Intent" /* DecodedMessageContentType.Intent */: {
153
+ return content.intent;
154
+ }
155
+ case "Custom" /* DecodedMessageContentType.Custom */: {
156
+ return content.custom;
157
+ }
158
+ default:
159
+ content.type;
160
+ return null;
161
+ }
162
+ };
39
163
  /**
40
164
  * Represents a decoded XMTP message
41
165
  *
@@ -44,107 +168,101 @@ function nsToDate(ns) {
44
168
  * @property {ContentTypeId} contentType - The content type of the message content
45
169
  * @property {string} conversationId - Unique identifier for the conversation
46
170
  * @property {MessageDeliveryStatus} deliveryStatus - Current delivery status of the message ("unpublished" | "published" | "failed")
171
+ * @property {bigint} expiresAtNs - Timestamp when the message will expire (in nanoseconds)
172
+ * @property {Date} expiresAt - Timestamp when the message will expire
47
173
  * @property {string} [fallback] - Optional fallback text for the message
48
174
  * @property {string} id - Unique identifier for the message
49
175
  * @property {MessageKind} kind - Type of message ("application" | "membership_change")
176
+ * @property {number} numReplies - Number of replies to the message
177
+ * @property {DecodedMessage<Reaction>[]} reactions - Reactions to the message
50
178
  * @property {string} senderInboxId - Identifier for the sender's inbox
51
179
  * @property {Date} sentAt - Timestamp when the message was sent
52
- * @property {number} sentAtNs - Timestamp when the message was sent (in nanoseconds)
180
+ * @property {bigint} sentAtNs - Timestamp when the message was sent (in nanoseconds)
53
181
  */
54
182
  class DecodedMessage {
55
- #client;
56
183
  content;
57
184
  contentType;
58
185
  conversationId;
59
186
  deliveryStatus;
187
+ expiresAtNs;
188
+ expiresAt;
60
189
  fallback;
61
190
  id;
62
191
  kind;
192
+ numReplies;
193
+ reactions;
63
194
  senderInboxId;
64
195
  sentAt;
65
196
  sentAtNs;
66
- constructor(client, message) {
67
- this.#client = client;
197
+ constructor(codecRegistry, message) {
68
198
  this.id = message.id;
199
+ this.expiresAtNs = message.expiresAtNs ?? undefined;
200
+ this.expiresAt = message.expiresAtNs
201
+ ? nsToDate(message.expiresAtNs)
202
+ : undefined;
69
203
  this.sentAtNs = message.sentAtNs;
70
204
  this.sentAt = nsToDate(message.sentAtNs);
71
205
  this.conversationId = message.conversationId;
72
206
  this.senderInboxId = message.senderInboxId;
73
207
  this.contentType = message.contentType;
74
- this.fallback = message.fallback;
75
- switch (message.kind) {
76
- case 0 /* GroupMessageKind.Application */:
77
- this.kind = "application";
78
- break;
79
- case 1 /* GroupMessageKind.MembershipChange */:
80
- this.kind = "membership_change";
81
- break;
82
- // no default
83
- }
84
- switch (message.deliveryStatus) {
85
- case 0 /* DeliveryStatus.Unpublished */:
86
- this.deliveryStatus = "unpublished";
87
- break;
88
- case 1 /* DeliveryStatus.Published */:
89
- this.deliveryStatus = "published";
90
- break;
91
- case 2 /* DeliveryStatus.Failed */:
92
- this.deliveryStatus = "failed";
93
- break;
94
- // no default
95
- }
96
- this.content = undefined;
208
+ this.fallback = message.fallback ?? undefined;
209
+ this.kind = message.kind;
210
+ this.deliveryStatus = message.deliveryStatus;
211
+ this.numReplies = message.numReplies;
212
+ this.reactions = message.reactions.map((reaction) => new DecodedMessage(codecRegistry, reaction));
213
+ this.content =
214
+ getContentFromDecodedMessageContent(message.content) ??
215
+ undefined;
97
216
  switch (message.content.type) {
98
- case "Text" /* DecodedMessageContentType.Text */: {
99
- this.content = message.content.text;
100
- break;
101
- }
102
- case "Markdown" /* DecodedMessageContentType.Markdown */: {
103
- this.content = message.content.markdown;
104
- break;
105
- }
106
217
  case "Reply" /* DecodedMessageContentType.Reply */: {
107
- this.content = message.content.reply;
108
- break;
109
- }
110
- case "Reaction" /* DecodedMessageContentType.Reaction */: {
111
- this.content = message.content.reaction;
112
- break;
113
- }
114
- case "Attachment" /* DecodedMessageContentType.Attachment */: {
115
- this.content = message.content.attachment;
116
- break;
117
- }
118
- case "RemoteAttachment" /* DecodedMessageContentType.RemoteAttachment */: {
119
- this.content = message.content.remoteAttachment;
120
- break;
121
- }
122
- case "MultiRemoteAttachment" /* DecodedMessageContentType.MultiRemoteAttachment */: {
123
- this.content = message.content.multiRemoteAttachment;
124
- break;
125
- }
126
- case "TransactionReference" /* DecodedMessageContentType.TransactionReference */: {
127
- this.content = message.content.transactionReference;
128
- break;
129
- }
130
- case "GroupUpdated" /* DecodedMessageContentType.GroupUpdated */: {
131
- this.content = message.content.groupUpdated;
132
- break;
133
- }
134
- case "ReadReceipt" /* DecodedMessageContentType.ReadReceipt */: {
135
- this.content = message.content.readReceipt;
136
- break;
137
- }
138
- case "LeaveRequest" /* DecodedMessageContentType.LeaveRequest */: {
139
- this.content = message.content.leaveRequest;
218
+ const reply = message.content.reply;
219
+ let replyContent = getContentFromDecodedMessageContent(reply.content);
220
+ if (reply.content.type === "Custom" /* DecodedMessageContentType.Custom */) {
221
+ const codec = codecRegistry.getCodec(reply.content.custom?.type);
222
+ if (codec) {
223
+ try {
224
+ replyContent = codec.decode(replyContent);
225
+ }
226
+ catch (error) {
227
+ if (error instanceof Error) {
228
+ console.warn(`Error decoding custom content: ${error.message}`);
229
+ }
230
+ else {
231
+ console.warn(`Error decoding custom content`);
232
+ }
233
+ }
234
+ }
235
+ }
236
+ this.content = {
237
+ referenceId: reply.referenceId,
238
+ content: replyContent,
239
+ inReplyTo: reply.inReplyTo
240
+ ? new DecodedMessage(codecRegistry, reply.inReplyTo)
241
+ : null,
242
+ };
140
243
  break;
141
244
  }
142
245
  case "Custom" /* DecodedMessageContentType.Custom */: {
143
246
  const customContent = message.content.custom;
144
247
  if (customContent !== null) {
145
- const codec = this.#client.codecFor(this.contentType);
248
+ const codec = codecRegistry.getCodec(this.contentType);
146
249
  if (codec) {
147
- this.content = codec.decode(customContent);
250
+ try {
251
+ this.content = codec.decode(customContent);
252
+ }
253
+ catch (error) {
254
+ if (error instanceof Error) {
255
+ console.warn(`Error decoding custom content: ${error.message}`);
256
+ }
257
+ else {
258
+ console.warn(`Error decoding custom content`);
259
+ }
260
+ this.content = undefined;
261
+ }
262
+ }
263
+ else {
264
+ console.warn(`No codec found for content type "${contentTypeToString(this.contentType)}"`);
265
+ this.content = undefined;
148
266
  }
149
267
  }
150
268
  break;
@@ -153,53 +271,6 @@ class DecodedMessage {
153
271
  }
154
272
  }
155
273
 
156
- class CodecNotFoundError extends Error {
157
- constructor(contentType) {
158
- super(`Codec not found for "${contentTypeToString(contentType)}" content type`);
159
- }
160
- }
161
- class InboxReassignError extends Error {
162
- constructor() {
163
- super("Unable to create add account signature text, `allowInboxReassign` must be true");
164
- }
165
- }
166
- class AccountAlreadyAssociatedError extends Error {
167
- constructor(inboxId) {
168
- super(`Account already associated with inbox ${inboxId}`);
169
- }
170
- }
171
- class InvalidGroupMembershipChangeError extends Error {
172
- constructor(messageId) {
173
- super(`Invalid group membership change for message ${messageId}`);
174
- }
175
- }
176
- class MissingContentTypeError extends Error {
177
- constructor() {
178
- super("Content type is required when sending encoded content");
179
- }
180
- }
181
- class SignerUnavailableError extends Error {
182
- constructor() {
183
- super("Signer unavailable, use Client.create to create a client with a signer");
184
- }
185
- }
186
- class ClientNotInitializedError extends Error {
187
- constructor() {
188
- super("Client not initialized, use Client.create or Client.build to create a client");
189
- }
190
- }
191
- class StreamFailedError extends Error {
192
- constructor(retryAttempts) {
193
- const times = `time${retryAttempts !== 1 ? "s" : ""}`;
194
- super(`Stream failed, retried ${retryAttempts} ${times}`);
195
- }
196
- }
197
- class StreamInvalidRetryAttemptsError extends Error {
198
- constructor() {
199
- super("Stream retry attempts must be greater than 0");
200
- }
201
- }
202
-
203
274
  /**
204
275
  * AsyncStream provides an async iterable interface for streaming data.
205
276
  *
@@ -491,19 +562,19 @@ const createStream = async (streamFunction, streamValueMutator, options) => {
491
562
  */
492
563
  class Conversation {
493
564
  #client;
565
+ #codecRegistry;
494
566
  #conversation;
495
- #isCommitLogForked = null;
496
567
  /**
497
568
  * Creates a new conversation instance
498
569
  *
499
570
  * @param client - The client instance managing the conversation
571
+ * @param codecRegistry - The codec registry instance
500
572
  * @param conversation - The underlying conversation instance
501
- * @param isCommitLogForked
502
573
  */
503
- constructor(client, conversation, isCommitLogForked) {
574
+ constructor(client, codecRegistry, conversation) {
504
575
  this.#client = client;
576
+ this.#codecRegistry = codecRegistry;
505
577
  this.#conversation = conversation;
506
- this.#isCommitLogForked = isCommitLogForked ?? null;
507
578
  }
508
579
  /**
509
580
  * Gets the unique identifier for this conversation
@@ -517,9 +588,6 @@ class Conversation {
517
588
  get isActive() {
518
589
  return this.#conversation.isActive();
519
590
  }
520
- get isCommitLogForked() {
521
- return this.#isCommitLogForked;
522
- }
523
591
  /**
524
592
  * Gets the inbox ID that added this client's inbox to the conversation
525
593
  */
@@ -538,6 +606,17 @@ class Conversation {
538
606
  get createdAt() {
539
607
  return nsToDate(this.createdAtNs);
540
608
  }
609
+ pausedForVersion() {
610
+ return this.#conversation.pausedForVersion() ?? undefined;
611
+ }
612
+ /**
613
+ * Gets HMAC keys for this conversation
614
+ *
615
+ * @returns The HMAC keys for this conversation
616
+ */
617
+ hmacKeys() {
618
+ return this.#conversation.getHmacKeys();
619
+ }
541
620
  /**
542
621
  * Gets the metadata for this conversation
543
622
  *
@@ -600,7 +679,7 @@ class Conversation {
600
679
  * @param sendOptions - Options for sending the message
601
680
  * @param sendOptions.shouldPush - Indicates whether this message should be
602
681
  * included in push notifications
603
- * @param sendOptions.optimistic - Indicates whether this message should be
682
+ * @param sendOptions.isOptimistic - Indicates whether this message should be
604
683
  * sent optimistically and published later via `publishMessages`
605
684
  * @returns Promise that resolves with the message ID after it has been sent
606
685
  */
@@ -614,121 +693,121 @@ class Conversation {
614
693
  * Sends a text message
615
694
  *
616
695
  * @param text - The text to send
617
- * @param optimistic - Whether to send the message optimistically
696
+ * @param isOptimistic - Whether to send the message optimistically
618
697
  * @returns Promise that resolves with the message ID after it has been sent
619
698
  */
620
- async sendText(text, optimistic) {
621
- return this.#conversation.sendText(text, optimistic);
699
+ async sendText(text, isOptimistic) {
700
+ return this.#conversation.sendText(text, isOptimistic);
622
701
  }
623
702
  /**
624
703
  * Sends a markdown message
625
704
  *
626
705
  * @param markdown - The markdown to send
627
- * @param optimistic - Whether to send the message optimistically
706
+ * @param isOptimistic - Whether to send the message optimistically
628
707
  * @returns Promise that resolves with the message ID after it has been sent
629
708
  */
630
- async sendMarkdown(markdown, optimistic) {
631
- return this.#conversation.sendMarkdown(markdown, optimistic);
709
+ async sendMarkdown(markdown, isOptimistic) {
710
+ return this.#conversation.sendMarkdown(markdown, isOptimistic);
632
711
  }
633
712
  /**
634
713
  * Sends a reaction message
635
714
  *
636
715
  * @param reaction - The reaction to send
637
- * @param optimistic - Whether to send the message optimistically
716
+ * @param isOptimistic - Whether to send the message optimistically
638
717
  * @returns Promise that resolves with the message ID after it has been sent
639
718
  */
640
- async sendReaction(reaction, optimistic) {
641
- return this.#conversation.sendReaction(reaction, optimistic);
719
+ async sendReaction(reaction, isOptimistic) {
720
+ return this.#conversation.sendReaction(reaction, isOptimistic);
642
721
  }
643
722
  /**
644
723
  * Sends a read receipt message
645
724
  *
646
725
  * @param readReceipt - The read receipt to send
647
- * @param optimistic - Whether to send the message optimistically
726
+ * @param isOptimistic - Whether to send the message optimistically
648
727
  * @returns Promise that resolves with the message ID after it has been sent
649
728
  */
650
- async sendReadReceipt(optimistic) {
651
- return this.#conversation.sendReadReceipt(optimistic);
729
+ async sendReadReceipt(isOptimistic) {
730
+ return this.#conversation.sendReadReceipt(isOptimistic);
652
731
  }
653
732
  /**
654
733
  * Sends a reply message
655
734
  *
656
735
  * @param reply - The reply to send
657
- * @param optimistic - Whether to send the message optimistically
736
+ * @param isOptimistic - Whether to send the message optimistically
658
737
  * @returns Promise that resolves with the message ID after it has been sent
659
738
  */
660
- async sendReply(reply, optimistic) {
661
- return this.#conversation.sendReply(reply, optimistic);
739
+ async sendReply(reply, isOptimistic) {
740
+ return this.#conversation.sendReply(reply, isOptimistic);
662
741
  }
663
742
  /**
664
743
  * Sends a transaction reference message
665
744
  *
666
745
  * @param transactionReference - The transaction reference to send
667
- * @param optimistic - Whether to send the message optimistically
746
+ * @param isOptimistic - Whether to send the message optimistically
668
747
  * @returns Promise that resolves with the message ID after it has been sent
669
748
  */
670
- async sendTransactionReference(transactionReference, optimistic) {
671
- return this.#conversation.sendTransactionReference(transactionReference, optimistic);
749
+ async sendTransactionReference(transactionReference, isOptimistic) {
750
+ return this.#conversation.sendTransactionReference(transactionReference, isOptimistic);
672
751
  }
673
752
  /**
674
753
  * Sends a wallet send calls message
675
754
  *
676
755
  * @param walletSendCalls - The wallet send calls to send
677
- * @param optimistic - Whether to send the message optimistically
756
+ * @param isOptimistic - Whether to send the message optimistically
678
757
  * @returns Promise that resolves with the message ID after it has been sent
679
758
  */
680
- async sendWalletSendCalls(walletSendCalls, optimistic) {
681
- return this.#conversation.sendWalletSendCalls(walletSendCalls, optimistic);
759
+ async sendWalletSendCalls(walletSendCalls, isOptimistic) {
760
+ return this.#conversation.sendWalletSendCalls(walletSendCalls, isOptimistic);
682
761
  }
683
762
  /**
684
763
  * Sends a actions message
685
764
  *
686
765
  * @param actions - The actions to send
687
- * @param optimistic - Whether to send the message optimistically
766
+ * @param isOptimistic - Whether to send the message optimistically
688
767
  * @returns Promise that resolves with the message ID after it has been sent
689
768
  */
690
- async sendActions(actions, optimistic) {
691
- return this.#conversation.sendActions(actions, optimistic);
769
+ async sendActions(actions, isOptimistic) {
770
+ return this.#conversation.sendActions(actions, isOptimistic);
692
771
  }
693
772
  /**
694
773
  * Sends a intent message
695
774
  *
696
775
  * @param intent - The intent to send
697
- * @param optimistic - Whether to send the message optimistically
776
+ * @param isOptimistic - Whether to send the message optimistically
698
777
  * @returns Promise that resolves with the message ID after it has been sent
699
778
  */
700
- async sendIntent(intent, optimistic) {
701
- return this.#conversation.sendIntent(intent, optimistic);
779
+ async sendIntent(intent, isOptimistic) {
780
+ return this.#conversation.sendIntent(intent, isOptimistic);
702
781
  }
703
782
  /**
704
783
  * Sends an attachment message
705
784
  *
706
785
  * @param attachment - The attachment to send
707
- * @param optimistic - Whether to send the message optimistically
786
+ * @param isOptimistic - Whether to send the message optimistically
708
787
  * @returns Promise that resolves with the message ID after it has been sent
709
788
  */
710
- async sendAttachment(attachment, optimistic) {
711
- return this.#conversation.sendAttachment(attachment, optimistic);
789
+ async sendAttachment(attachment, isOptimistic) {
790
+ return this.#conversation.sendAttachment(attachment, isOptimistic);
712
791
  }
713
792
  /**
714
793
  * Sends a multi remote attachment message
715
794
  *
716
795
  * @param multiRemoteAttachment - The multi remote attachment to send
717
- * @param optimistic - Whether to send the message optimistically
796
+ * @param isOptimistic - Whether to send the message optimistically
718
797
  * @returns Promise that resolves with the message ID after it has been sent
719
798
  */
720
- async sendMultiRemoteAttachment(multiRemoteAttachment, optimistic) {
721
- return this.#conversation.sendMultiRemoteAttachment(multiRemoteAttachment, optimistic);
799
+ async sendMultiRemoteAttachment(multiRemoteAttachment, isOptimistic) {
800
+ return this.#conversation.sendMultiRemoteAttachment(multiRemoteAttachment, isOptimistic);
722
801
  }
723
802
  /**
724
803
  * Sends a remote attachment message
725
804
  *
726
805
  * @param remoteAttachment - The remote attachment to send
727
- * @param optimistic - Whether to send the message optimistically
806
+ * @param isOptimistic - Whether to send the message optimistically
728
807
  * @returns Promise that resolves with the message ID after it has been sent
729
808
  */
730
- async sendRemoteAttachment(remoteAttachment, optimistic) {
731
- return this.#conversation.sendRemoteAttachment(remoteAttachment, optimistic);
809
+ async sendRemoteAttachment(remoteAttachment, isOptimistic) {
810
+ return this.#conversation.sendRemoteAttachment(remoteAttachment, isOptimistic);
732
811
  }
733
812
  /**
734
813
  * Lists messages in this conversation
@@ -738,7 +817,7 @@ class Conversation {
738
817
  */
739
818
  async messages(options) {
740
819
  const messages = await this.#conversation.findEnrichedMessages(options);
741
- return messages.map((message) => new DecodedMessage(this.#client, message));
820
+ return messages.map((message) => new DecodedMessage(this.#codecRegistry, message));
742
821
  }
743
822
  /**
744
823
  * Counts messages in this conversation
@@ -768,7 +847,7 @@ class Conversation {
768
847
  /**
769
848
  * Gets the consent state for this conversation
770
849
  */
771
- get consentState() {
850
+ consentState() {
772
851
  return this.#conversation.consentState();
773
852
  }
774
853
  /**
@@ -816,17 +895,6 @@ class Conversation {
816
895
  isMessageDisappearingEnabled() {
817
896
  return this.#conversation.isMessageDisappearingEnabled();
818
897
  }
819
- pausedForVersion() {
820
- return this.#conversation.pausedForVersion() ?? undefined;
821
- }
822
- /**
823
- * Retrieves HMAC keys for this conversation
824
- *
825
- * @returns The HMAC keys for this conversation
826
- */
827
- getHmacKeys() {
828
- return this.#conversation.getHmacKeys();
829
- }
830
898
  /**
831
899
  * Retrieves information for this conversation to help with debugging
832
900
  *
@@ -835,6 +903,15 @@ class Conversation {
835
903
  async debugInfo() {
836
904
  return this.#conversation.debugInfo();
837
905
  }
906
+ /**
907
+ * Retrieves the last read times for this conversation
908
+ *
909
+ * @returns A map keyed by inbox ID with the last read timestamp
910
+ * (nanoseconds since epoch)
911
+ */
912
+ async lastReadTimes() {
913
+ return this.#conversation.getLastReadTimes();
914
+ }
838
915
  }
839
916
 
840
917
  /**
@@ -844,17 +921,19 @@ class Conversation {
844
921
  */
845
922
  class Dm extends Conversation {
846
923
  #client;
924
+ #codecRegistry;
847
925
  #conversation;
848
926
  /**
849
927
  * Creates a new direct message conversation instance
850
928
  *
851
929
  * @param client - The client instance managing this direct message conversation
930
+ * @param codecRegistry - The codec registry instance
852
931
  * @param conversation - The underlying conversation instance
853
- * @param isCommitLogForked
854
932
  */
855
- constructor(client, conversation, isCommitLogForked) {
856
- super(client, conversation, isCommitLogForked);
933
+ constructor(client, codecRegistry, conversation) {
934
+ super(client, codecRegistry, conversation);
857
935
  this.#client = client;
936
+ this.#codecRegistry = codecRegistry;
858
937
  this.#conversation = conversation;
859
938
  }
860
939
  /**
@@ -865,9 +944,9 @@ class Dm extends Conversation {
865
944
  get peerInboxId() {
866
945
  return this.#conversation.dmPeerInboxId();
867
946
  }
868
- async getDuplicateDms() {
947
+ async duplicateDms() {
869
948
  const duplicateDms = await this.#conversation.findDuplicateDms();
870
- return duplicateDms.map((dm) => new Dm(this.#client, dm));
949
+ return duplicateDms.map((dm) => new Dm(this.#client, this.#codecRegistry, dm));
871
950
  }
872
951
  }
873
952
 
@@ -882,11 +961,11 @@ class Group extends Conversation {
882
961
  * Creates a new group conversation instance
883
962
  *
884
963
  * @param client - The client instance managing this group conversation
964
+ * @param codecRegistry - The codec registry instance
885
965
  * @param conversation - The underlying conversation object
886
- * @param isCommitLogForked
887
966
  */
888
- constructor(client, conversation, isCommitLogForked) {
889
- super(client, conversation, isCommitLogForked);
967
+ constructor(client, codecRegistry, conversation) {
968
+ super(client, codecRegistry, conversation);
890
969
  this.#conversation = conversation;
891
970
  }
892
971
  /**
@@ -948,7 +1027,7 @@ class Group extends Conversation {
948
1027
  /**
949
1028
  * The permissions of the group
950
1029
  */
951
- get permissions() {
1030
+ permissions() {
952
1031
  const permissions = this.#conversation.groupPermissions();
953
1032
  return {
954
1033
  policyType: permissions.policyType(),
@@ -968,13 +1047,13 @@ class Group extends Conversation {
968
1047
  /**
969
1048
  * The list of admins of the group
970
1049
  */
971
- get admins() {
1050
+ listAdmins() {
972
1051
  return this.#conversation.adminList();
973
1052
  }
974
1053
  /**
975
1054
  * The list of super admins of the group
976
1055
  */
977
- get superAdmins() {
1056
+ listSuperAdmins() {
978
1057
  return this.#conversation.superAdminList();
979
1058
  }
980
1059
  /**
@@ -1070,7 +1149,7 @@ class Group extends Conversation {
1070
1149
  *
1071
1150
  * @returns Boolean
1072
1151
  */
1073
- get isPendingRemoval() {
1152
+ isPendingRemoval() {
1074
1153
  return (this.#conversation.membershipState() ===
1075
1154
  4 /* GroupMembershipState.PendingRemove */);
1076
1155
  }
@@ -1083,15 +1162,18 @@ class Group extends Conversation {
1083
1162
  */
1084
1163
  class Conversations {
1085
1164
  #client;
1165
+ #codecRegistry;
1086
1166
  #conversations;
1087
1167
  /**
1088
1168
  * Creates a new conversations instance
1089
1169
  *
1090
1170
  * @param client - The client instance managing the conversations
1171
+ * @param codecRegistry - The codec registry instance
1091
1172
  * @param conversations - The underlying conversations instance
1092
1173
  */
1093
- constructor(client, conversations) {
1174
+ constructor(client, codecRegistry, conversations) {
1094
1175
  this.#client = client;
1176
+ this.#codecRegistry = codecRegistry;
1095
1177
  this.#conversations = conversations;
1096
1178
  }
1097
1179
  /**
@@ -1106,9 +1188,14 @@ class Conversations {
1106
1188
  // findGroupById will throw if group is not found
1107
1189
  const group = this.#conversations.findGroupById(id);
1108
1190
  const metadata = await group.groupMetadata();
1109
- return metadata.conversationType() === "group"
1110
- ? new Group(this.#client, group)
1111
- : new Dm(this.#client, group);
1191
+ switch (metadata.conversationType()) {
1192
+ case 1 /* ConversationType.Group */:
1193
+ return new Group(this.#client, this.#codecRegistry, group);
1194
+ case 0 /* ConversationType.Dm */:
1195
+ return new Dm(this.#client, this.#codecRegistry, group);
1196
+ default:
1197
+ return undefined;
1198
+ }
1112
1199
  }
1113
1200
  catch {
1114
1201
  return undefined;
@@ -1125,7 +1212,7 @@ class Conversations {
1125
1212
  try {
1126
1213
  // findDmByTargetInboxId will throw if group is not found
1127
1214
  const group = this.#conversations.findDmByTargetInboxId(inboxId);
1128
- return new Dm(this.#client, group);
1215
+ return new Dm(this.#client, this.#codecRegistry, group);
1129
1216
  }
1130
1217
  catch {
1131
1218
  return undefined;
@@ -1138,8 +1225,8 @@ class Conversations {
1138
1225
  * @returns Promise that resolves with the DM, if found
1139
1226
  * @see https://docs.xmtp.org/chat-apps/core-messaging/create-conversations#conversation-helper-methods
1140
1227
  */
1141
- async getDmByIdentifier(identifier) {
1142
- const inboxId = await this.#client.getInboxIdByIdentifier(identifier);
1228
+ async fetchDmByIdentifier(identifier) {
1229
+ const inboxId = await this.#client.fetchInboxIdByIdentifier(identifier);
1143
1230
  if (!inboxId) {
1144
1231
  return undefined;
1145
1232
  }
@@ -1156,22 +1243,22 @@ class Conversations {
1156
1243
  try {
1157
1244
  // findEnrichedMessageById will throw if message is not found
1158
1245
  const message = this.#conversations.findEnrichedMessageById(id);
1159
- return new DecodedMessage(this.#client, message);
1246
+ return new DecodedMessage(this.#codecRegistry, message);
1160
1247
  }
1161
1248
  catch {
1162
1249
  return undefined;
1163
1250
  }
1164
1251
  }
1165
1252
  /**
1166
- * Creates a new group conversation without syncing to the network
1253
+ * Creates a new group conversation without publishing to the network
1167
1254
  *
1168
1255
  * @param options - Optional group creation options
1169
1256
  * @returns The new group
1170
1257
  * @see https://docs.xmtp.org/chat-apps/core-messaging/create-conversations#optimistically-create-a-new-group-chat
1171
1258
  */
1172
- newGroupOptimistic(options) {
1259
+ createGroupOptimistic(options) {
1173
1260
  const group = this.#conversations.createGroupOptimistic(options);
1174
- return new Group(this.#client, group);
1261
+ return new Group(this.#client, this.#codecRegistry, group);
1175
1262
  }
1176
1263
  /**
1177
1264
  * Creates a new group conversation with the specified identifiers
@@ -1181,9 +1268,9 @@ class Conversations {
1181
1268
  * @returns The new group
1182
1269
  * @see https://docs.xmtp.org/chat-apps/core-messaging/create-conversations#create-a-new-group-chat
1183
1270
  */
1184
- async newGroupWithIdentifiers(identifiers, options) {
1271
+ async createGroupWithIdentifiers(identifiers, options) {
1185
1272
  const group = await this.#conversations.createGroup(identifiers, options);
1186
- const conversation = new Group(this.#client, group);
1273
+ const conversation = new Group(this.#client, this.#codecRegistry, group);
1187
1274
  return conversation;
1188
1275
  }
1189
1276
  /**
@@ -1194,9 +1281,9 @@ class Conversations {
1194
1281
  * @returns The new group
1195
1282
  * @see https://docs.xmtp.org/chat-apps/core-messaging/create-conversations#create-a-new-group-chat
1196
1283
  */
1197
- async newGroup(inboxIds, options) {
1284
+ async createGroup(inboxIds, options) {
1198
1285
  const group = await this.#conversations.createGroupByInboxId(inboxIds, options);
1199
- const conversation = new Group(this.#client, group);
1286
+ const conversation = new Group(this.#client, this.#codecRegistry, group);
1200
1287
  return conversation;
1201
1288
  }
1202
1289
  /**
@@ -1207,9 +1294,9 @@ class Conversations {
1207
1294
  * @returns The new DM
1208
1295
  * @see https://docs.xmtp.org/agents/build-agents/create-conversations#by-ethereum-address-1
1209
1296
  */
1210
- async newDmWithIdentifier(identifier, options) {
1297
+ async createDmWithIdentifier(identifier, options) {
1211
1298
  const group = await this.#conversations.createDm(identifier, options);
1212
- const conversation = new Dm(this.#client, group);
1299
+ const conversation = new Dm(this.#client, this.#codecRegistry, group);
1213
1300
  return conversation;
1214
1301
  }
1215
1302
  /**
@@ -1220,9 +1307,9 @@ class Conversations {
1220
1307
  * @returns The new DM
1221
1308
  * @see https://docs.xmtp.org/agents/build-agents/create-conversations#by-inbox-id-1
1222
1309
  */
1223
- async newDm(inboxId, options) {
1310
+ async createDm(inboxId, options) {
1224
1311
  const group = await this.#conversations.createDmByInboxId(inboxId, options);
1225
- const conversation = new Dm(this.#client, group);
1312
+ const conversation = new Dm(this.#client, this.#codecRegistry, group);
1226
1313
  return conversation;
1227
1314
  }
1228
1315
  /**
@@ -1238,10 +1325,10 @@ class Conversations {
1238
1325
  const metadata = await item.conversation.groupMetadata();
1239
1326
  const conversationType = metadata.conversationType();
1240
1327
  switch (conversationType) {
1241
- case "dm":
1242
- return new Dm(this.#client, item.conversation, item.isCommitLogForked);
1243
- case "group":
1244
- return new Group(this.#client, item.conversation, item.isCommitLogForked);
1328
+ case 0 /* ConversationType.Dm */:
1329
+ return new Dm(this.#client, this.#codecRegistry, item.conversation);
1330
+ case 1 /* ConversationType.Group */:
1331
+ return new Group(this.#client, this.#codecRegistry, item.conversation);
1245
1332
  default:
1246
1333
  return undefined;
1247
1334
  }
@@ -1261,7 +1348,7 @@ class Conversations {
1261
1348
  conversationType: 1 /* ConversationType.Group */,
1262
1349
  });
1263
1350
  return groups.map((item) => {
1264
- const conversation = new Group(this.#client, item.conversation, item.isCommitLogForked);
1351
+ const conversation = new Group(this.#client, this.#codecRegistry, item.conversation);
1265
1352
  return conversation;
1266
1353
  });
1267
1354
  }
@@ -1278,7 +1365,7 @@ class Conversations {
1278
1365
  conversationType: 0 /* ConversationType.Dm */,
1279
1366
  });
1280
1367
  return groups.map((item) => {
1281
- const conversation = new Dm(this.#client, item.conversation, item.isCommitLogForked);
1368
+ const conversation = new Dm(this.#client, this.#codecRegistry, item.conversation);
1282
1369
  return conversation;
1283
1370
  });
1284
1371
  }
@@ -1322,11 +1409,11 @@ class Conversations {
1322
1409
  const conversationType = metadata.conversationType();
1323
1410
  let conversation;
1324
1411
  switch (conversationType) {
1325
- case "dm":
1326
- conversation = new Dm(this.#client, value);
1412
+ case 0 /* ConversationType.Dm */:
1413
+ conversation = new Dm(this.#client, this.#codecRegistry, value);
1327
1414
  break;
1328
- case "group":
1329
- conversation = new Group(this.#client, value);
1415
+ case 1 /* ConversationType.Group */:
1416
+ conversation = new Group(this.#client, this.#codecRegistry, value);
1330
1417
  break;
1331
1418
  }
1332
1419
  return conversation;
@@ -1348,7 +1435,7 @@ class Conversations {
1348
1435
  return this.#conversations.stream(callback, onFail, 1 /* ConversationType.Group */);
1349
1436
  };
1350
1437
  const convertConversation = (value) => {
1351
- return new Group(this.#client, value);
1438
+ return new Group(this.#client, this.#codecRegistry, value);
1352
1439
  };
1353
1440
  return createStream(stream, convertConversation, options);
1354
1441
  }
@@ -1367,7 +1454,7 @@ class Conversations {
1367
1454
  return this.#conversations.stream(callback, onFail, 0 /* ConversationType.Dm */);
1368
1455
  };
1369
1456
  const convertConversation = (value) => {
1370
- return new Dm(this.#client, value);
1457
+ return new Dm(this.#client, this.#codecRegistry, value);
1371
1458
  };
1372
1459
  return createStream(stream, convertConversation, options);
1373
1460
  }
@@ -1439,7 +1526,7 @@ class Conversations {
1439
1526
  return createStream(stream, undefined, options);
1440
1527
  }
1441
1528
  /**
1442
- * Retrieves HMAC keys for all conversations
1529
+ * Gets the HMAC keys for all conversations
1443
1530
  *
1444
1531
  * @returns The HMAC keys for all conversations
1445
1532
  * @see https://docs.xmtp.org/chat-apps/push-notifs/push-notifs#get-hmac-keys-for-a-conversation
@@ -1495,32 +1582,39 @@ class Preferences {
1495
1582
  return this.#client.syncPreferences();
1496
1583
  }
1497
1584
  /**
1498
- * Retrieves the current inbox state
1585
+ * Retrieves the current inbox state of this client from the local database
1586
+ *
1587
+ * @returns Promise that resolves with the inbox state
1588
+ */
1589
+ async inboxState() {
1590
+ return this.#client.inboxState(false);
1591
+ }
1592
+ /**
1593
+ * Retrieves the latest inbox state of this clientfrom the network
1499
1594
  *
1500
- * @param refreshFromNetwork - Optional flag to force refresh from network
1501
1595
  * @returns Promise that resolves with the inbox state
1502
1596
  */
1503
- async inboxState(refreshFromNetwork = false) {
1504
- return this.#client.inboxState(refreshFromNetwork);
1597
+ async fetchInboxState() {
1598
+ return this.#client.inboxState(true);
1505
1599
  }
1506
1600
  /**
1507
- * Gets the latest inbox state for a specific inbox
1601
+ * Retrieves the current inbox states for specified inbox IDs from the local
1602
+ * database
1508
1603
  *
1509
- * @param inboxId - The inbox ID to get state for
1510
- * @returns Promise that resolves with the latest inbox state
1604
+ * @param inboxIds - Array of inbox IDs to get state for
1605
+ * @returns Promise that resolves with the inbox states for the inbox IDs
1511
1606
  */
1512
- async getLatestInboxState(inboxId) {
1513
- return this.#client.getLatestInboxState(inboxId);
1607
+ async getInboxStates(inboxIds) {
1608
+ return this.#client.addressesFromInboxId(false, inboxIds);
1514
1609
  }
1515
1610
  /**
1516
- * Retrieves inbox state for specific inbox IDs
1611
+ * Retrieves the latest inbox states for specified inbox IDs from the network
1517
1612
  *
1518
1613
  * @param inboxIds - Array of inbox IDs to get state for
1519
- * @param refreshFromNetwork - Optional flag to force refresh from network
1520
- * @returns Promise that resolves with the inbox state for the inbox IDs
1614
+ * @returns Promise that resolves with the inbox states for the inbox IDs
1521
1615
  */
1522
- async inboxStateFromInboxIds(inboxIds, refreshFromNetwork) {
1523
- return this.#client.addressesFromInboxId(refreshFromNetwork ?? false, inboxIds);
1616
+ async fetchInboxStates(inboxIds) {
1617
+ return this.#client.addressesFromInboxId(true, inboxIds);
1524
1618
  }
1525
1619
  /**
1526
1620
  * Updates consent states for multiple records
@@ -1573,25 +1667,6 @@ class Preferences {
1573
1667
  }
1574
1668
  }
1575
1669
 
1576
- const generateInboxId = (identifier, nonce) => {
1577
- return generateInboxId$1(identifier, nonce);
1578
- };
1579
- const getInboxIdForIdentifier = async (identifier, env = "dev", gatewayHost) => {
1580
- const host = ApiUrls[env];
1581
- const isSecure = host.startsWith("https");
1582
- return getInboxIdForIdentifier$1(host, gatewayHost, isSecure, identifier);
1583
- };
1584
-
1585
- function isHexString(value) {
1586
- return typeof value === "string" && /^0x(?:[0-9a-fA-F]{2})+$/.test(value);
1587
- }
1588
- function validHex(value) {
1589
- if (!isHexString(value)) {
1590
- throw new TypeError(`Value is not a hexadecimal string.`);
1591
- }
1592
- return value;
1593
- }
1594
-
1595
1670
  const createClient = async (identifier, options) => {
1596
1671
  const env = options?.env || "dev";
1597
1672
  const host = options?.apiUrl || ApiUrls[env];
@@ -1614,14 +1689,14 @@ const createClient = async (identifier, options) => {
1614
1689
  }
1615
1690
  const logOptions = {
1616
1691
  structured: options?.structuredLogging ?? false,
1617
- level: options?.loggingLevel ?? "off" /* LogLevel.off */,
1692
+ level: options?.loggingLevel ?? "Off" /* LogLevel.Off */,
1618
1693
  };
1619
1694
  const historySyncUrl = options?.historySyncUrl === undefined
1620
1695
  ? HistorySyncUrls[env]
1621
1696
  : options.historySyncUrl;
1622
1697
  const deviceSyncWorkerMode = options?.disableDeviceSync
1623
- ? "disabled" /* SyncWorkerMode.disabled */
1624
- : "enabled" /* SyncWorkerMode.enabled */;
1698
+ ? "Disabled" /* SyncWorkerMode.Disabled */
1699
+ : "Enabled" /* SyncWorkerMode.Enabled */;
1625
1700
  const dbEncryptionKey = isHexString(options?.dbEncryptionKey)
1626
1701
  ? Buffer.from(options.dbEncryptionKey.replace(/^0x/, ""), "hex")
1627
1702
  : options?.dbEncryptionKey;
@@ -1633,11 +1708,11 @@ const createClient = async (identifier, options) => {
1633
1708
  */
1634
1709
  class Client {
1635
1710
  #client;
1711
+ #codecRegistry;
1636
1712
  #conversations;
1637
1713
  #debugInformation;
1638
1714
  #preferences;
1639
1715
  #signer;
1640
- #codecs;
1641
1716
  #identifier;
1642
1717
  #options;
1643
1718
  /**
@@ -1650,8 +1725,7 @@ class Client {
1650
1725
  */
1651
1726
  constructor(options) {
1652
1727
  this.#options = options;
1653
- const codecs = [...(options?.codecs ?? [])];
1654
- this.#codecs = new Map(codecs.map((codec) => [contentTypeToString(codec.contentType), codec]));
1728
+ this.#codecRegistry = new CodecRegistry([...(options?.codecs ?? [])]);
1655
1729
  }
1656
1730
  /**
1657
1731
  * Initializes the client with the provided identifier
@@ -1668,7 +1742,7 @@ class Client {
1668
1742
  this.#identifier = identifier;
1669
1743
  this.#client = await createClient(identifier, this.#options);
1670
1744
  const conversations = this.#client.conversations();
1671
- this.#conversations = new Conversations(this, conversations);
1745
+ this.#conversations = new Conversations(this, this.#codecRegistry, conversations);
1672
1746
  this.#debugInformation = new DebugInformation(this.#client);
1673
1747
  this.#preferences = new Preferences(this.#client, conversations);
1674
1748
  }
@@ -2023,7 +2097,7 @@ class Client {
2023
2097
  async unsafe_addAccount(newAccountSigner, allowInboxReassign = false) {
2024
2098
  // check for existing inbox id
2025
2099
  const identifier = await newAccountSigner.getIdentifier();
2026
- const existingInboxId = await this.getInboxIdByIdentifier(identifier);
2100
+ const existingInboxId = await this.fetchInboxIdByIdentifier(identifier);
2027
2101
  if (existingInboxId && !allowInboxReassign) {
2028
2102
  throw new AccountAlreadyAssociatedError(existingInboxId);
2029
2103
  }
@@ -2100,17 +2174,6 @@ class Client {
2100
2174
  }
2101
2175
  await applySignatureRequest(host, gatewayHost, signatureRequest);
2102
2176
  }
2103
- /**
2104
- * Gets the inbox state for the specified inbox IDs without a client
2105
- *
2106
- * @param env - The environment to use
2107
- * @param inboxIds - The inbox IDs to get the state for
2108
- * @returns The inbox state for the specified inbox IDs
2109
- */
2110
- static async inboxStateFromInboxIds(inboxIds, env, gatewayHost) {
2111
- const host = ApiUrls[env ?? "dev"];
2112
- return inboxStateFromInboxIds(host, gatewayHost, inboxIds);
2113
- }
2114
2177
  /**
2115
2178
  * Changes the recovery identifier for the client's inbox
2116
2179
  *
@@ -2140,129 +2203,28 @@ class Client {
2140
2203
  return new Map(Object.entries(canMessage));
2141
2204
  }
2142
2205
  /**
2143
- * Checks if the specified identifiers can be messaged
2144
- *
2145
- * @param identifiers - The identifiers to check
2146
- * @param env - Optional XMTP environment
2147
- * @returns Map of identifiers to whether they can be messaged
2148
- */
2149
- static async canMessage(identifiers, env) {
2150
- const canMessageMap = new Map();
2151
- for (const identifier of identifiers) {
2152
- const inboxId = await getInboxIdForIdentifier(identifier, env);
2153
- canMessageMap.set(identifier.identifier.toLowerCase(), inboxId !== null);
2154
- }
2155
- return canMessageMap;
2156
- }
2157
- /**
2158
- * Gets the key package statuses for the specified installation IDs
2206
+ * Fetches the key package statuses from the network for the specified
2207
+ * installation IDs
2159
2208
  *
2160
2209
  * @param installationIds - The installation IDs to check
2161
2210
  * @returns The key package statuses
2162
2211
  * @throws {ClientNotInitializedError} if the client is not initialized
2163
2212
  */
2164
- async getKeyPackageStatusesForInstallationIds(installationIds) {
2213
+ async fetchKeyPackageStatuses(installationIds) {
2165
2214
  if (!this.#client) {
2166
2215
  throw new ClientNotInitializedError();
2167
2216
  }
2168
2217
  return this.#client.getKeyPackageStatusesForInstallationIds(installationIds);
2169
2218
  }
2170
2219
  /**
2171
- * Gets the codec for a given content type
2172
- *
2173
- * @param contentType - The content type to get the codec for
2174
- * @returns The codec, if found
2175
- */
2176
- codecFor(contentType) {
2177
- return this.#codecs.get(contentTypeToString(contentType));
2178
- }
2179
- /**
2180
- * Encodes content for a given content type
2181
- *
2182
- * @param content - The content to encode
2183
- * @param contentType - The content type to encode for
2184
- * @returns The encoded content
2185
- * @throws {CodecNotFoundError} if no codec is found for the content type
2186
- */
2187
- encodeContent(content, contentType) {
2188
- const codec = this.codecFor(contentType);
2189
- if (!codec) {
2190
- throw new CodecNotFoundError(contentType);
2191
- }
2192
- return this.#encodeWithCodec(content, codec);
2193
- }
2194
- /**
2195
- * Prepares content for sending by encoding it and generating send options from the codec
2196
- *
2197
- * @param content - The message content to prepare for sending
2198
- * @param contentType - The content type identifier for the appropriate codec
2199
- * @returns An object containing the encoded content and send options
2200
- * @throws {CodecNotFoundError} When no codec is registered for the specified content type
2201
- */
2202
- prepareForSend(content, contentType) {
2203
- const codec = this.codecFor(contentType);
2204
- if (!codec) {
2205
- throw new CodecNotFoundError(contentType);
2206
- }
2207
- return {
2208
- encodedContent: this.#encodeWithCodec(content, codec),
2209
- sendOptions: this.#sendMessageOpts(content, codec),
2210
- };
2211
- }
2212
- /**
2213
- * Encodes content using a specific codec and adds fallback information if available
2214
- *
2215
- * @param content - The content to encode
2216
- * @param codec - The codec to use for encoding
2217
- * @returns The encoded content with optional fallback
2218
- */
2219
- #encodeWithCodec(content, codec) {
2220
- const encoded = codec.encode(content);
2221
- const fallback = codec.fallback(content);
2222
- if (fallback) {
2223
- encoded.fallback = fallback;
2224
- }
2225
- return encoded;
2226
- }
2227
- /**
2228
- * Generates send options based on the content and codec
2229
- *
2230
- * @param content - The content being sent
2231
- * @param codec - The codec used for the content
2232
- * @returns Send options including whether to push notify recipients
2233
- */
2234
- #sendMessageOpts(content, codec) {
2235
- return { shouldPush: codec.shouldPush(content) };
2236
- }
2237
- /**
2238
- * Decodes a message for a given content type
2239
- *
2240
- * @param message - The message to decode
2241
- * @param contentType - The content type to decode for
2242
- * @returns The decoded content
2243
- * @throws {CodecNotFoundError} if no codec is found for the content type
2244
- * @throws {InvalidGroupMembershipChangeError} if the message is an invalid group membership change
2245
- */
2246
- decodeContent(message, contentType) {
2247
- const codec = this.codecFor(contentType);
2248
- if (!codec) {
2249
- throw new CodecNotFoundError(contentType);
2250
- }
2251
- // throw an error if there's an invalid group membership change message
2252
- if (contentTypesAreEqual(contentType, groupUpdatedContentType()) &&
2253
- message.kind !== 1 /* GroupMessageKind.MembershipChange */) {
2254
- throw new InvalidGroupMembershipChangeError(message.id);
2255
- }
2256
- return codec.decode(message.content);
2257
- }
2258
- /**
2259
- * Finds the inbox ID for a given identifier
2220
+ * Fetches the inbox ID for a given identifier from the local database
2221
+ * If not found, fetches from the network
2260
2222
  *
2261
2223
  * @param identifier - The identifier to look up
2262
2224
  * @returns The inbox ID, if found
2263
2225
  * @throws {ClientNotInitializedError} if the client is not initialized
2264
2226
  */
2265
- async getInboxIdByIdentifier(identifier) {
2227
+ async fetchInboxIdByIdentifier(identifier) {
2266
2228
  if (!this.#client) {
2267
2229
  throw new ClientNotInitializedError();
2268
2230
  }
@@ -2301,6 +2263,33 @@ class Client {
2301
2263
  return false;
2302
2264
  }
2303
2265
  }
2266
+ /**
2267
+ * Fetches the inbox states for the specified inbox IDs from the network
2268
+ * without a client
2269
+ *
2270
+ * @param env - The environment to use
2271
+ * @param inboxIds - The inbox IDs to get the state for
2272
+ * @returns The inbox states for the specified inbox IDs
2273
+ */
2274
+ static async fetchInboxStates(inboxIds, env, gatewayHost) {
2275
+ const host = ApiUrls[env ?? "dev"];
2276
+ return inboxStateFromInboxIds(host, gatewayHost, inboxIds);
2277
+ }
2278
+ /**
2279
+ * Checks if the specified identifiers can be messaged
2280
+ *
2281
+ * @param identifiers - The identifiers to check
2282
+ * @param env - Optional XMTP environment
2283
+ * @returns Map of identifiers to whether they can be messaged
2284
+ */
2285
+ static async canMessage(identifiers, env) {
2286
+ const canMessageMap = new Map();
2287
+ for (const identifier of identifiers) {
2288
+ const inboxId = await getInboxIdForIdentifier(identifier, env);
2289
+ canMessageMap.set(identifier.identifier.toLowerCase(), inboxId !== null);
2290
+ }
2291
+ return canMessageMap;
2292
+ }
2304
2293
  /**
2305
2294
  * Verifies a signature was made with a public key
2306
2295
  *
@@ -2344,5 +2333,5 @@ class Client {
2344
2333
  }
2345
2334
  }
2346
2335
 
2347
- export { AccountAlreadyAssociatedError, ApiUrls, Client, ClientNotInitializedError, CodecNotFoundError, Conversation, Conversations, DecodedMessage, Dm, Group, HistorySyncUrls, InboxReassignError, InvalidGroupMembershipChangeError, MissingContentTypeError, SignerUnavailableError, StreamFailedError, StreamInvalidRetryAttemptsError, generateInboxId, getInboxIdForIdentifier, isHexString, validHex };
2336
+ export { AccountAlreadyAssociatedError, ApiUrls, Client, ClientNotInitializedError, Conversation, Conversations, DecodedMessage, Dm, Group, HistorySyncUrls, InboxReassignError, MissingContentTypeError, SignerUnavailableError, StreamFailedError, StreamInvalidRetryAttemptsError, generateInboxId, getInboxIdForIdentifier, isHexString, validHex };
2348
2337
  //# sourceMappingURL=index.js.map