@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/dist/index.d.ts +774 -27
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/workers/client.js +1 -1
- package/dist/workers/client.js.map +1 -1
- package/dist/workers/utils.js +1 -1
- package/dist/workers/utils.js.map +1 -1
- package/package.json +8 -8
- package/src/Client.ts +351 -72
- package/src/Conversation.ts +104 -13
- package/src/Conversations.ts +130 -0
- package/src/DecodedMessage.ts +20 -12
- package/src/Dm.ts +17 -1
- package/src/Group.ts +124 -9
- package/src/Preferences.ts +54 -0
- package/src/Utils.ts +21 -4
- package/src/UtilsWorkerClass.ts +7 -0
- package/src/WorkerClient.ts +18 -2
- package/src/WorkerConversation.ts +5 -0
- package/src/constants.ts +16 -0
- package/src/index.ts +0 -1
- package/src/types/clientEvents.ts +26 -2
- package/src/types/options.ts +5 -1
- package/src/types/utilsEvents.ts +8 -2
- package/src/utils/conversions.ts +21 -0
- package/src/utils/createClient.ts +4 -3
- package/src/utils/errors.ts +86 -0
- package/src/workers/client.ts +40 -8
- package/src/workers/utils.ts +12 -2
|
@@ -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
|
|
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
|
-
|
|
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
|
+
}
|
package/src/workers/client.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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({
|
package/src/workers/utils.ts
CHANGED
|
@@ -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
|
-
|
|
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({
|