@xmtp/browser-sdk 1.1.4 → 2.0.1

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/Group.ts CHANGED
@@ -8,19 +8,18 @@ import type { Client } from "@/Client";
8
8
  import { Conversation } from "@/Conversation";
9
9
  import type { SafeConversation } from "@/utils/conversions";
10
10
 
11
+ /**
12
+ * Represents a group conversation between multiple inboxes
13
+ *
14
+ * This class is not intended to be initialized directly.
15
+ */
11
16
  export class Group extends Conversation {
17
+ #admins: SafeConversation["admins"] = [];
12
18
  #client: Client;
13
-
19
+ #description?: SafeConversation["description"];
14
20
  #id: string;
15
-
16
- #name?: SafeConversation["name"];
17
-
18
21
  #imageUrl?: SafeConversation["imageUrl"];
19
-
20
- #description?: SafeConversation["description"];
21
-
22
- #admins: SafeConversation["admins"] = [];
23
-
22
+ #name?: SafeConversation["name"];
24
23
  #superAdmins: SafeConversation["superAdmins"] = [];
25
24
 
26
25
  #syncData(data?: SafeConversation) {
@@ -31,6 +30,13 @@ export class Group extends Conversation {
31
30
  this.#superAdmins = data?.superAdmins ?? [];
32
31
  }
33
32
 
33
+ /**
34
+ * Creates a new group conversation instance
35
+ *
36
+ * @param client - The client instance managing this group conversation
37
+ * @param id - Identifier for the group conversation
38
+ * @param data - Optional conversation data to initialize with
39
+ */
34
40
  constructor(client: Client, id: string, data?: SafeConversation) {
35
41
  super(client, id, data);
36
42
  this.#client = client;
@@ -38,16 +44,29 @@ export class Group extends Conversation {
38
44
  this.#syncData(data);
39
45
  }
40
46
 
47
+ /**
48
+ * Synchronizes the group's data with the network
49
+ *
50
+ * @returns Updated group data
51
+ */
41
52
  async sync() {
42
53
  const data = await super.sync();
43
54
  this.#syncData(data);
44
55
  return data;
45
56
  }
46
57
 
58
+ /**
59
+ * The name of the group
60
+ */
47
61
  get name() {
48
62
  return this.#name;
49
63
  }
50
64
 
65
+ /**
66
+ * Updates the group's name
67
+ *
68
+ * @param name The new name for the group
69
+ */
51
70
  async updateName(name: string) {
52
71
  await this.#client.sendMessage("updateGroupName", {
53
72
  id: this.#id,
@@ -56,10 +75,18 @@ export class Group extends Conversation {
56
75
  this.#name = name;
57
76
  }
58
77
 
78
+ /**
79
+ * The image URL of the group
80
+ */
59
81
  get imageUrl() {
60
82
  return this.#imageUrl;
61
83
  }
62
84
 
85
+ /**
86
+ * Updates the group's image URL
87
+ *
88
+ * @param imageUrl The new image URL for the group
89
+ */
63
90
  async updateImageUrl(imageUrl: string) {
64
91
  await this.#client.sendMessage("updateGroupImageUrlSquare", {
65
92
  id: this.#id,
@@ -68,10 +95,18 @@ export class Group extends Conversation {
68
95
  this.#imageUrl = imageUrl;
69
96
  }
70
97
 
98
+ /**
99
+ * The description of the group
100
+ */
71
101
  get description() {
72
102
  return this.#description;
73
103
  }
74
104
 
105
+ /**
106
+ * Updates the group's description
107
+ *
108
+ * @param description The new description for the group
109
+ */
75
110
  async updateDescription(description: string) {
76
111
  await this.#client.sendMessage("updateGroupDescription", {
77
112
  id: this.#id,
@@ -80,14 +115,25 @@ export class Group extends Conversation {
80
115
  this.#description = description;
81
116
  }
82
117
 
118
+ /**
119
+ * The list of admins of the group by inbox ID
120
+ */
83
121
  get admins() {
84
122
  return this.#admins;
85
123
  }
86
124
 
125
+ /**
126
+ * The list of super admins of the group by inbox ID
127
+ */
87
128
  get superAdmins() {
88
129
  return this.#superAdmins;
89
130
  }
90
131
 
132
+ /**
133
+ * Fetches and updates the list of group admins from the server
134
+ *
135
+ * @returns Array of admin inbox IDs
136
+ */
91
137
  async listAdmins() {
92
138
  const admins = await this.#client.sendMessage("getGroupAdmins", {
93
139
  id: this.#id,
@@ -96,6 +142,11 @@ export class Group extends Conversation {
96
142
  return admins;
97
143
  }
98
144
 
145
+ /**
146
+ * Fetches and updates the list of group super admins from the server
147
+ *
148
+ * @returns Array of super admin inbox IDs
149
+ */
99
150
  async listSuperAdmins() {
100
151
  const superAdmins = await this.#client.sendMessage("getGroupSuperAdmins", {
101
152
  id: this.#id,
@@ -104,12 +155,24 @@ export class Group extends Conversation {
104
155
  return superAdmins;
105
156
  }
106
157
 
158
+ /**
159
+ * Retrieves the group's permissions
160
+ *
161
+ * @returns The group's permissions
162
+ */
107
163
  async permissions() {
108
164
  return this.#client.sendMessage("getGroupPermissions", {
109
165
  id: this.#id,
110
166
  });
111
167
  }
112
168
 
169
+ /**
170
+ * Updates a specific permission policy for the group
171
+ *
172
+ * @param permissionType The type of permission to update
173
+ * @param policy The new permission policy
174
+ * @param metadataField Optional metadata field for the permission
175
+ */
113
176
  async updatePermission(
114
177
  permissionType: PermissionUpdateType,
115
178
  policy: PermissionPolicy,
@@ -123,16 +186,33 @@ export class Group extends Conversation {
123
186
  });
124
187
  }
125
188
 
189
+ /**
190
+ * Checks if an inbox is an admin of the group
191
+ *
192
+ * @param inboxId The inbox ID to check
193
+ * @returns Boolean indicating if the inbox is an admin
194
+ */
126
195
  async isAdmin(inboxId: string) {
127
196
  const admins = await this.listAdmins();
128
197
  return admins.includes(inboxId);
129
198
  }
130
199
 
200
+ /**
201
+ * Checks if an inbox is a super admin of the group
202
+ *
203
+ * @param inboxId The inbox ID to check
204
+ * @returns Boolean indicating if the inbox is a super admin
205
+ */
131
206
  async isSuperAdmin(inboxId: string) {
132
207
  const superAdmins = await this.listSuperAdmins();
133
208
  return superAdmins.includes(inboxId);
134
209
  }
135
210
 
211
+ /**
212
+ * Adds members to the group using identifiers
213
+ *
214
+ * @param identifiers Array of member identifiers to add
215
+ */
136
216
  async addMembersByIdentifiers(identifiers: Identifier[]) {
137
217
  return this.#client.sendMessage("addGroupMembers", {
138
218
  id: this.#id,
@@ -140,6 +220,11 @@ export class Group extends Conversation {
140
220
  });
141
221
  }
142
222
 
223
+ /**
224
+ * Adds members to the group using inbox IDs
225
+ *
226
+ * @param inboxIds Array of inbox IDs to add
227
+ */
143
228
  async addMembers(inboxIds: string[]) {
144
229
  return this.#client.sendMessage("addGroupMembersByInboxId", {
145
230
  id: this.#id,
@@ -147,6 +232,11 @@ export class Group extends Conversation {
147
232
  });
148
233
  }
149
234
 
235
+ /**
236
+ * Removes members from the group using identifiers
237
+ *
238
+ * @param identifiers Array of member identifiers to remove
239
+ */
150
240
  async removeMembersByIdentifiers(identifiers: Identifier[]) {
151
241
  return this.#client.sendMessage("removeGroupMembers", {
152
242
  id: this.#id,
@@ -154,6 +244,11 @@ export class Group extends Conversation {
154
244
  });
155
245
  }
156
246
 
247
+ /**
248
+ * Removes members from the group using inbox IDs
249
+ *
250
+ * @param inboxIds Array of inbox IDs to remove
251
+ */
157
252
  async removeMembers(inboxIds: string[]) {
158
253
  return this.#client.sendMessage("removeGroupMembersByInboxId", {
159
254
  id: this.#id,
@@ -161,6 +256,11 @@ export class Group extends Conversation {
161
256
  });
162
257
  }
