@xmtp/browser-sdk 6.3.0 → 6.4.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.
package/src/Client.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  import { type ContentCodec } from "@xmtp/content-type-primitives";
2
- import { LogLevel, type Identifier } from "@xmtp/wasm-bindings";
2
+ import {
3
+ Backend,
4
+ LogLevel,
5
+ type ArchiveOptions,
6
+ type Identifier,
7
+ type InboxState,
8
+ } from "@xmtp/wasm-bindings";
3
9
  import { CodecRegistry } from "@/CodecRegistry";
4
10
  import { Conversations } from "@/Conversations";
5
11
  import { DebugInformation } from "@/DebugInformation";
@@ -10,6 +16,7 @@ import type {
10
16
  ExtractCodecContentTypes,
11
17
  XmtpEnv,
12
18
  } from "@/types/options";
19
+ import { createBackend } from "@/utils/createBackend";
13
20
  import {
14
21
  AccountAlreadyAssociatedError,
15
22
  InboxReassignError,
@@ -22,6 +29,23 @@ import { toSafeSigner, type SafeSigner, type Signer } from "@/utils/signer";
22
29
  import { uuid } from "@/utils/uuid";
23
30
  import { WorkerBridge } from "@/utils/WorkerBridge";
24
31
 
32
+ /**
33
+ * Resolves a `Backend` instance from either a `Backend` or an `XmtpEnv` string.
34
+ *
35
+ * @param envOrBackend - A `Backend` instance, or an `XmtpEnv` string
36
+ * @param gatewayHost - Optional gateway host (only used when `envOrBackend` is an `XmtpEnv`)
37
+ * @returns A `Backend` instance
38
+ */
39
+ const resolveBackend = async (
40
+ envOrBackend?: XmtpEnv | Backend,
41
+ gatewayHost?: string,
42
+ ): Promise<Backend> => {
43
+ if (envOrBackend instanceof Backend) {
44
+ return envOrBackend;
45
+ }
46
+ return createBackend({ env: envOrBackend, gatewayHost });
47
+ };
48
+
25
49
  /**
26
50
  * Client for interacting with the XMTP network
27
51
  */
@@ -30,6 +54,7 @@ export class Client<ContentTypes = ExtractCodecContentTypes> {
30
54
  #codecRegistry: CodecRegistry;
31
55
  #conversations: Conversations<ContentTypes>;
32
56
  #debugInformation: DebugInformation;
57
+ #env?: XmtpEnv;
33
58
  #identifier?: Identifier;
34
59
  #inboxId?: string;
35
60
  #installationId?: string;
@@ -50,6 +75,21 @@ export class Client<ContentTypes = ExtractCodecContentTypes> {
50
75
  * @param options - Optional configuration for the client
51
76
  */
52
77
  constructor(options?: ClientOptions) {
78
+ /*
79
+ * The Browser SDK runs XMTP's WASM bindings inside a Web Worker.
80
+ * The SDK sends options to the worker via postMessage(), which uses the
81
+ * structured clone algorithm. Codecs contain functions that can't be
82
+ * cloned, so we mark the codecs property as non-enumerable to exclude
83
+ * it from serialization.
84
+ *
85
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#things_that_dont_work_with_structured_clone
86
+ */
87
+ if (options) {
88
+ Object.defineProperty(options, "codecs", {
89
+ value: options.codecs,
90
+ enumerable: false,
91
+ });
92
+ }
53
93
  const worker = new Worker(new URL("./workers/client", import.meta.url), {
54
94
  type: "module",
55
95
  });
@@ -57,9 +97,13 @@ export class Client<ContentTypes = ExtractCodecContentTypes> {
57
97
  options?.loggingLevel !== undefined &&
58
98
  options.loggingLevel !== LogLevel.Off;
59
99
  this.#worker = new WorkerBridge<ClientWorkerAction>(worker, enableLogging);
60
- this.#options = options;
61
100
  this.#codecRegistry = new CodecRegistry([...(options?.codecs ?? [])]);
62
- this.#conversations = new Conversations(this.#worker, this.#codecRegistry);
101
+ this.#options = options;
102
+ this.#conversations = new Conversations(
103
+ this,
104
+ this.#worker,
105
+ this.#codecRegistry,
106
+ );
63
107
  this.#debugInformation = new DebugInformation(this.#worker);
64
108
  this.#preferences = new Preferences(this.#worker);
65
109
  }
@@ -78,6 +122,7 @@ export class Client<ContentTypes = ExtractCodecContentTypes> {
78
122
  options: this.#options,
79
123
  });
80
124
  this.#appVersion = result.appVersion;
125
+ this.#env = result.env as XmtpEnv;
81
126
  this.#identifier = identifier;
82
127
  this.#inboxId = result.inboxId;
83
128
  this.#installationId = result.installationId;
@@ -227,6 +272,13 @@ export class Client<ContentTypes = ExtractCodecContentTypes> {
227
272
  return this.#appVersion;
228
273
  }
229
274
 
275
+ /**
276
+ * Gets the XMTP environment used by this client
277
+ */
278
+ get env() {
279
+ return this.#env;
280
+ }
281
+
230
282
  /**
231
283
  * Creates signature text for creating a new inbox
232
284
  *
@@ -540,10 +592,27 @@ export class Client<ContentTypes = ExtractCodecContentTypes> {
540
592
  /**
541
593
  * Revokes specific installations of the client's inbox without a client
542
594
  *
543
- * @param env - The environment to use
544
595
  * @param signer - The signer to use
545
596
  * @param inboxId - The inbox ID to revoke installations for
546
597
  * @param installationIds - The installation IDs to revoke
598
+ * @param backend - Optional `Backend` instance created with `createBackend()`
599
+ */
600
+ static async revokeInstallations(
601
+ signer: Signer,
602
+ inboxId: string,
603
+ installationIds: Uint8Array[],
604
+ backend?: Backend,
605
+ ): Promise<void>;
606
+ /**
607
+ * Revokes specific installations of the client's inbox without a client
608
+ *
609
+ * @param signer - The signer to use
610
+ * @param inboxId - The inbox ID to revoke installations for
611
+ * @param installationIds - The installation IDs to revoke
612
+ * @param env - The environment to use
613
+ * @param gatewayHost - Optional gateway host
614
+ * @deprecated Pass a `Backend` instance created with `createBackend()` instead
615
+ * of `XmtpEnv` and `gatewayHost`.
547
616
  */
548
617
  static async revokeInstallations(
549
618
  signer: Signer,
@@ -551,30 +620,53 @@ export class Client<ContentTypes = ExtractCodecContentTypes> {
551
620
  installationIds: Uint8Array[],
552
621
  env?: XmtpEnv,
553
622
  gatewayHost?: string,
623
+ ): Promise<void>;
624
+ static async revokeInstallations(
625
+ signer: Signer,
626
+ inboxId: string,
627
+ installationIds: Uint8Array[],
628
+ envOrBackend?: XmtpEnv | Backend,
629
+ gatewayHost?: string,
554
630
  ) {
555
- await utilsRevokeInstallations(
556
- signer,
557
- inboxId,
558
- installationIds,
559
- env,
560
- gatewayHost,
561
- );
631
+ const backend = await resolveBackend(envOrBackend, gatewayHost);
632
+ await utilsRevokeInstallations(backend, signer, inboxId, installationIds);
562
633
  }
563
634
 
635
+ /**
636
+ * Fetches the inbox states for the specified inbox IDs from the network
637
+ * without a client
638
+ *
639
+ * @param inboxIds - The inbox IDs to get the state for
640
+ * @param backend - Optional `Backend` instance created with `createBackend()`
641
+ * @returns The inbox states for the specified inbox IDs
642
+ */
643
+ static async fetchInboxStates(
644
+ inboxIds: string[],
645
+ backend?: Backend,
646
+ ): Promise<InboxState[]>;
564
647
  /**
565
648
  * Fetches the inbox states for the specified inbox IDs from the network
566
649
  * without a client
567
650
  *
568
651
  * @param inboxIds - The inbox IDs to get the state for
569
652
  * @param env - The environment to use
653
+ * @param gatewayHost - Optional gateway host
570
654
  * @returns The inbox states for the specified inbox IDs
655
+ * @deprecated Pass a `Backend` instance created with `createBackend()` instead
656
+ * of `XmtpEnv` and `gatewayHost`.
571
657
  */
572
658
  static async fetchInboxStates(
573
659
  inboxIds: string[],
574
660
  env?: XmtpEnv,
575
661
  gatewayHost?: string,
662
+ ): Promise<InboxState[]>;
663
+ static async fetchInboxStates(
664
+ inboxIds: string[],
665
+ envOrBackend?: XmtpEnv | Backend,
666
+ gatewayHost?: string,
576
667
  ) {
577
- return utilsInboxStateFromInboxIds(inboxIds, env, gatewayHost);
668
+ const backend = await resolveBackend(envOrBackend, gatewayHost);
669
+ return utilsInboxStateFromInboxIds(backend, inboxIds);
578
670
  }
579
671
 
580
672
  /**
@@ -621,17 +713,40 @@ export class Client<ContentTypes = ExtractCodecContentTypes> {
621
713
  return this.#worker.action("client.canMessage", { identifiers });
622
714
  }
623
715
 
716
+ /**
717
+ * Checks if the specified identifiers can be messaged
718
+ *
719
+ * @param identifiers - The identifiers to check
720
+ * @param backend - Optional `Backend` instance created with `createBackend()`
721
+ * @returns Map of identifiers to whether they can be messaged
722
+ */
723
+ static async canMessage(
724
+ identifiers: Identifier[],
725
+ backend?: Backend,
726
+ ): Promise<Map<string, boolean>>;
624
727
  /**
625
728
  * Checks if the specified identifiers can be messaged
626
729
  *
627
730
  * @param identifiers - The identifiers to check
628
731
  * @param env - Optional XMTP environment
629
732
  * @returns Map of identifiers to whether they can be messaged
733
+ * @deprecated Pass a `Backend` instance created with `createBackend()` instead
734
+ * of `XmtpEnv`.
630
735
  */
631
- static async canMessage(identifiers: Identifier[], env?: XmtpEnv) {
736
+ /* eslint-disable @typescript-eslint/unified-signatures */
737
+ static async canMessage(
738
+ identifiers: Identifier[],
739
+ env?: XmtpEnv,
740
+ ): Promise<Map<string, boolean>>;
741
+ /* eslint-enable @typescript-eslint/unified-signatures */
742
+ static async canMessage(
743
+ identifiers: Identifier[],
744
+ envOrBackend?: XmtpEnv | Backend,
745
+ ) {
746
+ const backend = await resolveBackend(envOrBackend);
632
747
  const canMessageMap = new Map<string, boolean>();
633
748
  for (const identifier of identifiers) {
634
- const inboxId = await getInboxIdForIdentifier(identifier, env);
749
+ const inboxId = await getInboxIdForIdentifier(backend, identifier);
635
750
  canMessageMap.set(
636
751
  identifier.identifier.toLowerCase(),
637
752
  inboxId !== undefined,
@@ -716,9 +831,14 @@ export class Client<ContentTypes = ExtractCodecContentTypes> {
716
831
  /**
717
832
  * Send a sync request to other devices on the network
718
833
  *
834
+ * @param options - Archive options specifying what to sync
835
+ * @param serverUrl - The server URL for the sync request
719
836
  * @returns Promise that resolves when the sync request is sent
720
837
  */
721
- async sendSyncRequest() {
722
- return this.#worker.action("client.sendSyncRequest");
838
+ async sendSyncRequest(options: ArchiveOptions, serverUrl: string) {
839
+ return this.#worker.action("client.sendSyncRequest", {
840
+ options,
841
+ serverUrl,
842
+ });
723
843
  }
724
844
  }
@@ -86,6 +86,10 @@ export class Conversation<ContentTypes = unknown> {
86
86
  return this.#metadata;
87
87
  }
88
88
 
89
+ get topic() {
90
+ return `/xmtp/mls/1/g-${this.id}/proto`;
91
+ }
92
+
89
93
  async lastMessage() {
90
94
  const lastMessage = await this.#worker.action("conversation.lastMessage", {
91
95
  id: this.#id,
@@ -7,6 +7,7 @@ import {
7
7
  type ListConversationsOptions,
8
8
  type DecodedMessage as XmtpDecodedMessage,
9
9
  } from "@xmtp/wasm-bindings";
10
+ import type { Client } from "@/Client";
10
11
  import type { CodecRegistry } from "@/CodecRegistry";
11
12
  import { DecodedMessage } from "@/DecodedMessage";
12
13
  import { Dm } from "@/Dm";
@@ -27,6 +28,7 @@ import type { WorkerBridge } from "@/utils/WorkerBridge";
27
28
  * This class is not intended to be initialized directly.
28
29
  */
29
30
  export class Conversations<ContentTypes = unknown> {
31
+ #client: Client<ContentTypes>;
30
32
  #codecRegistry: CodecRegistry;
31
33
  #worker: WorkerBridge<ClientWorkerAction>;
32
34
 
@@ -37,13 +39,21 @@ export class Conversations<ContentTypes = unknown> {
37
39
  * @param codecRegistry - The codec registry instance
38
40
  */
39
41
  constructor(
42
+ client: Client<ContentTypes>,
40
43
  worker: WorkerBridge<ClientWorkerAction>,
41
44
  codecRegistry: CodecRegistry,
42
45
  ) {
46
+ this.#client = client;
43
47
  this.#worker = worker;
44
48
  this.#codecRegistry = codecRegistry;
45
49
  }
46
50
 
51
+ get topic() {
52
+ return this.#client.installationId
53
+ ? `/xmtp/mls/1/w-${this.#client.installationId}/proto`
54
+ : undefined;
55
+ }
56
+
47
57
  /**
48
58
  * Synchronizes conversations for the current client from the network
49
59
  *
@@ -285,7 +295,7 @@ export class Conversations<ContentTypes = unknown> {
285
295
  /**
286
296
  * Creates a new group conversation with the specified inbox IDs
287
297
  *
288
- * @param inboxIds - Array of inbox IDs for group members
298
+ * @param inboxIds - Array of inbox IDs for other group members (the creator is included automatically)
289
299
  * @param options - Optional group creation options
290
300
  * @returns Promise that resolves with the new group
291
301
  */
@@ -1,11 +1,12 @@
1
1
  import {
2
2
  verifySignedWithPublicKey,
3
+ type ArchiveOptions,
3
4
  type Client,
4
5
  type Identifier,
5
6
  type KeyPackageStatus,
6
7
  type SignatureRequestHandle,
7
8
  } from "@xmtp/wasm-bindings";
8
- import type { ClientOptions } from "@/types/options";
9
+ import type { ClientOptions, XmtpEnv } from "@/types/options";
9
10
  import { createClient } from "@/utils/createClient";
10
11
  import type { SafeSigner } from "@/utils/signer";
11
12
  import { WorkerConversations } from "@/WorkerConversations";
@@ -16,10 +17,12 @@ export class WorkerClient {
16
17
  #client: Client;
17
18
  #conversations: WorkerConversations;
18
19
  #debugInformation: WorkerDebugInformation;
20
+ #env: XmtpEnv;
19
21
  #preferences: WorkerPreferences;
20
22
 
21
- constructor(client: Client) {
23
+ constructor(client: Client, env: XmtpEnv) {
22
24
  this.#client = client;
25
+ this.#env = env;
23
26
  const conversations = client.conversations();
24
27
  this.#conversations = new WorkerConversations(this, conversations);
25
28
  this.#debugInformation = new WorkerDebugInformation(client);
@@ -30,8 +33,8 @@ export class WorkerClient {
30
33
  identifier: Identifier,
31
34
  options?: Omit<ClientOptions, "codecs">,
32
35
  ) {
33
- const client = await createClient(identifier, options);
34
- return new WorkerClient(client);
36
+ const { client, env } = await createClient(identifier, options);
37
+ return new WorkerClient(client, env);
35
38
  }
36
39
 
37
40
  get libxmtpVersion() {
@@ -42,6 +45,10 @@ export class WorkerClient {
42
45
  return this.#client.appVersion;
43
46
  }
44
47
 
48
+ get env() {
49
+ return this.#env;
50
+ }
51
+
45
52
  get accountIdentifier() {
46
53
  return this.#client.accountIdentifier;
47
54
  }
@@ -144,7 +151,7 @@ export class WorkerClient {
144
151
  }
145
152
 
146
153
  async getInboxIdByIdentifier(identifier: Identifier) {
147
- return this.#client.findInboxIdByIdentifier(identifier);
154
+ return this.#client.findInboxIdByIdentity(identifier);
148
155
  }
149
156
 
150
157
  signWithInstallationKey(signatureText: string) {
@@ -185,7 +192,7 @@ export class WorkerClient {
185
192
  ) as Promise<Map<string, KeyPackageStatus>>;
186
193
  }
187
194
 
188
- async sendSyncRequest() {
189
- return this.#client.sendSyncRequest();
195
+ async sendSyncRequest(options: ArchiveOptions, serverUrl: string) {
196
+ return this.#client.device_sync().sendSyncRequest(options, serverUrl);
190
197
  }
191
198
  }
@@ -153,19 +153,19 @@ export class WorkerConversation {
153
153
  }
154
154
 
155
155
  async addMembersByIdentifiers(identifiers: Identifier[]) {
156
- return this.#group.addMembers(identifiers);
156
+ return this.#group.addMembersByIdentity(identifiers);
157
157
  }
158
158
 
159
159
  async addMembers(inboxIds: string[]) {
160
- return this.#group.addMembersByInboxId(inboxIds);
160
+ return this.#group.addMembers(inboxIds);
161
161
  }
162
162
 
163
163
  async removeMembersByIdentifiers(identifiers: Identifier[]) {
164
- return this.#group.removeMembers(identifiers);
164
+ return this.#group.removeMembersByIdentity(identifiers);
165
165
  }
166
166
 
167
167
  async removeMembers(inboxIds: string[]) {
168
- return this.#group.removeMembersByInboxId(inboxIds);
168
+ return this.#group.removeMembers(inboxIds);
169
169
  }
170
170
 
171
171
  async addAdmin(inboxId: string) {
package/src/constants.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Pre-configured URLs for the XMTP network based on the environment
3
3
  *
4
+ * @deprecated Use `createBackend()` instead.
4
5
  * @constant
5
6
  * @property {string} local - The local URL for the XMTP network
6
7
  * @property {string} dev - The development URL for the XMTP network
@@ -24,4 +25,8 @@ export const HistorySyncUrls = {
24
25
  local: "http://localhost:5558",
25
26
  dev: "https://message-history.dev.ephemera.network",
26
27
  production: "https://message-history.production.ephemera.network",
28
+ "testnet-staging": "https://message-history.dev.ephemera.network",
29
+ "testnet-dev": "https://message-history.dev.ephemera.network",
30
+ testnet: "https://message-history.dev.ephemera.network",
31
+ mainnet: "https://message-history.production.ephemera.network",
27
32
  } as const;
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ export { Conversation } from "./Conversation";
5
5
  export { Dm } from "./Dm";
6
6
  export { Group } from "./Group";
7
7
  export { DecodedMessage } from "./DecodedMessage";
8
+ export { createBackend } from "./utils/createBackend";
8
9
  export { generateInboxId, getInboxIdForIdentifier } from "./utils/inboxId";
9
10
  export { metadataFieldName } from "./utils/metadata";
10
11
  export { ApiUrls, HistorySyncUrls } from "./constants";
@@ -16,7 +17,10 @@ export type {
16
17
  Action,
17
18
  Actions,
18
19
  ApiStats,
20
+ ArchiveOptions,
19
21
  Attachment,
22
+ Backend,
23
+ BackendBuilder,
20
24
  Consent,
21
25
  ConversationDebugInfo,
22
26
  ConversationListItem,
@@ -50,7 +54,6 @@ export type {
50
54
  Reaction,
51
55
  ReadReceipt,
52
56
  RemoteAttachment,
53
- RemoteAttachmentInfo,
54
57
  Reply,
55
58
  SendMessageOpts,
56
59
  SignatureRequestHandle,
@@ -62,6 +65,7 @@ export type {
62
65
  } from "@xmtp/wasm-bindings";
63
66
  export {
64
67
  ActionStyle,
68
+ BackupElementSelectionOption,
65
69
  ConsentEntityType,
66
70
  ConsentState,
67
71
  ContentType,
@@ -1,4 +1,8 @@
1
- import type { Identifier, KeyPackageStatus } from "@xmtp/wasm-bindings";
1
+ import type {
2
+ ArchiveOptions,
3
+ Identifier,
4
+ KeyPackageStatus,
5
+ } from "@xmtp/wasm-bindings";
2
6
  import type { ClientOptions } from "@/types/options";
3
7
  import type { SafeSigner } from "@/utils/signer";
4
8
 
@@ -8,6 +12,7 @@ export type ClientAction =
8
12
  id: string;
9
13
  result: {
10
14
  appVersion: string;
15
+ env: string;
11
16
  inboxId: string;
12
17
  installationId: string;
13
18
  installationIdBytes: Uint8Array;
@@ -216,5 +221,8 @@ export type ClientAction =
216
221
  action: "client.sendSyncRequest";
217
222
  id: string;
218
223
  result: undefined;
219
- data: undefined;
224
+ data: {
225
+ options: ArchiveOptions;
226
+ serverUrl: string;
227
+ };
220
228
  };
@@ -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,
@@ -17,10 +18,16 @@ import type {
17
18
  TransactionReference,
18
19
  WalletSendCalls,
19
20
  } from "@xmtp/wasm-bindings";
20
- import type { ApiUrls } from "@/constants";
21
21
  import type { DecodedMessage } from "@/DecodedMessage";
22
22
 
23
- export type XmtpEnv = keyof typeof ApiUrls;
23
+ export type XmtpEnv =
24
+ | "local"
25
+ | "dev"
26
+ | "production"
27
+ | "testnet-staging"
28
+ | "testnet-dev"
29
+ | "testnet"
30
+ | "mainnet";
24
31
 
25
32
  /**
26
33
  * Network options
@@ -35,15 +42,29 @@ export type NetworkOptions = {
35
42
  * specific endpoint
36
43
  */
37
44
  apiUrl?: string;
45
+ /**
46
+ * gatewayHost can be used to override the gateway endpoint
47
+ */
48
+ gatewayHost?: string;
49
+ /**
50
+ * Custom app version
51
+ */
52
+ appVersion?: string;
53
+ };
54
+
55
+ /**
56
+ * Device sync options
57
+ */
58
+ export type DeviceSyncOptions = {
38
59
  /**
39
60
  * historySyncUrl can be used to override the `env` flag and connect to a
40
61
  * specific endpoint for syncing history
41
62
  */
42
63
  historySyncUrl?: string | null;
43
64
  /**
44
- * gatewayHost can be used to override the gateway endpoint
65
+ * Disable device sync
45
66
  */
46
- gatewayHost?: string | null;
67
+ disableDeviceSync?: boolean;
47
68
  };
48
69
 
49
70
  export type ContentOptions = {
@@ -98,17 +119,10 @@ export type OtherOptions = {
98
119
  * Disable automatic registration when creating a client
99
120
  */
100
121
  disableAutoRegister?: boolean;
101
- /**
102
- * Disable device sync
103
- */
104
- disableDeviceSync?: boolean;
105
- /**
106
- * Custom app version
107
- */
108
- appVersion?: string;
109
122
  };
110
123
 
111
- export type ClientOptions = NetworkOptions &
124
+ export type ClientOptions = (NetworkOptions | { backend: Backend }) &
125
+ DeviceSyncOptions &
112
126
  ContentOptions &
113
127
  StorageOptions &
114
128
  OtherOptions;
@@ -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
+ };