@xmtp/browser-sdk 0.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.
@@ -0,0 +1,59 @@
1
+ import type { ContentCodec } from "@xmtp/content-type-primitives";
2
+ import type { ApiUrls } from "@/constants";
3
+
4
+ export type XmtpEnv = keyof typeof ApiUrls;
5
+
6
+ /**
7
+ * Network options
8
+ */
9
+ export type NetworkOptions = {
10
+ /**
11
+ * Specify which XMTP environment to connect to. (default: `dev`)
12
+ */
13
+ env?: XmtpEnv;
14
+ /**
15
+ * apiUrl can be used to override the `env` flag and connect to a
16
+ * specific endpoint
17
+ */
18
+ apiUrl?: string;
19
+ };
20
+
21
+ /**
22
+ * Encryption options
23
+ */
24
+ export type EncryptionOptions = {
25
+ /**
26
+ * Encryption key to use for the local DB
27
+ */
28
+ encryptionKey?: Uint8Array;
29
+ };
30
+
31
+ /**
32
+ * Storage options
33
+ */
34
+ export type StorageOptions = {
35
+ /**
36
+ * Path to the local DB
37
+ */
38
+ dbPath?: string;
39
+ };
40
+
41
+ export type ContentOptions = {
42
+ /**
43
+ * Allow configuring codecs for additional content types
44
+ */
45
+ codecs?: ContentCodec[];
46
+ };
47
+
48
+ export type OtherOptions = {
49
+ /**
50
+ * Enable logging of events between the client and worker
51
+ */
52
+ enableLogging?: boolean;
53
+ };
54
+
55
+ export type ClientOptions = NetworkOptions &
56
+ EncryptionOptions &
57
+ StorageOptions &
58
+ ContentOptions &
59
+ OtherOptions;
@@ -0,0 +1,46 @@
1
+ export type GenericEvent = {
2
+ action: string;
3
+ id: string;
4
+ result: unknown;
5
+ data: unknown;
6
+ };
7
+
8
+ export type EventsClientMessageData<Events extends GenericEvent> = {
9
+ [Action in Events["action"]]: Omit<
10
+ Extract<Events, { action: Action }>,
11
+ "result"
12
+ >;
13
+ }[Events["action"]];
14
+
15
+ export type EventsWorkerMessageData<Events extends GenericEvent> = {
16
+ [Action in Events["action"]]: Omit<
17
+ Extract<Events, { action: Action }>,
18
+ "data"
19
+ >;
20
+ }[Events["action"]];
21
+
22
+ export type EventsResult<
23
+ Events extends GenericEvent,
24
+ Action extends Events["action"],
25
+ > = Extract<Events, { action: Action }>["result"];
26
+
27
+ export type SendMessageData<
28
+ Events extends GenericEvent,
29
+ Action extends Events["action"],
30
+ > = Extract<Events, { action: Action }>["data"];
31
+
32
+ export type EventsWorkerPostMessageData<
33
+ Events extends GenericEvent,
34
+ Action extends Events["action"],
35
+ > = Omit<Extract<Events, { action: Action }>, "data">;
36
+
37
+ export type EventsClientPostMessageData<
38
+ Events extends GenericEvent,
39
+ Action extends Events["action"],
40
+ > = Omit<Extract<Events, { action: Action }>, "result">;
41
+
42
+ export type EventsErrorData<Events extends GenericEvent> = {
43
+ id: string;
44
+ action: Events["action"];
45
+ error: string;
46
+ };
@@ -0,0 +1,53 @@
1
+ import type {
2
+ EventsClientMessageData,
3
+ EventsClientPostMessageData,
4
+ EventsErrorData,
5
+ EventsResult,
6
+ EventsWorkerMessageData,
7
+ EventsWorkerPostMessageData,
8
+ SendMessageData,
9
+ XmtpEnv,
10
+ } from "@/types";
11
+
12
+ export type UtilsEvents =
13
+ | {
14
+ action: "generateInboxId";
15
+ id: string;
16
+ result: string;
17
+ data: {
18
+ address: string;
19
+ enableLogging: boolean;
20
+ };
21
+ }
22
+ | {
23
+ action: "getInboxIdForAddress";
24
+ id: string;
25
+ result: string | undefined;
26
+ data: {
27
+ address: string;
28
+ env?: XmtpEnv;
29
+ enableLogging: boolean;
30
+ };
31
+ };
32
+
33
+ export type UtilsEventsActions = UtilsEvents["action"];
34
+
35
+ export type UtilsEventsClientMessageData = EventsClientMessageData<UtilsEvents>;
36
+
37
+ export type UtilsEventsWorkerMessageData = EventsWorkerMessageData<UtilsEvents>;
38
+
39
+ export type UtilsEventsResult<A extends UtilsEventsActions> = EventsResult<
40
+ UtilsEvents,
41
+ A
42
+ >;
43
+
44
+ export type UtilsSendMessageData<A extends UtilsEventsActions> =
45
+ SendMessageData<UtilsEvents, A>;
46
+
47
+ export type UtilsEventsWorkerPostMessageData<A extends UtilsEventsActions> =
48
+ EventsWorkerPostMessageData<UtilsEvents, A>;
49
+
50
+ export type UtilsEventsClientPostMessageData<A extends UtilsEventsActions> =
51
+ EventsClientPostMessageData<UtilsEvents, A>;
52
+
53
+ export type UtilsEventsErrorData = EventsErrorData<UtilsEvents>;
@@ -0,0 +1,352 @@
1
+ import {
2
+ ContentTypeId,
3
+ type EncodedContent,
4
+ } from "@xmtp/content-type-primitives";
5
+ import {
6
+ WasmConsent,
7
+ WasmContentTypeId,
8
+ WasmCreateGroupOptions,
9
+ WasmEncodedContent,
10
+ WasmGroupMember,
11
+ WasmListConversationsOptions,
12
+ WasmListMessagesOptions,
13
+ type WasmConsentEntityType,
14
+ type WasmConsentState,
15
+ type WasmDeliveryStatus,
16
+ type WasmGroupMessageKind,
17
+ type WasmGroupPermissionsOptions,
18
+ type WasmInboxState,
19
+ type WasmInstallation,
20
+ type WasmMessage,
21
+ type WasmPermissionLevel,
22
+ type WasmPermissionPolicy,
23
+ } from "@xmtp/wasm-bindings";
24
+ import type { WorkerConversation } from "@/WorkerConversation";
25
+
26
+ export const toContentTypeId = (
27
+ contentTypeId: WasmContentTypeId,
28
+ ): ContentTypeId =>
29
+ new ContentTypeId({
30
+ authorityId: contentTypeId.authority_id,
31
+ typeId: contentTypeId.type_id,
32
+ versionMajor: contentTypeId.version_major,
33
+ versionMinor: contentTypeId.version_minor,
34
+ });
35
+
36
+ export const fromContentTypeId = (
37
+ contentTypeId: ContentTypeId,
38
+ ): WasmContentTypeId =>
39
+ new WasmContentTypeId(
40
+ contentTypeId.authorityId,
41
+ contentTypeId.typeId,
42
+ contentTypeId.versionMajor,
43
+ contentTypeId.versionMinor,
44
+ );
45
+
46
+ export type SafeContentTypeId = {
47
+ authorityId: string;
48
+ typeId: string;
49
+ versionMajor: number;
50
+ versionMinor: number;
51
+ };
52
+
53
+ export const toSafeContentTypeId = (
54
+ contentTypeId: ContentTypeId,
55
+ ): SafeContentTypeId => ({
56
+ authorityId: contentTypeId.authorityId,
57
+ typeId: contentTypeId.typeId,
58
+ versionMajor: contentTypeId.versionMajor,
59
+ versionMinor: contentTypeId.versionMinor,
60
+ });
61
+
62
+ export const fromSafeContentTypeId = (
63
+ contentTypeId: SafeContentTypeId,
64
+ ): ContentTypeId =>
65
+ new ContentTypeId({
66
+ authorityId: contentTypeId.authorityId,
67
+ typeId: contentTypeId.typeId,
68
+ versionMajor: contentTypeId.versionMajor,
69
+ versionMinor: contentTypeId.versionMinor,
70
+ });
71
+
72
+ export const toEncodedContent = (
73
+ content: WasmEncodedContent,
74
+ ): EncodedContent => ({
75
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
76
+ type: toContentTypeId(content.type!),
77
+ parameters: Object.fromEntries(content.parameters as Map<string, string>),
78
+ fallback: content.fallback,
79
+ compression: content.compression,
80
+ content: content.content,
81
+ });
82
+
83
+ export const fromEncodedContent = (
84
+ content: EncodedContent,
85
+ ): WasmEncodedContent =>
86
+ new WasmEncodedContent(
87
+ fromContentTypeId(content.type),
88
+ new Map(Object.entries(content.parameters)),
89
+ content.fallback,
90
+ content.compression,
91
+ content.content,
92
+ );
93
+
94
+ export type SafeEncodedContent = {
95
+ type: SafeContentTypeId;
96
+ parameters: Record<string, string>;
97
+ fallback?: string;
98
+ compression?: number;
99
+ content: Uint8Array;
100
+ };
101
+
102
+ export const toSafeEncodedContent = (
103
+ content: EncodedContent,
104
+ ): SafeEncodedContent => ({
105
+ type: toSafeContentTypeId(content.type),
106
+ parameters: content.parameters,
107
+ fallback: content.fallback,
108
+ compression: content.compression,
109
+ content: content.content,
110
+ });
111
+
112
+ export const fromSafeEncodedContent = (
113
+ content: SafeEncodedContent,
114
+ ): EncodedContent => ({
115
+ type: fromSafeContentTypeId(content.type),
116
+ parameters: content.parameters,
117
+ fallback: content.fallback,
118
+ compression: content.compression,
119
+ content: content.content,
120
+ });
121
+
122
+ export type SafeMessage = {
123
+ content: SafeEncodedContent;
124
+ convoId: string;
125
+ deliveryStatus: WasmDeliveryStatus;
126
+ id: string;
127
+ kind: WasmGroupMessageKind;
128
+ senderInboxId: string;
129
+ sentAtNs: bigint;
130
+ };
131
+
132
+ export const toSafeMessage = (message: WasmMessage): SafeMessage => ({
133
+ content: toSafeEncodedContent(toEncodedContent(message.content)),
134
+ convoId: message.convo_id,
135
+ deliveryStatus: message.delivery_status,
136
+ id: message.id,
137
+ kind: message.kind,
138
+ senderInboxId: message.sender_inbox_id,
139
+ sentAtNs: message.sent_at_ns,
140
+ });
141
+
142
+ export type SafeListMessagesOptions = {
143
+ delivery_status?: WasmDeliveryStatus;
144
+ limit?: bigint;
145
+ sent_after_ns?: bigint;
146
+ sent_before_ns?: bigint;
147
+ };
148
+
149
+ export const toSafeListMessagesOptions = (
150
+ options: WasmListMessagesOptions,
151
+ ): SafeListMessagesOptions => ({
152
+ delivery_status: options.delivery_status,
153
+ limit: options.limit,
154
+ sent_after_ns: options.sent_after_ns,
155
+ sent_before_ns: options.sent_before_ns,
156
+ });
157
+
158
+ export const fromSafeListMessagesOptions = (
159
+ options: SafeListMessagesOptions,
160
+ ): WasmListMessagesOptions =>
161
+ new WasmListMessagesOptions(
162
+ options.sent_before_ns,
163
+ options.sent_after_ns,
164
+ options.limit,
165
+ options.delivery_status,
166
+ );
167
+
168
+ export type SafeListConversationsOptions = {
169
+ created_after_ns?: bigint;
170
+ created_before_ns?: bigint;
171
+ limit?: bigint;
172
+ };
173
+
174
+ export const toSafeListConversationsOptions = (
175
+ options: WasmListConversationsOptions,
176
+ ): SafeListConversationsOptions => ({
177
+ created_after_ns: options.created_after_ns,
178
+ created_before_ns: options.created_before_ns,
179
+ limit: options.limit,
180
+ });
181
+
182
+ export const fromSafeListConversationsOptions = (
183
+ options: SafeListConversationsOptions,
184
+ ): WasmListConversationsOptions =>
185
+ new WasmListConversationsOptions(
186
+ options.created_after_ns,
187
+ options.created_before_ns,
188
+ options.limit,
189
+ );
190
+
191
+ export type SafeCreateGroupOptions = {
192
+ permissions?: WasmGroupPermissionsOptions;
193
+ name?: string;
194
+ imageUrlSquare?: string;
195
+ description?: string;
196
+ pinnedFrameUrl?: string;
197
+ };
198
+
199
+ export const toSafeCreateGroupOptions = (
200
+ options: WasmCreateGroupOptions,
201
+ ): SafeCreateGroupOptions => ({
202
+ permissions: options.permissions,
203
+ name: options.group_name,
204
+ imageUrlSquare: options.group_image_url_square,
205
+ description: options.group_description,
206
+ pinnedFrameUrl: options.group_pinned_frame_url,
207
+ });
208
+
209
+ export const fromSafeCreateGroupOptions = (
210
+ options: SafeCreateGroupOptions,
211
+ ): WasmCreateGroupOptions =>
212
+ new WasmCreateGroupOptions(
213
+ options.permissions,
214
+ options.name,
215
+ options.imageUrlSquare,
216
+ options.description,
217
+ options.pinnedFrameUrl,
218
+ );
219
+
220
+ export type SafeConversation = {
221
+ id: string;
222
+ name: string;
223
+ imageUrl: string;
224
+ description: string;
225
+ pinnedFrameUrl: string;
226
+ permissions: {
227
+ policyType: WasmGroupPermissionsOptions;
228
+ policySet: {
229
+ addAdminPolicy: WasmPermissionPolicy;
230
+ addMemberPolicy: WasmPermissionPolicy;
231
+ removeAdminPolicy: WasmPermissionPolicy;
232
+ removeMemberPolicy: WasmPermissionPolicy;
233
+ updateGroupDescriptionPolicy: WasmPermissionPolicy;
234
+ updateGroupImageUrlSquarePolicy: WasmPermissionPolicy;
235
+ updateGroupNamePolicy: WasmPermissionPolicy;
236
+ updateGroupPinnedFrameUrlPolicy: WasmPermissionPolicy;
237
+ };
238
+ };
239
+ isActive: boolean;
240
+ addedByInboxId: string;
241
+ metadata: {
242
+ creatorInboxId: string;
243
+ conversationType: string;
244
+ };
245
+ admins: string[];
246
+ superAdmins: string[];
247
+ createdAtNs: bigint;
248
+ };
249
+
250
+ export const toSafeConversation = (
251
+ conversation: WorkerConversation,
252
+ ): SafeConversation => ({
253
+ id: conversation.id,
254
+ name: conversation.name,
255
+ imageUrl: conversation.imageUrl,
256
+ description: conversation.description,
257
+ pinnedFrameUrl: conversation.pinnedFrameUrl,
258
+ permissions: {
259
+ policyType: conversation.permissions.policyType,
260
+ policySet: {
261
+ addAdminPolicy: conversation.permissions.policySet.add_admin_policy,
262
+ addMemberPolicy: conversation.permissions.policySet.add_member_policy,
263
+ removeAdminPolicy: conversation.permissions.policySet.remove_admin_policy,
264
+ removeMemberPolicy:
265
+ conversation.permissions.policySet.remove_member_policy,
266
+ updateGroupDescriptionPolicy:
267
+ conversation.permissions.policySet.update_group_description_policy,
268
+ updateGroupImageUrlSquarePolicy:
269
+ conversation.permissions.policySet.update_group_image_url_square_policy,
270
+ updateGroupNamePolicy:
271
+ conversation.permissions.policySet.update_group_name_policy,
272
+ updateGroupPinnedFrameUrlPolicy:
273
+ conversation.permissions.policySet.update_group_pinned_frame_url_policy,
274
+ },
275
+ },
276
+ isActive: conversation.isActive,
277
+ addedByInboxId: conversation.addedByInboxId,
278
+ metadata: conversation.metadata,
279
+ admins: conversation.admins,
280
+ superAdmins: conversation.superAdmins,
281
+ createdAtNs: conversation.createdAtNs,
282
+ });
283
+
284
+ export type SafeInstallation = {
285
+ id: string;
286
+ clientTimestampNs?: bigint;
287
+ };
288
+
289
+ export const toSafeInstallation = (
290
+ installation: WasmInstallation,
291
+ ): SafeInstallation => ({
292
+ id: installation.id,
293
+ clientTimestampNs: installation.client_timestamp_ns,
294
+ });
295
+
296
+ export type SafeInboxState = {
297
+ accountAddresses: string[];
298
+ inboxId: string;
299
+ installations: SafeInstallation[];
300
+ recoveryAddress: string;
301
+ };
302
+
303
+ export const toSafeInboxState = (
304
+ inboxState: WasmInboxState,
305
+ ): SafeInboxState => ({
306
+ accountAddresses: inboxState.account_addresses,
307
+ inboxId: inboxState.inbox_id,
308
+ installations: inboxState.installations.map(toSafeInstallation),
309
+ recoveryAddress: inboxState.recovery_address,
310
+ });
311
+
312
+ export type SafeConsent = {
313
+ entity: string;
314
+ entityType: WasmConsentEntityType;
315
+ state: WasmConsentState;
316
+ };
317
+
318
+ export const toSafeConsent = (consent: WasmConsent): SafeConsent => ({
319
+ entity: consent.entity,
320
+ entityType: consent.entity_type,
321
+ state: consent.state,
322
+ });
323
+
324
+ export const fromSafeConsent = (consent: SafeConsent): WasmConsent =>
325
+ new WasmConsent(consent.entityType, consent.state, consent.entity);
326
+
327
+ export type SafeGroupMember = {
328
+ accountAddresses: string[];
329
+ consentState: WasmConsentState;
330
+ inboxId: string;
331
+ installationIds: string[];
332
+ permissionLevel: WasmPermissionLevel;
333
+ };
334
+
335
+ export const toSafeGroupMember = (
336
+ member: WasmGroupMember,
337
+ ): SafeGroupMember => ({
338
+ accountAddresses: member.account_addresses,
339
+ consentState: member.consent_state,
340
+ inboxId: member.inbox_id,
341
+ installationIds: member.installation_ids,
342
+ permissionLevel: member.permission_level,
343
+ });
344
+
345
+ export const fromSafeGroupMember = (member: SafeGroupMember): WasmGroupMember =>
346
+ new WasmGroupMember(
347
+ member.inboxId,
348
+ member.accountAddresses,
349
+ member.installationIds,
350
+ member.permissionLevel,
351
+ member.consentState,
352
+ );
@@ -0,0 +1,30 @@
1
+ import init, {
2
+ createClient as createWasmClient,
3
+ generateInboxId,
4
+ getInboxIdForAddress,
5
+ } from "@xmtp/wasm-bindings";
6
+ import { ApiUrls } from "@/constants";
7
+ import type { ClientOptions } from "@/types";
8
+
9
+ export const createClient = async (
10
+ accountAddress: string,
11
+ options?: Omit<ClientOptions, "codecs">,
12
+ ) => {
13
+ // initialize WASM module
14
+ await init();
15
+
16
+ const host = options?.apiUrl ?? ApiUrls[options?.env ?? "dev"];
17
+ const dbPath = `xmtp-${options?.env ?? "dev"}-${accountAddress}.db3`;
18
+
19
+ const inboxId =
20
+ (await getInboxIdForAddress(host, accountAddress)) ||
21
+ generateInboxId(accountAddress);
22
+
23
+ return createWasmClient(
24
+ host,
25
+ inboxId,
26
+ accountAddress,
27
+ dbPath,
28
+ options?.encryptionKey,
29
+ );
30
+ };
@@ -0,0 +1,3 @@
1
+ export function nsToDate(ns: bigint): Date {
2
+ return new Date(Number(ns / 1_000_000n));
3
+ }