163
258
 
259
+ /**
260
+ * Promotes a group member to admin status
261
+ *
262
+ * @param inboxId The inbox ID of the member to promote
263
+ */
164
264
  async addAdmin(inboxId: string) {
165
265
  return this.#client.sendMessage("addGroupAdmin", {
166
266
  id: this.#id,
@@ -168,6 +268,11 @@ export class Group extends Conversation {
168
268
  });
169
269
  }
170
270
 
271
+ /**
272
+ * Removes admin status from a group member
273
+ *
274
+ * @param inboxId The inbox ID of the admin to demote
275
+ */
171
276
  async removeAdmin(inboxId: string) {
172
277
  return this.#client.sendMessage("removeGroupAdmin", {
173
278
  id: this.#id,
@@ -175,6 +280,11 @@ export class Group extends Conversation {
175
280
  });
176
281
  }
177
282
 
283
+ /**
284
+ * Promotes a group member to super admin status
285
+ *
286
+ * @param inboxId The inbox ID of the member to promote
287
+ */
178
288
  async addSuperAdmin(inboxId: string) {
179
289
  return this.#client.sendMessage("addGroupSuperAdmin", {
180
290
  id: this.#id,
@@ -182,6 +292,11 @@ export class Group extends Conversation {
182
292
  });
