@xmtp/browser-sdk 6.5.0 → 7.0.0-dev.57a7203

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.
@@ -1,5 +1,15 @@
1
- import type { Identifier, KeyPackageStatus } from "@xmtp/wasm-bindings";
2
- import type { ClientOptions } from "@/types/options";
1
+ import type {
2
+ ArchiveMetadata,
3
+ ArchiveOptions,
4
+ AvailableArchiveInfo,
5
+ GroupSyncSummary,
6
+ Identifier,
7
+ KeyPackageStatus,
8
+ } from "@xmtp/wasm-bindings";
9
+ import type {
10
+ ClientOptions,
11
+ VisibilityConfirmationOptions,
12
+ } from "@/types/options";
3
13
  import type { SafeSigner } from "@/utils/signer";
4
14
 
5
15
  export type ClientAction =
@@ -8,6 +18,7 @@ export type ClientAction =
8
18
  id: string;
9
19
  result: {
10
20
  appVersion: string;
21
+ env: string;
11
22
  inboxId: string;
12
23
  installationId: string;
13
24
  installationIdBytes: Uint8Array;
@@ -104,6 +115,7 @@ export type ClientAction =
104
115
  data: {
105
116
  signer: SafeSigner;
106
117
  signatureRequestId: string;
118
+ waitForRegistrationVisible?: VisibilityConfirmationOptions;
107
119
  };
108
120
  }
109
121
  | {
@@ -169,6 +181,20 @@ export type ClientAction =
169
181
  identifiers: Identifier[];
170
182
  };
171
183
  }
184
+ | {
185
+ action: "client.fetchLatestInboxUpdatesCount";
186
+ id: string;
187
+ result: Record<string, number>;
188
+ data: {
189
+ inboxIds: string[];
190
+ };
191
+ }
192
+ | {
193
+ action: "client.fetchOwnInboxUpdatesCount";
194
+ id: string;
195
+ result: number;
196
+ data: Record<string, never>;
197
+ }
172
198
  | {
173
199
  action: "client.getInboxIdByIdentifier";
174
200
  id: string;
@@ -216,5 +242,67 @@ export type ClientAction =
216
242
  action: "client.sendSyncRequest";
217
243
  id: string;
218
244
  result: undefined;
245
+ data: {
246
+ options: ArchiveOptions;
247
+ serverUrl: string;
248
+ };
249
+ }
250
+ | {
251
+ action: "client.sendSyncArchive";
252
+ id: string;
253
+ result: undefined;
254
+ data: {
255
+ options: ArchiveOptions;
256
+ serverUrl: string;
257
+ pin: string;
258
+ };
259
+ }
260
+ | {
261
+ action: "client.processSyncArchive";
262
+ id: string;
263
+ result: undefined;
264
+ data: {
265
+ archivePin?: string | null;
266
+ };
267
+ }
268
+ | {
269
+ action: "client.listAvailableArchives";
270
+ id: string;
271
+ result: AvailableArchiveInfo[];
272
+ data: {
273
+ daysCutoff: number;
274
+ };
275
+ }
276
+ | {
277
+ action: "client.createArchive";
278
+ id: string;
279
+ result: Uint8Array;
280
+ data: {
281
+ opts: ArchiveOptions;
282
+ key: Uint8Array;
283
+ };
284
+ }
285
+ | {
286
+ action: "client.importArchive";
287
+ id: string;
288
+ result: undefined;
289
+ data: {
290
+ data: Uint8Array;
291
+ key: Uint8Array;
292
+ };
293
+ }
294
+ | {
295
+ action: "client.archiveMetadata";
296
+ id: string;
297
+ result: ArchiveMetadata;
298
+ data: {
299
+ data: Uint8Array;
300
+ key: Uint8Array;
301
+ };
302
+ }
303
+ | {
304
+ action: "client.syncAllDeviceSyncGroups";
305
+ id: string;
306
+ result: GroupSyncSummary;
219
307
  data: undefined;
220
308
  };
@@ -15,6 +15,7 @@ import type {
15
15
  RemoteAttachment,
16
16
  Reply,
17
17
  SendMessageOpts,
18
+ SendOpts,
18
19
  TransactionReference,
19
20
  WalletSendCalls,
20
21
  } from "@xmtp/wasm-bindings";
