@xmtp/browser-sdk 0.0.16 → 0.0.18

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.
@@ -1,9 +1,14 @@
1
+ import { ConversationType } from "@xmtp/wasm-bindings";
2
+ import { v4 } from "uuid";
3
+ import { AsyncStream, type StreamCallback } from "@/AsyncStream";
1
4
  import type { Client } from "@/Client";
2
5
  import { Conversation } from "@/Conversation";
3
6
  import { DecodedMessage } from "@/DecodedMessage";
4
7
  import type {
8
+ SafeConversation,
5
9
  SafeCreateGroupOptions,
6
10
  SafeListConversationsOptions,
11
+ SafeMessage,
7
12
  } from "@/utils/conversions";
8
13
 
9
14
  export class Conversations {
@@ -99,4 +104,78 @@ export class Conversations {
99
104
  async getHmacKeys() {
100
105
  return this.#client.sendMessage("getHmacKeys", undefined);
101
106
  }
107
+
108
+ async stream(
109
+ callback?: StreamCallback<Conversation>,
110
+ conversationType?: ConversationType,
111
+ ) {
112
+ const streamId = v4();
113
+ const asyncStream = new AsyncStream<Conversation>();
114
+ const endStream = this.#client.handleStreamMessage<SafeConversation>(
115
+ streamId,
116
+ (error, value) => {
117
+ const conversation = value
118
+ ? new Conversation(this.#client, value.id, value)
119
+ : undefined;
120
+ void asyncStream.callback(error, conversation);
121
+ void callback?.(error, conversation);
122
+ },
123
+ );
124
+ await this.#client.sendMessage("streamAllGroups", {
125
+ streamId,
126
+ conversationType,
127
+ });
128
+ asyncStream.onReturn = () => {
129
+ void this.#client.sendMessage("endStream", {
130
+ streamId,
131
+ });
132
+ endStream();
133
+ };
134
+ return asyncStream;
135
+ }
136
+
137
+ async streamGroups(callback?: StreamCallback<Conversation>) {
138
+ return this.stream(callback, ConversationType.Group);
139
+ }
140
+
141
+ async streamDms(callback?: StreamCallback<Conversation>) {
142
+ return this.stream(callback, ConversationType.Dm);
143
+ }
144
+
145
+ async streamAllMessages(
146
+ callback?: StreamCallback<DecodedMessage>,
147
+ conversationType?: ConversationType,
148
+ ) {
149
+ const streamId = v4();
150
+ const asyncStream = new AsyncStream<DecodedMessage>();
151
+ const endStream = this.#client.handleStreamMessage<SafeMessage>(
152
+ streamId,
153
+ (error, value) => {
154
+ const decodedMessage = value
155
+ ? new DecodedMessage(this.#client, value)
156
+ : undefined;
157
+ void asyncStream.callback(error, decodedMessage);
158
+ void callback?.(error, decodedMessage);
159
+ },
160
+ );
161
+ await this.#client.sendMessage("streamAllMessages", {
162
+ streamId,
163
+ conversationType,
164
+ });
165
+ asyncStream.onReturn = () => {
166
+ void this.#client.sendMessage("endStream", {
167
+ streamId,
168
+ });
169
+ endStream();
170
+ };
171
+ return asyncStream;
172
+ }
173
+
174
+ async streamAllGroupMessages(callback?: StreamCallback<DecodedMessage>) {
175
+ return this.streamAllMessages(callback, ConversationType.Group);
176
+ }
177
+
178
+ async streamAllDmMessages(callback?: StreamCallback<DecodedMessage>) {
179
+ return this.streamAllMessages(callback, ConversationType.Dm);
180
+ }
102
181
  }
@@ -51,9 +51,9 @@ export class WorkerClient {
51
51
  return this.#client.isRegistered;
52
52
  }
53
53
 
