@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.
@@ -10,7 +10,6 @@ import type { ClientOptions } from "@/types";
10
10
 
11
11
  export const createClient = async (
12
12
  identifier: Identifier,
13
- encryptionKey: Uint8Array,
14
13
  options?: Omit<ClientOptions, "codecs">,
15
14
  ) => {
16
15
  const host = options?.apiUrl || ApiUrls[options?.env || "dev"];
@@ -18,7 +17,9 @@ export const createClient = async (
18
17
  (await getInboxIdForIdentifier(host, identifier)) ||
19
18
  generateInboxId(identifier);
20
19
  const dbPath =
21
- options?.dbPath || `xmtp-${options?.env || "dev"}-${inboxId}.db3`;
20
+ options?.dbPath === undefined
21
+ ? `xmtp-${options?.env || "dev"}-${inboxId}.db3`
22
+ : options.dbPath;
22
23
  const isLogging =
23
24
  options &&
24
25
  (options.loggingLevel !== undefined ||
@@ -33,7 +34,7 @@ export const createClient = async (
33
34
  inboxId,
34
35
  identifier,
35
36
  dbPath,
36
- encryptionKey,
37
+ options?.dbEncryptionKey,
37
38
  historySyncUrl,
38
39
  isLogging
39
40
  ? new LogOptions(
@@ -0,0 +1,86 @@
1
+ import type { ContentTypeId } from "@xmtp/content-type-primitives";
2
+ import { SignatureRequestType } from "@xmtp/wasm-bindings";
3
+
4
+ export class ClientNotInitializedError extends Error {
5
+ constructor() {
6
+ super("Client not initialized");
7
+ }
8
+ }
9
+
10
+ export class SignerUnavailableError extends Error {
11
+ constructor() {
12
+ super(
13
+ "Signer unavailable, use Client.create to create a client with a signer",
14
+ );
15
+ }
16
+ }
17
+
18
+ export class CodecNotFoundError extends Error {
19
+ constructor(contentType: ContentTypeId) {
20
+ super(`Codec not found for "${contentType.toString()}" content type`);
21
+ }
22
+ }
23
+
24
+ export class InboxReassignError extends Error {
25
+ constructor() {
26
+ super(
27
+ "Unable to create add account signature text, `allowInboxReassign` must be true",
28
+ );
29
+ }
30
+ }
31
+
32
+ export class AccountAlreadyAssociatedError extends Error {
33
+ constructor(inboxId: string) {
34
+ super(`Account already associated with inbox ${inboxId}`);
35
+ }
36
+ }
37
+
38
+ export class GenerateSignatureError extends Error {
39
+ constructor(signatureType: SignatureRequestType) {
40
+ let type = "";
41
+
42
+ switch (signatureType) {
43
+ case SignatureRequestType.AddWallet:
44
+ type = "add account";
45
+ break;
46
+ case SignatureRequestType.CreateInbox:
47
+ type = "create inbox";
48
+ break;
49
+ case SignatureRequestType.RevokeWallet:
50
+ type = "remove account";
51
+ break;
52
+ case SignatureRequestType.RevokeInstallations:
53
+ type = "revoke installations";
54
+ break;
55
+ case SignatureRequestType.ChangeRecoveryIdentifier:
56
+ type = "change recovery identifier";
57
+ break;
58
+ }
59
+
60
+ super(`Failed to generate ${type} signature text`);
61
+ }
62
+ }
63
+
64
+ export class GroupNotFoundError extends Error {
65
+ constructor(groupId: string) {
66
+ super(`Group "${groupId}" not found`);
67
+ }
68
+ }
69
+
70
+ export class StreamNotFoundError extends Error {
71
+ constructor(streamId: string) {
72
+ super(`Stream "${streamId}" not found`);
73
+ }
74
+ }
75
+
76
+ export class InvalidGroupMembershipChangeError extends Error {
77
+ constructor(messageId: string) {
78
+ super(`Invalid group membership change for message ${messageId}`);
79
+ }
80
+ }
81
+
82
+ export class MissingContentTypeError extends Error {
83
+ constructor() {
84
+ super("Content type is required when sending content other than text");
85
+ }
86
+ }
@@ -23,9 +23,15 @@ import {
23
23
  toSafeConversation,
24
24
  toSafeHmacKey,
25
25
  toSafeInboxState,
26
+ toSafeKeyPackageStatus,
26
27
  toSafeMessage,
27
28
  toSafeMessageDisappearingSettings,
28
29
  } from "@/utils/conversions";
30
+ import {
31
+ ClientNotInitializedError,
32
+ GroupNotFoundError,
33
+ StreamNotFoundError,
34
+ } from "@/utils/errors";
29
35
  import { WorkerClient } from "@/WorkerClient";
30
36
  import { WorkerConversation } from "@/WorkerConversation";
31
37
 
@@ -79,11 +85,7 @@ self.onmessage = async (event: MessageEvent<ClientEventsClientMessageData>) => {
79
85
  try {
80
86
  // init is a special action that initializes the client
81
87
  if (action === "init" && !maybeClient) {
82
- maybeClient = await WorkerClient.create(
83
- data.identifier,
84
- data.encryptionKey,
85
- data.options,
86
- );
88
+ maybeClient = await WorkerClient.create(data.identifier, data.options);
87
89
  enableLogging =
88
90
  data.options?.loggingLevel !== undefined &&
89
91
  data.options.loggingLevel !== "off";
@@ -101,7 +103,7 @@ self.onmessage = async (event: MessageEvent<ClientEventsClientMessageData>) => {
101
103
 
102
104
  // a client is required for all other actions
103
105
  if (!maybeClient) {
104
- throw new Error("Client not initialized");
106
+ throw new ClientNotInitializedError();
105
107
  }
106
108
 
107
109
  // let typescript know that a client will be available for the rest
@@ -112,7 +114,7 @@ self.onmessage = async (event: MessageEvent<ClientEventsClientMessageData>) => {
112
114
  const getGroup = (groupId: string) => {
113
115
  const group = client.conversations.getConversationById(groupId);
114
116
  if (!group) {
115
- throw new Error(`Group "${groupId}" not found`);
117
+ throw new GroupNotFoundError(groupId);
116
118
  }
117
119
  return group;
118
120
  };
@@ -128,7 +130,7 @@ self.onmessage = async (event: MessageEvent<ClientEventsClientMessageData>) => {
128
130
  streamClosers.delete(data.streamId);
129
131
  postMessage({ id, action, result: undefined });
130
132
  } else {
131
- throw new Error(`Stream "${data.streamId}" not found`);
133
+ throw new StreamNotFoundError(data.streamId);
132
134
  }
133
135
  break;
134
136
  }
@@ -162,6 +164,13 @@ self.onmessage = async (event: MessageEvent<ClientEventsClientMessageData>) => {
162
164
  postMessage({ id, action, result });
163
165
  break;
164
166
  }
167
+ case "changeRecoveryIdentifierSignatureText": {
168
+ const result = await client.changeRecoveryIdentifierSignatureText(
169
+ data.identifier,
170
+ );
171
+ postMessage({ id, action, result });
172
+ break;
173
+ }
165
174
  case "addEcdsaSignature":
166
175
  await client.addEcdsaSignature(data.type, data.bytes);
167
176
  postMessage({ id, action, result: undefined });
@@ -258,6 +267,23 @@ self.onmessage = async (event: MessageEvent<ClientEventsClientMessageData>) => {
258
267
  postMessage({ id, action, result });
259
268
  break;
260
269
  }
270
+ case "getKeyPackageStatusesForInstallationIds": {
271
+ const result = await client.getKeyPackageStatusesForInstallationIds(
272
+ data.installationIds,
273
+ );
274
+ const safeResult = new Map(
275
+ Array.from(result.entries()).map(([installationId, status]) => [
276
+ installationId,
277
+ toSafeKeyPackageStatus(status),
278
+ ]),
279
+ );
280
+ postMessage({
281
+ id,
282
+ action,
283
+ result: safeResult,
284
+ });
285
+ break;
286
+ }
261
287
  /**
262
288
  * Conversations actions
263
289
  */
@@ -715,6 +741,12 @@ self.onmessage = async (event: MessageEvent<ClientEventsClientMessageData>) => {
715
741
  postMessage({ id, action, result });
716
742
  break;
717
743
  }
744
+ case "getGroupHmacKeys": {
745
+ const group = getGroup(data.id);
746
+ const result = group.getHmacKeys();
747
+ postMessage({ id, action, result });
748
+ break;
749
+ }
718
750
  }
719
751
  } catch (e) {
720
752
  postMessageError({
@@ -36,9 +36,12 @@ const getInboxIdForIdentifier = async (
36
36
  return get_inbox_id_for_identifier(host, identifier);
37
37
  };
38
38
 
39
+ let enableLogging = false;
40
+
39
41
  self.onmessage = async (event: MessageEvent<UtilsEventsClientMessageData>) => {
40
42
  const { action, id, data } = event.data;
41
- if (data.enableLogging) {
43
+
44
+ if (enableLogging) {
42
45
  console.log("utils worker received event data", event.data);
43
46
  }
44
47
 
@@ -47,6 +50,14 @@ self.onmessage = async (event: MessageEvent<UtilsEventsClientMessageData>) => {
47
50
 
48
51
  try {
49
52
  switch (action) {
53
+ case "init":
54
+ enableLogging = data.enableLogging;
55
+ postMessage({
56
+ id,
57
+ action,
58
+ result: undefined,
59
+ });
60
+ break;
50
61
  case "generateInboxId":
51
62
  postMessage({
52
63
  id,
@@ -61,7 +72,6 @@ self.onmessage = async (event: MessageEvent<UtilsEventsClientMessageData>) => {
61
72
  result: await getInboxIdForIdentifier(data.identifier, data.env),
62
73
  });
63
74
  break;
64
- // no default
65
75
  }
66
76
  } catch (e) {
67
77
  postMessageError({