@xmtp/browser-sdk 5.1.0 → 5.3.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/src/Utils.ts CHANGED
@@ -37,12 +37,18 @@ export class Utils extends UtilsWorkerClass {
37
37
  *
38
38
  * @param identifier - The identifier to get the inbox ID for
39
39
  * @param env - Optional XMTP environment configuration (default: "dev")
40
+ * @param gatewayHost - Optional gateway host override
40
41
  * @returns Promise that resolves with the inbox ID for the identifier
41
42
  */
42
- async getInboxIdForIdentifier(identifier: Identifier, env?: XmtpEnv) {
43
+ async getInboxIdForIdentifier(
44
+ identifier: Identifier,
45
+ env?: XmtpEnv,
46
+ gatewayHost?: string,
47
+ ) {
43
48
  return this.sendMessage("utils.getInboxIdForIdentifier", {
44
49
  identifier,
45
50
  env,
51
+ gatewayHost,
46
52
  });
47
53
  }
48
54
 
@@ -59,6 +65,7 @@ export class Utils extends UtilsWorkerClass {
59
65
  * @param identifier - The identifier to revoke installations for
60
66
  * @param inboxId - The inbox ID to revoke installations for
61
67
  * @param installationIds - The installation IDs to revoke
68
+ * @param gatewayHost - Optional gateway host override
62
69
  * @returns The signature text and signature request ID
63
70
  */
64
71
  async revokeInstallationsSignatureText(
@@ -66,6 +73,7 @@ export class Utils extends UtilsWorkerClass {
66
73
  inboxId: string,
67
74
  installationIds: Uint8Array[],
68
75
  env?: XmtpEnv,
76
+ gatewayHost?: string,
69
77
  ) {
70
78
  return this.sendMessage("utils.revokeInstallationsSignatureText", {
71
79
  env,
@@ -73,6 +81,7 @@ export class Utils extends UtilsWorkerClass {
73
81
  inboxId,
74
82
  installationIds,
75
83
  signatureRequestId: v4(),
84
+ gatewayHost,
76
85
  });
77
86
  }
78
87
 
@@ -83,6 +92,7 @@ export class Utils extends UtilsWorkerClass {
83
92
  * @param signer - The signer to use
84
93
  * @param inboxId - The inbox ID to revoke installations for
85
94
  * @param installationIds - The installation IDs to revoke
95
+ * @param gatewayHost - Optional gateway host override
86
96
  * @returns Promise that resolves with the result of the revoke installations operation
87
97
  */
88
98
  async revokeInstallations(
@@ -90,6 +100,7 @@ export class Utils extends UtilsWorkerClass {
90
100
  inboxId: string,
91
101
  installationIds: Uint8Array[],
92
102
  env?: XmtpEnv,
103
+ gatewayHost?: string,
93
104
  ) {
94
105
  const identifier = await signer.getIdentifier();
95
106
  const { signatureText, signatureRequestId } =
@@ -98,6 +109,7 @@ export class Utils extends UtilsWorkerClass {
98
109
  inboxId,
99
110
  installationIds,
100
111
  env,
112
+ gatewayHost,
101
113
  );
102
114
  const signature = await signer.signMessage(signatureText);
103
115
  const safeSigner = await toSafeSigner(signer, signature);
@@ -106,6 +118,7 @@ export class Utils extends UtilsWorkerClass {
106
118
  signer: safeSigner,
107
119
  signatureRequestId,
108
120
  env,
121
+ gatewayHost,
109
122
  });
110
123
  }
111
124
 
@@ -116,10 +129,15 @@ export class Utils extends UtilsWorkerClass {
116
129
  * @param env - The environment to use
117
130
  * @returns The inbox state for the specified inbox IDs
118
131
  */
119
- async inboxStateFromInboxIds(inboxIds: string[], env?: XmtpEnv) {
132
+ async inboxStateFromInboxIds(
133
+ inboxIds: string[],
134
+ env?: XmtpEnv,
135
+ gatewayHost?: string,
136
+ ) {
120
137
  return this.sendMessage("utils.inboxStateFromInboxIds", {
121
138
  inboxIds,
122
139
  env,
140
+ gatewayHost,
123
141
  });
124
142
  }
125
143
  }
@@ -34,6 +34,14 @@ export class WorkerClient {
34
34
  return new WorkerClient(client, options);
35
35
  }
36
36
 
37
+ get libxmtpVersion() {
38
+ return this.#client.libxmtpVersion;
39
+ }
40
+
41
+ get appVersion() {
42
+ return this.#client.appVersion;
43
+ }
44
+
37
45
  get accountIdentifier() {
38
46
  return this.#client.accountIdentifier;
39
47
  }
@@ -1,4 +1,5 @@
1
1
  import {
2
+ GroupMembershipState,
2
3
  MessageDisappearingSettings,
3
4
  SortDirection,
4
5
  type ConsentState,
@@ -12,6 +13,7 @@ import {
12
13
  type MetadataField,
13
14
  type PermissionPolicy,
14
15
  type PermissionUpdateType,
16
+ type SendMessageOpts,
15
17
  } from "@xmtp/wasm-bindings";
16
18
  import {
17
19
  fromSafeListMessagesOptions,
@@ -64,6 +66,19 @@ export class WorkerConversation {
64
66
  return this.#group.updateGroupDescription(description);
65
67
  }
66
68
 
69
+ get appData() {
70
+ try {
71
+ return this.#group.appData();
72
+ } catch {
73
+ // DM groups don't support appData
74
+ return "";
75
+ }
76
+ }
77
+
78
+ async updateAppData(appData: string) {
79
+ return this.#group.updateAppData(appData);
80
+ }
81
+
67
82
  get isActive() {
68
83
  return this.#group.isActive();
69
84
  }
@@ -180,12 +195,14 @@ export class WorkerConversation {
180
195
  return this.#group.publishMessages();
181
196
  }
182
197
 
183
- sendOptimistic(encodedContent: EncodedContent) {
184
- return this.#group.sendOptimistic(encodedContent);
198
+ sendOptimistic(encodedContent: EncodedContent, opts: SendMessageOpts) {
199
+ // Pass through to underlying implementation - it will handle undefined opts
200
+ return this.#group.sendOptimistic(encodedContent, opts);
185
201
  }
186
202
 
187
- async send(encodedContent: EncodedContent) {
188
- return this.#group.send(encodedContent);
203
+ async send(encodedContent: EncodedContent, opts: SendMessageOpts) {
204
+ // Pass through to underlying implementation - it will handle undefined opts
205
+ return this.#group.send(encodedContent, opts);
189
206
  }
190
207
 
191
208
  async messages(options?: SafeListMessagesOptions) {
@@ -194,6 +211,12 @@ export class WorkerConversation {
194
211
  );
195
212
  }
196
213
 
214
+ async countMessages(options?: SafeListMessagesOptions) {
215
+ return this.#group.countMessages(
216
+ options ? fromSafeListMessagesOptions(options) : undefined,
217
+ );
218
+ }
219
+
197
220
  get consentState() {
198
221
  return this.#group.consentState();
199
222
  }
@@ -252,4 +275,12 @@ export class WorkerConversation {
252
275
  const dms = await this.#group.findDuplicateDms();
253
276
  return dms.map((dm) => new WorkerConversation(this.#client, dm));
254
277
  }
278
+
279
+ async requestRemoval() {
280
+ return this.#group.leaveGroup();
281
+ }
282
+
283
+ get isPendingRemoval() {
284
+ return this.#group.membershipState() === GroupMembershipState.PendingRemove;
285
+ }
255
286
  }
@@ -214,4 +214,17 @@ export class WorkerConversations {
214
214
  consentStates,
215
215
  );
216
216
  }
217
+
218
+ streamMessageDeletions(callback: StreamCallback<string>) {
219
+ const on_message_deleted = (messageId: string) => {
220
+ callback(null, messageId);
221
+ };
222
+ const on_error = (error: Error | null) => {
223
+ callback(error, undefined);
224
+ };
225
+ return this.#conversations.streamMessageDeletions({
226
+ on_message_deleted,
227
+ on_error,
228
+ });
229
+ }
217
230
  }
package/src/constants.ts CHANGED
@@ -7,9 +7,9 @@
7
7
  * @property {string} production - The production URL for the XMTP network
8
8
  */
9
9
  export const ApiUrls = {
10
- local: "http://localhost:5555",
11
- dev: "https://dev.xmtp.network",
12
- production: "https://production.xmtp.network",
10
+ local: "http://localhost:5557",
11
+ dev: "https://api.dev.xmtp.network:5558",
12
+ production: "https://api.production.xmtp.network:5558",
13
13
  } as const;
14
14
 
15
15
  /**
package/src/index.ts CHANGED
@@ -12,6 +12,7 @@ export type * from "./types/options";
12
12
  export * from "./utils/conversions";
13
13
  export type { AsyncStreamProxy } from "./AsyncStream";
14
14
  export type {
15
+ GroupSyncSummary,
15
16
  Identifier,
16
17
  IdentifierKind,
17
18
  UserPreference,
@@ -65,7 +65,7 @@ export type ClientAction =
65
65
  action: "client.revokeAllOtherInstallationsSignatureText";
66
66
  id: string;
67
67
  result: {
68
- signatureText: string;
68
+ signatureText: string | undefined;
69
69
  signatureRequestId: string;
70
70
  };
71
71
  data: {
@@ -210,4 +210,16 @@ export type ClientAction =
210
210
  data: {
211
211
  installationIds: string[];
212
212
  };
213
+ }
214
+ | {
215
+ action: "client.libxmtpVersion";
216
+ id: string;
217
+ result: string;
218
+ data: undefined;
219
+ }
220
+ | {
221
+ action: "client.appVersion";
222
+ id: string;
223
+ result: string;
224
+ data: undefined;
213
225
  };
@@ -8,6 +8,7 @@ import type {
8
8
  SafeListMessagesOptions,
9
9
  SafeMessage,
10
10
  SafeMessageDisappearingSettings,
11
+ SafeSendMessageOpts,
11
12
  } from "@/utils/conversions";
12
13
 
13
14
  export type ConversationAction =
@@ -26,6 +27,7 @@ export type ConversationAction =
26
27
  data: {
27
28
  id: string;
28
29
  content: SafeEncodedContent;
30
+ sendOptions: SafeSendMessageOpts;
29
31
  };
30
32
  }
31
33
  | {
@@ -35,6 +37,7 @@ export type ConversationAction =
35
37
  data: {
36
38
  id: string;
37
39
  content: SafeEncodedContent;
40
+ sendOptions: SafeSendMessageOpts;
38
41
  };
39
42
  }
40
43
  | {
@@ -54,6 +57,15 @@ export type ConversationAction =
54
57
  options?: SafeListMessagesOptions;
55
58
  };
56
59
  }
60
+ | {
61
+ action: "conversation.countMessages";
62
+ id: string;
63
+ result: bigint;
64
+ data: {
65
+ id: string;
66
+ options?: Omit<SafeListMessagesOptions, "limit" | "direction">;
67
+ };
68
+ }
57
69
  | {
58
70
  action: "conversation.members";
59
71
  id: string;
@@ -143,4 +143,12 @@ export type ConversationsAction =
143
143
  conversationType?: ConversationType;
144
144
  consentStates?: ConsentState[];
145
145
  };
146
+ }
147
+ | {
148
+ action: "conversations.streamMessageDeletions";
149
+ id: string;
150
+ result: undefined;
151
+ data: {
152
+ streamId: string;
153
+ };
146
154
  };
@@ -140,6 +140,15 @@ export type GroupAction =
140
140
  imageUrl: string;
141
141
  };
142
142
  }
143
+ | {
144
+ action: "group.updateAppData";
145
+ id: string;
146
+ result: undefined;
147
+ data: {
148
+ id: string;
149
+ appData: string;
150
+ };
151
+ }
143
152
  | {
144
153
  action: "group.updatePermission";
145
154
  id: string;
@@ -158,4 +167,20 @@ export type GroupAction =
158
167
  data: {
159
168
  id: string;
160
169
  };
170
+ }
171
+ | {
172
+ action: "group.requestRemoval";
173
+ id: string;
174
+ result: undefined;
175
+ data: {
176
+ id: string;
177
+ };
178
+ }
179
+ | {
180
+ action: "group.isPendingRemoval";
181
+ id: string;
182
+ result: boolean;
183
+ data: {
184
+ id: string;
185
+ };
161
186
  };
@@ -1,4 +1,8 @@
1
- import type { ConsentEntityType, ConsentState } from "@xmtp/wasm-bindings";
1
+ import type {
2
+ ConsentEntityType,
3
+ ConsentState,
4
+ GroupSyncSummary,
5
+ } from "@xmtp/wasm-bindings";
2
6
  import type { SafeConsent, SafeInboxState } from "@/utils/conversions";
3
7
 
4
8
  export type PreferencesAction =
@@ -47,7 +51,7 @@ export type PreferencesAction =
47
51
  | {
48
52
  action: "preferences.sync";
49
53
  id: string;
50
- result: number;
54
+ result: GroupSyncSummary;
51
55
  data: undefined;
52
56
  }
53
57
  | {
@@ -26,6 +26,11 @@ export type StreamAction =
26
26
  streamId: string;
27
27
  result: UserPreference[] | undefined;
28
28
  }
29
+ | {
30
+ action: "stream.messageDeleted";
31
+ streamId: string;
32
+ result: string | undefined;
33
+ }
29
34
  | {
30
35
  action: "stream.fail";
31
36
  streamId: string;
@@ -27,6 +27,7 @@ export type UtilsWorkerAction =
27
27
  data: {
28
28
  identifier: Identifier;
29
29
  env?: XmtpEnv;
30
+ gatewayHost?: string;
30
31
  };
31
32
  }
32
33
  | {
@@ -40,6 +41,7 @@ export type UtilsWorkerAction =
40
41
  env?: XmtpEnv;
41
42
  identifier: Identifier;
42
43
  inboxId: string;
44
+ gatewayHost?: string;
43
45
  installationIds: Uint8Array[];
44
46
  signatureRequestId: string;
45
47
  };
@@ -52,6 +54,7 @@ export type UtilsWorkerAction =
52
54
  env?: XmtpEnv;
53
55
  signer: SafeSigner;
54
56
  signatureRequestId: string;
57
+ gatewayHost?: string;
55
58
  };
56
59
  }
57
60
  | {
@@ -61,5 +64,6 @@ export type UtilsWorkerAction =
61
64
  data: {
62
65
  inboxIds: string[];
63
66
  env?: XmtpEnv;
67
+ gatewayHost?: string;
64
68
  };
65
69
  };
@@ -21,6 +21,10 @@ export type NetworkOptions = {
21
21
  * specific endpoint for syncing history
22
22
  */
23
23
  historySyncUrl?: string | null;
24
+ /**
25
+ * gatewayHost can be used to override the gateway endpoint
26
+ */
27
+ gatewayHost?: string | null;
24
28
  };
25
29
 
26
30
  export type ContentOptions = {
@@ -12,6 +12,7 @@ import {
12
12
  ListMessagesOptions,
13
13
  MessageDisappearingSettings,
14
14
  PermissionPolicySet,
15
+ SendMessageOpts,
15
16
  ContentTypeId as WasmContentTypeId,
16
17
  EncodedContent as WasmEncodedContent,
17
18
  type ApiStats,
@@ -28,7 +29,9 @@ import {
28
29
  type InboxState,
29
30
  type Installation,
30
31
  type KeyPackageStatus,
32
+ type ListConversationsOrderBy,
31
33
  type Message,
34
+ type MessageSortBy,
32
35
  type PermissionLevel,
33
36
  type PermissionPolicy,
34
37
  type SortDirection,
@@ -155,9 +158,15 @@ export type SafeListMessagesOptions = {
155
158
  contentTypes?: ContentType[];
156
159
  deliveryStatus?: DeliveryStatus;
157
160
  direction?: SortDirection;
161
+ excludeContentTypes?: ContentType[];
162
+ excludeSenderInboxIds?: string[];
163
+ insertedAfterNs?: bigint;
164
+ insertedBeforeNs?: bigint;
165
+ kind?: GroupMessageKind;
158
166
  limit?: bigint;
159
167
  sentAfterNs?: bigint;
160
168
  sentBeforeNs?: bigint;
169
+ sortBy?: MessageSortBy;
161
170
  };
162
171
 
163
172
  export const toSafeListMessagesOptions = (
@@ -166,9 +175,15 @@ export const toSafeListMessagesOptions = (
166
175
  contentTypes: options.contentTypes,
167
176
  deliveryStatus: options.deliveryStatus,
168
177
  direction: options.direction,
178
+ excludeContentTypes: options.excludeContentTypes,
179
+ excludeSenderInboxIds: options.excludeSenderInboxIds,
180
+ insertedAfterNs: options.insertedAfterNs,
181
+ insertedBeforeNs: options.insertedBeforeNs,
182
+ kind: options.kind,
169
183
  limit: options.limit,
170
184
  sentAfterNs: options.sentAfterNs,
171
185
  sentBeforeNs: options.sentBeforeNs,
186
+ sortBy: options.sortBy,
172
187
  });
173
188
 
174
189
  export const fromSafeListMessagesOptions = (
@@ -181,8 +196,30 @@ export const fromSafeListMessagesOptions = (
181
196
  options.deliveryStatus,
182
197
  options.direction,
183
198
  options.contentTypes,
199
+ options.excludeContentTypes,
200
+ options.kind,
201
+ options.excludeSenderInboxIds,
202
+ options.sortBy,
203
+ options.insertedAfterNs,
204
+ options.insertedBeforeNs,
184
205
  );
185
206
 
207
+ export type SafeSendMessageOpts = {
208
+ shouldPush: boolean;
209
+ };
210
+
211
+ export const toSafeSendMessageOpts = (
212
+ opts: SendMessageOpts,
213
+ ): SafeSendMessageOpts => ({
214
+ shouldPush: opts.shouldPush,
215
+ });
216
+
217
+ export const fromSafeSendMessageOpts = (
218
+ opts: SafeSendMessageOpts,
219
+ ): SendMessageOpts => {
220
+ return new SendMessageOpts(opts.shouldPush);
221
+ };
222
+
186
223
  export type SafeListConversationsOptions = {
187
224
  consentStates?: ConsentState[];
188
225
  conversationType?: ConversationType;
@@ -190,6 +227,7 @@ export type SafeListConversationsOptions = {
190
227
  createdBeforeNs?: bigint;
191
228
  includeDuplicateDms?: boolean;
192
229
  limit?: bigint;
230
+ orderBy?: ListConversationsOrderBy;
193
231
  };
194
232
 
195
233
  export const toSafeListConversationsOptions = (
@@ -201,6 +239,7 @@ export const toSafeListConversationsOptions = (
201
239
  createdBeforeNs: options.createdBeforeNs,
202
240
  includeDuplicateDms: options.includeDuplicateDms,
203
241
  limit: options.limit,
242
+ orderBy: options.orderBy,
204
243
  });
205
244
 
206
245
  export const fromSafeListConversationsOptions = (
@@ -213,6 +252,7 @@ export const fromSafeListConversationsOptions = (
213
252
  options.createdBeforeNs,
214
253
  options.includeDuplicateDms ?? false,
215
254
  options.limit,
255
+ options.orderBy,
216
256
  );
217
257
 
218
258
  export type SafePermissionPolicySet = {
@@ -319,6 +359,7 @@ export type SafeConversation = {
319
359
  name: string;
320
360
  imageUrl: string;
321
361
  description: string;
362
+ appData: string;
322
363
  permissions: {
323
364
  policyType: GroupPermissionsOptions;
324
365
  policySet: {
@@ -350,6 +391,7 @@ export const toSafeConversation = async (
350
391
  const name = conversation.name;
351
392
  const imageUrl = conversation.imageUrl;
352
393
  const description = conversation.description;
394
+ const appData = conversation.appData;
353
395
  const permissions = conversation.permissions;
354
396
  const addedByInboxId = conversation.addedByInboxId;
355
397
  const metadata = await conversation.metadata();
@@ -364,6 +406,7 @@ export const toSafeConversation = async (
364
406
  name,
365
407
  imageUrl,
366
408
  description,
409
+ appData,
367
410
  permissions: {
368
411
  policyType,
369
412
  policySet: {
@@ -506,6 +549,11 @@ export const toSafeKeyPackageStatus = (
506
549
  validationError: status.validationError,
507
550
  });
508
551
 
552
+ export type SafeXMTPCursor = {
553
+ originatorID: number;
554
+ sequenceID: bigint;
555
+ };
556
+
509
557
  export type SafeConversationDebugInfo = {
510
558
  epoch: bigint;
511
559
  maybeForked: boolean;
@@ -513,7 +561,7 @@ export type SafeConversationDebugInfo = {
513
561
  isCommitLogForked?: boolean;
514
562
  localCommitLog: string;
515
563
  remoteCommitLog: string;
516
- cursor: bigint;
564
+ cursor: SafeXMTPCursor[];
517
565
  };
518
566
 
519
567
  export const toSafeConversationDebugInfo = (
@@ -525,7 +573,10 @@ export const toSafeConversationDebugInfo = (
525
573
  isCommitLogForked: debugInfo.isCommitLogForked,
526
574
  localCommitLog: debugInfo.localCommitLog,
527
575
  remoteCommitLog: debugInfo.remoteCommitLog,
528
- cursor: debugInfo.cursor,
576
+ cursor: debugInfo.cursor.map((cursor) => ({
577
+ originatorID: cursor.originator_id,
578
+ sequenceID: cursor.sequence_id,
579
+ })),
529
580
  });
530
581
 
531
582
  export type SafeApiStats = {
@@ -14,8 +14,9 @@ export const createClient = async (
14
14
  ) => {
15
15
  const env = options?.env || "dev";
16
16
  const host = options?.apiUrl || ApiUrls[env];
17
+ const gatewayHost = options?.gatewayHost ?? null;
17
18
  const inboxId =
18
- (await getInboxIdForIdentifier(host, identifier)) ||
19
+ (await getInboxIdForIdentifier(host, gatewayHost, identifier)) ||
19
20
  generateInboxId(identifier);
20
21
  const dbPath =
21
22
  options?.dbPath === undefined
@@ -54,5 +55,6 @@ export const createClient = async (
54
55
  undefined,
55
56
  options?.debugEventsEnabled,
56
57
  options?.appVersion,
58
+ options?.gatewayHost,
57
59
  );
58
60
  };
@@ -55,6 +55,11 @@ export type StreamOptions<T = unknown, V = T> = {
55
55
  * (default: true)
56
56
  */
57
57
  retryOnFail?: boolean;
58
+ /**
59
+ * Whether to disable network sync before starting the stream
60
+ * (default: false)
61
+ */
62
+ disableSync?: boolean;
58
63
  };
59
64
 
60
65
  export type StreamCallback<T = unknown> = (