@xmtp/node-sdk 4.6.0 → 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,8 +1,6 @@
1
- import { GroupUpdatedCodec, ContentTypeGroupUpdated } from '@xmtp/content-type-group-updated';
2
- import { ContentTypeText, TextCodec } from '@xmtp/content-type-text';
3
1
  import { generateInboxId as generateInboxId$1, getInboxIdForIdentifier as getInboxIdForIdentifier$1, createClient as createClient$1, revokeInstallationsSignatureRequest, applySignatureRequest, inboxStateFromInboxIds, verifySignedWithPublicKey, isAddressAuthorized, isInstallationAuthorized } from '@xmtp/node-bindings';
4
- export { ConsentEntityType, ConsentState, ConversationType, DeliveryStatus, GroupMember, GroupMembershipState, GroupMessageKind, GroupMetadata, GroupPermissions, GroupPermissionsOptions, IdentifierKind, LogLevel, MetadataField, PermissionLevel, PermissionPolicy, PermissionUpdateType, SignatureRequestHandle, SortDirection } from '@xmtp/node-bindings';
5
- import { ContentTypeId } from '@xmtp/content-type-primitives';
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';
6
4
  import { isPromise } from 'node:util/types';
7
5
  import { join } from 'node:path';
8
6
  import process from 'node:process';
@@ -34,137 +32,245 @@ const HistorySyncUrls = {
34
32
  production: "https://message-history.production.ephemera.network",
35
33
  };
36
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
+
37
107
  function nsToDate(ns) {
38
- return new Date(ns / 1_000_000);
108
+ return new Date(Number(ns / 1000000n));
39
109
  }
40
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
+ };
41
163
  /**
42
164
  * Represents a decoded XMTP message
43
165
  *
44
- * This class transforms network messages into a structured format with
45
- * content decoding.
46
- *
47
166
  * @class
48
- * @property {any} content - The decoded content of the message
167
+ * @property {unknown} content - The decoded content of the message
49
168
  * @property {ContentTypeId} contentType - The content type of the message content
50
169
  * @property {string} conversationId - Unique identifier for the conversation
51
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
52
173
  * @property {string} [fallback] - Optional fallback text for the message
53
- * @property {number} [compression] - Optional compression level applied to the message
54
174
  * @property {string} id - Unique identifier for the message
55
175
  * @property {MessageKind} kind - Type of message ("application" | "membership_change")
56
- * @property {Record<string, string>} parameters - Additional parameters associated with the message
176
+ * @property {number} numReplies - Number of replies to the message
177
+ * @property {DecodedMessage<Reaction>[]} reactions - Reactions to the message
57
178
  * @property {string} senderInboxId - Identifier for the sender's inbox
58
179
  * @property {Date} sentAt - Timestamp when the message was sent
59
- * @property {number} sentAtNs - Timestamp when the message was sent (in nanoseconds)
180
+ * @property {bigint} sentAtNs - Timestamp when the message was sent (in nanoseconds)
60
181
  */