183
293
  }
184
294
 
295
+ /**
296
+ * Removes super admin status from a group member
297
+ *
298
+ * @param inboxId The inbox ID of the super admin to demote
299
+ */
185
300
  async removeSuperAdmin(inboxId: string) {
186
301
  return this.#client.sendMessage("removeGroupSuperAdmin", {
187
302
  id: this.#id,
@@ -4,19 +4,42 @@ import { AsyncStream, type StreamCallback } from "@/AsyncStream";
4
4
  import type { SafeConsent } from "@/utils/conversions";
5
5
  import type { Client } from "./Client";
6
6
 
7
+ /**
8
+ * Manages user preferences and consent states
9
+ *
10
+ * This class is not intended to be initialized directly.
11
+ */
7
12
  export class Preferences {
8
13
  #client: Client;
9
14
 
15
+ /**
16
+ * Creates a new preferences instance
17
+ *
18
+ * @param client - The client instance managing preferences
19
+ */
10
20
  constructor(client: Client) {
11
21
  this.#client = client;
12
22
  }
13
23
 
24
+ /**
25
+ * Retrieves the current inbox state
26
+ *
27
+ * @param refreshFromNetwork - Optional flag to force refresh from network
28
+ * @returns Promise that resolves with the inbox state
29
+ */
14
30
  async inboxState(refreshFromNetwork?: boolean) {
15
31
  return this.#client.sendMessage("inboxState", {
16
32
  refreshFromNetwork: refreshFromNetwork ?? false,
17
33
  });
18
34
  }
19
35
 
36
+ /**
37
+ * Retrieves inbox state for specific inbox IDs
38
+ *
39
+ * @param inboxIds - Array of inbox IDs to get state for
40
+ * @param refreshFromNetwork - Optional flag to force refresh from network
41
+ * @returns Promise that resolves with the inbox state for the inbox IDs
42
+ */
20
43
  async inboxStateFromInboxIds(
21
44
  inboxIds: string[],
22
45
  refreshFromNetwork?: boolean,
@@ -27,18 +50,43 @@ export class Preferences {
27
50
  });
28
51
  }
29
52
 
53
+ /**
54
+ * Gets the latest inbox state for a specific inbox
55
+ *
56
+ * @param inboxId - The inbox ID to get state for
57
+ * @returns Promise that resolves with the latest inbox state
58
+ */
30
59
  async getLatestInboxState(inboxId: string) {
31
60
  return this.#client.sendMessage("getLatestInboxState", { inboxId });
32
61
  }
33
62
 
63
+ /**
64
+ * Updates consent states for multiple records
65
+ *
66
+ * @param records - Array of consent records to update
67
+ * @returns Promise that resolves when consent states are updated
68
+ */
34
69
  async setConsentStates(records: SafeConsent[]) {
35
70
  return this.#client.sendMessage("setConsentStates", { records });
36
71
  }