54
- async createInboxSignatureText() {
54
+ createInboxSignatureText() {
55
55
  try {
56
- return await this.#client.createInboxSignatureText();
56
+ return this.#client.createInboxSignatureText();
57
57
  } catch {
58
58
  return undefined;
59
59
  }
@@ -3,10 +3,12 @@ import type {
3
3
  Conversation,
4
4
  EncodedContent,
5
5
  GroupMember,
6
+ Message,
6
7
  MetadataField,
7
8
  PermissionPolicy,
8
9
  PermissionUpdateType,
9
10
  } from "@xmtp/wasm-bindings";
11
+ import { type StreamCallback } from "@/AsyncStream";
10
12
  import {
11
13
  fromSafeListMessagesOptions,
12
14
  toSafeGroupMember,
@@ -53,14 +55,6 @@ export class WorkerConversation {
53
55
  return this.#group.updateGroupDescription(description);
54
56
  }
55
57
 
56
- get pinnedFrameUrl() {
57
- return this.#group.groupPinnedFrameUrl();
58
- }
59
-
60
- async updatePinnedFrameUrl(pinnedFrameUrl: string) {
61
- return this.#group.updateGroupPinnedFrameUrl(pinnedFrameUrl);
62
- }
63
-
64
58
  get isActive() {
65
59
  return this.#group.isActive();
66
60
  }
@@ -187,4 +181,14 @@ export class WorkerConversation {
187
181
  dmPeerInboxId() {
188
182
  return this.#group.dmPeerInboxId();
189
183
  }
184
+
185
+ stream(callback?: StreamCallback<Message>) {
186
+ const on_message = (message: Message) => {
187
+ void callback?.(null, message);
188
+ };
189
+ const on_error = (error: Error | null) => {
190
+ void callback?.(error, undefined);
191
+ };
192
+ return this.#group.stream({ on_message, on_error });
193
+ }
190
194
  }
@@ -1,4 +1,10 @@
1
- import type { Conversation, Conversations } from "@xmtp/wasm-bindings";
1
+ import {
2
+ ConversationType,
3
+ type Conversation,
4
+ type Conversations,
5
+ type Message,
6
+ } from "@xmtp/wasm-bindings";
7
+ import type { StreamCallback } from "@/AsyncStream";
2
8
  import {
3
9
  fromSafeCreateGroupOptions,
4
10
  fromSafeListConversationsOptions,
@@ -94,4 +100,44 @@ export class WorkerConversations {
94
100
  getHmacKeys() {
95
101
  return this.#conversations.getHmacKeys() as HmacKeys;
96
102
  }
103
+
104
+ stream(
105
+ callback?: StreamCallback<Conversation>,
106
+ conversationType?: ConversationType,
107
+ ) {
108
+ const on_conversation = (conversation: Conversation) => {
109
+ void callback?.(null, conversation);
110
+ };
111
+ const on_error = (error: Error | null) => {
112
+ void callback?.(error, undefined);
113
+ };
114
+ return this.#conversations.stream(
115
+ { on_conversation, on_error },
116
+ conversationType,
117
+ );
118
+ }
119
+
120
+ streamGroups(callback?: StreamCallback<Conversation>) {
121
+ return this.#conversations.stream(callback, ConversationType.Group);
122
+ }
123
+
124
+ streamDms(callback?: StreamCallback<Conversation>) {
125
+ return this.#conversations.stream(callback, ConversationType.Dm);
126
+ }
127
+
128
+ streamAllMessages(
129
+ callback?: StreamCallback<Message>,
130
+ conversationType?: ConversationType,
131
+ ) {
132
+ const on_message = (message: Message) => {
133
+ void callback?.(null, message);
134
+ };
135
+ const on_error = (error: Error | null) => {
136
+ void callback?.(error, undefined);
137
+ };
138
+ return this.#conversations.streamAllMessages(
139
+ { on_message, on_error },
140
+ conversationType,
141
+ );
142
+ }
97
143
  }
@@ -1,6 +1,7 @@
1
1
  import type {
2
2
  ConsentEntityType,
3
3
  ConsentState,
4
+ ConversationType,
4
5
  MetadataField,
5
6
  PermissionPolicy,
6
7
  PermissionUpdateType,
@@ -30,6 +31,17 @@ import type {
30
31
  } from "@/utils/conversions";
31
32
 
32
33
  export type ClientEvents =
34
+ /**
35
+ * Stream actions
36
+ */
37
+ | {
38
+ action: "endStream";
39
+ id: string;
40
+ result: undefined;
41
+ data: {
42
+ streamId: string;
43
+ };
44
+ }
33
45
  /**
34
46
  * Client actions
35
47
  */
@@ -283,6 +295,24 @@ export type ClientEvents =
283
295
  result: SafeHmacKeys;
284
296
  data: undefined;
285
297
  }
298
+ | {
299
+ action: "streamAllGroups";
300
+ id: string;
301
+ result: undefined;
302
+ data: {
303
+ streamId: string;
304
+ conversationType?: ConversationType;
305
+ };
306
+ }
307
+ | {
308
+ action: "streamAllMessages";
309
+ id: string;
310
+ result: undefined;
311
+ data: {
312
+ streamId: string;
313
+ conversationType?: ConversationType;
314
+ };
315
+ }
286
316
  /**
287
317
  * Group actions
288
318
  */
@@ -470,15 +500,6 @@ export type ClientEvents =
470
500
  imageUrl: string;
471
501
  };
472
502
  }
