@xmtp/browser-sdk 6.4.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/dist/index.d.ts +112 -54
- 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/package.json +3 -3
- package/src/Client.ts +131 -15
- package/src/Conversations.ts +1 -1
- package/src/WorkerClient.ts +14 -7
- package/src/WorkerConversation.ts +4 -4
- package/src/constants.ts +5 -0
- package/src/index.ts +5 -1
- package/src/types/actions/client.ts +10 -2
- package/src/types/options.ts +27 -13
- package/src/utils/createBackend.ts +45 -0
- package/src/utils/createClient.ts +58 -27
- package/src/utils/inboxId.ts +5 -15
- package/src/utils/inboxState.ts +5 -9
- package/src/utils/installations.ts +8 -17
- package/src/workers/client.ts +2 -1
package/src/Client.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { type ContentCodec } from "@xmtp/content-type-primitives";
|
|
2
|
-
import {
|
|
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,8 +97,8 @@ 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 ?? [])]);
|
|
101
|
+
this.#options = options;
|
|
62
102
|
this.#conversations = new Conversations(
|
|
63
103
|
this,
|
|
64
104
|
this.#worker,
|
|
@@ -82,6 +122,7 @@ export class Client<ContentTypes = ExtractCodecContentTypes> {
|
|
|
82
122
|
options: this.#options,
|
|
83
123
|
});
|
|
84
124
|
this.#appVersion = result.appVersion;
|
|
125
|
+
this.#env = result.env as XmtpEnv;
|
|
85
126
|
this.#identifier = identifier;
|
|
86
127
|
this.#inboxId = result.inboxId;
|
|
87
128
|
this.#installationId = result.installationId;
|
|
@@ -231,6 +272,13 @@ export class Client<ContentTypes = ExtractCodecContentTypes> {
|
|
|
231
272
|
return this.#appVersion;
|
|
232
273
|
}
|
|
233
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Gets the XMTP environment used by this client
|
|
277
|
+
*/
|
|
278
|
+
get env() {
|
|
279
|
+
return this.#env;
|
|
280
|
+
}
|
|
281
|
+
|
|
234
282
|
/**
|
|
235
283
|
* Creates signature text for creating a new inbox
|
|
236
284
|
*
|
|
@@ -544,10 +592,27 @@ export class Client<ContentTypes = ExtractCodecContentTypes> {
|
|
|
544
592
|
/**
|
|
545
593
|
* Revokes specific installations of the client's inbox without a client
|
|
546
594
|
*
|
|
547
|
-
* @param env - The environment to use
|
|
548
595
|
* @param signer - The signer to use
|
|
549
596
|
* @param inboxId - The inbox ID to revoke installations for
|
|
550
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`.
|
|
551
616
|
*/
|
|
552
617
|
static async revokeInstallations(
|
|
553
618
|
signer: Signer,
|
|
@@ -555,30 +620,53 @@ export class Client<ContentTypes = ExtractCodecContentTypes> {
|
|
|
555
620
|
installationIds: Uint8Array[],
|
|
556
621
|
env?: XmtpEnv,
|
|
557
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,
|
|
558
630
|
) {
|
|
559
|
-
await
|
|
560
|
-
|
|
561
|
-
inboxId,
|
|
562
|
-
installationIds,
|
|
563
|
-
env,
|
|
564
|
-
gatewayHost,
|
|
565
|
-
);
|
|
631
|
+
const backend = await resolveBackend(envOrBackend, gatewayHost);
|
|
632
|
+
await utilsRevokeInstallations(backend, signer, inboxId, installationIds);
|
|
566
633
|
}
|
|
567
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[]>;
|
|
568
647
|
/**
|
|
569
648
|
* Fetches the inbox states for the specified inbox IDs from the network
|
|
570
649
|
* without a client
|
|
571
650
|
*
|
|
572
651
|
* @param inboxIds - The inbox IDs to get the state for
|
|
573
652
|
* @param env - The environment to use
|
|
653
|
+
* @param gatewayHost - Optional gateway host
|
|
574
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`.
|
|
575
657
|
*/
|
|
576
658
|
static async fetchInboxStates(
|
|
577
659
|
inboxIds: string[],
|
|
578
660
|
env?: XmtpEnv,
|
|
579
661
|
gatewayHost?: string,
|
|
662
|
+
): Promise<InboxState[]>;
|
|
663
|
+
static async fetchInboxStates(
|
|
664
|
+
inboxIds: string[],
|
|
665
|
+
envOrBackend?: XmtpEnv | Backend,
|
|
666
|
+
gatewayHost?: string,
|
|
580
667
|
) {
|
|
581
|
-
|
|
668
|
+
const backend = await resolveBackend(envOrBackend, gatewayHost);
|
|
669
|
+
return utilsInboxStateFromInboxIds(backend, inboxIds);
|
|
582
670
|
}
|
|
583
671
|
|
|
584
672
|
/**
|
|
@@ -625,17 +713,40 @@ export class Client<ContentTypes = ExtractCodecContentTypes> {
|
|
|
625
713
|
return this.#worker.action("client.canMessage", { identifiers });
|
|
626
714
|
}
|
|
627
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>>;
|
|
628
727
|
/**
|
|
629
728
|
* Checks if the specified identifiers can be messaged
|
|
630
729
|
*
|
|
631
730
|
* @param identifiers - The identifiers to check
|
|
632
731
|
* @param env - Optional XMTP environment
|
|
633
732
|
* @returns Map of identifiers to whether they can be messaged
|
|
733
|
+
* @deprecated Pass a `Backend` instance created with `createBackend()` instead
|
|
734
|
+
* of `XmtpEnv`.
|
|
634
735
|
*/
|
|
635
|
-
|
|
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);
|
|
636
747
|
const canMessageMap = new Map<string, boolean>();
|
|
637
748
|
for (const identifier of identifiers) {
|
|
638
|
-
const inboxId = await getInboxIdForIdentifier(
|
|
749
|
+
const inboxId = await getInboxIdForIdentifier(backend, identifier);
|
|
639
750
|
canMessageMap.set(
|
|
640
751
|
identifier.identifier.toLowerCase(),
|
|
641
752
|
inboxId !== undefined,
|
|
@@ -720,9 +831,14 @@ export class Client<ContentTypes = ExtractCodecContentTypes> {
|
|
|
720
831
|
/**
|
|
721
832
|
* Send a sync request to other devices on the network
|
|
722
833
|
*
|
|
834
|
+
* @param options - Archive options specifying what to sync
|
|
835
|
+
* @param serverUrl - The server URL for the sync request
|
|
723
836
|
* @returns Promise that resolves when the sync request is sent
|
|
724
837
|
*/
|
|
725
|
-
async sendSyncRequest() {
|
|
726
|
-
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
|
+
});
|
|
727
843
|
}
|
|
728
844
|
}
|
package/src/Conversations.ts
CHANGED
|
@@ -295,7 +295,7 @@ export class Conversations<ContentTypes = unknown> {
|
|
|
295
295
|
/**
|
|
296
296
|
* Creates a new group conversation with the specified inbox IDs
|
|
297
297
|
*
|
|
298
|
-
* @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)
|
|
299
299
|
* @param options - Optional group creation options
|
|
300
300
|
* @returns Promise that resolves with the new group
|
|
301
301
|
*/
|
package/src/WorkerClient.ts
CHANGED
|
@@ -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.
|
|
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.
|
|
156
|
+
return this.#group.addMembersByIdentity(identifiers);
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
async addMembers(inboxIds: string[]) {
|
|
160
|
-
return this.#group.
|
|
160
|
+
return this.#group.addMembers(inboxIds);
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
async removeMembersByIdentifiers(identifiers: Identifier[]) {
|
|
164
|
-
return this.#group.
|
|
164
|
+
return this.#group.removeMembersByIdentity(identifiers);
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
async removeMembers(inboxIds: string[]) {
|
|
168
|
-
return this.#group.
|
|
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 {
|
|
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:
|
|
224
|
+
data: {
|
|
225
|
+
options: ArchiveOptions;
|
|
226
|
+
serverUrl: string;
|
|
227
|
+
};
|
|
220
228
|
};
|
package/src/types/options.ts
CHANGED
|
@@ -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 =
|
|
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
|
-
*
|
|
65
|
+
* Disable device sync
|
|
45
66
|
*/
|
|
46
|
-
|
|
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
|
+
};
|
|
@@ -1,51 +1,85 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
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 {
|
|
9
|
-
import
|
|
9
|
+
import type { ClientOptions, NetworkOptions } from "@/types/options";
|
|
10
|
+
import { createBackend, envToString } from "@/utils/createBackend";
|
|
11
|
+
|
|
12
|
+
const networkOptionKeys = [
|
|
13
|
+
"env",
|
|
14
|
+
"apiUrl",
|
|
15
|
+
"gatewayHost",
|
|
16
|
+
"appVersion",
|
|
17
|
+
] as const;
|
|
18
|
+
|
|
19
|
+
const hasBackend = (options: object): options is { backend: Backend } => {
|
|
20
|
+
return "backend" in options;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const resolveBackend = async (
|
|
24
|
+
options?: Omit<ClientOptions, "codecs">,
|
|
25
|
+
): Promise<Backend> => {
|
|
26
|
+
if (!options) {
|
|
27
|
+
return createBackend();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (hasBackend(options)) {
|
|
31
|
+
// Validate that no NetworkOptions fields are also set
|
|
32
|
+
const conflicting = networkOptionKeys.filter(
|
|
33
|
+
(key) =>
|
|
34
|
+
key in options && (options as Record<string, unknown>)[key] != null,
|
|
35
|
+
);
|
|
36
|
+
if (conflicting.length > 0) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`Cannot specify both 'backend' and network options (${conflicting.join(", ")}). ` +
|
|
39
|
+
`Use either a pre-built Backend or network options, not both.`,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
return options.backend;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// No backend provided — build one from NetworkOptions
|
|
46
|
+
return createBackend(options as NetworkOptions);
|
|
47
|
+
};
|
|
10
48
|
|
|
11
49
|
export const createClient = async (
|
|
12
50
|
identifier: Identifier,
|
|
13
51
|
options?: Omit<ClientOptions, "codecs">,
|
|
14
52
|
) => {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
const gatewayHost = options?.gatewayHost || undefined;
|
|
18
|
-
const isSecure = host.startsWith("https");
|
|
53
|
+
const backend = await resolveBackend(options);
|
|
54
|
+
|
|
19
55
|
const inboxId =
|
|
20
|
-
(await getInboxIdForIdentifier(
|
|
56
|
+
(await getInboxIdForIdentifier(backend, identifier)) ||
|
|
21
57
|
generateInboxId(identifier);
|
|
58
|
+
|
|
59
|
+
const envString = envToString(backend.env);
|
|
60
|
+
|
|
22
61
|
const dbPath =
|
|
23
62
|
options?.dbPath === undefined
|
|
24
|
-
? `xmtp-${
|
|
63
|
+
? `xmtp-${envString}-${inboxId}.db3`
|
|
25
64
|
: options.dbPath;
|
|
65
|
+
|
|
26
66
|
const isLogging =
|
|
27
67
|
options &&
|
|
28
68
|
(options.loggingLevel !== undefined ||
|
|
29
69
|
options.structuredLogging ||
|
|
30
70
|
options.performanceLogging);
|
|
31
71
|
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
: options.historySyncUrl;
|
|
36
|
-
|
|
37
|
-
const deviceSyncWorkerMode = options?.disableDeviceSync
|
|
38
|
-
? DeviceSyncWorkerMode.Disabled
|
|
39
|
-
: DeviceSyncWorkerMode.Enabled;
|
|
72
|
+
const deviceSyncMode = options?.disableDeviceSync
|
|
73
|
+
? DeviceSyncMode.Disabled
|
|
74
|
+
: DeviceSyncMode.Enabled;
|
|
40
75
|
|
|
41
|
-
|
|
42
|
-
|
|
76
|
+
const client = await createClientWithBackend(
|
|
77
|
+
backend,
|
|
43
78
|
inboxId,
|
|
44
79
|
identifier,
|
|
45
80
|
dbPath,
|
|
46
81
|
options?.dbEncryptionKey,
|
|
47
|
-
|
|
48
|
-
deviceSyncWorkerMode,
|
|
82
|
+
deviceSyncMode,
|
|
49
83
|
isLogging
|
|
50
84
|
? {
|
|
51
85
|
structured: options.structuredLogging ?? false,
|
|
@@ -54,11 +88,8 @@ export const createClient = async (
|
|
|
54
88
|
}
|
|
55
89
|
: undefined,
|
|
56
90
|
undefined, // allowOffline
|
|
57
|
-
options?.appVersion,
|
|
58
|
-
options?.gatewayHost,
|
|
59
91
|
undefined, // nonce
|
|
60
|
-
undefined, // authCallback
|
|
61
|
-
undefined, // authHandle
|
|
62
|
-
undefined, // clientMode
|
|
63
92
|
);
|
|
93
|
+
|
|
94
|
+
return { client, env: envString };
|
|
64
95
|
};
|