@account-kit/signer 4.0.0-alpha.1 → 4.0.0-alpha.11

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.
Files changed (58) hide show
  1. package/dist/cjs/base.js +8 -1
  2. package/dist/cjs/base.js.map +1 -1
  3. package/dist/cjs/client/base.d.ts +3 -2
  4. package/dist/cjs/client/base.js +13 -0
  5. package/dist/cjs/client/base.js.map +1 -1
  6. package/dist/cjs/client/index.js +2 -1
  7. package/dist/cjs/client/index.js.map +1 -1
  8. package/dist/cjs/client/types.d.ts +4 -0
  9. package/dist/cjs/client/types.js.map +1 -1
  10. package/dist/cjs/index.d.ts +5 -4
  11. package/dist/cjs/index.js +9 -7
  12. package/dist/cjs/index.js.map +1 -1
  13. package/dist/cjs/signer.d.ts +5 -1
  14. package/dist/cjs/signer.js +5 -5
  15. package/dist/cjs/signer.js.map +1 -1
  16. package/dist/cjs/version.d.ts +1 -1
  17. package/dist/cjs/version.js +1 -1
  18. package/dist/cjs/version.js.map +1 -1
  19. package/dist/esm/base.js +8 -1
  20. package/dist/esm/base.js.map +1 -1
  21. package/dist/esm/client/base.d.ts +3 -2
  22. package/dist/esm/client/base.js +13 -0
  23. package/dist/esm/client/base.js.map +1 -1
  24. package/dist/esm/client/index.js +2 -1
  25. package/dist/esm/client/index.js.map +1 -1
  26. package/dist/esm/client/types.d.ts +4 -0
  27. package/dist/esm/client/types.js.map +1 -1
  28. package/dist/esm/index.d.ts +5 -4
  29. package/dist/esm/index.js +3 -2
  30. package/dist/esm/index.js.map +1 -1
  31. package/dist/esm/signer.d.ts +5 -1
  32. package/dist/esm/signer.js +5 -5
  33. package/dist/esm/signer.js.map +1 -1
  34. package/dist/esm/version.d.ts +1 -1
  35. package/dist/esm/version.js +1 -1
  36. package/dist/esm/version.js.map +1 -1
  37. package/dist/types/base.d.ts +248 -14
  38. package/dist/types/base.d.ts.map +1 -1
  39. package/dist/types/client/base.d.ts +63 -7
  40. package/dist/types/client/base.d.ts.map +1 -1
  41. package/dist/types/client/index.d.ts +158 -0
  42. package/dist/types/client/index.d.ts.map +1 -1
  43. package/dist/types/client/types.d.ts +4 -0
  44. package/dist/types/client/types.d.ts.map +1 -1
  45. package/dist/types/index.d.ts +5 -4
  46. package/dist/types/index.d.ts.map +1 -1
  47. package/dist/types/signer.d.ts +26 -4
  48. package/dist/types/signer.d.ts.map +1 -1
  49. package/dist/types/version.d.ts +1 -1
  50. package/dist/types/version.d.ts.map +1 -1
  51. package/package.json +5 -4
  52. package/src/base.ts +266 -18
  53. package/src/client/base.ts +74 -8
  54. package/src/client/index.ts +161 -2
  55. package/src/client/types.ts +5 -0
  56. package/src/index.ts +5 -6
  57. package/src/signer.ts +32 -6
  58. package/src/version.ts +1 -1
@@ -1,9 +1,10 @@
1
- export type * from "./signer.js";
2
- export { AlchemyWebSigner } from "./signer.js";
3
- export type * from "./types.js";
4
- export { AlchemySignerStatus } from "./types.js";
1
+ export { BaseAlchemySigner } from "./base.js";
5
2
  export { BaseSignerClient } from "./client/base.js";
6
3
  export { AlchemySignerWebClient } from "./client/index.js";
7
4
  export type * from "./client/types.js";
8
5
  export { DEFAULT_SESSION_MS } from "./session/manager.js";