473
- | {
474
- action: "updateGroupPinnedFrameUrl";
475
- id: string;
476
- result: undefined;
477
- data: {
478
- id: string;
479
- pinnedFrameUrl: string;
480
- };
481
- }
482
503
  | {
483
504
  action: "getGroupConsentState";
484
505
  id: string;
@@ -522,6 +543,15 @@ export type ClientEvents =
522
543
  data: {
523
544
  id: string;
524
545
  };
546
+ }
547
+ | {
548
+ action: "streamGroupMessages";
549
+ id: string;
550
+ result: undefined;
551
+ data: {
552
+ groupId: string;
553
+ streamId: string;
554
+ };
525
555
  };
526
556
 
527
557
  export type ClientEventsActions = ClientEvents["action"];
@@ -0,0 +1,30 @@
1
+ import type {
2
+ StreamEventsClientPostMessageData,
3
+ StreamEventsErrorData,
4
+ StreamEventsResult,
5
+ } from "@/types";
6
+ import type { SafeConversation, SafeMessage } from "@/utils/conversions";
7
+
8
+ export type ClientStreamEvents =
9
+ | {
10
+ type: "message";
11
+ streamId: string;
12
+ result: SafeMessage | undefined;
13
+ }
14
+ | {
15
+ type: "group";
16
+ streamId: string;
17
+ result: SafeConversation | undefined;
18
+ };
19
+
20
+ export type ClientStreamEventsTypes = ClientStreamEvents["type"];
21
+
22
+ export type ClientStreamEventsResult<A extends ClientStreamEventsTypes> =
23
+ StreamEventsResult<ClientStreamEvents, A>;
24
+
25
+ export type ClientStreamEventsWorkerPostMessageData<
26
+ A extends ClientStreamEventsTypes,
27
+ > = StreamEventsClientPostMessageData<ClientStreamEvents, A>;
28
+
29
+ export type ClientStreamEventsErrorData =
30
+ StreamEventsErrorData<ClientStreamEvents>;
@@ -44,3 +44,29 @@ export type EventsErrorData<Events extends GenericEvent> = {
44
44
  action: Events["action"];
45
45
  error: string;
46
46
  };
47
+
48
+ export type GenericStreamEvent = {
49
+ type: string;
50
+ streamId: string;
51
+ result: unknown;
52
+ };
53
+
54
+ export type StreamEventsClientMessageData<Events extends GenericStreamEvent> = {
55
+ [Type in Events["type"]]: Omit<Extract<Events, { type: Type }>, "result">;
56
+ }[Events["type"]];
57
+
58
+ export type StreamEventsResult<
59
+ Events extends GenericStreamEvent,
60
+ Type extends Events["type"],
61
+ > = Extract<Events, { type: Type }>["result"];
62
+
63
+ export type StreamEventsClientPostMessageData<
64
+ Events extends GenericStreamEvent,
65
+ Type extends Events["type"],
66
+ > = Extract<Events, { type: Type }>;
67
+
68
+ export type StreamEventsErrorData<Events extends GenericStreamEvent> = {
69
+ streamId: string;
70
+ type: Events["type"];
71
+ error: string;
72
+ };
@@ -210,8 +210,7 @@ export type SafePermissionPolicySet = {
210
210
  updateGroupDescriptionPolicy: PermissionPolicy;
211
211
  updateGroupImageUrlSquarePolicy: PermissionPolicy;
212
212
  updateGroupNamePolicy: PermissionPolicy;
213
- updateGroupPinnedFrameUrlPolicy: PermissionPolicy;
214
- updateMessageExpirationPolicy: PermissionPolicy;
213
+ updateMessageDisappearingPolicy: PermissionPolicy;
215
214
  };
