@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.d.ts +295 -229
- package/dist/index.js +481 -373
- package/dist/index.js.map +1 -1
- package/package.json +11 -14
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,
|
|
5
|
-
import {
|
|
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 /
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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
|
-
|
|
192
|
+
numReplies;
|
|
193
|
+
reactions;
|
|
72
194
|
senderInboxId;
|
|
73
195
|
sentAt;
|
|
74
196
|
sentAtNs;
|
|
75
|
-
constructor(
|
|
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.
|
|
205
|
+
this.conversationId = message.conversationId;
|
|
81
206
|
this.senderInboxId = message.senderInboxId;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
switch (message.
|
|
92
|
-
case
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
115
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
*
|
|
676
|
+
* Sends a message with configurable delivery behavior
|
|
562
677
|
*
|
|
563
|
-
* @param
|
|
564
|
-
* @param
|
|
565
|
-
* @
|
|
566
|
-
*
|
|
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
|
-
|
|
569
|
-
if (
|
|
686
|
+
async send(encodedContent, sendOptions) {
|
|
687
|
+
if (!encodedContent.type) {
|
|
570
688
|
throw new MissingContentTypeError();
|
|
571
689
|
}
|
|
572
|
-
|
|
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
|
-
*
|
|
693
|
+
* Sends a text message
|
|
580
694
|
*
|
|
581
|
-
* @param
|
|
582
|
-
* @param
|
|
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
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
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.
|
|
604
|
-
return messages.map((message) => new DecodedMessage(this.#
|
|
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
|
-
|
|
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,
|
|
719
|
-
super(client,
|
|
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
|
|
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,
|
|
752
|
-
super(client,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
973
|
-
|
|
974
|
-
|
|
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
|
|
1005
|
-
const inboxId = await this.#client.
|
|
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
|
-
//
|
|
1021
|
-
const message = this.#conversations.
|
|
1022
|
-
return new DecodedMessage(this.#
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1105
|
-
return new Dm(this.#client,
|
|
1106
|
-
case
|
|
1107
|
-
return new Group(this.#client,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
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(
|
|
1373
|
-
return this.#client.inboxState(
|
|
1589
|
+
async inboxState() {
|
|
1590
|
+
return this.#client.inboxState(false);
|
|
1374
1591
|
}
|
|
1375
1592
|
/**
|
|
1376
|
-
*
|
|
1593
|
+
* Retrieves the latest inbox state of this clientfrom the network
|
|
1377
1594
|
*
|
|
1378
|
-
* @
|
|
1379
|
-
* @returns Promise that resolves with the latest inbox state
|
|
1595
|
+
* @returns Promise that resolves with the inbox state
|
|
1380
1596
|
*/
|
|
1381
|
-
async
|
|
1382
|
-
return this.#client.
|
|
1597
|
+
async fetchInboxState() {
|
|
1598
|
+
return this.#client.inboxState(true);
|
|
1383
1599
|
}
|
|
1384
1600
|
/**
|
|
1385
|
-
* Retrieves inbox
|
|
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
|
-
* @
|
|
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
|
|
1392
|
-
return this.#client.addressesFromInboxId(
|
|
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 ?? "
|
|
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
|
-
? "
|
|
1493
|
-
: "
|
|
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?.
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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,
|
|
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
|