@account-kit/signer 4.0.0-alpha.5 → 4.0.0-alpha.6
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/cjs/base.js.map +1 -1
- package/dist/cjs/client/base.d.ts +1 -1
- package/dist/cjs/client/base.js.map +1 -1
- package/dist/cjs/client/index.js.map +1 -1
- package/dist/cjs/index.d.ts +5 -4
- package/dist/cjs/index.js +9 -7
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/signer.d.ts +1 -1
- package/dist/cjs/signer.js +5 -5
- package/dist/cjs/signer.js.map +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/version.js.map +1 -1
- package/dist/esm/base.js.map +1 -1
- package/dist/esm/client/base.d.ts +1 -1
- package/dist/esm/client/base.js.map +1 -1
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/index.d.ts +5 -4
- package/dist/esm/index.js +3 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/signer.d.ts +1 -1
- package/dist/esm/signer.js +5 -5
- package/dist/esm/signer.js.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/types/base.d.ts +248 -14
- package/dist/types/base.d.ts.map +1 -1
- package/dist/types/client/base.d.ts +52 -6
- package/dist/types/client/base.d.ts.map +1 -1
- package/dist/types/client/index.d.ts +158 -0
- package/dist/types/client/index.d.ts.map +1 -1
- package/dist/types/index.d.ts +5 -4
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/signer.d.ts +22 -1
- package/dist/types/signer.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +4 -3
- package/src/base.ts +250 -16
- package/src/client/base.ts +53 -6
- package/src/client/index.ts +159 -1
- package/src/index.ts +5 -6
- package/src/signer.ts +27 -6
- package/src/version.ts +1 -1
package/src/base.ts
CHANGED
|
@@ -44,6 +44,10 @@ type InternalStore = Mutate<
|
|
|
44
44
|
[["zustand/subscribeWithSelector", never]]
|
|
45
45
|
>;
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Base abstract class for Alchemy Signer, providing authentication and session management for smart accounts.
|
|
49
|
+
* Implements the `SmartAccountAuthenticator` interface and handles various signer events.
|
|
50
|
+
*/
|
|
47
51
|
export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
48
52
|
implements SmartAccountAuthenticator<AuthParams, User, TClient>
|
|
49
53
|
{
|
|
@@ -52,6 +56,15 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
52
56
|
private sessionManager: SessionManager;
|
|
53
57
|
private store: InternalStore;
|
|
54
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Initializes an instance with the provided client and session configuration.
|
|
61
|
+
* This function sets up the internal store, initializes the session manager,
|
|
62
|
+
* registers listeners and initializes the session manager to manage session state.
|
|
63
|
+
*
|
|
64
|
+
* @param {BaseAlchemySignerParams<TClient>} param0 Object containing the client and session configuration
|
|
65
|
+
* @param {TClient} param0.client The client instance to be used internally
|
|
66
|
+
* @param {SessionConfig} param0.sessionConfig Configuration for managing sessions
|
|
67
|
+
*/
|
|
55
68
|
constructor({ client, sessionConfig }: BaseAlchemySignerParams<TClient>) {
|
|
56
69
|
this.inner = client;
|
|
57
70
|
this.store = createStore(
|
|
@@ -88,9 +101,9 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
88
101
|
/**
|
|
89
102
|
* Allows you to subscribe to events emitted by the signer
|
|
90
103
|
*
|
|
91
|
-
* @param event the event to subscribe to
|
|
92
|
-
* @param listener the function to run when the event is emitted
|
|
93
|
-
* @returns a function to remove the listener
|
|
104
|
+
* @param {AlchemySignerEvent} event the event to subscribe to
|
|
105
|
+
* @param {AlchemySignerEvents[AlchemySignerEvent]} listener the function to run when the event is emitted
|
|
106
|
+
* @returns {() => void} a function to remove the listener
|
|
94
107
|
*/
|
|
95
108
|
on = <E extends AlchemySignerEvent>(
|
|
96
109
|
event: E,
|
|
@@ -132,8 +145,29 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
132
145
|
/**
|
|
133
146
|
* Authenticate a user with either an email or a passkey and create a session for that user
|
|
134
147
|
*
|
|
135
|
-
* @
|
|
136
|
-
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* import { AlchemyWebSigner } from "@account-kit/signer";
|
|
151
|
+
*
|
|
152
|
+
* const signer = new AlchemyWebSigner({
|
|
153
|
+
* client: {
|
|
154
|
+
* connection: {
|
|
155
|
+
* rpcUrl: "/api/rpc",
|
|
156
|
+
* },
|
|
157
|
+
* iframeConfig: {
|
|
158
|
+
* iframeContainerId: "alchemy-signer-iframe-container",
|
|
159
|
+
* },
|
|
160
|
+
* },
|
|
161
|
+
* });
|
|
162
|
+
*
|
|
163
|
+
* const result = await signer.authenticate({
|
|
164
|
+
* type: "email",
|
|
165
|
+
* email: "foo@mail.com",
|
|
166
|
+
* });
|
|
167
|
+
* ```
|
|
168
|
+
*
|
|
169
|
+
* @param {AuthParams} params - undefined if passkey login, otherwise an object with email and bundle to resolve
|
|
170
|
+
* @returns {Promise<User>} the user that was authenticated
|
|
137
171
|
*/
|
|
138
172
|
authenticate: (params: AuthParams) => Promise<User> = async (params) => {
|
|
139
173
|
if (params.type === "email") {
|
|
@@ -144,7 +178,27 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
144
178
|
};
|
|
145
179
|
|
|
146
180
|
/**
|
|
147
|
-
*
|
|
181
|
+
* Clear a user session and log them out
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```ts
|
|
185
|
+
* import { AlchemyWebSigner } from "@account-kit/signer";
|
|
186
|
+
*
|
|
187
|
+
* const signer = new AlchemyWebSigner({
|
|
188
|
+
* client: {
|
|
189
|
+
* connection: {
|
|
190
|
+
* rpcUrl: "/api/rpc",
|
|
191
|
+
* },
|
|
192
|
+
* iframeConfig: {
|
|
193
|
+
* iframeContainerId: "alchemy-signer-iframe-container",
|
|
194
|
+
* },
|
|
195
|
+
* },
|
|
196
|
+
* });
|
|
197
|
+
*
|
|
198
|
+
* await signer.disconnect();
|
|
199
|
+
* ```
|
|
200
|
+
*
|
|
201
|
+
* @returns {Promise<void>} a promise that resolves when the user is logged out
|
|
148
202
|
*/
|
|
149
203
|
disconnect: () => Promise<void> = async () => {
|
|
150
204
|
await this.inner.disconnect();
|
|
@@ -155,10 +209,29 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
155
209
|
* If a user has an ongoing session, it will use that session and
|
|
156
210
|
* try to authenticate
|
|
157
211
|
*
|
|
212
|
+
* @example
|
|
213
|
+
* ```ts
|
|
214
|
+
* import { AlchemyWebSigner } from "@account-kit/signer";
|
|
215
|
+
*
|
|
216
|
+
* const signer = new AlchemyWebSigner({
|
|
217
|
+
* client: {
|
|
218
|
+
* connection: {
|
|
219
|
+
* rpcUrl: "/api/rpc",
|
|
220
|
+
* },
|
|
221
|
+
* iframeConfig: {
|
|
222
|
+
* iframeContainerId: "alchemy-signer-iframe-container",
|
|
223
|
+
* },
|
|
224
|
+
* },
|
|
225
|
+
* });
|
|
226
|
+
*
|
|
227
|
+
* // throws if not logged in
|
|
228
|
+
* const user = await signer.getAuthDetails();
|
|
229
|
+
* ```
|
|
230
|
+
*
|
|
158
231
|
* @throws if there is no user logged in
|
|
159
|
-
* @returns the current user
|
|
232
|
+
* @returns {Promise<User>} the current user
|
|
160
233
|
*/
|
|
161
|
-
getAuthDetails
|
|
234
|
+
getAuthDetails = async (): Promise<User> => {
|
|
162
235
|
const sessionUser = await this.sessionManager.getSessionUser();
|
|
163
236
|
if (sessionUser != null) {
|
|
164
237
|
return sessionUser;
|
|
@@ -167,12 +240,41 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
167
240
|
return this.inner.whoami();
|
|
168
241
|
};
|
|
169
242
|
|
|
243
|
+
/**
|
|
244
|
+
* Retrieves the address of the current user by calling the `whoami` method on `this.inner`.
|
|
245
|
+
*
|
|
246
|
+
* @returns {Promise<string>} A promise that resolves to the address of the current user.
|
|
247
|
+
*/
|
|
170
248
|
getAddress: () => Promise<`0x${string}`> = async () => {
|
|
171
249
|
const { address } = await this.inner.whoami();
|
|
172
250
|
|
|
173
251
|
return address;
|
|
174
252
|
};
|
|
175
253
|
|
|
254
|
+
/**
|
|
255
|
+
* Signs a raw message after hashing it.
|
|
256
|
+
*
|
|
257
|
+
* @example
|
|
258
|
+
* ```ts
|
|
259
|
+
* import { AlchemyWebSigner } from "@account-kit/signer";
|
|
260
|
+
*
|
|
261
|
+
* const signer = new AlchemyWebSigner({
|
|
262
|
+
* client: {
|
|
263
|
+
* connection: {
|
|
264
|
+
* rpcUrl: "/api/rpc",
|
|
265
|
+
* },
|
|
266
|
+
* iframeConfig: {
|
|
267
|
+
* iframeContainerId: "alchemy-signer-iframe-container",
|
|
268
|
+
* },
|
|
269
|
+
* },
|
|
270
|
+
* });
|
|
271
|
+
*
|
|
272
|
+
* const signature = await signer.signMessage("Hello, world!");
|
|
273
|
+
* ```
|
|
274
|
+
*
|
|
275
|
+
* @param {string} msg the message to be hashed and then signed
|
|
276
|
+
* @returns {Promise<string>} a promise that resolves to the signed message
|
|
277
|
+
*/
|
|
176
278
|
signMessage: (msg: SignableMessage) => Promise<`0x${string}`> = async (
|
|
177
279
|
msg
|
|
178
280
|
) => {
|
|
@@ -181,6 +283,35 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
181
283
|
return this.inner.signRawMessage(messageHash);
|
|
182
284
|
};
|
|
183
285
|
|
|
286
|
+
/**
|
|
287
|
+
* Signs a typed message by first hashing it and then signing the hashed message using the `signRawMessage` method.
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* ```ts
|
|
291
|
+
* import { AlchemyWebSigner } from "@account-kit/signer";
|
|
292
|
+
*
|
|
293
|
+
* const signer = new AlchemyWebSigner({
|
|
294
|
+
* client: {
|
|
295
|
+
* connection: {
|
|
296
|
+
* rpcUrl: "/api/rpc",
|
|
297
|
+
* },
|
|
298
|
+
* iframeConfig: {
|
|
299
|
+
* iframeContainerId: "alchemy-signer-iframe-container",
|
|
300
|
+
* },
|
|
301
|
+
* },
|
|
302
|
+
* });
|
|
303
|
+
*
|
|
304
|
+
* const signature = await signer.signTypedData({
|
|
305
|
+
* domain: {},
|
|
306
|
+
* types: {},
|
|
307
|
+
* primaryType: "",
|
|
308
|
+
* message: {},
|
|
309
|
+
* });
|
|
310
|
+
* ```
|
|
311
|
+
*
|
|
312
|
+
* @param {TypedDataDefinition<TTypedData, TPrimaryType>} params The parameters for the typed message to be hashed and signed
|
|
313
|
+
* @returns {Promise<any>} A promise that resolves to the signed message
|
|
314
|
+
*/
|
|
184
315
|
signTypedData: <
|
|
185
316
|
const TTypedData extends TypedData | { [key: string]: unknown },
|
|
186
317
|
TPrimaryType extends keyof TTypedData | "EIP712Domain" = keyof TTypedData
|
|
@@ -192,6 +323,36 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
192
323
|
return this.inner.signRawMessage(messageHash);
|
|
193
324
|
};
|
|
194
325
|
|
|
326
|
+
/**
|
|
327
|
+
* Serializes a transaction, signs it with a raw message, and then returns the serialized transaction with the signature.
|
|
328
|
+
*
|
|
329
|
+
* @example
|
|
330
|
+
* ```ts
|
|
331
|
+
* import { AlchemyWebSigner } from "@account-kit/signer";
|
|
332
|
+
*
|
|
333
|
+
* const signer = new AlchemyWebSigner({
|
|
334
|
+
* client: {
|
|
335
|
+
* connection: {
|
|
336
|
+
* rpcUrl: "/api/rpc",
|
|
337
|
+
* },
|
|
338
|
+
* iframeConfig: {
|
|
339
|
+
* iframeContainerId: "alchemy-signer-iframe-container",
|
|
340
|
+
* },
|
|
341
|
+
* },
|
|
342
|
+
* });
|
|
343
|
+
*
|
|
344
|
+
* const tx = await signer.signTransaction({
|
|
345
|
+
* to: "0x1234",
|
|
346
|
+
* value: "0x1234",
|
|
347
|
+
* data: "0x1234",
|
|
348
|
+
* });
|
|
349
|
+
* ```
|
|
350
|
+
*
|
|
351
|
+
* @param {Transaction} tx the transaction to be serialized and signed
|
|
352
|
+
* @param {{serializer?: SerializeTransactionFn}} args options for serialization
|
|
353
|
+
* @param {() => Hex} [args.serializer] an optional serializer function. If not provided, the default `serializeTransaction` function will be used
|
|
354
|
+
* @returns {Promise<string>} a promise that resolves to the serialized transaction with the signature
|
|
355
|
+
*/
|
|
195
356
|
signTransaction: CustomSource["signTransaction"] = async (tx, args) => {
|
|
196
357
|
const serializeFn = args?.serializer ?? serializeTransaction;
|
|
197
358
|
const serializedTx = serializeFn(tx);
|
|
@@ -211,8 +372,26 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
211
372
|
/**
|
|
212
373
|
* Unauthenticated call to look up a user's organizationId by email
|
|
213
374
|
*
|
|
214
|
-
* @
|
|
215
|
-
*
|
|
375
|
+
* @example
|
|
376
|
+
* ```ts
|
|
377
|
+
* import { AlchemyWebSigner } from "@account-kit/signer";
|
|
378
|
+
*
|
|
379
|
+
* const signer = new AlchemyWebSigner({
|
|
380
|
+
* client: {
|
|
381
|
+
* connection: {
|
|
382
|
+
* rpcUrl: "/api/rpc",
|
|
383
|
+
* },
|
|
384
|
+
* iframeConfig: {
|
|
385
|
+
* iframeContainerId: "alchemy-signer-iframe-container",
|
|
386
|
+
* },
|
|
387
|
+
* },
|
|
388
|
+
* });
|
|
389
|
+
*
|
|
390
|
+
* const result = await signer.getUser("foo@mail.com");
|
|
391
|
+
* ```
|
|
392
|
+
*
|
|
393
|
+
* @param {string} email the email to lookup
|
|
394
|
+
* @returns {Promise<{orgId: string}>} the organization id for the user if they exist
|
|
216
395
|
*/
|
|
217
396
|
getUser: (email: string) => Promise<{ orgId: string } | null> = async (
|
|
218
397
|
email
|
|
@@ -231,8 +410,26 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
231
410
|
/**
|
|
232
411
|
* Adds a passkey to the user's account
|
|
233
412
|
*
|
|
234
|
-
* @
|
|
235
|
-
*
|
|
413
|
+
* @example
|
|
414
|
+
* ```ts
|
|
415
|
+
* import { AlchemyWebSigner } from "@account-kit/signer";
|
|
416
|
+
*
|
|
417
|
+
* const signer = new AlchemyWebSigner({
|
|
418
|
+
* client: {
|
|
419
|
+
* connection: {
|
|
420
|
+
* rpcUrl: "/api/rpc",
|
|
421
|
+
* },
|
|
422
|
+
* iframeConfig: {
|
|
423
|
+
* iframeContainerId: "alchemy-signer-iframe-container",
|
|
424
|
+
* },
|
|
425
|
+
* },
|
|
426
|
+
* });
|
|
427
|
+
*
|
|
428
|
+
* const result = await signer.addPasskey()
|
|
429
|
+
* ```
|
|
430
|
+
*
|
|
431
|
+
* @param {CredentialCreationOptions | undefined} params optional parameters for the passkey creation
|
|
432
|
+
* @returns {Promise<string[]>} an array of the authenticator ids added to the user
|
|
236
433
|
*/
|
|
237
434
|
addPasskey: (params?: CredentialCreationOptions) => Promise<string[]> =
|
|
238
435
|
async (params) => {
|
|
@@ -244,8 +441,27 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
244
441
|
* If the user is authenticated with an Email, this will return a seed phrase
|
|
245
442
|
* If the user is authenticated with a Passkey, this will return a private key
|
|
246
443
|
*
|
|
247
|
-
* @
|
|
248
|
-
*
|
|
444
|
+
* @example
|
|
445
|
+
* ```ts
|
|
446
|
+
* import { AlchemyWebSigner } from "@account-kit/signer";
|
|
447
|
+
*
|
|
448
|
+
* const signer = new AlchemyWebSigner({
|
|
449
|
+
* client: {
|
|
450
|
+
* connection: {
|
|
451
|
+
* rpcUrl: "/api/rpc",
|
|
452
|
+
* },
|
|
453
|
+
* iframeConfig: {
|
|
454
|
+
* iframeContainerId: "alchemy-signer-iframe-container",
|
|
455
|
+
* },
|
|
456
|
+
* },
|
|
457
|
+
* });
|
|
458
|
+
*
|
|
459
|
+
* // the params passed to this are different based on the specific signer
|
|
460
|
+
* const result = signer.exportWallet()
|
|
461
|
+
* ```
|
|
462
|
+
*
|
|
463
|
+
* @param {unknown} params export wallet parameters
|
|
464
|
+
* @returns {boolean} true if the wallet was exported successfully
|
|
249
465
|
*/
|
|
250
466
|
exportWallet: (
|
|
251
467
|
params: Parameters<(typeof this.inner)["exportWallet"]>[0]
|
|
@@ -257,10 +473,28 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
|
257
473
|
* This method lets you adapt your AlchemySigner to a viem LocalAccount, which
|
|
258
474
|
* will let you use the signer as an EOA directly.
|
|
259
475
|
*
|
|
476
|
+
* @example
|
|
477
|
+
* ```ts
|
|
478
|
+
* import { AlchemyWebSigner } from "@account-kit/signer";
|
|
479
|
+
*
|
|
480
|
+
* const signer = new AlchemyWebSigner({
|
|
481
|
+
* client: {
|
|
482
|
+
* connection: {
|
|
483
|
+
* rpcUrl: "/api/rpc",
|
|
484
|
+
* },
|
|
485
|
+
* iframeConfig: {
|
|
486
|
+
* iframeContainerId: "alchemy-signer-iframe-container",
|
|
487
|
+
* },
|
|
488
|
+
* },
|
|
489
|
+
* });
|
|
490
|
+
*
|
|
491
|
+
* const account = signer.toViemAccount();
|
|
492
|
+
* ```
|
|
493
|
+
*
|
|
260
494
|
* @throws if your signer is not authenticated
|
|
261
|
-
* @returns a LocalAccount object that can be used with viem's wallet client
|
|
495
|
+
* @returns {LocalAccount} a LocalAccount object that can be used with viem's wallet client
|
|
262
496
|
*/
|
|
263
|
-
toViemAccount
|
|
497
|
+
toViemAccount = (): LocalAccount => {
|
|
264
498
|
// if we want this method to be synchronous, then we need to do this check here
|
|
265
499
|
// otherwise we can use the sessionManager to get the user
|
|
266
500
|
if (!this.inner.getUser()) {
|
package/src/client/base.ts
CHANGED
|
@@ -71,10 +71,23 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
71
71
|
this._user = user;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Sets the stamper of the TurnkeyClient.
|
|
76
|
+
*
|
|
77
|
+
* @param {TurnkeyClient["stamper"]} stamper the stamper function to set for the TurnkeyClient
|
|
78
|
+
*/
|
|
74
79
|
protected setStamper(stamper: TurnkeyClient["stamper"]) {
|
|
75
80
|
this.turnkeyClient.stamper = stamper;
|
|
76
81
|
}
|
|
77
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Exports wallet credentials based on the specified type, either as a SEED_PHRASE or PRIVATE_KEY.
|
|
85
|
+
*
|
|
86
|
+
* @param {object} params The parameters for exporting the wallet
|
|
87
|
+
* @param {ExportWalletStamper} params.exportStamper The stamper used for exporting the wallet
|
|
88
|
+
* @param {"SEED_PHRASE" | "PRIVATE_KEY"} params.exportAs Specifies the format for exporting the wallet, either as a SEED_PHRASE or PRIVATE_KEY
|
|
89
|
+
* @returns {Promise<boolean>} A promise that resolves to true if the export is successful
|
|
90
|
+
*/
|
|
78
91
|
protected exportWalletInner(params: {
|
|
79
92
|
exportStamper: ExportWalletStamper;
|
|
80
93
|
exportAs: "SEED_PHRASE" | "PRIVATE_KEY";
|
|
@@ -120,9 +133,9 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
120
133
|
/**
|
|
121
134
|
* Listen to events emitted by the client
|
|
122
135
|
*
|
|
123
|
-
* @param event the event you want to listen to
|
|
124
|
-
* @param listener the callback function to execute when an event is fired
|
|
125
|
-
* @returns a function that will remove the listener when called
|
|
136
|
+
* @param {AlchemySignerClientEvent} event the event you want to listen to
|
|
137
|
+
* @param {AlchemySignerClientEvents[AlchemySignerClientEvent]} listener the callback function to execute when an event is fired
|
|
138
|
+
* @returns {() => void} a function that will remove the listener when called
|
|
126
139
|
*/
|
|
127
140
|
public on = <E extends AlchemySignerClientEvent>(
|
|
128
141
|
event: E,
|
|
@@ -133,6 +146,13 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
133
146
|
return () => this.eventEmitter.removeListener(event, listener as any);
|
|
134
147
|
};
|
|
135
148
|
|
|
149
|
+
/**
|
|
150
|
+
* Handles the creation of authenticators using WebAuthn attestation and the provided options. Requires the user to be authenticated.
|
|
151
|
+
*
|
|
152
|
+
* @param {CredentialCreationOptions} options The options used to create the WebAuthn attestation
|
|
153
|
+
* @returns {Promise<string[]>} A promise that resolves to an array of authenticator IDs
|
|
154
|
+
* @throws {NotAuthenticatedError} If the user is not authenticated
|
|
155
|
+
*/
|
|
136
156
|
public addPasskey = async (options: CredentialCreationOptions) => {
|
|
137
157
|
if (!this.user) {
|
|
138
158
|
throw new NotAuthenticatedError();
|
|
@@ -166,6 +186,13 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
166
186
|
return authenticatorIds;
|
|
167
187
|
};
|
|
168
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Retrieves the current user or fetches the user information if not already available.
|
|
191
|
+
*
|
|
192
|
+
* @param {string} [orgId] optional organization ID, defaults to the user's organization ID
|
|
193
|
+
* @returns {Promise<User>} A promise that resolves to the user object
|
|
194
|
+
* @throws {Error} if no organization ID is provided when there is no current user
|
|
195
|
+
*/
|
|
169
196
|
public whoami = async (orgId = this.user?.orgId): Promise<User> => {
|
|
170
197
|
if (this.user) {
|
|
171
198
|
return this.user;
|
|
@@ -200,6 +227,12 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
200
227
|
return this.user;
|
|
201
228
|
};
|
|
202
229
|
|
|
230
|
+
/**
|
|
231
|
+
* Looks up information based on an email address.
|
|
232
|
+
*
|
|
233
|
+
* @param {string} email the email address to look up
|
|
234
|
+
* @returns {Promise<any>} the result of the lookup request
|
|
235
|
+
*/
|
|
203
236
|
public lookupUserByEmail = async (email: string) => {
|
|
204
237
|
return this.request("/v1/lookup", { email });
|
|
205
238
|
};
|
|
@@ -209,10 +242,10 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
209
242
|
* For SignMessage or SignTypedData, the caller should hash the message before calling this method and pass
|
|
210
243
|
* that result here.
|
|
211
244
|
*
|
|
212
|
-
* @param msg the hex representation of the bytes to sign
|
|
213
|
-
* @returns the signature over the raw hex
|
|
245
|
+
* @param {Hex} msg the hex representation of the bytes to sign
|
|
246
|
+
* @returns {Promise<Hex>} the signature over the raw hex
|
|
214
247
|
*/
|
|
215
|
-
public signRawMessage = async (msg: Hex) => {
|
|
248
|
+
public signRawMessage = async (msg: Hex): Promise<Hex> => {
|
|
216
249
|
if (!this.user) {
|
|
217
250
|
throw new NotAuthenticatedError();
|
|
218
251
|
}
|
|
@@ -236,10 +269,23 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
236
269
|
return signature;
|
|
237
270
|
};
|
|
238
271
|
|
|
272
|
+
/**
|
|
273
|
+
* Returns the current user or null if no user is set.
|
|
274
|
+
*
|
|
275
|
+
* @returns {User | null} the current user object or null if no user is available
|
|
276
|
+
*/
|
|
239
277
|
public getUser = (): User | null => {
|
|
240
278
|
return this.user ?? null;
|
|
241
279
|
};
|
|
242
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Sends a POST request to the given signer route with the specified body and returns the response.
|
|
283
|
+
* Not intended to be used directly, use the specific methods instead on the client instead.
|
|
284
|
+
*
|
|
285
|
+
* @param {SignerRoutes} route The route to which the request should be sent
|
|
286
|
+
* @param {SignerBody<R>} body The request body containing the data to be sent
|
|
287
|
+
* @returns {Promise<SignerResponse<R>>} A promise that resolves to the response from the signer
|
|
288
|
+
*/
|
|
243
289
|
public request = async <R extends SignerRoutes>(
|
|
244
290
|
route: R,
|
|
245
291
|
body: SignerBody<R>
|
|
@@ -356,6 +402,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
356
402
|
return result;
|
|
357
403
|
};
|
|
358
404
|
|
|
405
|
+
// eslint-disable-next-line eslint-rules/require-jsdoc-on-reexported-functions
|
|
359
406
|
protected pollActivityCompletion = async <
|
|
360
407
|
T extends keyof Awaited<
|
|
361
408
|
ReturnType<(typeof this.turnkeyClient)["getActivity"]>
|
package/src/client/index.ts
CHANGED
|
@@ -40,6 +40,29 @@ export class AlchemySignerWebClient extends BaseSignerClient<ExportWalletParams>
|
|
|
40
40
|
private webauthnStamper: WebauthnStamper;
|
|
41
41
|
iframeContainerId: string;
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Initializes a new instance with the given parameters, setting up the connection, iframe configuration, and WebAuthn stamper.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* import { AlchemySignerWebClient } from "@account-kit/signer";
|
|
49
|
+
*
|
|
50
|
+
* const client = new AlchemySignerWebClient({
|
|
51
|
+
* connection: {
|
|
52
|
+
* apiKey: "your-api-key",
|
|
53
|
+
* },
|
|
54
|
+
* iframeConfig: {
|
|
55
|
+
* iframeContainerId: "signer-iframe-container",
|
|
56
|
+
* },
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @param {AlchemySignerClientParams} params the parameters required to initialize the client
|
|
61
|
+
* @param {ConnectionConfig} params.connection The connection details needed to connect to the service
|
|
62
|
+
* @param {{ iframeElementId?: string; iframeContainerId: string }} params.iframeConfig The configuration details for setting up the iframe stamper
|
|
63
|
+
* @param {string} params.rpId The relying party ID, defaulting to the current hostname if not provided
|
|
64
|
+
* @param {string} params.rootOrgId The root organization ID
|
|
65
|
+
*/
|
|
43
66
|
constructor(params: AlchemySignerClientParams) {
|
|
44
67
|
const { connection, iframeConfig, rpId, rootOrgId } =
|
|
45
68
|
AlchemySignerClientParamsSchema.parse(params);
|
|
@@ -64,7 +87,29 @@ export class AlchemySignerWebClient extends BaseSignerClient<ExportWalletParams>
|
|
|
64
87
|
});
|
|
65
88
|
}
|
|
66
89
|
|
|
67
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Authenticates the user by either email or passkey account creation flow. Emits events during the process.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* import { AlchemySignerWebClient } from "@account-kit/signer";
|
|
96
|
+
*
|
|
97
|
+
* const client = new AlchemySignerWebClient({
|
|
98
|
+
* connection: {
|
|
99
|
+
* apiKey: "your-api-key",
|
|
100
|
+
* },
|
|
101
|
+
* iframeConfig: {
|
|
102
|
+
* iframeContainerId: "signer-iframe-container",
|
|
103
|
+
* },
|
|
104
|
+
* });
|
|
105
|
+
*
|
|
106
|
+
* const account = await client.createAccount({ type: "email", email: "you@mail.com" });
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @param {CreateAccountParams} params The parameters for creating an account, including the type (email or passkey) and additional details.
|
|
110
|
+
* @returns {Promise<SignupResponse>} A promise that resolves with the response object containing the account creation result.
|
|
111
|
+
*/
|
|
112
|
+
createAccount = async (params: CreateAccountParams) => {
|
|
68
113
|
this.eventEmitter.emit("authenticating");
|
|
69
114
|
if (params.type === "email") {
|
|
70
115
|
const { email, expirationSeconds } = params;
|
|
@@ -105,6 +150,29 @@ export class AlchemySignerWebClient extends BaseSignerClient<ExportWalletParams>
|
|
|
105
150
|
return result;
|
|
106
151
|
};
|
|
107
152
|
|
|
153
|
+
/**
|
|
154
|
+
* Begin authenticating a user with their email and an expiration time for the authentication request. Initializes the iframe stamper to get the target public key.
|
|
155
|
+
* This method sends an email to the user to complete their login
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```ts
|
|
159
|
+
* import { AlchemySignerWebClient } from "@account-kit/signer";
|
|
160
|
+
*
|
|
161
|
+
* const client = new AlchemySignerWebClient({
|
|
162
|
+
* connection: {
|
|
163
|
+
* apiKey: "your-api-key",
|
|
164
|
+
* },
|
|
165
|
+
* iframeConfig: {
|
|
166
|
+
* iframeContainerId: "signer-iframe-container",
|
|
167
|
+
* },
|
|
168
|
+
* });
|
|
169
|
+
*
|
|
170
|
+
* const account = await client.initEmailAuth({ email: "you@mail.com" });
|
|
171
|
+
* ```
|
|
172
|
+
*
|
|
173
|
+
* @param {Omit<EmailAuthParams, "targetPublicKey">} params The parameters for email authentication, excluding the target public key
|
|
174
|
+
* @returns {Promise<any>} The response from the authentication request
|
|
175
|
+
*/
|
|
108
176
|
public initEmailAuth = async (
|
|
109
177
|
params: Omit<EmailAuthParams, "targetPublicKey">
|
|
110
178
|
) => {
|
|
@@ -120,6 +188,28 @@ export class AlchemySignerWebClient extends BaseSignerClient<ExportWalletParams>
|
|
|
120
188
|
});
|
|
121
189
|
};
|
|
122
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Completes email auth for the user by injecting a credential bundle and retrieving the user information based on the provided organization ID. Emits events during the process.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```ts
|
|
196
|
+
* import { AlchemySignerWebClient } from "@account-kit/signer";
|
|
197
|
+
*
|
|
198
|
+
* const client = new AlchemySignerWebClient({
|
|
199
|
+
* connection: {
|
|
200
|
+
* apiKey: "your-api-key",
|
|
201
|
+
* },
|
|
202
|
+
* iframeConfig: {
|
|
203
|
+
* iframeContainerId: "signer-iframe-container",
|
|
204
|
+
* },
|
|
205
|
+
* });
|
|
206
|
+
*
|
|
207
|
+
* const account = await client.completeEmailAuth({ orgId: "user-org-id", bundle: "bundle-from-email" });
|
|
208
|
+
* ```
|
|
209
|
+
*
|
|
210
|
+
* @param {{ bundle: string; orgId: string }} config The configuration object for the authentication function containing the credential bundle to inject and the organization id associated with the user
|
|
211
|
+
* @returns {Promise<User>} A promise that resolves to the authenticated user information
|
|
212
|
+
*/
|
|
123
213
|
public completeEmailAuth = async ({
|
|
124
214
|
bundle,
|
|
125
215
|
orgId,
|
|
@@ -142,6 +232,28 @@ export class AlchemySignerWebClient extends BaseSignerClient<ExportWalletParams>
|
|
|
142
232
|
return user;
|
|
143
233
|
};
|
|
144
234
|
|
|
235
|
+
/**
|
|
236
|
+
* Asynchronously handles the authentication process using WebAuthn Stamper. If a user is provided, sets the user and returns it. Otherwise, retrieves the current user and initializes the WebAuthn stamper.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```ts
|
|
240
|
+
* import { AlchemySignerWebClient } from "@account-kit/signer";
|
|
241
|
+
*
|
|
242
|
+
* const client = new AlchemySignerWebClient({
|
|
243
|
+
* connection: {
|
|
244
|
+
* apiKey: "your-api-key",
|
|
245
|
+
* },
|
|
246
|
+
* iframeConfig: {
|
|
247
|
+
* iframeContainerId: "signer-iframe-container",
|
|
248
|
+
* },
|
|
249
|
+
* });
|
|
250
|
+
*
|
|
251
|
+
* const account = await client.lookupUserWithPasskey();
|
|
252
|
+
* ```
|
|
253
|
+
*
|
|
254
|
+
* @param {User} [user] An optional user object to authenticate
|
|
255
|
+
* @returns {Promise<User>} A promise that resolves to the authenticated user object
|
|
256
|
+
*/
|
|
145
257
|
public lookupUserWithPasskey = async (user: User | undefined = undefined) => {
|
|
146
258
|
this.eventEmitter.emit("authenticating");
|
|
147
259
|
await this.initWebauthnStamper(user);
|
|
@@ -157,6 +269,33 @@ export class AlchemySignerWebClient extends BaseSignerClient<ExportWalletParams>
|
|
|
157
269
|
return result;
|
|
158
270
|
};
|
|
159
271
|
|
|
272
|
+
/**
|
|
273
|
+
* Initiates the export of a wallet by creating an iframe stamper and calling the appropriate export function.
|
|
274
|
+
* The export can be based on a seed phrase or a private key.
|
|
275
|
+
*
|
|
276
|
+
* @example
|
|
277
|
+
* ```ts
|
|
278
|
+
* import { AlchemySignerWebClient } from "@account-kit/signer";
|
|
279
|
+
*
|
|
280
|
+
* const client = new AlchemySignerWebClient({
|
|
281
|
+
* connection: {
|
|
282
|
+
* apiKey: "your-api-key",
|
|
283
|
+
* },
|
|
284
|
+
* iframeConfig: {
|
|
285
|
+
* iframeContainerId: "signer-iframe-container",
|
|
286
|
+
* },
|
|
287
|
+
* });
|
|
288
|
+
*
|
|
289
|
+
* const account = await client.exportWallet({
|
|
290
|
+
* iframeContainerId: "export-iframe-container",
|
|
291
|
+
* });
|
|
292
|
+
* ```
|
|
293
|
+
*
|
|
294
|
+
* @param {ExportWalletParams} config The parameters for exporting the wallet
|
|
295
|
+
* @param {string} config.iframeContainerId The ID of the container element that will hold the iframe stamper
|
|
296
|
+
* @param {string} [config.iframeElementId] Optional ID for the iframe element
|
|
297
|
+
* @returns {Promise<void>} A promise that resolves when the export process is complete
|
|
298
|
+
*/
|
|
160
299
|
public exportWallet = async ({
|
|
161
300
|
iframeContainerId,
|
|
162
301
|
iframeElementId = "turnkey-export-iframe",
|
|
@@ -181,6 +320,25 @@ export class AlchemySignerWebClient extends BaseSignerClient<ExportWalletParams>
|
|
|
181
320
|
});
|
|
182
321
|
};
|
|
183
322
|
|
|
323
|
+
/**
|
|
324
|
+
* Asynchronous function that clears the user and resets the iframe stamper.
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* ```ts
|
|
328
|
+
* import { AlchemySignerWebClient } from "@account-kit/signer";
|
|
329
|
+
*
|
|
330
|
+
* const client = new AlchemySignerWebClient({
|
|
331
|
+
* connection: {
|
|
332
|
+
* apiKey: "your-api-key",
|
|
333
|
+
* },
|
|
334
|
+
* iframeConfig: {
|
|
335
|
+
* iframeContainerId: "signer-iframe-container",
|
|
336
|
+
* },
|
|
337
|
+
* });
|
|
338
|
+
*
|
|
339
|
+
* const account = await client.disconnect();
|
|
340
|
+
* ```
|
|
341
|
+
*/
|
|
184
342
|
public disconnect = async () => {
|
|
185
343
|
this.user = undefined;
|
|
186
344
|
this.iframeStamper.clear();
|