@xmtp/browser-sdk 0.0.3 → 0.0.5
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/README.md +46 -10
- package/dist/index.d.ts +35 -21
- 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.map +1 -1
- package/package.json +17 -17
- package/src/Client.ts +146 -45
- package/src/WorkerClient.ts +4 -4
- package/src/index.ts +5 -0
- package/src/types/clientEvents.ts +5 -5
- package/src/types/options.ts +4 -0
- package/src/utils/signer.ts +19 -0
- package/src/workers/client.ts +9 -9
- package/tsconfig.json +0 -11
package/src/Client.ts
CHANGED
|
@@ -9,38 +9,34 @@ import type {
|
|
|
9
9
|
import { TextCodec } from "@xmtp/content-type-text";
|
|
10
10
|
import {
|
|
11
11
|
GroupMessageKind,
|
|
12
|
+
SignatureRequestType,
|
|
12
13
|
type ConsentEntityType,
|
|
13
|
-
type SignatureRequestType,
|
|
14
14
|
} from "@xmtp/wasm-bindings";
|
|
15
15
|
import { ClientWorkerClass } from "@/ClientWorkerClass";
|
|
16
16
|
import { Conversations } from "@/Conversations";
|
|
17
|
-
import type { ClientOptions } from "@/types";
|
|
17
|
+
import type { ClientOptions, XmtpEnv } from "@/types";
|
|
18
18
|
import {
|
|
19
19
|
fromSafeEncodedContent,
|
|
20
20
|
toSafeEncodedContent,
|
|
21
21
|
type SafeConsent,
|
|
22
22
|
type SafeMessage,
|
|
23
23
|
} from "@/utils/conversions";
|
|
24
|
+
import { isSmartContractSigner, type Signer } from "@/utils/signer";
|
|
24
25
|
|
|
25
26
|
export class Client extends ClientWorkerClass {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
options?: ClientOptions;
|
|
29
|
-
|
|
30
|
-
#isReady = false;
|
|
31
|
-
|
|
32
|
-
#inboxId: string | undefined;
|
|
33
|
-
|
|
34
|
-
#installationId: string | undefined;
|
|
35
|
-
|
|
36
|
-
#conversations: Conversations;
|
|
37
|
-
|
|
27
|
+
#accountAddress: string;
|
|
38
28
|
#codecs: Map<string, ContentCodec>;
|
|
39
|
-
|
|
29
|
+
#conversations: Conversations;
|
|
40
30
|
#encryptionKey: Uint8Array;
|
|
31
|
+
#inboxId: string | undefined;
|
|
32
|
+
#installationId: string | undefined;
|
|
33
|
+
#isReady = false;
|
|
34
|
+
#signer: Signer;
|
|
35
|
+
options?: ClientOptions;
|
|
41
36
|
|
|
42
37
|
constructor(
|
|
43
|
-
|
|
38
|
+
signer: Signer,
|
|
39
|
+
accountAddress: string,
|
|
44
40
|
encryptionKey: Uint8Array,
|
|
45
41
|
options?: ClientOptions,
|
|
46
42
|
) {
|
|
@@ -51,9 +47,10 @@ export class Client extends ClientWorkerClass {
|
|
|
51
47
|
worker,
|
|
52
48
|
options?.loggingLevel !== undefined && options.loggingLevel !== "off",
|
|
53
49
|
);
|
|
54
|
-
this
|
|
50
|
+
this.#accountAddress = accountAddress;
|
|
55
51
|
this.options = options;
|
|
56
52
|
this.#encryptionKey = encryptionKey;
|
|
53
|
+
this.#signer = signer;
|
|
57
54
|
this.#conversations = new Conversations(this);
|
|
58
55
|
const codecs = [
|
|
59
56
|
new GroupUpdatedCodec(),
|
|
@@ -65,9 +62,13 @@ export class Client extends ClientWorkerClass {
|
|
|
65
62
|
);
|
|
66
63
|
}
|
|
67
64
|
|
|
65
|
+
get accountAddress() {
|
|
66
|
+
return this.#accountAddress;
|
|
67
|
+
}
|
|
68
|
+
|
|
68
69
|
async init() {
|
|
69
70
|
const result = await this.sendMessage("init", {
|
|
70
|
-
address: this.
|
|
71
|
+
address: this.accountAddress,
|
|
71
72
|
encryptionKey: this.#encryptionKey,
|
|
72
73
|
options: this.options,
|
|
73
74
|
});
|
|
@@ -77,12 +78,19 @@ export class Client extends ClientWorkerClass {
|
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
static async create(
|
|
80
|
-
|
|
81
|
+
signer: Signer,
|
|
81
82
|
encryptionKey: Uint8Array,
|
|
82
83
|
options?: ClientOptions,
|
|
83
84
|
) {
|
|
84
|
-
const
|
|
85
|
+
const address = await signer.getAddress();
|
|
86
|
+
const client = new Client(signer, address, encryptionKey, options);
|
|
87
|
+
|
|
85
88
|
await client.init();
|
|
89
|
+
|
|
90
|
+
if (!options?.disableAutoRegister) {
|
|
91
|
+
await client.register();
|
|
92
|
+
}
|
|
93
|
+
|
|
86
94
|
return client;
|
|
87
95
|
}
|
|
88
96
|
|
|
@@ -98,48 +106,124 @@ export class Client extends ClientWorkerClass {
|
|
|
98
106
|
return this.#installationId;
|
|
99
107
|
}
|
|
100
108
|
|
|
101
|
-
async
|
|
102
|
-
return this.sendMessage("
|
|
109
|
+
async #createInboxSignatureText() {
|
|
110
|
+
return this.sendMessage("createInboxSignatureText", undefined);
|
|
103
111
|
}
|
|
104
112
|
|
|
105
|
-
async
|
|
106
|
-
return this.sendMessage("
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
async getRevokeWalletSignatureText(accountAddress: string) {
|
|
110
|
-
return this.sendMessage("getRevokeWalletSignatureText", { accountAddress });
|
|
113
|
+
async #addAccountSignatureText(newAccountAddress: string) {
|
|
114
|
+
return this.sendMessage("addAccountSignatureText", {
|
|
115
|
+
newAccountAddress,
|
|
116
|
+
});
|
|
111
117
|
}
|
|
112
118
|
|
|
113
|
-
async
|
|
114
|
-
return this.sendMessage("
|
|
119
|
+
async #removeAccountSignatureText(accountAddress: string) {
|
|
120
|
+
return this.sendMessage("removeAccountSignatureText", { accountAddress });
|
|
115
121
|
}
|
|
116
122
|
|
|
117
|
-
async
|
|
118
|
-
return this.sendMessage("
|
|
123
|
+
async #revokeInstallationsSignatureText() {
|
|
124
|
+
return this.sendMessage("revokeInstallationsSignatureText", undefined);
|
|
119
125
|
}
|
|
120
126
|
|
|
121
|
-
async
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
blockNumber?: bigint,
|
|
127
|
+
async #addSignature(
|
|
128
|
+
signatureType: SignatureRequestType,
|
|
129
|
+
signatureText: string,
|
|
130
|
+
signer: Signer,
|
|
126
131
|
) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
132
|
+
const signature = await signer.signMessage(signatureText);
|
|
133
|
+
|
|
134
|
+
if (isSmartContractSigner(signer)) {
|
|
135
|
+
await this.sendMessage("addScwSignature", {
|
|
136
|
+
type: signatureType,
|
|
137
|
+
bytes: signature,
|
|
138
|
+
chainId: signer.getChainId(),
|
|
139
|
+
blockNumber: signer.getBlockNumber(),
|
|
140
|
+
});
|
|
141
|
+
} else {
|
|
142
|
+
await this.sendMessage("addSignature", {
|
|
143
|
+
type: signatureType,
|
|
144
|
+
bytes: signature,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
133
147
|
}
|
|
134
148
|
|
|
135
|
-
async applySignatures() {
|
|
149
|
+
async #applySignatures() {
|
|
136
150
|
return this.sendMessage("applySignatures", undefined);
|
|
137
151
|
}
|
|
138
152
|
|
|
139
|
-
async
|
|
153
|
+
async register() {
|
|
154
|
+
const signatureText = await this.#createInboxSignatureText();
|
|
155
|
+
|
|
156
|
+
// if the signature text is not available, the client is already registered
|
|
157
|
+
if (!signatureText) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
await this.#addSignature(
|
|
162
|
+
SignatureRequestType.CreateInbox,
|
|
163
|
+
signatureText,
|
|
164
|
+
this.#signer,
|
|
165
|
+
);
|
|
166
|
+
|
|
140
167
|
return this.sendMessage("registerIdentity", undefined);
|
|
141
168
|
}
|
|
142
169
|
|
|
170
|
+
async addAccount(newAccountSigner: Signer) {
|
|
171
|
+
const signatureText = await this.#addAccountSignatureText(
|
|
172
|
+
await newAccountSigner.getAddress(),
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
if (!signatureText) {
|
|
176
|
+
throw new Error("Unable to generate add account signature text");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
await this.#addSignature(
|
|
180
|
+
SignatureRequestType.AddWallet,
|
|
181
|
+
signatureText,
|
|
182
|
+
this.#signer,
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
await this.#addSignature(
|
|
186
|
+
SignatureRequestType.AddWallet,
|
|
187
|
+
signatureText,
|
|
188
|
+
newAccountSigner,
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
await this.#applySignatures();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async removeAccount(accountAddress: string) {
|
|
195
|
+
const signatureText =
|
|
196
|
+
await this.#removeAccountSignatureText(accountAddress);
|
|
197
|
+
|
|
198
|
+
if (!signatureText) {
|
|
199
|
+
throw new Error("Unable to generate remove account signature text");
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
await this.#addSignature(
|
|
203
|
+
SignatureRequestType.RevokeWallet,
|
|
204
|
+
signatureText,
|
|
205
|
+
this.#signer,
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
await this.#applySignatures();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async revokeInstallations() {
|
|
212
|
+
const signatureText = await this.#revokeInstallationsSignatureText();
|
|
213
|
+
|
|
214
|
+
if (!signatureText) {
|
|
215
|
+
throw new Error("Unable to generate revoke installations signature text");
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
await this.#addSignature(
|
|
219
|
+
SignatureRequestType.RevokeInstallations,
|
|
220
|
+
signatureText,
|
|
221
|
+
this.#signer,
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
await this.#applySignatures();
|
|
225
|
+
}
|
|
226
|
+
|
|
143
227
|
async isRegistered() {
|
|
144
228
|
return this.sendMessage("isRegistered", undefined);
|
|
145
229
|
}
|
|
@@ -148,6 +232,23 @@ export class Client extends ClientWorkerClass {
|
|
|
148
232
|
return this.sendMessage("canMessage", { accountAddresses });
|
|
149
233
|
}
|
|
150
234
|
|
|
235
|
+
static async canMessage(accountAddresses: string[], env?: XmtpEnv) {
|
|
236
|
+
const accountAddress = "0x0000000000000000000000000000000000000000";
|
|
237
|
+
const signer: Signer = {
|
|
238
|
+
getAddress: () => accountAddress,
|
|
239
|
+
signMessage: () => new Uint8Array(),
|
|
240
|
+
};
|
|
241
|
+
const client = await Client.create(
|
|
242
|
+
signer,
|
|
243
|
+
window.crypto.getRandomValues(new Uint8Array(32)),
|
|
244
|
+
{
|
|
245
|
+
disableAutoRegister: true,
|
|
246
|
+
env,
|
|
247
|
+
},
|
|
248
|
+
);
|
|
249
|
+
return client.canMessage(accountAddresses);
|
|
250
|
+
}
|
|
251
|
+
|
|
151
252
|
async findInboxIdByAddress(address: string) {
|
|
152
253
|
return this.sendMessage("findInboxIdByAddress", { address });
|
|
153
254
|
}
|
package/src/WorkerClient.ts
CHANGED
|
@@ -46,7 +46,7 @@ export class WorkerClient {
|
|
|
46
46
|
return this.#client.isRegistered;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
async
|
|
49
|
+
async createInboxSignatureText() {
|
|
50
50
|
try {
|
|
51
51
|
return await this.#client.createInboxSignatureText();
|
|
52
52
|
} catch {
|
|
@@ -54,7 +54,7 @@ export class WorkerClient {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
async
|
|
57
|
+
async addAccountSignatureText(accountAddress: string) {
|
|
58
58
|
try {
|
|
59
59
|
return await this.#client.addWalletSignatureText(
|
|
60
60
|
this.#accountAddress,
|
|
@@ -65,7 +65,7 @@ export class WorkerClient {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
async
|
|
68
|
+
async removeAccountSignatureText(accountAddress: string) {
|
|
69
69
|
try {
|
|
70
70
|
return await this.#client.revokeWalletSignatureText(accountAddress);
|
|
71
71
|
} catch {
|
|
@@ -73,7 +73,7 @@ export class WorkerClient {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
async
|
|
76
|
+
async revokeInstallationsSignatureText() {
|
|
77
77
|
try {
|
|
78
78
|
return await this.#client.revokeInstallationsSignatureText();
|
|
79
79
|
} catch {
|
package/src/index.ts
CHANGED
|
@@ -43,21 +43,21 @@ export type ClientEvents =
|
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
| {
|
|
46
|
-
action: "
|
|
46
|
+
action: "createInboxSignatureText";
|
|
47
47
|
id: string;
|
|
48
48
|
result: string | undefined;
|
|
49
49
|
data: undefined;
|
|
50
50
|
}
|
|
51
51
|
| {
|
|
52
|
-
action: "
|
|
52
|
+
action: "addAccountSignatureText";
|
|
53
53
|
id: string;
|
|
54
54
|
result: string | undefined;
|
|
55
55
|
data: {
|
|
56
|
-
|
|
56
|
+
newAccountAddress: string;
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
59
|
| {
|
|
60
|
-
action: "
|
|
60
|
+
action: "removeAccountSignatureText";
|
|
61
61
|
id: string;
|
|
62
62
|
result: string | undefined;
|
|
63
63
|
data: {
|
|
@@ -65,7 +65,7 @@ export type ClientEvents =
|
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
67
|
| {
|
|
68
|
-
action: "
|
|
68
|
+
action: "revokeInstallationsSignatureText";
|
|
69
69
|
id: string;
|
|
70
70
|
result: string | undefined;
|
|
71
71
|
data: undefined;
|
package/src/types/options.ts
CHANGED
|
@@ -48,6 +48,10 @@ export type OtherOptions = {
|
|
|
48
48
|
* Logging level
|
|
49
49
|
*/
|
|
50
50
|
loggingLevel?: "off" | "error" | "warn" | "info" | "debug" | "trace";
|
|
51
|
+
/**
|
|
52
|
+
* Disable automatic registration when creating a client
|
|
53
|
+
*/
|
|
54
|
+
disableAutoRegister?: boolean;
|
|
51
55
|
};
|
|
52
56
|
|
|
53
57
|
export type ClientOptions = NetworkOptions &
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type SignMessage = (message: string) => Promise<Uint8Array> | Uint8Array;
|
|
2
|
+
export type GetAddress = () => Promise<string> | string;
|
|
3
|
+
export type GetChainId = () => bigint;
|
|
4
|
+
export type GetBlockNumber = () => bigint;
|
|
5
|
+
|
|
6
|
+
export type Signer = {
|
|
7
|
+
getAddress: GetAddress;
|
|
8
|
+
signMessage: SignMessage;
|
|
9
|
+
// these fields indicate that the signer is a smart contract wallet
|
|
10
|
+
getBlockNumber?: GetBlockNumber;
|
|
11
|
+
getChainId?: GetChainId;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type SmartContractSigner = Required<Signer>;
|
|
15
|
+
|
|
16
|
+
export const isSmartContractSigner = (
|
|
17
|
+
signer: Signer,
|
|
18
|
+
): signer is SmartContractSigner =>
|
|
19
|
+
"getBlockNumber" in signer && "getChainId" in signer;
|
package/src/workers/client.ts
CHANGED
|
@@ -73,8 +73,8 @@ self.onmessage = async (event: MessageEvent<ClientEventsClientMessageData>) => {
|
|
|
73
73
|
},
|
|
74
74
|
});
|
|
75
75
|
break;
|
|
76
|
-
case "
|
|
77
|
-
const result = await client.
|
|
76
|
+
case "createInboxSignatureText": {
|
|
77
|
+
const result = await client.createInboxSignatureText();
|
|
78
78
|
postMessage({
|
|
79
79
|
id,
|
|
80
80
|
action,
|
|
@@ -82,9 +82,9 @@ self.onmessage = async (event: MessageEvent<ClientEventsClientMessageData>) => {
|
|
|
82
82
|
});
|
|
83
83
|
break;
|
|
84
84
|
}
|
|
85
|
-
case "
|
|
86
|
-
const result = await client.
|
|
87
|
-
data.
|
|
85
|
+
case "addAccountSignatureText": {
|
|
86
|
+
const result = await client.addAccountSignatureText(
|
|
87
|
+
data.newAccountAddress,
|
|
88
88
|
);
|
|
89
89
|
postMessage({
|
|
90
90
|
id,
|
|
@@ -93,8 +93,8 @@ self.onmessage = async (event: MessageEvent<ClientEventsClientMessageData>) => {
|
|
|
93
93
|
});
|
|
94
94
|
break;
|
|
95
95
|
}
|
|
96
|
-
case "
|
|
97
|
-
const result = await client.
|
|
96
|
+
case "removeAccountSignatureText": {
|
|
97
|
+
const result = await client.removeAccountSignatureText(
|
|
98
98
|
data.accountAddress,
|
|
99
99
|
);
|
|
100
100
|
postMessage({
|
|
@@ -104,8 +104,8 @@ self.onmessage = async (event: MessageEvent<ClientEventsClientMessageData>) => {
|
|
|
104
104
|
});
|
|
105
105
|
break;
|
|
106
106
|
}
|
|
107
|
-
case "
|
|
108
|
-
const result = await client.
|
|
107
|
+
case "revokeInstallationsSignatureText": {
|
|
108
|
+
const result = await client.revokeInstallationsSignatureText();
|
|
109
109
|
postMessage({
|
|
110
110
|
id,
|
|
111
111
|
action,
|
package/tsconfig.json
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "tsconfig/react-sdk.json",
|
|
3
|
-
"include": ["src", "test", "vite.config.ts", "rollup.config.js"],
|
|
4
|
-
"compilerOptions": {
|
|
5
|
-
"paths": {
|
|
6
|
-
"@/*": ["./src/*"],
|
|
7
|
-
"@test/*": ["./test/*"]
|
|
8
|
-
},
|
|
9
|
-
"types": ["@vitest/browser/providers/playwright"]
|
|
10
|
-
}
|
|
11
|
-
}
|