61
182
  class DecodedMessage {
62
- #client;
63
183
  content;
64
184
  contentType;
65
185
  conversationId;
66
186
  deliveryStatus;
187
+ expiresAtNs;
188
+ expiresAt;
67
189
  fallback;
68
- compression;
69
190
  id;
70
191
  kind;
71
- parameters;
192
+ numReplies;
193
+ reactions;
72
194
  senderInboxId;
73
195
  sentAt;
74
196
  sentAtNs;
75
- constructor(client, message) {
76
- this.#client = client;
197
+ constructor(codecRegistry, message) {
77
198
  this.id = message.id;
199
+ this.expiresAtNs = message.expiresAtNs ?? undefined;
200
+ this.expiresAt = message.expiresAtNs
201
+ ? nsToDate(message.expiresAtNs)
202
+ : undefined;
78
203
  this.sentAtNs = message.sentAtNs;
79
204
  this.sentAt = nsToDate(message.sentAtNs);
80
- this.conversationId = message.convoId;
205
+ this.conversationId = message.conversationId;
81
206
  this.senderInboxId = message.senderInboxId;
82
- switch (message.kind) {
83
- case 0 /* GroupMessageKind.Application */:
84
- this.kind = "application";
85
- break;
86
- case 1 /* GroupMessageKind.MembershipChange */:
87
- this.kind = "membership_change";
88
- break;
89
- // no default
90
- }
91
- switch (message.deliveryStatus) {
92
- case 0 /* DeliveryStatus.Unpublished */:
93
- this.deliveryStatus = "unpublished";
94
- break;
95
- case 1 /* DeliveryStatus.Published */:
96
- this.deliveryStatus = "published";
97
- break;
98
- case 2 /* DeliveryStatus.Failed */:
99
- this.deliveryStatus = "failed";
207
+ this.contentType = message.contentType;
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;
216
+ switch (message.content.type) {
217
+ case "Reply" /* DecodedMessageContentType.Reply */: {
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
+ };
100
243
  break;
101
- // no default
102
- }
103
- this.contentType = message.content.type
104
- ? new ContentTypeId(message.content.type)
105
- : undefined;
106
- this.parameters = message.content.parameters;
107
- this.fallback = message.content.fallback;
108
- this.compression = message.content.compression;
109
- this.content = undefined;
110
- if (this.contentType) {
111
- try {
112
- this.content = this.#client.decodeContent(message, this.contentType);
113
244
  }
114
- catch {
115
- this.content = undefined;
245
+ case "Custom" /* DecodedMessageContentType.Custom */: {
246
+ const customContent = message.content.custom;
247
+ if (customContent !== null) {
248
+ const codec = codecRegistry.getCodec(this.contentType);
249
+ if (codec) {
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;
266
+ }
267
+ }
268
+ break;
116
269
  }
117
270
  }
118
271
  }
119
272
  }
120
273
 
121
- class CodecNotFoundError extends Error {
122
- constructor(contentType) {
123
- super(`Codec not found for "${contentType.toString()}" content type`);
124
- }
125
- }
126
- class InboxReassignError extends Error {
127
- constructor() {
128
- super("Unable to create add account signature text, `allowInboxReassign` must be true");
129
- }
130
- }
131
- class AccountAlreadyAssociatedError extends Error {
132
- constructor(inboxId) {
133
- super(`Account already associated with inbox ${inboxId}`);
134
- }
135
- }
136
- class InvalidGroupMembershipChangeError extends Error {
137
- constructor(messageId) {
138
- super(`Invalid group membership change for message ${messageId}`);
139
- }
140
- }
141
- class MissingContentTypeError extends Error {
142
- constructor() {
143
- super("Content type is required when sending content other than text");
144
- }
145
- }
146
- class SignerUnavailableError extends Error {
147
- constructor() {
148
- super("Signer unavailable, use Client.create to create a client with a signer");
149
- }
150
- }
151
- class ClientNotInitializedError extends Error {
152
- constructor() {
153
- super("Client not initialized, use Client.create or Client.build to create a client");
154
- }
155
- }
156
- class StreamFailedError extends Error {
157
- constructor(retryAttempts) {
158
- const times = `time${retryAttempts !== 1 ? "s" : ""}`;
159
- super(`Stream failed, retried ${retryAttempts} ${times}`);
160
- }
161
- }
162
- class StreamInvalidRetryAttemptsError extends Error {
163
- constructor() {
164
- super("Stream retry attempts must be greater than 0");
165
- }
166
- }
167
-
168
274
  /**
169
275
  * AsyncStream provides an async iterable interface for streaming data.
170
276
  *
@@ -456,19 +562,19 @@ const createStream = async (streamFunction, streamValueMutator, options) => {
456
562
  */
457
563
  class Conversation {
458
564
  #client;
565
+ #codecRegistry;
459
566
  #conversation;
460
- #isCommitLogForked = null;
461
567
  /**
462
568
  * Creates a new conversation instance
463
569
  *
464
570
  * @param client - The client instance managing the conversation
571
+ * @param codecRegistry - The codec registry instance
465
572
  * @param conversation - The underlying conversation instance
466
- * @param isCommitLogForked
467
573
  */
468
- constructor(client, conversation, isCommitLogForked) {
574
+ constructor(client, codecRegistry, conversation) {
469
575
  this.#client = client;
576
+ this.#codecRegistry = codecRegistry;
470
577
  this.#conversation = conversation;
471
- this.#isCommitLogForked = isCommitLogForked ?? null;
472
578
  }
473
579
  /**
474
580
  * Gets the unique identifier for this conversation
@@ -482,9 +588,6 @@ class Conversation {
482
588
  get isActive() {
483
589
  return this.#conversation.isActive();
484
590
  }
485
- get isCommitLogForked() {
486
- return this.#isCommitLogForked;
487
- }
488
591
  /**
489
592
  * Gets the inbox ID that added this client's inbox to the conversation
490
593
  */
@@ -503,6 +606,17 @@ class Conversation {
503
606
  get createdAt() {
504
607
  return nsToDate(this.createdAtNs);
505
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
+ }
506
620
  /**
507
621
  * Gets the metadata for this conversation
508
622
  *
@@ -545,7 +659,8 @@ class Conversation {
545
659
  return this.#conversation.stream(callback, onFail);
546
660
  };
547
661
  const convertMessage = (value) => {
548
- return new DecodedMessage(this.#client, value);
662
+ const enrichedMessage = this.#client.conversations.getMessageById(value.id);
663
+ return enrichedMessage ?? value;
549
664
  };
550
665
  return createStream(stream, convertMessage, options);
551
666
  }
@@ -558,40 +673,141 @@ class Conversation {
558
673
  return this.#conversation.publishMessages();
559
674
  }
560
675
  /**
561
- * Prepares a message to be published
676
+ * Sends a message with configurable delivery behavior
562
677
  *
563
- * @param content - The content to send
564
- * @param contentType - Optional content type of the message content
565
- * @returns Promise that resolves with the message ID
566
- * @throws {MissingContentTypeError} if content type is required but not provided
678
+ * @param encodedContent - The encoded content to send
679
+ * @param sendOptions - Options for sending the message
680
+ * @param sendOptions.shouldPush - Indicates whether this message should be
681
+ * included in push notifications
682
+ * @param sendOptions.isOptimistic - Indicates whether this message should be
683
+ * sent optimistically and published later via `publishMessages`
684
+ * @returns Promise that resolves with the message ID after it has been sent
567
685
  */
568
- sendOptimistic(content, contentType) {
569
- if (typeof content !== "string" && !contentType) {
686
+ async send(encodedContent, sendOptions) {
687
+ if (!encodedContent.type) {
570
688
  throw new MissingContentTypeError();
571
689
  }
572
- const { encodedContent, sendOptions } = typeof content === "string"
573
- ? this.#client.prepareForSend(content, contentType ?? ContentTypeText)
574
- : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
575
- this.#client.prepareForSend(content, contentType);
576
- return this.#conversation.sendOptimistic(encodedContent, sendOptions);
690
+ return this.#conversation.send(encodedContent, sendOptions ?? { shouldPush: false });
577
691
  }
578
692
  /**
579
- * Publishes a new message
693
+ * Sends a text message
580
694
  *
581
- * @param content - The content to send
582
- * @param contentType - Optional content type of the message content
695
+ * @param text - The text to send
696
+ * @param isOptimistic - Whether to send the message optimistically
583
697
  * @returns Promise that resolves with the message ID after it has been sent
584
- * @throws {MissingContentTypeError} if content type is required but not provided
585
698
  */
586
- async send(content, contentType) {
587
- if (typeof content !== "string" && !contentType) {
588
- throw new MissingContentTypeError();
589
- }
590
- const { encodedContent, sendOptions } = typeof content === "string"
591
- ? this.#client.prepareForSend(content, contentType ?? ContentTypeText)
592
- : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
593
- this.#client.prepareForSend(content, contentType);
594
- return this.#conversation.send(encodedContent, sendOptions);
699
+ async sendText(text, isOptimistic) {
700
+ return this.#conversation.sendText(text, isOptimistic);
701
+ }
702
+ /**
703
+ * Sends a markdown message
704
+ *
705
+ * @param markdown - The markdown to send
706
+ * @param isOptimistic - Whether to send the message optimistically
707
+ * @returns Promise that resolves with the message ID after it has been sent
708
+ */
709
+ async sendMarkdown(markdown, isOptimistic) {
710
+ return this.#conversation.sendMarkdown(markdown, isOptimistic);
711
+ }
712
+ /**
713
+ * Sends a reaction message
714
+ *
715
+ * @param reaction - The reaction to send
716
+ * @param isOptimistic - Whether to send the message optimistically
717
+ * @returns Promise that resolves with the message ID after it has been sent
718
+ */
719
+ async sendReaction(reaction, isOptimistic) {
720
+ return this.#conversation.sendReaction(reaction, isOptimistic);
721
+ }
722
+ /**
723
+ * Sends a read receipt message
724
+ *
725
+ * @param readReceipt - The read receipt to send
726
+ * @param isOptimistic - Whether to send the message optimistically
727
+ * @returns Promise that resolves with the message ID after it has been sent
728
+ */
729
+ async sendReadReceipt(isOptimistic) {
730
+ return this.#conversation.sendReadReceipt(isOptimistic);
731
+ }
732
+ /**
733
+ * Sends a reply message
734
+ *
735
+ * @param reply - The reply to send
736
+ * @param isOptimistic - Whether to send the message optimistically
737
+ * @returns Promise that resolves with the message ID after it has been sent
738
+ */
739
+ async sendReply(reply, isOptimistic) {
740
+ return this.#conversation.sendReply(reply, isOptimistic);
741
+ }
742
+ /**
743
+ * Sends a transaction reference message
744
+ *
745
+ * @param transactionReference - The transaction reference to send
746
+ * @param isOptimistic - Whether to send the message optimistically
747
+ * @returns Promise that resolves with the message ID after it has been sent
748
+ */
749
+ async sendTransactionReference(transactionReference, isOptimistic) {
750
+ return this.#conversation.sendTransactionReference(transactionReference, isOptimistic);
751
+ }
752
+ /**
753
+ * Sends a wallet send calls message
754
+ *
755
+ * @param walletSendCalls - The wallet send calls to send
756
+ * @param isOptimistic - Whether to send the message optimistically
757
+ * @returns Promise that resolves with the message ID after it has been sent
758
+ */
759
+ async sendWalletSendCalls(walletSendCalls, isOptimistic) {
760
+ return this.#conversation.sendWalletSendCalls(walletSendCalls, isOptimistic);
761
+ }
762
+ /**
763
+ * Sends a actions message
764
+ *
765
+ * @param actions - The actions to send
766
+ * @param isOptimistic - Whether to send the message optimistically
767
+ * @returns Promise that resolves with the message ID after it has been sent
768
+ */
769
+ async sendActions(actions, isOptimistic) {
770
+ return this.#conversation.sendActions(actions, isOptimistic);
771
+ }
772
+ /**
773
+ * Sends a intent message
774
+ *
775
+ * @param intent - The intent to send
776
+ * @param isOptimistic - Whether to send the message optimistically
777
+ * @returns Promise that resolves with the message ID after it has been sent
778
+ */
779
+ async sendIntent(intent, isOptimistic) {
780
+ return this.#conversation.sendIntent(intent, isOptimistic);
781
+ }
782
+ /**
783
+ * Sends an attachment message
784
+ *
785
+ * @param attachment - The attachment to send
786
+ * @param isOptimistic - Whether to send the message optimistically
787
+ * @returns Promise that resolves with the message ID after it has been sent
788
+ */
789
+ async sendAttachment(attachment, isOptimistic) {
790
+ return this.#conversation.sendAttachment(attachment, isOptimistic);
791
+ }
792
+ /**
793
+ * Sends a multi remote attachment message
794
+ *
795
+ * @param multiRemoteAttachment - The multi remote attachment to send
796
+ * @param isOptimistic - Whether to send the message optimistically
797
+ * @returns Promise that resolves with the message ID after it has been sent
798
+ */
799
+ async sendMultiRemoteAttachment(multiRemoteAttachment, isOptimistic) {
800
+ return this.#conversation.sendMultiRemoteAttachment(multiRemoteAttachment, isOptimistic);
801
+ }
802
+ /**
803
+ * Sends a remote attachment message
804
+ *
805
+ * @param remoteAttachment - The remote attachment to send
806
+ * @param isOptimistic - Whether to send the message optimistically
807
+ * @returns Promise that resolves with the message ID after it has been sent
808
+ */
809
+ async sendRemoteAttachment(remoteAttachment, isOptimistic) {
810
+ return this.#conversation.sendRemoteAttachment(remoteAttachment, isOptimistic);
595
811
  }
596
812
  /**
597
813
  * Lists messages in this conversation
@@ -600,8 +816,8 @@ class Conversation {
600
816
  * @returns Promise that resolves with an array of decoded messages
601
817
  */
602
818
  async messages(options) {
603
- const messages = await this.#conversation.findMessages(options);
604
- return messages.map((message) => new DecodedMessage(this.#client, message));
819
+ const messages = await this.#conversation.findEnrichedMessages(options);
820
+ return messages.map((message) => new DecodedMessage(this.#codecRegistry, message));
605
821
  }
606
822
  /**
607
823
  * Counts messages in this conversation
@@ -631,7 +847,7 @@ class Conversation {
631
847
  /**
632
848
  * Gets the consent state for this conversation
633
849
  */
634
- get consentState() {
850
+ consentState() {
635
851
  return this.#conversation.consentState();
636
852
  }
637
853
  /**
@@ -679,17 +895,6 @@ class Conversation {
679
895
  isMessageDisappearingEnabled() {
680
896
  return this.#conversation.isMessageDisappearingEnabled();
681
897
  }
682
- pausedForVersion() {
683
- return this.#conversation.pausedForVersion() ?? undefined;
684
- }
685
- /**
686
- * Retrieves HMAC keys for this conversation
687
- *
688
- * @returns The HMAC keys for this conversation
689
- */
690
- getHmacKeys() {
691
- return this.#conversation.getHmacKeys();
692
- }
693
898
  /**
694
899
  * Retrieves information for this conversation to help with debugging
695
900
  *
@@ -698,6 +903,15 @@ class Conversation {
698
903
  async debugInfo() {
699
904
  return this.#conversation.debugInfo();
700
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
+ }
701
915
  }
702
916
 
703
917
  /**
@@ -707,17 +921,19 @@ class Conversation {
707
921
  */
708
922
  class Dm extends Conversation {
709
923
  #client;
924
+ #codecRegistry;
710
925
  #conversation;
711
926
  /**
712
927
  * Creates a new direct message conversation instance
713
928
  *
714
929
  * @param client - The client instance managing this direct message conversation
930
+ * @param codecRegistry - The codec registry instance
715
931
  * @param conversation - The underlying conversation instance
716
- * @param isCommitLogForked
717
932
  */
718
- constructor(client, conversation, isCommitLogForked) {
719
- super(client, conversation, isCommitLogForked);
933
+ constructor(client, codecRegistry, conversation) {
934
+ super(client, codecRegistry, conversation);
720
935
  this.#client = client;
936
+ this.#codecRegistry = codecRegistry;
721
937
  this.#conversation = conversation;
722
938
  }
723
939
  /**
@@ -728,9 +944,9 @@ class Dm extends Conversation {
728
944
  get peerInboxId() {
729
945
  return this.#conversation.dmPeerInboxId();
730
946
  }
731
- async getDuplicateDms() {
947
+ async duplicateDms() {
732
948
  const duplicateDms = await this.#conversation.findDuplicateDms();
733
- return duplicateDms.map((dm) => new Dm(this.#client, dm));
949
+ return duplicateDms.map((dm) => new Dm(this.#client, this.#codecRegistry, dm));
734
950
  }
735
951
  }
736
952
 
@@ -745,11 +961,11 @@ class Group extends Conversation {
745
961
  * Creates a new group conversation instance
746
962
  *
747
963
  * @param client - The client instance managing this group conversation
964
+ * @param codecRegistry - The codec registry instance
748
965
  * @param conversation - The underlying conversation object
749
- * @param isCommitLogForked
750
966
  */
751
- constructor(client, conversation, isCommitLogForked) {
752
- super(client, conversation, isCommitLogForked);
967
+ constructor(client, codecRegistry, conversation) {
968
+ super(client, codecRegistry, conversation);
753
969
  this.#conversation = conversation;
754
970
  }
755
971
  /**
@@ -811,7 +1027,7 @@ class Group extends Conversation {
811
1027
  /**
812
1028
  * The permissions of the group
813
1029
  */
814
- get permissions() {
1030
+ permissions() {
815
1031
  const permissions = this.#conversation.groupPermissions();
816
1032
  return {
817
1033
  policyType: permissions.policyType(),
@@ -831,13 +1047,13 @@ class Group extends Conversation {
831
1047
  /**
832
1048
  * The list of admins of the group
833
1049
  */
834
- get admins() {
1050
+ listAdmins() {
835
1051
  return this.#conversation.adminList();
836
1052
  }
837
1053
  /**
838
1054
  * The list of super admins of the group
839
1055
  */
840
- get superAdmins() {
1056
+ listSuperAdmins() {
841
1057
  return this.#conversation.superAdminList();
842
1058
  }
843
1059
  /**
@@ -933,7 +1149,7 @@ class Group extends Conversation {
933
1149
  *
934
1150
  * @returns Boolean
935
1151
  */
936
- get isPendingRemoval() {
1152
+ isPendingRemoval() {
937
1153
  return (this.#conversation.membershipState() ===
938
1154
  4 /* GroupMembershipState.PendingRemove */);
939
1155
  }
@@ -946,15 +1162,18 @@ class Group extends Conversation {
946
1162
  */
947
1163
  class Conversations {
948
1164
  #client;
1165
+ #codecRegistry;
949
1166
  #conversations;
950
1167
  /**
951
1168
  * Creates a new conversations instance
952
1169
  *
953
1170
  * @param client - The client instance managing the conversations
1171
+ * @param codecRegistry - The codec registry instance
954
1172
  * @param conversations - The underlying conversations instance
955
1173
  */
956
- constructor(client, conversations) {
1174
+ constructor(client, codecRegistry, conversations) {
957
1175
  this.#client = client;
1176
+ this.#codecRegistry = codecRegistry;
958
1177
  this.#conversations = conversations;
959
1178
  }
960
1179
  /**
@@ -969,9 +1188,14 @@ class Conversations {
969
1188
  // findGroupById will throw if group is not found
970
1189
  const group = this.#conversations.findGroupById(id);
971
1190
  const metadata = await group.groupMetadata();
972
- return metadata.conversationType() === "group"
973
- ? new Group(this.#client, group)
974
- : 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
+ }
975
1199
  }
976
1200
  catch {
977
1201
  return undefined;
@@ -988,7 +1212,7 @@ class Conversations {
988
1212
  try {
989
1213
  // findDmByTargetInboxId will throw if group is not found
990
1214
  const group = this.#conversations.findDmByTargetInboxId(inboxId);
991
- return new Dm(this.#client, group);
1215
+ return new Dm(this.#client, this.#codecRegistry, group);
992
1216
  }
993
1217
  catch {
994
1218
  return undefined;
@@ -1001,8 +1225,8 @@ class Conversations {
1001
1225
  * @returns Promise that resolves with the DM, if found
1002
1226
  * @see https://docs.xmtp.org/chat-apps/core-messaging/create-conversations#conversation-helper-methods
1003
1227
  */
1004
- async getDmByIdentifier(identifier) {
1005
- const inboxId = await this.#client.getInboxIdByIdentifier(identifier);
1228
+ async fetchDmByIdentifier(identifier) {
1229
+ const inboxId = await this.#client.fetchInboxIdByIdentifier(identifier);
1006
1230
  if (!inboxId) {
1007
1231
  return undefined;
1008
1232
  }
@@ -1017,24 +1241,24 @@ class Conversations {
1017
1241
  */
1018
1242
  getMessageById(id) {
1019
1243
  try {
1020
- // findMessageById will throw if message is not found
1021
- const message = this.#conversations.findMessageById(id);
1022
- return new DecodedMessage(this.#client, message);
1244
+ // findEnrichedMessageById will throw if message is not found
1245
+ const message = this.#conversations.findEnrichedMessageById(id);
1246
+ return new DecodedMessage(this.#codecRegistry, message);
1023
1247
  }
1024
1248
  catch {
1025
1249
  return undefined;
1026
1250
  }
1027
1251
  }
1028
1252
  /**
1029
- * Creates a new group conversation without syncing to the network
1253
+ * Creates a new group conversation without publishing to the network
1030
1254
  *
1031
1255
  * @param options - Optional group creation options
1032
1256
  * @returns The new group
1033
1257
  * @see https://docs.xmtp.org/chat-apps/core-messaging/create-conversations#optimistically-create-a-new-group-chat
1034
1258
  */
1035
- newGroupOptimistic(options) {
1259
+ createGroupOptimistic(options) {
1036
1260
  const group = this.#conversations.createGroupOptimistic(options);
1037
- return new Group(this.#client, group);
1261
+ return new Group(this.#client, this.#codecRegistry, group);
1038
1262
  }
1039
1263
  /**
1040
1264
  * Creates a new group conversation with the specified identifiers
@@ -1044,9 +1268,9 @@ class Conversations {
1044
1268
  * @returns The new group
1045
1269
  * @see https://docs.xmtp.org/chat-apps/core-messaging/create-conversations#create-a-new-group-chat
1046
1270
  */
1047
- async newGroupWithIdentifiers(identifiers, options) {
1271
+ async createGroupWithIdentifiers(identifiers, options) {
1048
1272
  const group = await this.#conversations.createGroup(identifiers, options);
1049
- const conversation = new Group(this.#client, group);
1273
+ const conversation = new Group(this.#client, this.#codecRegistry, group);
1050
1274
  return conversation;
1051
1275
  }
1052
1276
  /**
@@ -1057,9 +1281,9 @@ class Conversations {
1057
1281
  * @returns The new group
1058
1282
  * @see https://docs.xmtp.org/chat-apps/core-messaging/create-conversations#create-a-new-group-chat
1059
1283
  */
1060
- async newGroup(inboxIds, options) {
1284
+ async createGroup(inboxIds, options) {
1061
1285
  const group = await this.#conversations.createGroupByInboxId(inboxIds, options);
1062
- const conversation = new Group(this.#client, group);
1286
+ const conversation = new Group(this.#client, this.#codecRegistry, group);
1063
1287
  return conversation;
1064
1288
  }
1065
1289
  /**
@@ -1070,9 +1294,9 @@ class Conversations {
1070
1294
  * @returns The new DM
1071
1295
  * @see https://docs.xmtp.org/agents/build-agents/create-conversations#by-ethereum-address-1
1072
1296
  */
1073
- async newDmWithIdentifier(identifier, options) {
1297
+ async createDmWithIdentifier(identifier, options) {
1074
1298
  const group = await this.#conversations.createDm(identifier, options);
1075
- const conversation = new Dm(this.#client, group);
1299
+ const conversation = new Dm(this.#client, this.#codecRegistry, group);
1076
1300
  return conversation;
1077
1301
  }
1078
1302
  /**
@@ -1083,9 +1307,9 @@ class Conversations {
1083
1307
  * @returns The new DM
1084
1308
  * @see https://docs.xmtp.org/agents/build-agents/create-conversations#by-inbox-id-1
1085
1309
  */
1086
- async newDm(inboxId, options) {
1310
+ async createDm(inboxId, options) {
1087
1311
  const group = await this.#conversations.createDmByInboxId(inboxId, options);
1088
- const conversation = new Dm(this.#client, group);
1312
+ const conversation = new Dm(this.#client, this.#codecRegistry, group);
1089
1313
  return conversation;
1090
1314
  }
1091
1315
  /**
@@ -1101,10 +1325,10 @@ class Conversations {
1101
1325
  const metadata = await item.conversation.groupMetadata();
1102
1326
  const conversationType = metadata.conversationType();
1103
1327
  switch (conversationType) {
1104
- case "dm":
1105
- return new Dm(this.#client, item.conversation, item.isCommitLogForked);
1106
- case "group":
1107
- 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);
1108
1332
  default:
1109
1333
  return undefined;
1110
1334
  }
@@ -1124,7 +1348,7 @@ class Conversations {
1124
1348
  conversationType: 1 /* ConversationType.Group */,
1125
1349
  });
1126
1350
  return groups.map((item) => {
1127
- const conversation = new Group(this.#client, item.conversation, item.isCommitLogForked);
1351
+ const conversation = new Group(this.#client, this.#codecRegistry, item.conversation);
1128
1352
  return conversation;
1129
1353
  });
1130
1354
  }
@@ -1141,7 +1365,7 @@ class Conversations {
1141
1365
  conversationType: 0 /* ConversationType.Dm */,
1142
1366
  });
1143
1367
  return groups.map((item) => {
1144
- const conversation = new Dm(this.#client, item.conversation, item.isCommitLogForked);
1368
+ const conversation = new Dm(this.#client, this.#codecRegistry, item.conversation);
1145
1369
  return conversation;
1146
1370
  });
1147
1371
  }
@@ -1185,11 +1409,11 @@ class Conversations {
1185
1409
  const conversationType = metadata.conversationType();
1186
1410
  let conversation;
1187
1411
  switch (conversationType) {
1188
- case "dm":
1189
- conversation = new Dm(this.#client, value);
1412
+ case 0 /* ConversationType.Dm */:
1413
+ conversation = new Dm(this.#client, this.#codecRegistry, value);
1190
1414
  break;
1191
- case "group":
1192
- conversation = new Group(this.#client, value);
1415
+ case 1 /* ConversationType.Group */:
1416
+ conversation = new Group(this.#client, this.#codecRegistry, value);
1193
1417
  break;
1194
1418
  }
1195
1419
  return conversation;
@@ -1211,7 +1435,7 @@ class Conversations {
1211
1435
  return this.#conversations.stream(callback, onFail, 1 /* ConversationType.Group */);
1212
1436
  };
1213
1437
  const convertConversation = (value) => {
1214
- return new Group(this.#client, value);
1438
+ return new Group(this.#client, this.#codecRegistry, value);
1215
1439
  };
1216
1440
  return createStream(stream, convertConversation, options);
1217
1441
  }
@@ -1230,7 +1454,7 @@ class Conversations {
1230
1454
  return this.#conversations.stream(callback, onFail, 0 /* ConversationType.Dm */);
1231
1455
  };
1232
1456
  const convertConversation = (value) => {
1233
- return new Dm(this.#client, value);
1457
+ return new Dm(this.#client, this.#codecRegistry, value);
1234
1458
  };
1235
1459
  return createStream(stream, convertConversation, options);
1236
1460
  }
@@ -1251,7 +1475,8 @@ class Conversations {
1251
1475
  return this.#conversations.streamAllMessages(callback, onFail, options?.conversationType, options?.consentStates);
1252
1476
  };
1253
1477
  const convertMessage = (value) => {
1254
- return new DecodedMessage(this.#client, value);
1478
+ const enrichedMessage = this.getMessageById(value.id);
1479
+ return enrichedMessage ?? value;
1255
1480
  };
1256
1481
  return createStream(streamAllMessages, convertMessage, options);
1257
1482
  }
@@ -1301,7 +1526,7 @@ class Conversations {
1301
1526
  return createStream(stream, undefined, options);
1302
1527
  }
1303
1528
  /**
1304
- * Retrieves HMAC keys for all conversations
1529
+ * Gets the HMAC keys for all conversations
1305
1530
  *
1306
1531
  * @returns The HMAC keys for all conversations
1307
1532
  * @see https://docs.xmtp.org/chat-apps/push-notifs/push-notifs#get-hmac-keys-for-a-conversation
@@ -1318,10 +1543,8 @@ class Conversations {
1318
1543
  */
1319
1544
  class DebugInformation {
1320
1545
  #client;
1321
- #options;
1322
- constructor(client, options) {
1546
+ constructor(client) {
1323
1547
  this.#client = client;
1324
- this.#options = options;
1325
1548
  }
1326
1549
  apiStatistics() {
1327
1550
  return this.#client.apiStatistics();
@@ -1335,11 +1558,6 @@ class DebugInformation {
1335
1558
  clearAllStatistics() {
1336
1559
  this.#client.clearAllStatistics();
1337
1560
  }
1338
- uploadDebugArchive(serverUrl) {
1339
- const env = this.#options?.env || "dev";
1340
- const historySyncUrl = this.#options?.historySyncUrl || HistorySyncUrls[env];
1341
- return this.#client.uploadDebugArchive(serverUrl || historySyncUrl);
1342
- }
1343
1561
  }
1344
1562
 
1345
1563
  /**
@@ -1364,32 +1582,39 @@ class Preferences {
1364
1582
  return this.#client.syncPreferences();
1365
1583
  }
1366
1584
  /**
1367
- * Retrieves the current inbox state
1585
+ * Retrieves the current inbox state of this client from the local database
1368
1586
  *
1369
- * @param refreshFromNetwork - Optional flag to force refresh from network
1370
1587
  * @returns Promise that resolves with the inbox state
1371
1588
  */
1372
- async inboxState(refreshFromNetwork = false) {
1373
- return this.#client.inboxState(refreshFromNetwork);
1589
+ async inboxState() {
1590
+ return this.#client.inboxState(false);
1374
1591
  }
1375
1592
  /**
1376
- * Gets the latest inbox state for a specific inbox
1593
+ * Retrieves the latest inbox state of this clientfrom the network
1377
1594
  *
1378
- * @param inboxId - The inbox ID to get state for
1379
- * @returns Promise that resolves with the latest inbox state
1595
+ * @returns Promise that resolves with the inbox state
1380
1596
  */
1381
- async getLatestInboxState(inboxId) {
1382
- return this.#client.getLatestInboxState(inboxId);
1597
+ async fetchInboxState() {
1598
+ return this.#client.inboxState(true);
1383
1599
  }
1384
1600
  /**
1385
- * Retrieves inbox state for specific inbox IDs
1601
+ * Retrieves the current inbox states for specified inbox IDs from the local
1602
+ * database
1386
1603
  *
1387
1604
  * @param inboxIds - Array of inbox IDs to get state for
1388
- * @param refreshFromNetwork - Optional flag to force refresh from network
1389
- * @returns Promise that resolves with the inbox state for the inbox IDs
1605
+ * @returns Promise that resolves with the inbox states for the inbox IDs
1390
1606
  */
1391
- async inboxStateFromInboxIds(inboxIds, refreshFromNetwork) {
1392
- return this.#client.addressesFromInboxId(refreshFromNetwork ?? false, inboxIds);
1607
+ async getInboxStates(inboxIds) {
1608
+ return this.#client.addressesFromInboxId(false, inboxIds);
1609
+ }
1610
+ /**
1611
+ * Retrieves the latest inbox states for specified inbox IDs from the network
1612
+ *
1613
+ * @param inboxIds - Array of inbox IDs to get state for
1614
+ * @returns Promise that resolves with the inbox states for the inbox IDs
1615
+ */
1616
+ async fetchInboxStates(inboxIds) {
1617
+ return this.#client.addressesFromInboxId(true, inboxIds);
1393
1618
  }
1394
1619
  /**
1395
1620
  * Updates consent states for multiple records
@@ -1442,25 +1667,6 @@ class Preferences {
1442
1667
  }
1443
1668
  }
1444
1669
 
1445
- const generateInboxId = (identifier, nonce) => {
1446
- return generateInboxId$1(identifier, nonce);
1447
- };
1448
- const getInboxIdForIdentifier = async (identifier, env = "dev", gatewayHost) => {
1449
- const host = ApiUrls[env];
1450
- const isSecure = host.startsWith("https");
1451
- return getInboxIdForIdentifier$1(host, gatewayHost, isSecure, identifier);
1452
- };
1453
-
1454
- function isHexString(value) {
1455
- return typeof value === "string" && /^0x(?:[0-9a-fA-F]{2})+$/.test(value);
1456
- }
1457
- function validHex(value) {
1458
- if (!isHexString(value)) {
1459
- throw new TypeError(`Value is not a hexadecimal string.`);
1460
- }
1461
- return value;
1462
- }
1463
-
1464
1670
  const createClient = async (identifier, options) => {
1465
1671
  const env = options?.env || "dev";
1466
1672
  const host = options?.apiUrl || ApiUrls[env];
@@ -1483,18 +1689,18 @@ const createClient = async (identifier, options) => {
1483
1689
  }
1484
1690
  const logOptions = {
1485
1691
  structured: options?.structuredLogging ?? false,
1486
- level: options?.loggingLevel ?? "off" /* LogLevel.off */,
1692
+ level: options?.loggingLevel ?? "Off" /* LogLevel.Off */,
1487
1693
  };
1488
1694
  const historySyncUrl = options?.historySyncUrl === undefined
1489
1695
  ? HistorySyncUrls[env]
1490
1696
  : options.historySyncUrl;
1491
1697
  const deviceSyncWorkerMode = options?.disableDeviceSync
1492
- ? "disabled" /* SyncWorkerMode.disabled */
1493
- : "enabled" /* SyncWorkerMode.enabled */;
1698
+ ? "Disabled" /* SyncWorkerMode.Disabled */
1699
+ : "Enabled" /* SyncWorkerMode.Enabled */;
1494
1700
  const dbEncryptionKey = isHexString(options?.dbEncryptionKey)
1495
1701
  ? Buffer.from(options.dbEncryptionKey.replace(/^0x/, ""), "hex")
1496
1702
  : options?.dbEncryptionKey;
1497
- return createClient$1(host, gatewayHost, isSecure, dbPath, inboxId, identifier, dbEncryptionKey, historySyncUrl, deviceSyncWorkerMode, logOptions, undefined, options?.debugEventsEnabled, options?.appVersion);
1703
+ return createClient$1(host, gatewayHost, isSecure, dbPath, inboxId, identifier, dbEncryptionKey, historySyncUrl, deviceSyncWorkerMode, logOptions, undefined, options?.appVersion);
1498
1704
  };
1499
1705
 
1500
1706
  /**
@@ -1502,11 +1708,11 @@ const createClient = async (identifier, options) => {
1502
1708
  */
1503
1709
  class Client {
1504
1710
  #client;
1711
+ #codecRegistry;
1505
1712
  #conversations;
1506
1713
  #debugInformation;
1507
1714
  #preferences;
1508
1715
  #signer;
1509
- #codecs;
1510
1716
  #identifier;
1511
1717
  #options;
1512
1718
  /**
@@ -1519,12 +1725,7 @@ class Client {
1519
1725
  */
1520
1726
  constructor(options) {
1521
1727
  this.#options = options;
1522
- const codecs = [
1523
- new GroupUpdatedCodec(),
1524
- new TextCodec(),
1525
- ...(options?.codecs ?? []),
1526
- ];
1527
- this.#codecs = new Map(codecs.map((codec) => [codec.contentType.toString(), codec]));
1728
+ this.#codecRegistry = new CodecRegistry([...(options?.codecs ?? [])]);
1528
1729
  }
1529
1730
  /**
1530
1731
  * Initializes the client with the provided identifier
@@ -1541,8 +1742,8 @@ class Client {
1541
1742
  this.#identifier = identifier;
1542
1743
  this.#client = await createClient(identifier, this.#options);
1543
1744
  const conversations = this.#client.conversations();
1544
- this.#conversations = new Conversations(this, conversations);
1545
- this.#debugInformation = new DebugInformation(this.#client, this.#options);
1745
+ this.#conversations = new Conversations(this, this.#codecRegistry, conversations);
1746
+ this.#debugInformation = new DebugInformation(this.#client);
1546
1747
  this.#preferences = new Preferences(this.#client, conversations);
1547
1748
  }
1548
1749
  /**
@@ -1896,7 +2097,7 @@ class Client {
1896
2097
  async unsafe_addAccount(newAccountSigner, allowInboxReassign = false) {
1897
2098
  // check for existing inbox id
1898
2099
  const identifier = await newAccountSigner.getIdentifier();
1899
- const existingInboxId = await this.getInboxIdByIdentifier(identifier);
2100
+ const existingInboxId = await this.fetchInboxIdByIdentifier(identifier);
1900
2101
  if (existingInboxId && !allowInboxReassign) {
1901
2102
  throw new AccountAlreadyAssociatedError(existingInboxId);
1902
2103
  }
@@ -1973,17 +2174,6 @@ class Client {
1973
2174
  }
1974
2175
  await applySignatureRequest(host, gatewayHost, signatureRequest);
1975
2176
  }
1976
- /**
1977
- * Gets the inbox state for the specified inbox IDs without a client
1978
- *
1979
- * @param env - The environment to use
1980
- * @param inboxIds - The inbox IDs to get the state for
1981
- * @returns The inbox state for the specified inbox IDs
1982
- */
1983
- static async inboxStateFromInboxIds(inboxIds, env, gatewayHost) {
1984
- const host = ApiUrls[env ?? "dev"];
1985
- return inboxStateFromInboxIds(host, gatewayHost, inboxIds);
1986
- }
1987
2177
  /**
1988
2178
  * Changes the recovery identifier for the client's inbox
1989
2179
  *
@@ -2013,129 +2203,28 @@ class Client {
2013
2203
  return new Map(Object.entries(canMessage));
2014
2204
  }
2015
2205
  /**
2016
- * Checks if the specified identifiers can be messaged
2017
- *
2018
- * @param identifiers - The identifiers to check
2019
- * @param env - Optional XMTP environment
2020
- * @returns Map of identifiers to whether they can be messaged
2021
- */
2022
- static async canMessage(identifiers, env) {
2023
- const canMessageMap = new Map();
2024
- for (const identifier of identifiers) {
2025
- const inboxId = await getInboxIdForIdentifier(identifier, env);
2026
- canMessageMap.set(identifier.identifier.toLowerCase(), inboxId !== null);
2027
- }
2028
- return canMessageMap;
2029
- }
2030
- /**
2031
- * 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
2032
2208
  *
2033
2209
  * @param installationIds - The installation IDs to check
2034
2210
  * @returns The key package statuses
2035
2211
  * @throws {ClientNotInitializedError} if the client is not initialized
2036
2212
  */
2037
- async getKeyPackageStatusesForInstallationIds(installationIds) {
2213
+ async fetchKeyPackageStatuses(installationIds) {
2038
2214
  if (!this.#client) {
2039
2215
  throw new ClientNotInitializedError();
2040
2216
  }
2041
2217
  return this.#client.getKeyPackageStatusesForInstallationIds(installationIds);
2042
2218
  }
2043
2219
  /**
2044
- * Gets the codec for a given content type
2045
- *
2046
- * @param contentType - The content type to get the codec for
2047
- * @returns The codec, if found
2048
- */
2049
- codecFor(contentType) {
2050
- return this.#codecs.get(contentType.toString());
2051
- }
2052
- /**
2053
- * Encodes content for a given content type
2054
- *
2055
- * @param content - The content to encode
2056
- * @param contentType - The content type to encode for
2057
- * @returns The encoded content
2058
- * @throws {CodecNotFoundError} if no codec is found for the content type
2059
- */
2060
- encodeContent(content, contentType) {
2061
- const codec = this.codecFor(contentType);
2062
- if (!codec) {
2063
- throw new CodecNotFoundError(contentType);
2064
- }
2065
- return this.#encodeWithCodec(content, codec);
2066
- }
2067
- /**
2068
- * Prepares content for sending by encoding it and generating send options from the codec
2069
- *
2070
- * @param content - The message content to prepare for sending
2071
- * @param contentType - The content type identifier for the appropriate codec
2072
- * @returns An object containing the encoded content and send options
2073
- * @throws {CodecNotFoundError} When no codec is registered for the specified content type
2074
- */
2075
- prepareForSend(content, contentType) {
2076
- const codec = this.codecFor(contentType);
2077
- if (!codec) {
2078
- throw new CodecNotFoundError(contentType);
2079
- }
2080
- return {
2081
- encodedContent: this.#encodeWithCodec(content, codec),
2082
- sendOptions: this.#sendMessageOpts(content, codec),
2083
- };
2084
- }
2085
- /**
2086
- * Encodes content using a specific codec and adds fallback information if available
2087
- *
2088
- * @param content - The content to encode
2089
- * @param codec - The codec to use for encoding
2090
- * @returns The encoded content with optional fallback
2091
- */
2092
- #encodeWithCodec(content, codec) {
2093
- const encoded = codec.encode(content, this);
2094
- const fallback = codec.fallback(content);
2095
- if (fallback) {
2096
- encoded.fallback = fallback;
2097
- }
2098
- return encoded;
2099
- }
2100
- /**
2101
- * Generates send options based on the content and codec
2102
- *
2103
- * @param content - The content being sent
2104
- * @param codec - The codec used for the content
2105
- * @returns Send options including whether to push notify recipients
2106
- */
2107
- #sendMessageOpts(content, codec) {
2108
- return { shouldPush: codec.shouldPush(content) };
2109
- }
2110
- /**
2111
- * Decodes a message for a given content type
2112
- *
2113
- * @param message - The message to decode
2114
- * @param contentType - The content type to decode for
2115
- * @returns The decoded content
2116
- * @throws {CodecNotFoundError} if no codec is found for the content type
2117
- * @throws {InvalidGroupMembershipChangeError} if the message is an invalid group membership change
2118
- */
2119
- decodeContent(message, contentType) {
2120
- const codec = this.codecFor(contentType);
2121
- if (!codec) {
2122
- throw new CodecNotFoundError(contentType);
2123
- }
2124
- // throw an error if there's an invalid group membership change message
2125
- if (contentType.sameAs(ContentTypeGroupUpdated) &&
2126
- message.kind !== 1 /* GroupMessageKind.MembershipChange */) {
2127
- throw new InvalidGroupMembershipChangeError(message.id);
2128
- }
2129
- return codec.decode(message.content, this);
2130
- }
2131
- /**
2132
- * 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
2133
2222
  *
2134
2223
  * @param identifier - The identifier to look up
2135
2224
  * @returns The inbox ID, if found
2136
2225
  * @throws {ClientNotInitializedError} if the client is not initialized
2137
2226
  */
2138
- async getInboxIdByIdentifier(identifier) {
2227
+ async fetchInboxIdByIdentifier(identifier) {
2139
2228
  if (!this.#client) {
2140
2229
  throw new ClientNotInitializedError();
2141
2230
  }
@@ -2174,6 +2263,33 @@ class Client {
2174
2263
  return false;
2175
2264
  }
2176
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
+ }
2177
2293
  /**
2178
2294
  * Verifies a signature was made with a public key
2179
2295
  *
@@ -2215,15 +2331,7 @@ class Client {
2215
2331
  const host = ApiUrls[env ?? "dev"];
2216
2332
  return await isInstallationAuthorized(host, gatewayHost, inboxId, installation);
2217
2333
  }
2218
- /**
2219
- * Gets the version of the Node bindings
2220
- * @deprecated
2221
- */
2222
- static get version() {
2223
- console.warn("Client.version is deprecated. Use Client.libxmtpVersion instead.");
2224
- return undefined;
2225
- }
2226
2334
  }
2227
2335
 
2228
- 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 };
2229
2337
  //# sourceMappingURL=index.js.map