@@ -199,7 +200,7 @@ export type ConversationAction =
199
200
  data: {
200
201
  id: string;
201
202
  text: string;
202
- isOptimistic?: boolean;
203
+ opts?: SendOpts;
203
204
  };
204
205
  }
205
206
  | {
@@ -209,7 +210,7 @@ export type ConversationAction =
209
210
  data: {
210
211
  id: string;
211
212
  markdown: string;
212
- isOptimistic?: boolean;
213
+ opts?: SendOpts;
213
214
  };
214
215
  }
215
216
  | {
@@ -219,7 +220,7 @@ export type ConversationAction =
219
220
  data: {
220
221
  id: string;
221
222
  reaction: Reaction;
222
- isOptimistic?: boolean;
223
+ opts?: SendOpts;
223
224
  };
224
225
  }
225
226
  | {
@@ -228,7 +229,7 @@ export type ConversationAction =
228
229
  result: string;
229
230
  data: {
230
231
  id: string;
231
- isOptimistic?: boolean;
232
+ opts?: SendOpts;
232
233
  };
233
234
  }
234
235
  | {
@@ -238,7 +239,7 @@ export type ConversationAction =
238
239
  data: {
239
240
  id: string;
240
241
  reply: Reply;
241
- isOptimistic?: boolean;
242
+ opts?: SendOpts;
242
243
  };
243
244
  }
244
245
  | {
@@ -248,7 +249,7 @@ export type ConversationAction =
248
249
  data: {
249
250
  id: string;
250
251
  transactionReference: TransactionReference;
251
- isOptimistic?: boolean;
252
+ opts?: SendOpts;
252
253
  };
253
254
  }
254
255
  | {
@@ -258,7 +259,7 @@ export type ConversationAction =
258
259
  data: {
259
260
  id: string;
260
261
  walletSendCalls: WalletSendCalls;
261
- isOptimistic?: boolean;
262
+ opts?: SendOpts;
262
263
  };
263
264
  }
264
265
  | {
@@ -268,7 +269,7 @@ export type ConversationAction =
268
269
  data: {
269
270
  id: string;
270
271
  actions: Actions;
271
- isOptimistic?: boolean;
272
+ opts?: SendOpts;
272
273
  };
273
274
  }
274
275
  | {
@@ -278,7 +279,7 @@ export type ConversationAction =
278
279
  data: {
279
280
  id: string;
280
281
  intent: Intent;
281
- isOptimistic?: boolean;
282
+ opts?: SendOpts;
282
283
  };
283
284
  }
284
285
  | {
@@ -288,7 +289,7 @@ export type ConversationAction =
288
289
  data: {
289
290
  id: string;
290
291
  attachment: Attachment;
291
- isOptimistic?: boolean;
292
+ opts?: SendOpts;
292
293
  };
293
294
  }
294
295
  | {
@@ -298,7 +299,7 @@ export type ConversationAction =
298
299
  data: {
299
300
  id: string;
300
301
  multiRemoteAttachment: MultiRemoteAttachment;
301
- isOptimistic?: boolean;
302
+ opts?: SendOpts;
302
303
  };
303
304
  }
304
305
  | {
@@ -308,6 +309,6 @@ export type ConversationAction =
308
309
  data: {
309
310
  id: string;
310
311
  remoteAttachment: RemoteAttachment;
311
- isOptimistic?: boolean;
312
+ opts?: SendOpts;
312
313
  };
313
314
  };
