@xmtp/browser-sdk 1.1.3 → 2.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/src/Client.ts CHANGED
@@ -16,30 +16,46 @@ import { ClientWorkerClass } from "@/ClientWorkerClass";
16
16
  import { Conversations } from "@/Conversations";
17
17
  import { Preferences } from "@/Preferences";
18
18
  import type { ClientOptions, XmtpEnv } from "@/types";
19
+ import { Utils } from "@/Utils";
19
20
  import {
20
21
  fromSafeEncodedContent,
21
22
  toSafeEncodedContent,
22
23
  type SafeMessage,
23
24
  } from "@/utils/conversions";
25
+ import {
26
+ AccountAlreadyAssociatedError,
27
+ CodecNotFoundError,
28
+ GenerateSignatureError,
29
+ InboxReassignError,
30
+ InvalidGroupMembershipChangeError,
31
+ SignerUnavailableError,
32
+ } from "@/utils/errors";
24
33
  import { type Signer } from "@/utils/signer";
25
34
 
35
+ /**
36
+ * Client for interacting with the XMTP network
37
+ */
26
38
  export class Client extends ClientWorkerClass {
27
39
  #codecs: Map<string, ContentCodec>;
28
40
  #conversations: Conversations;
29
- #encryptionKey: Uint8Array;
41
+ #identifier?: Identifier;
30
42
  #inboxId: string | undefined;
31
43
  #installationId: string | undefined;
32
44
  #installationIdBytes: Uint8Array | undefined;
33
45
  #isReady = false;
34
46
  #preferences: Preferences;
35
- #signer: Signer;
36
- options?: ClientOptions;
47
+ #signer?: Signer;
48
+ #options?: ClientOptions;
37
49
 
38
- constructor(
39
- signer: Signer,
40
- encryptionKey: Uint8Array,
41
- options?: ClientOptions,
42
- ) {
50
+ /**
51
+ * Creates a new XMTP client instance
52
+ *
53
+ * This class is not intended to be initialized directly.
54
+ * Use `Client.create` or `Client.build` instead.
55
+ *
56
+ * @param options - Optional configuration for the client
57
+ */
58
+ constructor(options?: ClientOptions) {
43
59
  const worker = new Worker(new URL("./workers/client", import.meta.url), {
44
60
  type: "module",
45
61
  });
@@ -47,9 +63,7 @@ export class Client extends ClientWorkerClass {
47
63
  worker,
48
64
  options?.loggingLevel !== undefined && options.loggingLevel !== "off",
49
65
  );
50
- this.options = options;
51
- this.#encryptionKey = encryptionKey;
52
- this.#signer = signer;
66
+ this.#options = options;
53
67
  this.#conversations = new Conversations(this);
54
68
  this.#preferences = new Preferences(this);
55
69
  const codecs = [
@@ -62,26 +76,38 @@ export class Client extends ClientWorkerClass {
62
76
  );
63
77
  }
64
78
 
65
- async init() {
79
+ /**
80
+ * Initializes the client with the provided identifier
81
+ *
82
+ * This is not meant to be called directly.
83
+ * Use `Client.create` or `Client.build` instead.
84
+ *
85
+ * @param identifier - The identifier to initialize the client with
86
+ */
87
+ async init(identifier: Identifier) {
66
88
  const result = await this.sendMessage("init", {
67
- identifier: await this.#signer.getIdentifier(),
68
- encryptionKey: this.#encryptionKey,
69
- options: this.options,
89
+ identifier,
90
+ options: this.#options,
70
91
  });
92
+ this.#identifier = identifier;
71
93
  this.#inboxId = result.inboxId;
72
94
  this.#installationId = result.installationId;
73
95
  this.#installationIdBytes = result.installationIdBytes;
74
96
  this.#isReady = true;
75
97
  }
76
98
 
77
- static async create(
78
- signer: Signer,
79
- encryptionKey: Uint8Array,
80
- options?: ClientOptions,
81
- ) {
82
- const client = new Client(signer, encryptionKey, options);
99
+ /**
100
+ * Creates a new client instance with a signer
101
+ *
102
+ * @param signer - The signer to use for authentication
103
+ * @param options - Optional configuration for the client
104
+ * @returns A new client instance
105
+ */
106
+ static async create(signer: Signer, options?: ClientOptions) {
107
+ const client = new Client(options);
108
+ client.#signer = signer;
83
109
 
84
- await client.init();
110
+ await client.init(await signer.getIdentifier());
85
111
 
86
112
  if (!options?.disableAutoRegister) {
87
113
  await client.register();
@@ -90,63 +116,115 @@ export class Client extends ClientWorkerClass {
90
116
  return client;
91
117
  }
92
118
 
119
+ /**
120
+ * Creates a new client instance with an identifier
121
+ *
122
+ * Clients created with this method must already be registered.
123
+ * Any methods called that require a signer will throw an error.
124
+ *
125
+ * @param identifier - The identifier to use
126
+ * @param options - Optional configuration for the client
127
+ * @returns A new client instance
128
+ */
129
+ static async build(identifier: Identifier, options?: ClientOptions) {
130
+ const client = new Client({
131
+ ...options,
132
+ disableAutoRegister: true,
133
+ });
134
+ await client.init(identifier);
135
+ return client;
136
+ }
137
+
138
+ /**
139
+ * Gets the client options
140
+ */
141
+ get options() {
142
+ return this.#options;
143
+ }
144
+
145
+ /**
146
+ * Gets whether the client has been initialized
147
+ */
93
148
  get isReady() {
94
149
  return this.#isReady;
95
150
  }
96
151
 
152
+ /**
153
+ * Gets the inbox ID associated with this client
154
+ */
97
155
  get inboxId() {
98
156
  return this.#inboxId;
99
157
  }
100
158
 
101
- async accountIdentifier() {
102
- return this.#signer.getIdentifier();
159
+ /**
160
+ * Gets the account identifier for this client
161
+ */
162
+ get accountIdentifier() {
163
+ return this.#identifier;
103
164
  }
104
165
 
166
+ /**
167
+ * Gets the installation ID for this client
168
+ */
105
169
  get installationId() {
106
170
  return this.#installationId;
107
171
  }
108
172
 
173
+ /**
174
+ * Gets the installation ID bytes for this client
175
+ */
109
176
  get installationIdBytes() {
110
177
  return this.#installationIdBytes;
111
178
  }
112
179
 
180
+ /**
181
+ * Gets the conversations manager for this client
182
+ */
113
183
  get conversations() {
114
184
  return this.#conversations;
115
185
  }
116
186
 
187
+ /**
188
+ * Gets the preferences manager for this client
189
+ */
117
190
  get preferences() {
118
191
  return this.#preferences;
119
192
  }
120
193
 
121
194
  /**
195
+ * Creates signature text for creating a new inbox
196
+ *
122
197
  * WARNING: This function should be used with caution. It is only provided
123
198
  * for use in special cases where the provided workflows do not meet the
124
199
  * requirements of an application.
125
200
  *
126
- * It is highly recommended to use the `register` function instead.
201
+ * It is highly recommended to use the `register` method instead.
202
+ *
203
+ * @returns The signature text
127
204
  */
128
205
  async unsafe_createInboxSignatureText() {
129
206
  return this.sendMessage("createInboxSignatureText", undefined);
130
207
  }
131
208
 
132
209
  /**
210
+ * Creates signature text for adding a new account to the client's inbox
211
+ *
133
212
  * WARNING: This function should be used with caution. It is only provided
134
213
  * for use in special cases where the provided workflows do not meet the
135
214
  * requirements of an application.
136
215
  *
137
- * It is highly recommended to use the `unsafe_addAccount` function instead.
216
+ * It is highly recommended to use the `unsafe_addAccount` method instead.
138
217
  *
139
- * The `allowInboxReassign` parameter must be true or this function will
140
- * throw an error.
218
+ * @param newIdentifier - The identifier of the new account
219
+ * @param allowInboxReassign - Whether to allow inbox reassignment
220
+ * @returns The signature text
141
221
  */
142
222
  async unsafe_addAccountSignatureText(
143
223
  newIdentifier: Identifier,
144
224
  allowInboxReassign: boolean = false,
145
225
  ) {
146
226
  if (!allowInboxReassign) {
147
- throw new Error(
148
- "Unable to create add account signature text, `allowInboxReassign` must be true",
149
- );
227
+ throw new InboxReassignError();
150
228
  }
151
229
 
152
230
  return this.sendMessage("addAccountSignatureText", {
@@ -155,11 +233,16 @@ export class Client extends ClientWorkerClass {
155
233
  }
156
234
 
157
235
  /**
236
+ * Creates signature text for removing an account from the client's inbox
237
+ *
158
238
  * WARNING: This function should be used with caution. It is only provided
159
239
  * for use in special cases where the provided workflows do not meet the
160
240
  * requirements of an application.
161
241
  *
162
- * It is highly recommended to use the `removeAccount` function instead.
242
+ * It is highly recommended to use the `removeAccount` method instead.
243
+ *
244
+ * @param identifier - The identifier of the account to remove
245
+ * @returns The signature text
163
246
  */
164
247
  async unsafe_removeAccountSignatureText(identifier: Identifier) {
165
248
  return this.sendMessage("removeAccountSignatureText", {
@@ -168,12 +251,16 @@ export class Client extends ClientWorkerClass {
168
251
  }
169
252
 
170
253
  /**
254
+ * Creates signature text for revoking all other installations of the
255
+ * client's inbox
256
+ *
171
257
  * WARNING: This function should be used with caution. It is only provided
172
258
  * for use in special cases where the provided workflows do not meet the
173
259
  * requirements of an application.
174
260
  *
175
- * It is highly recommended to use the `revokeAllOtherInstallations` function
176
- * instead.
261
+ * It is highly recommended to use the `revokeAllOtherInstallations` method instead.
262
+ *
263
+ * @returns The signature text
177
264
  */
178
265
  async unsafe_revokeAllOtherInstallationsSignatureText() {
179
266
  return this.sendMessage(
@@ -183,11 +270,17 @@ export class Client extends ClientWorkerClass {
183
270
  }
184
271
 
185
272
  /**
273
+ * Creates signature text for revoking specific installations of the
274
+ * client's inbox
275
+ *
186
276
  * WARNING: This function should be used with caution. It is only provided
187
277
  * for use in special cases where the provided workflows do not meet the
188
278
  * requirements of an application.
189
279
  *
190
- * It is highly recommended to use the `revokeInstallations` function instead.
280
+ * It is highly recommended to use the `revokeInstallations` method instead.
281
+ *
282
+ * @param installationIds - The installation IDs to revoke
283
+ * @returns The signature text
191
284
  */
192
285
  async unsafe_revokeInstallationsSignatureText(installationIds: Uint8Array[]) {
193
286
  return this.sendMessage("revokeInstallationsSignatureText", {
@@ -196,13 +289,39 @@ export class Client extends ClientWorkerClass {
196
289
  }
197
290
 
198
291
  /**
292
+ * Creates signature text for changing the recovery identifier for this
293
+ * client's inbox
294
+ *
199
295
  * WARNING: This function should be used with caution. It is only provided
200
296
  * for use in special cases where the provided workflows do not meet the
201
297
  * requirements of an application.
202
298
  *
203
- * It is highly recommended to use the `register`, `addAccount`,
299
+ * It is highly recommended to use the `changeRecoveryIdentifier` method instead.
300
+ *
301
+ * @param identifier - The new recovery identifier
302
+ * @returns The signature text
303
+ */
304
+ async unsafe_changeRecoveryIdentifierSignatureText(identifier: Identifier) {
305
+ return this.sendMessage("changeRecoveryIdentifierSignatureText", {
306
+ identifier,
307
+ });
308
+ }
309
+
310
+ /**
311
+ * Adds a signature for a specific request type
312
+ *
313
+ * WARNING: This function should be used with caution. It is only provided
314
+ * for use in special cases where the provided workflows do not meet the
315
+ * requirements of an application.
316
+ *
317
+ * It is highly recommended to use the `register`, `unsafe_addAccount`,
204
318
  * `removeAccount`, `revokeAllOtherInstallations`, or `revokeInstallations`
205
- * functions instead.
319
+ * methods instead.
320
+ *
321
+ * @param signatureType - The type of signature request
322
+ * @param signatureText - The text to sign
323
+ * @param signer - The signer to use
324
+ * @warning This is an unsafe operation and should be used with caution
206
325
  */
207
326
  async unsafe_addSignature(
208
327
  signatureType: SignatureRequestType,
@@ -230,19 +349,32 @@ export class Client extends ClientWorkerClass {
230
349
  }
231
350
 
232
351
  /**
352
+ * Applies all pending signatures
353
+ *
233
354
  * WARNING: This function should be used with caution. It is only provided
234
355
  * for use in special cases where the provided workflows do not meet the
235
356
  * requirements of an application.
236
357
  *
237
- * It is highly recommended to use the `register`, `addAccount`,
358
+ * It is highly recommended to use the `register`, `unsafe_addAccount`,
238
359
  * `removeAccount`, `revokeAllOtherInstallations`, or `revokeInstallations`
239
- * functions instead.
360
+ * methods instead.
240
361
  */
241
362
  async unsafe_applySignatures() {
242
363
  return this.sendMessage("applySignatures", undefined);
243
364
  }
244
365
 
366
+ /**
367
+ * Registers the client with the XMTP network
368
+ *
369
+ * Requires a signer, use `Client.create` to create a client with a signer.
370
+ *
371
+ * @throws {SignerUnavailableError} if no signer is available
372
+ */
245
373
  async register() {
374
+ if (!this.#signer) {
375
+ throw new SignerUnavailableError();
376
+ }
377
+
246
378
  const signatureText = await this.unsafe_createInboxSignatureText();
247
379
 
248
380
  // if the signature text is not available, the client is already registered
@@ -260,12 +392,22 @@ export class Client extends ClientWorkerClass {
260
392
  }
261
393
 
262
394
  /**
395
+ * Adds a new account to the client inbox
396
+ *
263
397
  * WARNING: This function should be used with caution. Adding a wallet already
264
- * associated with an inboxId will cause the wallet to lose access to
398
+ * associated with an inbox ID will cause the wallet to lose access to
265
399
  * that inbox.
266
400
  *
267
401
  * The `allowInboxReassign` parameter must be true to reassign an inbox
268
402
  * already associated with a different account.
403
+ *
404
+ * Requires a signer, use `Client.create` to create a client with a signer.
405
+ *
406
+ * @param newAccountSigner - The signer for the new account
407
+ * @param allowInboxReassign - Whether to allow inbox reassignment
408
+ * @throws {AccountAlreadyAssociatedError} if the account is already associated with an inbox ID
409
+ * @throws {GenerateSignatureError} if the signature cannot be generated
410
+ * @throws {SignerUnavailableError} if no signer is available
269
411
  */
270
412
  async unsafe_addAccount(
271
413
  newAccountSigner: Signer,
@@ -277,9 +419,7 @@ export class Client extends ClientWorkerClass {
277
419
  );
278
420
 
279
421
  if (existingInboxId && !allowInboxReassign) {
280
- throw new Error(
281
- `Signer address already associated with inbox ${existingInboxId}`,
282
- );
422
+ throw new AccountAlreadyAssociatedError(existingInboxId);
283
423
  }
284
424
 
285
425
  const signatureText = await this.unsafe_addAccountSignatureText(
@@ -288,7 +428,7 @@ export class Client extends ClientWorkerClass {
288
428
  );
289
429
 
290
430
  if (!signatureText) {
291
- throw new Error("Unable to generate add account signature text");
431
+ throw new GenerateSignatureError(SignatureRequestType.AddWallet);
292
432
  }
293
433
 
294
434
  await this.unsafe_addSignature(
@@ -300,12 +440,25 @@ export class Client extends ClientWorkerClass {
300
440
  await this.unsafe_applySignatures();
301
441
  }
302
442
 
443
+ /**
444
+ * Removes an account from the client's inbox
445
+ *
446
+ * Requires a signer, use `Client.create` to create a client with a signer.
447
+ *
448
+ * @param accountIdentifier - The identifier of the account to remove
449
+ * @throws {GenerateSignatureError} if the signature cannot be generated
450
+ * @throws {SignerUnavailableError} if no signer is available
451
+ */
303
452
  async removeAccount(accountIdentifier: Identifier) {
453
+ if (!this.#signer) {
454
+ throw new SignerUnavailableError();
455
+ }
456
+
304
457
  const signatureText =
305
458
  await this.unsafe_removeAccountSignatureText(accountIdentifier);
306
459
 
307
460
  if (!signatureText) {
308
- throw new Error("Unable to generate remove account signature text");
461
+ throw new GenerateSignatureError(SignatureRequestType.RevokeWallet);
309
462
  }
310
463
 
311
464
  await this.unsafe_addSignature(
@@ -317,13 +470,25 @@ export class Client extends ClientWorkerClass {
317
470
  await this.unsafe_applySignatures();
318
471
  }
319
472
 
473
+ /**
474
+ * Revokes all other installations of the client's inbox
475
+ *
476
+ * Requires a signer, use `Client.create` to create a client with a signer.
477
+ *
478
+ * @throws {GenerateSignatureError} if the signature cannot be generated
479
+ * @throws {SignerUnavailableError} if no signer is available
480
+ */
320
481
  async revokeAllOtherInstallations() {
482
+ if (!this.#signer) {
483
+ throw new SignerUnavailableError();
484
+ }
485
+
321
486
  const signatureText =
322
487
  await this.unsafe_revokeAllOtherInstallationsSignatureText();
323
488
 
324
489
  if (!signatureText) {
325
- throw new Error(
326
- "Unable to generate revoke all other installations signature text",
490
+ throw new GenerateSignatureError(
491
+ SignatureRequestType.RevokeInstallations,
327
492
  );
328
493
  }
329
494
 
@@ -336,12 +501,27 @@ export class Client extends ClientWorkerClass {
336
501
  await this.unsafe_applySignatures();
337
502
  }
338
503
 
504
+ /**
505
+ * Revokes specific installations of the client's inbox
506
+ *
507
+ * Requires a signer, use `Client.create` to create a client with a signer.
508
+ *
509
+ * @param installationIds - The installation IDs to revoke
510
+ * @throws {GenerateSignatureError} if the signature cannot be generated
511
+ * @throws {SignerUnavailableError} if no signer is available
512
+ */
339
513
  async revokeInstallations(installationIds: Uint8Array[]) {
514
+ if (!this.#signer) {
515
+ throw new SignerUnavailableError();
516
+ }
517
+
340
518
  const signatureText =
341
519
  await this.unsafe_revokeInstallationsSignatureText(installationIds);
342
520
 
343
521
  if (!signatureText) {
344
- throw new Error("Unable to generate revoke installations signature text");
522
+ throw new GenerateSignatureError(
523
+ SignatureRequestType.RevokeInstallations,
524
+ );
345
525
  }
346
526
 
347
527
  await this.unsafe_addSignature(
@@ -353,48 +533,107 @@ export class Client extends ClientWorkerClass {
353
533
  await this.unsafe_applySignatures();
354
534
  }
355
535
 
536
+ /**
537
+ * Changes the recovery identifier for the client's inbox
538
+ *
539
+ * Requires a signer, use `Client.create` to create a client with a signer.
540
+ *
541
+ * @param identifier - The new recovery identifier
542
+ * @throws {GenerateSignatureError} if the signature cannot be generated
543
+ * @throws {SignerUnavailableError} if no signer is available
544
+ */
545
+ async changeRecoveryIdentifier(identifier: Identifier) {
546
+ if (!this.#signer) {
547
+ throw new SignerUnavailableError();
548
+ }
549
+
550
+ const signatureText =
551
+ await this.unsafe_changeRecoveryIdentifierSignatureText(identifier);
552
+
553
+ if (!signatureText) {
554
+ throw new GenerateSignatureError(
555
+ SignatureRequestType.ChangeRecoveryIdentifier,
556
+ );
557
+ }
558
+
559
+ await this.unsafe_addSignature(
560
+ SignatureRequestType.ChangeRecoveryIdentifier,
561
+ signatureText,
562
+ this.#signer,
563
+ );
564
+
565
+ await this.unsafe_applySignatures();
566
+ }
567
+
568
+ /**
569
+ * Checks if the client is registered with the XMTP network
570
+ *
571
+ * @returns Whether the client is registered
572
+ */
356
573
  async isRegistered() {
357
574
  return this.sendMessage("isRegistered", undefined);
358
575
  }
359
576
 
577
+ /**
578
+ * Checks if the client can message the specified identifiers
579
+ *
580
+ * @param identifiers - The identifiers to check
581
+ * @returns Whether the client can message the identifiers
582
+ */
360
583
  async canMessage(identifiers: Identifier[]) {
361
584
  return this.sendMessage("canMessage", { identifiers });
362
585
  }
363
586
 
587
+ /**
588
+ * Checks if the specified identifiers can be messaged
589
+ *
590
+ * @param identifiers - The identifiers to check
591
+ * @param env - Optional XMTP environment
592
+ * @returns Map of identifiers to whether they can be messaged
593
+ */
364
594
  static async canMessage(identifiers: Identifier[], env?: XmtpEnv) {
365
- const signer: Signer = {
366
- type: "EOA",
367
- getIdentifier: () => ({
368
- identifier: "0x0000000000000000000000000000000000000000",
369
- identifierKind: "Ethereum",
370
- }),
371
- signMessage: () => new Uint8Array(),
372
- };
373
- const client = await Client.create(
374
- signer,
375
- window.crypto.getRandomValues(new Uint8Array(32)),
376
- {
377
- disableAutoRegister: true,
378
- env,
379
- },
380
- );
381
- return client.canMessage(identifiers);
595
+ const canMessageMap = new Map<string, boolean>();
596
+ const utils = new Utils();
597
+ for (const identifier of identifiers) {
598
+ const inboxId = await utils.getInboxIdForIdentifier(identifier, env);
599
+ canMessageMap.set(identifier.identifier, inboxId !== undefined);
600
+ }
601
+ utils.close();
602
+ return canMessageMap;
382
603
  }
383
604
 
605
+ /**
606
+ * Finds the inbox ID for a given identifier
607
+ *
608
+ * @param identifier - The identifier to look up
609
+ * @returns The inbox ID, if found
610
+ */
384
611
  async findInboxIdByIdentifier(identifier: Identifier) {
385
612
  return this.sendMessage("findInboxIdByIdentifier", { identifier });
386
613
  }
387
614
 
615
+ /**
616
+ * Gets the codec for a given content type
617
+ *
618
+ * @param contentType - The content type to get the codec for
619
+ * @returns The codec, if found
620
+ */
388
621
  codecFor(contentType: ContentTypeId) {
389
622
  return this.#codecs.get(contentType.toString());
390
623
  }
391
624
 
625
+ /**
626
+ * Encodes content for a given content type
627
+ *
628
+ * @param content - The content to encode
629
+ * @param contentType - The content type to encode for
630
+ * @returns The encoded content
631
+ * @throws {CodecNotFoundError} if no codec is found for the content type
632
+ */
392
633
  encodeContent(content: any, contentType: ContentTypeId) {
393
634
  const codec = this.codecFor(contentType);
394
635
  if (!codec) {
395
- throw new Error(
396
- `Codec not found for "${contentType.toString()}" content type`,
397
- );
636
+ throw new CodecNotFoundError(contentType);
398
637
  }
399
638
  const encoded = codec.encode(content, this);
400
639
  const fallback = codec.fallback(content);
@@ -404,12 +643,19 @@ export class Client extends ClientWorkerClass {
404
643
  return toSafeEncodedContent(encoded);
405
644
  }
406
645
 
646
+ /**
647
+ * Decodes a message for a given content type
648
+ *
649
+ * @param message - The message to decode
650
+ * @param contentType - The content type to decode for
651
+ * @returns The decoded content
652
+ * @throws {CodecNotFoundError} if no codec is found for the content type
653
+ * @throws {InvalidGroupMembershipChangeError} if the message is an invalid group membership change
654
+ */
407
655
  decodeContent(message: SafeMessage, contentType: ContentTypeId) {
408
656
  const codec = this.codecFor(contentType);
409
657
  if (!codec) {
410
- throw new Error(
411
- `Codec not found for "${contentType.toString()}" content type`,
412
- );
658
+ throw new CodecNotFoundError(contentType);
413
659
  }
414
660
 
415
661
  // throw an error if there's an invalid group membership change message
@@ -417,7 +663,7 @@ export class Client extends ClientWorkerClass {
417
663
  contentType.sameAs(ContentTypeGroupUpdated) &&
418
664
  message.kind !== GroupMessageKind.MembershipChange
419
665
  ) {
420
- throw new Error("Error decoding group membership change");
666
+ throw new InvalidGroupMembershipChangeError(message.id);
421
667
  }
422
668
 
423
669
  const encodedContent = fromSafeEncodedContent(message.content);
@@ -425,10 +671,23 @@ export class Client extends ClientWorkerClass {
425
671
  return codec.decode(encodedContent, this);
426
672
  }
427
673
 
674
+ /**
675
+ * Signs a message with the installation key
676
+ *
677
+ * @param signatureText - The text to sign
678
+ * @returns The signature
679
+ */
428
680
  signWithInstallationKey(signatureText: string) {
429
681
  return this.sendMessage("signWithInstallationKey", { signatureText });
430
682
  }
431
683
 
684
+ /**
685
+ * Verifies a signature was made with the installation key
686
+ *
687
+ * @param signatureText - The text that was signed
688
+ * @param signatureBytes - The signature bytes to verify
689
+ * @returns Whether the signature is valid
690
+ */
432
691
  verifySignedWithInstallationKey(
433
692
  signatureText: string,
434
693
  signatureBytes: Uint8Array,
@@ -439,6 +698,14 @@ export class Client extends ClientWorkerClass {
439
698
  });
440
699
  }
441
700
 
701
+ /**
702
+ * Verifies a signature was made with a public key
703
+ *
704
+ * @param signatureText - The text that was signed
705
+ * @param signatureBytes - The signature bytes to verify
706
+ * @param publicKey - The public key to verify against
707
+ * @returns Whether the signature is valid
708
+ */
442
709
  verifySignedWithPublicKey(
443
710
  signatureText: string,
444
711
  signatureBytes: Uint8Array,
@@ -450,4 +717,16 @@ export class Client extends ClientWorkerClass {
450
717
  publicKey,
451
718
  });
452
719
  }
720
+
721
+ /**
722
+ * Gets the key package statuses for the specified installation IDs
723
+ *
724
+ * @param installationIds - The installation IDs to check
725
+ * @returns The key package statuses
726
+ */
727
+ async getKeyPackageStatusesForInstallationIds(installationIds: string[]) {
728
+ return this.sendMessage("getKeyPackageStatusesForInstallationIds", {
729
+ installationIds,
730
+ });
731
+ }
453
732
  }