37
72
 
73
+ /**
74
+ * Retrieves consent state for a specific entity
75
+ *
76
+ * @param entityType - Type of entity to get consent for
77
+ * @param entity - Entity identifier
78
+ * @returns Promise that resolves with the consent state
79
+ */
38
80
  async getConsentState(entityType: ConsentEntityType, entity: string) {
39
81
  return this.#client.sendMessage("getConsentState", { entityType, entity });
40
82
  }
41
83
 
84
+ /**
85
+ * Creates a stream of consent state updates
86
+ *
87
+ * @param callback - Optional callback function for handling stream updates
88
+ * @returns AsyncStream instance for consent updates
89
+ */
42
90
  async streamConsent(callback?: StreamCallback<SafeConsent[]>) {
43
91
  const streamId = v4();
44
92
  const asyncStream = new AsyncStream<SafeConsent[]>();
@@ -61,6 +109,12 @@ export class Preferences {
61
109
  return asyncStream;
62
110
  }
63
111
 
112
+ /**
113
+ * Creates a stream of user preference updates
114
+ *
115
+ * @param callback - Optional callback function for handling stream updates
116
+ * @returns AsyncStream instance for preference updates
117
+ */
64
118
  async streamPreferences(callback?: StreamCallback<UserPreference[]>) {
65
119
  const streamId = v4();
66
120
  const asyncStream = new AsyncStream<UserPreference[]>();
package/src/Utils.ts CHANGED
@@ -2,28 +2,45 @@ import type { Identifier } from "@xmtp/wasm-bindings";
2
2
  import type { XmtpEnv } from "@/types/options";
3
3
  import { UtilsWorkerClass } from "@/UtilsWorkerClass";
4
4
 
5
+ /**
6
+ * Utility class that provides helper functions for XMTP inbox IDs
7
+ */
5
8
  export class Utils extends UtilsWorkerClass {
6
- #enableLogging: boolean;
9
+ /**
10
+ * Creates a new Utils instance
11
+ *
12
+ * @param enableLogging - Optional flag to enable logging
13
+ */
7
14
  constructor(enableLogging?: boolean) {
8
15
  const worker = new Worker(new URL("./workers/utils", import.meta.url), {
9
16
  type: "module",
10
17
  });
11
18
  super(worker, enableLogging ?? false);
12
- this.#enableLogging = enableLogging ?? false;
13
19
  }
14
20
 
21
+ /**
22
+ * Generates an inbox ID for a given identifier
23
+ *
24
+ * @param identifier - The identifier to generate an inbox ID for
25
+ * @returns Promise that resolves with the generated inbox ID
26
+ */
15
27
  async generateInboxId(identifier: Identifier) {
16
28
  return this.sendMessage("generateInboxId", {
17
29
  identifier,
18
- enableLogging: this.#enableLogging,
19
30
  });
20
31
  }
21
32
 
33
+ /**
34
+ * Gets the inbox ID for a specific identifier and optional environment
35
+ *
36
+ * @param identifier - The identifier to get the inbox ID for
37
+ * @param env - Optional XMTP environment configuration (default: "dev")
38
+ * @returns Promise that resolves with the inbox ID for the identifier
39
+ */
22
40
  async getInboxIdForIdentifier(identifier: Identifier, env?: XmtpEnv) {
23
41
  return this.sendMessage("getInboxIdForIdentifier", {
24
42
  identifier,
25
43
  env,
26
- enableLogging: this.#enableLogging,
27
44
  });
28
45
  }
29
46
  }
@@ -27,6 +27,13 @@ export class UtilsWorkerClass {
27
27
  this.#worker.addEventListener("message", this.handleMessage);
28
28
  this.#worker.addEventListener("error", handleError);
29
29
  this.#enableLogging = enableLogging;
30
+ void this.init(enableLogging);
31
+ }
32
+
33
+ async init(enableLogging: boolean) {
34
+ return this.sendMessage("init", {
35
+ enableLogging,
36
+ });
30
37
  }
31
38
 
32
39
  sendMessage<A extends UtilsEventsActions>(
@@ -2,6 +2,7 @@ import {
2
2
  verifySignedWithPublicKey,
3
3
  type Client,
4
4
  type Identifier,
5
+ type KeyPackageStatus,
5
6
  type SignatureRequestType,
6
7
  } from "@xmtp/wasm-bindings";
7
8
  import type { ClientOptions } from "@/types";
@@ -23,10 +24,9 @@ export class WorkerClient {
23
24
 
24
25
  static async create(
25
26
  identifier: Identifier,
26
- encryptionKey: Uint8Array,
27
27
  options?: Omit<ClientOptions, "codecs">,
28
28
  ) {
29
- const client = await createClient(identifier, encryptionKey, options);
29
+ const client = await createClient(identifier, options);
30
30
  return new WorkerClient(client);
31
31
  }
32
32
 
@@ -100,6 +100,16 @@ export class WorkerClient {
100
100
  }
101
101
  }
102
102
 
103
+ async changeRecoveryIdentifierSignatureText(identifier: Identifier) {
104
+ try {
105
+ return await this.#client.changeRecoveryIdentifierSignatureText(
106
+ identifier,
107
+ );
108
+ } catch {
109
+ return undefined;
110
+ }
111
+ }
112
+
103
113
  async addEcdsaSignature(type: SignatureRequestType, bytes: Uint8Array) {
104
114
  return this.#client.addEcdsaSignature(type, bytes);
105
115
  }
@@ -162,4 +172,10 @@ export class WorkerClient {
162
172
  return false;
163
173
  }
164
174
  }
175
+
176
+ async getKeyPackageStatusesForInstallationIds(installationIds: string[]) {
177
+ return this.#client.getKeyPackageStatusesForInstallationIds(
178
+ installationIds,
179
+ ) as Promise<Map<string, KeyPackageStatus>>;
180
+ }
165
181
  }