@@ -5,6 +5,7 @@ import type {
5
5
  import type {
6
6
  Actions,
7
7
  Attachment,
8
+ Backend,
8
9
  DeletedMessage,
9
10
  GroupUpdated,
10
11
  Intent,
@@ -16,11 +17,21 @@ import type {
16
17
  RemoteAttachment,
17
18
  TransactionReference,
18
19
  WalletSendCalls,
20
+ WasmVisibilityConfirmationOptions,
21
+ WorkerConfigOptions,
19
22
  } from "@xmtp/wasm-bindings";
20
- import type { ApiUrls } from "@/constants";
21
23
  import type { DecodedMessage } from "@/DecodedMessage";
22
24
 
23
- export type XmtpEnv = keyof typeof ApiUrls;
25
+ export type VisibilityConfirmationOptions = WasmVisibilityConfirmationOptions;
26
+
27
+ export type XmtpEnv =
28
+ | "local"
29
+ | "dev"
30
+ | "production"
31
+ | "testnet-staging"
32
+ | "testnet-dev"
33
+ | "testnet"
34
+ | "mainnet";
24
35
 
25
36
  /**
26
37
  * Network options
@@ -35,15 +46,29 @@ export type NetworkOptions = {
35
46
  * specific endpoint
36
47
  */
37
48
  apiUrl?: string;
49
+ /**
50
+ * gatewayHost can be used to override the gateway endpoint
51
+ */
52
+ gatewayHost?: string;
53
+ /**
54
+ * Custom app version
55
+ */
56
+ appVersion?: string;
57
+ };
58
+
59
+ /**
60
+ * Device sync options
61
+ */
62
+ export type DeviceSyncOptions = {
38
63
  /**
39
64
  * historySyncUrl can be used to override the `env` flag and connect to a
40
65
  * specific endpoint for syncing history
41
66
  */
42
67
  historySyncUrl?: string | null;
43
68
  /**
44
- * gatewayHost can be used to override the gateway endpoint
69
+ * Disable device sync
45
70
  */
46
- gatewayHost?: string | null;
71
+ disableDeviceSync?: boolean;
47
72
  };
48
73
 
49
74
  export type ContentOptions = {
@@ -95,20 +120,28 @@ export type OtherOptions = {
95
120
  */
96
121
  loggingLevel?: LogLevel;
97
122
  /**
98
- * Disable automatic registration when creating a client
123
+ * Tuning for the background worker scheduler (intervals, jitter, per-worker
124
+ * overrides, and disabled workers). All fields are optional; omitting this
125
+ * object preserves the default worker behavior.
126
+ *
127
+ * Intervals are specified in nanoseconds.
99
128
  */
100
- disableAutoRegister?: boolean;
129
+ workerConfig?: WorkerConfigOptions;
101
130
  /**
102
- * Disable device sync
131
+ * Disable automatic registration when creating a client
103
132
  */
104
- disableDeviceSync?: boolean;
133
+ disableAutoRegister?: boolean;
105
134
  /**
106
- * Custom app version
135
+ * Options for waiting until client registration is visible on the network.
136
+ *
137
+ * When set, `registerIdentity` will wait for the specified quorum of nodes
138
+ * to confirm the registration before resolving.
107
139
  */
108
- appVersion?: string;
140
+ waitForRegistrationVisible?: VisibilityConfirmationOptions;
109
141
  };
110
142
 
111
- export type ClientOptions = NetworkOptions &
143
+ export type ClientOptions = (NetworkOptions | { backend: Backend }) &
144
+ DeviceSyncOptions &
112
145
  ContentOptions &
113
146
  StorageOptions &
114
147
  OtherOptions;
@@ -65,7 +65,7 @@ export class WorkerBridge<T extends UnknownAction> {
65
65
  });
66
66
  const promise = new Promise((resolve, reject) => {
67
67
  this.#promises.set(promiseId, {
68
- resolve: resolve as (value: unknown) => void,
68
+ resolve: resolve,
69
69
  reject,
70
70
  });
71
71
  });
