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