216
215
 
217
216
  export const toSafePermissionPolicySet = (
@@ -224,8 +223,7 @@ export const toSafePermissionPolicySet = (
224
223
  updateGroupDescriptionPolicy: policySet.updateGroupDescriptionPolicy,
225
224
  updateGroupImageUrlSquarePolicy: policySet.updateGroupImageUrlSquarePolicy,
226
225
  updateGroupNamePolicy: policySet.updateGroupNamePolicy,
227
- updateGroupPinnedFrameUrlPolicy: policySet.updateGroupPinnedFrameUrlPolicy,
228
- updateMessageExpirationPolicy: policySet.updateMessageExpirationPolicy,
226
+ updateMessageDisappearingPolicy: policySet.updateMessageDisappearingPolicy,
229
227
  });
230
228
 
231
229
  export const fromSafePermissionPolicySet = (
@@ -239,8 +237,7 @@ export const fromSafePermissionPolicySet = (
239
237
  policySet.updateGroupNamePolicy,
240
238
  policySet.updateGroupDescriptionPolicy,
241
239
  policySet.updateGroupImageUrlSquarePolicy,
242
- policySet.updateGroupPinnedFrameUrlPolicy,
243
- policySet.updateMessageExpirationPolicy,
240
+ policySet.updateMessageDisappearingPolicy,
244
241
  );
245
242
 
246
243
  export type SafeCreateGroupOptions = {
@@ -249,7 +246,6 @@ export type SafeCreateGroupOptions = {
249
246
  imageUrlSquare?: string;
250
247
  name?: string;
251
248
  permissions?: GroupPermissionsOptions;
252
- pinnedFrameUrl?: string;
253
249
  };
254
250
 
255
251
  export const toSafeCreateGroupOptions = (
@@ -258,7 +254,6 @@ export const toSafeCreateGroupOptions = (
258
254
  description: options.groupDescription,
259
255
  imageUrlSquare: options.groupImageUrlSquare,
260
256
  name: options.groupName,
261
- pinnedFrameUrl: options.groupPinnedFrameUrl,
262
257
  permissions: options.permissions,
263
258
  customPermissionPolicySet: options.customPermissionPolicySet,
264
259
  });
@@ -271,7 +266,6 @@ export const fromSafeCreateGroupOptions = (
271
266
  options.name,
272
267
  options.imageUrlSquare,
273
268
  options.description,
274
- options.pinnedFrameUrl,
275
269
  // only include custom policy set if permissions are set to CustomPolicy
276
270
  options.customPermissionPolicySet &&
277
271
  options.permissions === GroupPermissionsOptions.CustomPolicy
@@ -284,7 +278,6 @@ export type SafeConversation = {
284
278
  name: string;
285
279
  imageUrl: string;
286
280
  description: string;
287
- pinnedFrameUrl: string;
288
281
  permissions: {
289
282
  policyType: GroupPermissionsOptions;
290
283
  policySet: {
@@ -295,8 +288,7 @@ export type SafeConversation = {
295
288
  updateGroupDescriptionPolicy: PermissionPolicy;
296
289
  updateGroupImageUrlSquarePolicy: PermissionPolicy;
297
290
  updateGroupNamePolicy: PermissionPolicy;
298
- updateGroupPinnedFrameUrlPolicy: PermissionPolicy;
299
- updateMessageExpirationPolicy: PermissionPolicy;
291
+ updateMessageDisappearingPolicy: PermissionPolicy;
300
292
  };
301
293
  };
302
294
  isActive: boolean;
@@ -312,38 +304,48 @@ export type SafeConversation = {
312
304
 
313
305
  export const toSafeConversation = async (
314
306
  conversation: WorkerConversation,
315
- ): Promise<SafeConversation> => ({
316
- id: conversation.id,
317
- name: conversation.name,
318
- imageUrl: conversation.imageUrl,
319
- description: conversation.description,
320
- pinnedFrameUrl: conversation.pinnedFrameUrl,
321
- permissions: {
322
- policyType: conversation.permissions.policyType,
323
- policySet: {
324
- addAdminPolicy: conversation.permissions.policySet.addAdminPolicy,
325
- addMemberPolicy: conversation.permissions.policySet.addMemberPolicy,
326
- removeAdminPolicy: conversation.permissions.policySet.removeAdminPolicy,
327
- removeMemberPolicy: conversation.permissions.policySet.removeMemberPolicy,
328
- updateGroupDescriptionPolicy:
329
- conversation.permissions.policySet.updateGroupDescriptionPolicy,
330
- updateGroupImageUrlSquarePolicy:
331
- conversation.permissions.policySet.updateGroupImageUrlSquarePolicy,
332
- updateGroupNamePolicy:
333
- conversation.permissions.policySet.updateGroupNamePolicy,
334
- updateGroupPinnedFrameUrlPolicy:
335
- conversation.permissions.policySet.updateGroupPinnedFrameUrlPolicy,
336
- updateMessageExpirationPolicy:
337
- conversation.permissions.policySet.updateMessageExpirationPolicy,
307
+ ): Promise<SafeConversation> => {
308
+ const id = conversation.id;
309
+ const name = conversation.name;
310
+ const imageUrl = conversation.imageUrl;
311
+ const description = conversation.description;
312
+ const permissions = conversation.permissions;
313
+ const isActive = conversation.isActive;
314
+ const addedByInboxId = conversation.addedByInboxId;
315
+ const metadata = await conversation.metadata();
316
+ const admins = conversation.admins;
317
+ const superAdmins = conversation.superAdmins;
318
+ const createdAtNs = conversation.createdAtNs;
319
+ const policyType = permissions.policyType;
320
+ const policySet = permissions.policySet;
321
+ return {
322
+ id,
323
+ name,
324
+ imageUrl,
325
+ description,
326
+ permissions: {
327
+ policyType,
328
+ policySet: {
329
+ addAdminPolicy: policySet.addAdminPolicy,
330
+ addMemberPolicy: policySet.addMemberPolicy,
331
+ removeAdminPolicy: policySet.removeAdminPolicy,
332
+ removeMemberPolicy: policySet.removeMemberPolicy,
333
+ updateGroupDescriptionPolicy: policySet.updateGroupDescriptionPolicy,
334
+ updateGroupImageUrlSquarePolicy:
335
+ policySet.updateGroupImageUrlSquarePolicy,
336
+ updateGroupNamePolicy: policySet.updateGroupNamePolicy,
337
+ updateMessageDisappearingPolicy:
338
+ policySet.updateMessageDisappearingPolicy,
339
+ },
338
340
  },
339
- },
340
- isActive: conversation.isActive,
341
- addedByInboxId: conversation.addedByInboxId,
342
- metadata: await conversation.metadata(),
343
- admins: conversation.admins,
344
- superAdmins: conversation.superAdmins,
345
- createdAtNs: conversation.createdAtNs,
346
- });
341
+ isActive,
342
+ addedByInboxId,
343
+ metadata,
344
+ admins,
345
+ superAdmins,
346
+ createdAtNs,
347
+ };
348
+ };
347
349
 
348
350
  export type SafeInstallation = {
349
351
  bytes: Uint8Array;
@@ -15,9 +15,9 @@ export const createClient = async (
15
15
  // initialize WASM module
16
16
  await init();
17
17
 
18
- const host = options?.apiUrl ?? ApiUrls[options?.env ?? "dev"];
18
+ const host = options?.apiUrl || ApiUrls[options?.env || "dev"];
19
19
  const dbPath =
20
- options?.dbPath ?? `xmtp-${options?.env ?? "dev"}-${accountAddress}.db3`;
20
+ options?.dbPath || `xmtp-${options?.env || "dev"}-${accountAddress}.db3`;
21
21
 
22
22
  const inboxId =
23
23
  (await getInboxIdForAddress(host, accountAddress)) ||
@@ -30,7 +30,7 @@ export const createClient = async (
30
30
  options.performanceLogging);
31
31
 
32
32
  const historySyncUrl =
33
- options?.historySyncUrl ?? HistorySyncUrls[options?.env ?? "dev"];
33
+ options?.historySyncUrl || HistorySyncUrls[options?.env || "dev"];
34
34
 
35
35
  return createWasmClient(
36
36
  host,