@@ -0,0 +1,45 @@
1
+ import init, {
2
+ BackendBuilder,
3
+ XmtpEnv as BindingsEnv,
4
+ type Backend,
5
+ } from "@xmtp/wasm-bindings";
6
+ import type { NetworkOptions, XmtpEnv } from "@/types/options";
7
+
8
+ const envMap: Record<XmtpEnv, BindingsEnv> = {
9
+ local: BindingsEnv.Local,
10
+ dev: BindingsEnv.Dev,
11
+ production: BindingsEnv.Production,
12
+ "testnet-staging": BindingsEnv.TestnetStaging,
13
+ "testnet-dev": BindingsEnv.TestnetDev,
14
+ testnet: BindingsEnv.Testnet,
15
+ mainnet: BindingsEnv.Mainnet,
16
+ };
17
+
18
+ const reverseEnvMap: Record<BindingsEnv, XmtpEnv> = {
19
+ [BindingsEnv.Local]: "local",
20
+ [BindingsEnv.Dev]: "dev",
21
+ [BindingsEnv.Production]: "production",
22
+ [BindingsEnv.TestnetStaging]: "testnet-staging",
23
+ [BindingsEnv.TestnetDev]: "testnet-dev",
24
+ [BindingsEnv.Testnet]: "testnet",
25
+ [BindingsEnv.Mainnet]: "mainnet",
26
+ };
27
+
28
+ export const envToString = (env: BindingsEnv): XmtpEnv => {
29
+ return reverseEnvMap[env];
30
+ };
31
+
32
+ export const createBackend = async (
33
+ options?: NetworkOptions,
34
+ ): Promise<Backend> => {
35
+ await init();
36
+ const env = options?.env ?? "dev";
37
+ let builder = new BackendBuilder(envMap[env]);
38
+ // WASM builder methods consume `self` and return a new instance,
39
+ // so we must reassign from the return value.
40
+ if (options?.apiUrl) builder = builder.setApiUrl(options.apiUrl);
41
+ if (options?.gatewayHost)
42
+ builder = builder.setGatewayHost(options.gatewayHost);
43
+ if (options?.appVersion) builder = builder.setAppVersion(options.appVersion);
44
+ return builder.build();
45
+ };
@@ -1,51 +1,92 @@
1
1
  import {
2
- createClient as createWasmClient,
3
- DeviceSyncWorkerMode,
2
+ createClientWithBackend,
3
+ DeviceSyncMode,
4
4
  generateInboxId,
5
5
  getInboxIdForIdentifier,
6
+ type Backend,
6
7
  type Identifier,
7
8
  } from "@xmtp/wasm-bindings";
8
- import { ApiUrls, HistorySyncUrls } from "@/constants";
9
9
  import type { ClientOptions } from "@/types/options";
10
+ import { createBackend, envToString } from "@/utils/createBackend";
11
+
12
+ type CreateClientOptions = ClientOptions extends infer T
13
+ ? T extends ClientOptions
14
+ ? Omit<T, "codecs">
15
+ : never
16
+ : never;
17
+
18
+ const networkOptionKeys = [
19
+ "env",
20
+ "apiUrl",
21
+ "gatewayHost",
22
+ "appVersion",
23
+ ] as const;
24
+
25
+ const hasBackend = (options: object): options is { backend: Backend } => {
26
+ return "backend" in options;
27
+ };
28
+
29
+ const resolveBackend = async (
30
+ options?: CreateClientOptions,
31
+ ): Promise<Backend> => {
32
+ if (!options) {
33
+ return createBackend();
34
+ }
35
+
36
+ if (hasBackend(options)) {
37
+ // Validate that no NetworkOptions fields are also set
38
+ const conflicting = networkOptionKeys.filter(
39
+ (key) =>
40
+ key in options && (options as Record<string, unknown>)[key] != null,
41
+ );
42
+ if (conflicting.length > 0) {
43
+ throw new Error(
44
+ `Cannot specify both 'backend' and network options (${conflicting.join(", ")}). ` +
45
+ `Use either a pre-built Backend or network options, not both.`,
46
+ );
47
+ }
48
+ return options.backend;
49
+ }
50
+
51
+ // No backend provided — build one from NetworkOptions
52
+ return createBackend(options);
53
+ };
10
54
 