@@ -4,6 +4,7 @@ import {
4
4
  type Conversation,
5
5
  type EncodedContent,
6
6
  type GroupMember,
7
+ type HmacKey,
7
8
  type Identifier,
8
9
  type Message,
9
10
  type MetadataField,
@@ -214,4 +215,8 @@ export class WorkerConversation {
214
215
  pausedForVersion() {
215
216
  return this.#group.pausedForVersion();
216
217
  }
218
+
219
+ getHmacKeys() {
220
+ return this.#group.getHmacKeys() as HmacKey[];
221
+ }
217
222
  }
package/src/constants.ts CHANGED
@@ -1,9 +1,25 @@
1
+ /**
2
+ * Pre-configured URLs for the XMTP network based on the environment
3
+ *
4
+ * @constant
5
+ * @property {string} local - The local URL for the XMTP network
6
+ * @property {string} dev - The development URL for the XMTP network
7
+ * @property {string} production - The production URL for the XMTP network
8
+ */
1
9
  export const ApiUrls = {
2
10
  local: "http://localhost:5555",
3
11
  dev: "https://dev.xmtp.network",
4
12
  production: "https://production.xmtp.network",
5
13
  } as const;
6
14
 
15
+ /**
16
+ * Pre-configured URLs for the XMTP history sync service based on the environment
17
+ *
18
+ * @constant
19
+ * @property {string} local - The local URL for the XMTP history sync service
20
+ * @property {string} dev - The development URL for the XMTP history sync service
21
+ * @property {string} production - The production URL for the XMTP history sync service
22
+ */
7
23
  export const HistorySyncUrls = {
8
24
  local: "http://localhost:5558",
9
25
  dev: "https://message-history.dev.ephemera.network",
package/src/index.ts CHANGED
@@ -41,7 +41,6 @@ export {
41
41
  Message,
42
42
  MessageDisappearingSettings,
43
43
  MetadataField,
44
- Opfs,
45
44
  PermissionLevel,
46
45
  PermissionPolicy,
47
46
  PermissionPolicySet,
@@ -25,8 +25,10 @@ import type {
25
25
  SafeCreateGroupOptions,
26
26
  SafeEncodedContent,
27
27
  SafeGroupMember,
28
+ SafeHmacKey,
28
29
  SafeHmacKeys,
29
30
  SafeInboxState,
31
+ SafeKeyPackageStatus,
30
32
  SafeListConversationsOptions,
31
33
  SafeListMessagesOptions,
32
34
  SafeMessage,
@@ -58,7 +60,6 @@ export type ClientEvents =
58
60
  };
59
61
  data: {
60
62
  identifier: Identifier;
61
- encryptionKey: Uint8Array;
62
63
  options?: ClientOptions;
63
64
  };
64
65
  }
@@ -98,6 +99,14 @@ export type ClientEvents =
98
99
  installationIds: Uint8Array[];
99
100
  };
100
101
  }