6
+ export type * from "./signer.js";
7
+ export { AlchemyWebSigner } from "./signer.js";
8
+ export type * from "./types.js";
9
+ export { AlchemySignerStatus } from "./types.js";
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,aAAa,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,mBAAmB,YAAY,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,mBAAmB,mBAAmB,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,mBAAmB,mBAAmB,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,mBAAmB,aAAa,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,mBAAmB,YAAY,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
@@ -10,6 +10,10 @@ export type AuthParams = {
10
10
  type: "email";
11
11
  bundle: string;
12
12
  orgId?: string;
13
+ } | {
14
+ type: "passkey";
15
+ email: string;
16
+ creationOpts?: CredentialCreationOptionOverrides;
13
17
  } | {
14
18
  type: "passkey";
15
19
  createNew: false;
@@ -48,9 +52,6 @@ export declare const AlchemySignerParamsSchema: z.ZodObject<{
48
52
  }>, z.ZodObject<{
49
53
  rpcUrl: z.ZodString;
50
54
  apiKey: z.ZodOptional<z.ZodNever>;
51
- /**
52
- * A SmartAccountSigner that can be used with any SmartContractAccount
53
- */
54
55
  jwt: z.ZodOptional<z.ZodNever>;
55
56
  }, "strip", z.ZodTypeAny, {
56
57
  rpcUrl: string;
@@ -264,6 +265,27 @@ export type AlchemySignerParams = z.input<typeof AlchemySignerParamsSchema>;
264
265
  * A SmartAccountSigner that can be used with any SmartContractAccount
265
266
  */
266
267
  export declare class AlchemyWebSigner extends BaseAlchemySigner<AlchemySignerWebClient> {
267
- constructor(params_: AlchemySignerParams);
268
+ /**
269
+ * Initializes an instance with the provided Alchemy signer parameters after parsing them with a schema.
270
+ *
271
+ * @example
272
+ * ```ts
273
+ * import { AlchemyWebSigner } from "@account-kit/signer";
274
+ *
275
+ * const signer = new AlchemyWebSigner({
276
+ * client: {
277
+ * connection: {
278
+ * rpcUrl: "/api/rpc",
279
+ * },
280
+ * iframeConfig: {
281
+ * iframeContainerId: "alchemy-signer-iframe-container",
282
+ * },
283
+ * },
284
+ * });
285
+ * ```
286
+ *
287
+ * @param {AlchemySignerParams} params The parameters for the Alchemy signer, including the client and session configuration
288
+ */
289
+ constructor(params: AlchemySignerParams);
268
290
  }
269
291
  //# sourceMappingURL=signer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../../src/signer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAEL,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,mBAAmB,CAAC;AAG3E,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,eAAe,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACjD;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,KAAK,CAAC;CAClB,GACD;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,iCAAiC,CAAC;CAClD,CAAC;AAEN,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAYtC;;eAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EANC,CAAC;AAEL,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,iBAAiB,CAAC,sBAAsB,CAAC;gBACjE,OAAO,EAAE,mBAAmB;CAezC"}
1
+ {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../../src/signer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAEL,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,mBAAmB,CAAC;AAG3E,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,eAAe,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACjD;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,iCAAiC,CAAC;CAClD,GACD;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,KAAK,CAAC;CAClB,GACD;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,iCAAiC,CAAC;CAClD,CAAC;AAEN,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQlC,CAAC;AAEL,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,iBAAiB,CAAC,sBAAsB,CAAC;IAC7E;;;;;;;;;;;;;;;;;;;;OAoBG;gBACS,MAAM,EAAE,mBAAmB;CAexC"}
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "4.0.0-alpha.1";
1
+ export declare const VERSION = "4.0.0-alpha.11";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO,kBAAkB,CAAC"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO,mBAAmB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@account-kit/signer",
3
- "version": "4.0.0-alpha.1",
3
+ "version": "4.0.0-alpha.11",
4
4
  "description": "Core interfaces and clients for interfacing with the Alchemy Signer API",
5
5
  "author": "Alchemy",
6
6
  "license": "MIT",
@@ -34,6 +34,7 @@
34
34
  "build:cjs": "tsc --project tsconfig.build.json --module commonjs --outDir ./dist/cjs --removeComments --verbatimModuleSyntax false && echo > ./dist/cjs/package.json '{\"type\":\"commonjs\"}'",
35
35
  "build:esm": "tsc --project tsconfig.build.json --module es2020 --outDir ./dist/esm --removeComments && echo > ./dist/esm/package.json '{\"type\":\"module\"}'",
36
36
  "build:types": "tsc --project tsconfig.build.json --module esnext --declarationDir ./dist/types --emitDeclarationOnly --declaration --declarationMap",
37
+ "docs:gen": "npx ak-docgen generate --in ./src/index.ts --out ../../site/pages/reference/account-kit/signer",
37
38
  "clean": "rm -rf ./dist",
38
39
  "test": "vitest --passWithNoTests",
39
40
  "test:run": "vitest run --passWithNoTests",
@@ -46,10 +47,10 @@
46
47
  "tailwindcss": "^3.4.3",
47
48
  "typescript": "^5.0.4",
48
49
  "typescript-template": "*",
49
- "vitest": "^0.31.0"
50
+ "vitest": "^2.0.4"
50
51
  },
51
52
  "dependencies": {
52
- "@aa-sdk/core": "^4.0.0-alpha.1",
53
+ "@aa-sdk/core": "^4.0.0-alpha.11",
53
54
  "@turnkey/http": "^2.6.2",
54
55
  "@turnkey/iframe-stamper": "^1.0.0",
55
56
  "@turnkey/viem": "^0.4.8",
@@ -75,5 +76,5 @@
75
76
  "url": "https://github.com/alchemyplatform/aa-sdk/issues"
76
77
  },
77
78
  "homepage": "https://github.com/alchemyplatform/aa-sdk#readme",
78
- "gitHead": "cb4bf5f8a9aa8fdff1610130821b69ff806e79e6"
79
+ "gitHead": "7dde8daa73a0bee97f3c0068d7e4818669db9a26"
79
80
  }
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
- * @param params - undefined if passkey login, otherwise an object with email and bundle to resolve
136
- * @returns the user that was authenticated
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
- * NOTE: right now this only clears the session locally.
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: () => Promise<User> = async () => {
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
- * @param email the email to lookup
215
- * @returns the organization id for the user if they exist
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
- * @param params optional parameters for the passkey creation
235
- * @returns an array of the authenticator ids added to the user
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
- * @param params export wallet parameters
248
- * @returns true if the wallet was exported successfully
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: () => LocalAccount = () => {
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()) {
@@ -336,8 +570,22 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
336
570
  args: Extract<AuthParams, { type: "passkey" }>
337
571
  ) => {
338
572
  let user: User;
339
- if (args.createNew) {
340
- const result = await this.inner.createAccount(args);
573
+ const shouldCreateNew = async () => {
574
+ if ("email" in args) {
575
+ const existingUser = await this.getUser(args.email);
576
+ return existingUser == null;
577
+ }
578
+
579
+ return args.createNew;
580
+ };
581
+
582
+ if (await shouldCreateNew()) {
583
+ const result = await this.inner.createAccount(
584
+ args as Extract<
585
+ AuthParams,
586
+ { type: "passkey" } & ({ email: string } | { createNew: true })
587
+ >
588
+ );
341
589
  // account creation for passkeys returns the whoami response so we don't have to
342
590
  // call it again after signup
343
591
  user = {
@@ -1,5 +1,5 @@
1
- import { type ConnectionConfig, ConnectionConfigSchema } from "@aa-sdk/core";
2
- import { TurnkeyClient } from "@turnkey/http";
1
+ import { ConnectionConfigSchema, type ConnectionConfig } from "@aa-sdk/core";
2
+ import { TurnkeyClient, type TSignedRequest } from "@turnkey/http";
3
3
  import EventEmitter from "eventemitter3";
4
4
  import type { Hex } from "viem";
5
5
  import { NotAuthenticatedError } from "../errors.js";
@@ -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,31 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
200
227
  return this.user;
201
228
  };
202
229
 
230
+ /**
231
+ * Generates a stamped whoami request for the current user. This request can then be used to call /signer/v1/whoami to get the user information.
232
+ * This is useful if you want to get the user information in a different context like a server. You can pass the stamped request to the server
233
+ * and then call our API to get the user information. Using this stamp is the most trusted way to get the user information since a stamp can only
234
+ * belong to the user who created it.
235
+ *
236
+ * @returns {Promise<TSignedRequest>} a promise that resolves to the "whoami" information for the logged in user
237
+ * @throws {Error} if no organization ID is provided
238
+ */
239
+ public stampWhoami = async (): Promise<TSignedRequest> => {
240
+ if (!this.user) {
241
+ throw new Error("User must be authenticated to stamp a whoami request");
242
+ }
243
+
244
+ return await this.turnkeyClient.stampGetWhoami({
245
+ organizationId: this.user.orgId,
246
+ });
247
+ };
248
+
249
+ /**
250
+ * Looks up information based on an email address.
251
+ *
252
+ * @param {string} email the email address to look up
253
+ * @returns {Promise<any>} the result of the lookup request
254
+ */
203
255
  public lookupUserByEmail = async (email: string) => {
204
256
  return this.request("/v1/lookup", { email });
205
257
  };
@@ -209,10 +261,10 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
209
261
  * For SignMessage or SignTypedData, the caller should hash the message before calling this method and pass
210
262
  * that result here.
211
263
  *
212
- * @param msg the hex representation of the bytes to sign
213
- * @returns the signature over the raw hex
264
+ * @param {Hex} msg the hex representation of the bytes to sign
265
+ * @returns {Promise<Hex>} the signature over the raw hex
214
266
  */
215
- public signRawMessage = async (msg: Hex) => {
267
+ public signRawMessage = async (msg: Hex): Promise<Hex> => {
216
268
  if (!this.user) {
217
269
  throw new NotAuthenticatedError();
218
270
  }
@@ -236,10 +288,23 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
236
288
  return signature;
237
289
  };
238
290
 
291
+ /**
292
+ * Returns the current user or null if no user is set.
293
+ *
294
+ * @returns {User | null} the current user object or null if no user is available
295
+ */
239
296
  public getUser = (): User | null => {
240
297
  return this.user ?? null;
241
298
  };
242
299
 
300
+ /**
301
+ * Sends a POST request to the given signer route with the specified body and returns the response.
302
+ * Not intended to be used directly, use the specific methods instead on the client instead.
303
+ *
304
+ * @param {SignerRoutes} route The route to which the request should be sent
305
+ * @param {SignerBody<R>} body The request body containing the data to be sent
306
+ * @returns {Promise<SignerResponse<R>>} A promise that resolves to the response from the signer
307
+ */
243
308
  public request = async <R extends SignerRoutes>(
244
309
  route: R,
245
310
  body: SignerBody<R>
@@ -356,6 +421,7 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
356
421
  return result;
357
422
  };
358
423
 
424
+ // eslint-disable-next-line eslint-rules/require-jsdoc-on-reexported-functions
359
425
  protected pollActivityCompletion = async <
360
426
  T extends keyof Awaited<
361
427
  ReturnType<(typeof this.turnkeyClient)["getActivity"]>