11
55
  export const createClient = async (
12
56
  identifier: Identifier,
13
- options?: Omit<ClientOptions, "codecs">,
57
+ options?: CreateClientOptions,
14
58
  ) => {
15
- const env = options?.env || "dev";
16
- const host = options?.apiUrl || ApiUrls[env];
17
- const gatewayHost = options?.gatewayHost || undefined;
18
- const isSecure = host.startsWith("https");
59
+ const backend = await resolveBackend(options);
60
+
19
61
  const inboxId =
20
- (await getInboxIdForIdentifier(host, gatewayHost, isSecure, identifier)) ||
62
+ (await getInboxIdForIdentifier(backend, identifier)) ||
21
63
  generateInboxId(identifier);
64
+
65
+ const envString = envToString(backend.env);
66
+
22
67
  const dbPath =
23
68
  options?.dbPath === undefined
24
- ? `xmtp-${env}-${inboxId}.db3`
69
+ ? `xmtp-${envString}-${inboxId}.db3`
25
70
  : options.dbPath;
71
+
26
72
  const isLogging =
27
73
  options &&
28
74
  (options.loggingLevel !== undefined ||
29
75
  options.structuredLogging ||
30
76
  options.performanceLogging);
31
77
 
32
- const historySyncUrl =
33
- options?.historySyncUrl === undefined
34
- ? HistorySyncUrls[env]
35
- : options.historySyncUrl;
36
-
37
- const deviceSyncWorkerMode = options?.disableDeviceSync
38
- ? DeviceSyncWorkerMode.Disabled
39
- : DeviceSyncWorkerMode.Enabled;
78
+ const deviceSyncMode = options?.disableDeviceSync
79
+ ? DeviceSyncMode.Disabled
80
+ : DeviceSyncMode.Enabled;
40
81
 
41
- return createWasmClient(
42
- host,
82
+ const client = await createClientWithBackend(
83
+ backend,
43
84
  inboxId,
44
85
  identifier,
45
86
  dbPath,
46
87
  options?.dbEncryptionKey,
47
- historySyncUrl,
48
- deviceSyncWorkerMode,
88
+ deviceSyncMode,
89
+ options?.workerConfig,
49
90
  isLogging
50
91
  ? {
51
92
  structured: options.structuredLogging ?? false,
@@ -54,11 +95,8 @@ export const createClient = async (
54
95
  }
55
96
  : undefined,
56
97
  undefined, // allowOffline
57
- options?.appVersion,
58
- options?.gatewayHost,
59
98
  undefined, // nonce
60
- undefined, // authCallback
61
- undefined, // authHandle
62
- undefined, // clientMode
63
99
  );
100
+
101
+ return { client, env: envString };
64
102
  };
@@ -1,10 +1,9 @@
1
1
  import init, {
2
2
  generateInboxId as wasmGenerateInboxId,
3
3
  getInboxIdForIdentifier as wasmGetInboxIdForIdentifier,
4
+ type Backend,
4
5
  type Identifier,
5
6
  } from "@xmtp/wasm-bindings";
6
- import { ApiUrls } from "@/constants";
7
- import type { XmtpEnv } from "@/types/options";
8
7
 
9
8
  /**
10
9
  * Generates an inbox ID for a given identifier
@@ -22,25 +21,16 @@ export const generateInboxId = async (
22
21
  };
23
22
 
24
23
  /**
25
- * Gets the inbox ID for a specific identifier and optional environment
24
+ * Gets the inbox ID for a specific identifier using a Backend
26
25
  *
26
+ * @param backend - The Backend instance for API communication
27
27
  * @param identifier - The identifier to get the inbox ID for
28
- * @param env - Optional XMTP environment configuration (default: "dev")
29
- * @param gatewayHost - Optional gateway host override
30
28
  * @returns Promise that resolves with the inbox ID for the identifier
31
29
  */
32
30
  export const getInboxIdForIdentifier = async (
31
+ backend: Backend,
33
32
  identifier: Identifier,
34
- env?: XmtpEnv,
35
- gatewayHost?: string,
36
33
  ): Promise<string | undefined> => {
37
34
  await init();
38
- const host = env ? ApiUrls[env] : ApiUrls.dev;
39
- const isSecure = host.startsWith("https");
40
- return wasmGetInboxIdForIdentifier(
41
- host,
42
- gatewayHost ?? null,
43
- isSecure,
44
- identifier,
45
- );
35
+ return wasmGetInboxIdForIdentifier(backend, identifier);
46
36
  };
@@ -1,23 +1,19 @@
1
1
  import init, {
2
2
  inboxStateFromInboxIds as wasmInboxStateFromInboxIds,
3
+ type Backend,
3
4
  } from "@xmtp/wasm-bindings";
4
- import { ApiUrls } from "@/constants";
5
- import type { XmtpEnv } from "@/types/options";
6
5
 
7
6
  /**
8
- * Gets the inbox state for the specified inbox IDs without a client
7
+ * Gets the inbox state for the specified inbox IDs using a Backend
9
8
  *
9
+ * @param backend - The Backend instance for API communication
10
10
  * @param inboxIds - The inbox IDs to get the state for
11
- * @param env - Optional XMTP environment configuration (default: "dev")
12
- * @param gatewayHost - Optional gateway host override
13
11
  * @returns The inbox state for the specified inbox IDs
14
12
  */
15
13
  export const inboxStateFromInboxIds = async (
14
+ backend: Backend,
16
15
  inboxIds: string[],
17
- env?: XmtpEnv,
18
- gatewayHost?: string,
19
16
  ) => {
20
17
  await init();
21
- const host = ApiUrls[env ?? "dev"];
22
- return wasmInboxStateFromInboxIds(host, gatewayHost ?? null, inboxIds);
18
+ return wasmInboxStateFromInboxIds(backend, inboxIds);
23
19
  };
@@ -1,11 +1,10 @@
1
1
  import init, {
2
2
  applySignatureRequest,
3
3
  revokeInstallationsSignatureRequest,
4
+ type Backend,
4
5
  type Identifier,
5
6
  type SignatureRequestHandle,
6
7
  } from "@xmtp/wasm-bindings";
7
- import { ApiUrls } from "@/constants";
8
- import type { XmtpEnv } from "@/types/options";
9
8
  import type { Signer } from "@/utils/signer";
10
9
 
11
10
  /**
@@ -17,28 +16,24 @@ import type { Signer } from "@/utils/signer";
17
16
  *
18
17
  * It is highly recommended to use the `revokeInstallations` function instead.
19
18
  *
19
+ * @param backend - The Backend instance for API communication
20
20
  * @param identifier - The identifier to revoke installations for
21
21
  * @param inboxId - The inbox ID to revoke installations for
22
22
  * @param installationIds - The installation IDs to revoke
23
- * @param env - Optional XMTP environment configuration (default: "dev")
24
- * @param gatewayHost - Optional gateway host override
25
23
  * @returns The signature text and signature request ID
26
24
  */
27
25
  export const revokeInstallationsSignatureText = async (
26
+ backend: Backend,
28
27
  identifier: Identifier,
29
28
  inboxId: string,
30
29
  installationIds: Uint8Array[],
31
- env?: XmtpEnv,
32
- gatewayHost?: string,
33
30
  ): Promise<{
34
31
  signatureText: string;
35
32
  signatureRequest: SignatureRequestHandle;
36
33
  }> => {
37
34
  await init();
38
- const host = ApiUrls[env ?? "dev"];
39
35
  const signatureRequest = revokeInstallationsSignatureRequest(
40
- host,
41
- gatewayHost ?? null,
36
+ backend,
42
37
  identifier,
43
38
  inboxId,
44
39
  installationIds,
@@ -50,32 +45,28 @@ export const revokeInstallationsSignatureText = async (
50
45
  /**
51
46
  * Revokes installations for a given inbox ID
52
47
  *
48
+ * @param backend - The Backend instance for API communication
53
49
  * @param signer - The signer to use
54
50
  * @param inboxId - The inbox ID to revoke installations for
55
51
  * @param installationIds - The installation IDs to revoke
56
- * @param env - Optional XMTP environment configuration (default: "dev")
57
- * @param gatewayHost - Optional gateway host override
58
52
  * @returns Promise that resolves when the revoke installations operation is complete
59
53
  */
60
54
  export const revokeInstallations = async (
55
+ backend: Backend,
61
56
  signer: Signer,
62
57
  inboxId: string,
63
58
  installationIds: Uint8Array[],
64
- env?: XmtpEnv,
65
- gatewayHost?: string,
66
59
  ): Promise<void> => {
67
60
  await init();
68
61
  const identifier = await signer.getIdentifier();
69
62
  const { signatureText, signatureRequest } =
70
63
  await revokeInstallationsSignatureText(
64
+ backend,
71
65
  identifier,
72
66
  inboxId,
73
67
  installationIds,
74
- env,
75
- gatewayHost,
76
68
  );
77
69
  const signature = await signer.signMessage(signatureText);
78
- const host = ApiUrls[env ?? "dev"];
79
70
 
80
71
  switch (signer.type) {
81
72
  case "EOA":
@@ -91,5 +82,5 @@ export const revokeInstallations = async (
91
82
  break;
92
83
  }
93
84
 
94
- await applySignatureRequest(host, gatewayHost ?? null, signatureRequest);
85
+ await applySignatureRequest(backend, signatureRequest);
95
86
  };