102
+ | {
103
+ action: "changeRecoveryIdentifierSignatureText";
104
+ id: string;
105
+ result: string | undefined;
106
+ data: {
107
+ identifier: Identifier;
108
+ };
109
+ }
101
110
  | {
102
111
  action: "addEcdsaSignature";
103
112
  id: string;
@@ -221,6 +230,14 @@ export type ClientEvents =
221
230
  publicKey: Uint8Array;
222
231
  };
223
232
  }
233
+ | {
234
+ action: "getKeyPackageStatusesForInstallationIds";
235
+ id: string;
236
+ result: Map<string, SafeKeyPackageStatus>;
237
+ data: {
238
+ installationIds: string[];
239
+ };
240
+ }
224
241
  /**
225
242
  * Conversations actions
226
243
  */
@@ -641,8 +658,15 @@ export type ClientEvents =
641
658
  data: {
642
659
  id: string;
643
660
  };
661
+ }
662
+ | {
663
+ action: "getGroupHmacKeys";
664
+ id: string;
665
+ result: SafeHmacKey[];
666
+ data: {
667
+ id: string;
668
+ };
644
669
  };
645
-
646
670
  export type ClientEventsActions = ClientEvents["action"];
647
671
 
648
672
  export type ClientEventsClientMessageData =
@@ -37,7 +37,11 @@ export type StorageOptions = {
37
37
  /**
38
38
  * Path to the local DB
39
39
  */
40
- dbPath?: string;
40
+ dbPath?: string | null;
41
+ /**
42
+ * Encryption key for the local DB
43
+ */
44
+ dbEncryptionKey?: Uint8Array;
41
45
  };
42
46
 
43
47
  export type OtherOptions = {
@@ -11,13 +11,20 @@ import type {
11
11
  } from "@/types";
12
12
 
13
13
  export type UtilsEvents =
14
+ | {
15
+ action: "init";
16
+ id: string;
17
+ result: undefined;
18
+ data: {
19
+ enableLogging: boolean;
20
+ };
21
+ }
14
22
  | {
15
23
  action: "generateInboxId";
16
24
  id: string;
17
25
  result: string;
18
26
  data: {
19
27
  identifier: Identifier;
20
- enableLogging: boolean;
21
28
  };
22
29
  }
23
30
  | {
@@ -27,7 +34,6 @@ export type UtilsEvents =
27
34
  data: {
28
35
  identifier: Identifier;
29
36
  env?: XmtpEnv;
30
- enableLogging: boolean;
31
37
  };
32
38
  };
33
39
 
@@ -23,6 +23,7 @@ import {
23
23
  type Identifier,
24
24
  type InboxState,
25
25
  type Installation,
26
+ type KeyPackageStatus,
26
27
  type Message,
27
28
  type PermissionLevel,
28
29
  type PermissionPolicy,
@@ -477,3 +478,23 @@ export const fromSafeMessageDisappearingSettings = (
477
478
  settings: SafeMessageDisappearingSettings,
478
479
  ): MessageDisappearingSettings =>
479
480
  new MessageDisappearingSettings(settings.fromNs, settings.inNs);
481
+
482
+ export type SafeKeyPackageStatus = {
483
+ lifetime?: {
484
+ notBefore: bigint;
485
+ notAfter: bigint;
486
+ };
487
+ validationError?: string;
488
+ };
489
+
490
+ export const toSafeKeyPackageStatus = (
491
+ status: KeyPackageStatus,
492
+ ): SafeKeyPackageStatus => ({
493
+ lifetime: status.lifetime
494
+ ? {
495
+ notBefore: status.lifetime.not_before,
496
+ notAfter: status.lifetime.not_after,
497
+ }
498
+ : undefined,
499
+ validationError: status.validationError,
500
+ });