@account-kit/signer 4.60.1 → 4.61.0

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.
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "4.60.1";
1
+ export declare const VERSION = "4.61.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@account-kit/signer",
3
- "version": "4.60.1",
3
+ "version": "4.61.0",
4
4
  "description": "Core interfaces and clients for interfacing with the Alchemy Signer API",
5
5
  "author": "Alchemy",
6
6
  "license": "MIT",
@@ -48,8 +48,8 @@
48
48
  "typescript-template": "*"
49
49
  },
50
50
  "dependencies": {
51
- "@aa-sdk/core": "^4.60.1",
52
- "@account-kit/logging": "^4.60.1",
51
+ "@aa-sdk/core": "^4.61.0",
52
+ "@account-kit/logging": "^4.61.0",
53
53
  "@noble/curves": "^1.9.2",
54
54
  "@noble/hashes": "1.7.1",
55
55
  "@noble/secp256k1": "^2.3.0",
@@ -78,5 +78,5 @@
78
78
  "url": "https://github.com/alchemyplatform/aa-sdk/issues"
79
79
  },
80
80
  "homepage": "https://github.com/alchemyplatform/aa-sdk#readme",
81
- "gitHead": "a12e3557ed0067bfe432d427280b8b4495a8a748"
81
+ "gitHead": "cb25c3a1f44b589de97fefcf930fc373a6ff9bc9"
82
82
  }
package/src/base.ts CHANGED
@@ -960,11 +960,9 @@ export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
960
960
  * ```
961
961
  *
962
962
  * @param {unknown} params export wallet parameters
963
- * @returns {boolean} true if the wallet was exported successfully
963
+ * @returns {Promise<unknown>} the result of the wallet export operation
964
964
  */
965
- exportWallet: (
966
- params: Parameters<(typeof this.inner)["exportWallet"]>[0],
967
- ) => Promise<boolean> = async (params) => {
965
+ exportWallet: TClient["exportWallet"] = async (params) => {
968
966
  return this.inner.exportWallet(params);
969
967
  };
970
968
 
@@ -15,7 +15,6 @@ import { getDefaultProviderCustomization } from "../oauth.js";
15
15
  import type { OauthMode } from "../signer.js";
16
16
  import { base64UrlEncode } from "../utils/base64UrlEncode.js";
17
17
  import { resolveRelativeUrl } from "../utils/resolveRelativeUrl.js";
18
- import { assertNever } from "../utils/typeAssertions.js";
19
18
  import type {
20
19
  AlchemySignerClientEvent,
21
20
  AlchemySignerClientEvents,
@@ -81,7 +80,10 @@ const withHexPrefix = (hex: string) => `0x${hex}` as const;
81
80
  /**
82
81
  * Base class for all Alchemy Signer clients
83
82
  */
84
- export abstract class BaseSignerClient<TExportWalletParams = unknown> {
83
+ export abstract class BaseSignerClient<
84
+ TExportWalletParams = unknown,
85
+ TExportWalletOutput = unknown,
86
+ > {
85
87
  private _user: User | undefined;
86
88
  private connectionConfig: ConnectionConfig;
87
89
  protected turnkeyClient: TurnkeyClient;
@@ -137,29 +139,6 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
137
139
  this.turnkeyClient.stamper = stamper;
138
140
  }
139
141
 
140
- /**
141
- * Exports wallet credentials based on the specified type, either as a SEED_PHRASE or PRIVATE_KEY.
142
- *
143
- * @param {object} params The parameters for exporting the wallet
144
- * @param {ExportWalletStamper} params.exportStamper The stamper used for exporting the wallet
145
- * @param {"SEED_PHRASE" | "PRIVATE_KEY"} params.exportAs Specifies the format for exporting the wallet, either as a SEED_PHRASE or PRIVATE_KEY
146
- * @returns {Promise<boolean>} A promise that resolves to true if the export is successful
147
- */
148
- protected exportWalletInner(params: {
149
- exportStamper: ExportWalletStamper;
150
- exportAs: "SEED_PHRASE" | "PRIVATE_KEY";
151
- }): Promise<boolean> {
152
- const { exportAs } = params;
153
- switch (exportAs) {
154
- case "PRIVATE_KEY":
155
- return this.exportAsPrivateKey(params.exportStamper);
156
- case "SEED_PHRASE":
157
- return this.exportAsSeedPhrase(params.exportStamper);
158
- default:
159
- assertNever(exportAs, `Unknown export mode: ${exportAs}`);
160
- }
161
- }
162
-
163
142
  /**
164
143
  * Authenticates the user by either email or passkey account creation flow. Emits events during the process.
165
144
  *
@@ -265,7 +244,9 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
265
244
 
266
245
  public abstract disconnect(): Promise<void>;
267
246
 
268
- public abstract exportWallet(params: TExportWalletParams): Promise<boolean>;
247
+ public abstract exportWallet(
248
+ params: TExportWalletParams,
249
+ ): Promise<TExportWalletOutput>;
269
250
 
270
251
  public abstract targetPublicKey(): Promise<string>;
271
252
 
@@ -1141,94 +1122,6 @@ export abstract class BaseSignerClient<TExportWalletParams = unknown> {
1141
1122
  // #endregion
1142
1123
 
1143
1124
  // #region PRIVATE METHODS
1144
- private exportAsSeedPhrase = async (stamper: ExportWalletStamper) => {
1145
- if (!this.user) {
1146
- throw new NotAuthenticatedError();
1147
- }
1148
-
1149
- const { wallets } = await this.turnkeyClient.getWallets({
1150
- organizationId: this.user.orgId,
1151
- });
1152
-
1153
- const walletAccounts = await Promise.all(
1154
- wallets.map(({ walletId }) =>
1155
- this.turnkeyClient.getWalletAccounts({
1156
- organizationId: this.user!.orgId,
1157
- walletId,
1158
- }),
1159
- ),
1160
- ).then((x) => x.flatMap((x) => x.accounts));
1161
-
1162
- const walletAccount = walletAccounts.find(
1163
- (x) => x.address === this.user!.address,
1164
- );
1165
-
1166
- if (!walletAccount) {
1167
- throw new Error(
1168
- `Could not find wallet associated with ${this.user.address}`,
1169
- );
1170
- }
1171
-
1172
- const { activity } = await this.turnkeyClient.exportWallet({
1173
- organizationId: this.user.orgId,
1174
- type: "ACTIVITY_TYPE_EXPORT_WALLET",
1175
- timestampMs: Date.now().toString(),
1176
- parameters: {
1177
- walletId: walletAccount!.walletId,
1178
- targetPublicKey: stamper.publicKey()!,
1179
- },
1180
- });
1181
-
1182
- const { exportBundle } = await this.pollActivityCompletion(
1183
- activity,
1184
- this.user.orgId,
1185
- "exportWalletResult",
1186
- );
1187
-
1188
- const result = await stamper.injectWalletExportBundle(
1189
- exportBundle,
1190
- this.user.orgId,
1191
- );
1192
-
1193
- if (!result) {
1194
- throw new Error("Failed to inject wallet export bundle");
1195
- }
1196
-
1197
- return result;
1198
- };
1199
-
1200
- private exportAsPrivateKey = async (stamper: ExportWalletStamper) => {
1201
- if (!this.user) {
1202
- throw new NotAuthenticatedError();
1203
- }
1204
-
1205
- const { activity } = await this.turnkeyClient.exportWalletAccount({
1206
- organizationId: this.user.orgId,
1207
- type: "ACTIVITY_TYPE_EXPORT_WALLET_ACCOUNT",
1208
- timestampMs: Date.now().toString(),
1209
- parameters: {
1210
- address: this.user.address,
1211
- targetPublicKey: stamper.publicKey()!,
1212
- },
1213
- });
1214
-
1215
- const { exportBundle } = await this.pollActivityCompletion(
1216
- activity,
1217
- this.user.orgId,
1218
- "exportWalletAccountResult",
1219
- );
1220
-
1221
- const result = await stamper.injectKeyExportBundle(
1222
- exportBundle,
1223
- this.user.orgId,
1224
- );
1225
-
1226
- if (!result) {
1227
- throw new Error("Failed to inject wallet export bundle");
1228
- }
1229
-
1230
- return result;
1231
- };
1232
1125
 
1233
1126
  /**
1234
1127
  * Returns the authentication url for the selected OAuth Proivder
@@ -5,7 +5,9 @@ import { WebauthnStamper } from "@turnkey/webauthn-stamper";
5
5
  import { z } from "zod";
6
6
  import type { AuthParams } from "../signer.js";
7
7
  import { generateRandomBuffer } from "../utils/generateRandomBuffer.js";
8
- import { BaseSignerClient } from "./base.js";
8
+ import { assertNever } from "../utils/typeAssertions.js";
9
+ import { BaseSignerClient, type ExportWalletStamper } from "./base.js";
10
+ import { NotAuthenticatedError } from "../errors.js";
9
11
  import type {
10
12
  AlchemySignerClientEvents,
11
13
  AuthenticatingEventMetadata,
@@ -22,6 +24,7 @@ import type {
22
24
  GetWebAuthnAttestationResult,
23
25
  IdTokenOnly,
24
26
  SmsAuthParams,
27
+ ExportWalletOutput,
25
28
  } from "./types.js";
26
29
  import { MfaRequiredError } from "../errors.js";
27
30
  import { parseMfaError } from "../utils/parseMfaError.js";
@@ -54,7 +57,10 @@ export type AlchemySignerClientParams = z.input<
54
57
  * A lower level client used by the AlchemySigner used to communicate with
55
58
  * Alchemy's signer service.
56
59
  */
57
- export class AlchemySignerWebClient extends BaseSignerClient<ExportWalletParams> {
60
+ export class AlchemySignerWebClient extends BaseSignerClient<
61
+ ExportWalletParams,
62
+ ExportWalletOutput
63
+ > {
58
64
  private iframeStamper: IframeStamper;
59
65
  private webauthnStamper: WebauthnStamper;
60
66
  oauthCallbackUrl: string;
@@ -389,7 +395,7 @@ export class AlchemySignerWebClient extends BaseSignerClient<ExportWalletParams>
389
395
  public override exportWallet = async ({
390
396
  iframeContainerId,
391
397
  iframeElementId = "turnkey-export-iframe",
392
- }: ExportWalletParams) => {
398
+ }: ExportWalletParams): Promise<ExportWalletOutput> => {
393
399
  const exportWalletIframeStamper = new IframeStamper({
394
400
  iframeContainer: document.getElementById(iframeContainerId),
395
401
  iframeElementId: iframeElementId,
@@ -410,6 +416,29 @@ export class AlchemySignerWebClient extends BaseSignerClient<ExportWalletParams>
410
416
  });
411
417
  };
412
418
 
419
+ /**
420
+ * Exports wallet credentials based on the specified type, either as a SEED_PHRASE or PRIVATE_KEY.
421
+ *
422
+ * @param {object} params The parameters for exporting the wallet
423
+ * @param {ExportWalletStamper} params.exportStamper The stamper used for exporting the wallet
424
+ * @param {"SEED_PHRASE" | "PRIVATE_KEY"} params.exportAs Specifies the format for exporting the wallet, either as a SEED_PHRASE or PRIVATE_KEY
425
+ * @returns {Promise<boolean>} A promise that resolves to true if the export is successful
426
+ */
427
+ protected exportWalletInner(params: {
428
+ exportStamper: ExportWalletStamper;
429
+ exportAs: "SEED_PHRASE" | "PRIVATE_KEY";
430
+ }): Promise<ExportWalletOutput> {
431
+ const { exportAs } = params;
432
+ switch (exportAs) {
433
+ case "PRIVATE_KEY":
434
+ return this.exportAsPrivateKey(params.exportStamper);
435
+ case "SEED_PHRASE":
436
+ return this.exportAsSeedPhrase(params.exportStamper);
437
+ default:
438
+ assertNever(exportAs, `Unknown export mode: ${exportAs}`);
439
+ }
440
+ }
441
+
413
442
  /**
414
443
  * Asynchronous function that clears the user and resets the iframe stamper.
415
444
  *
@@ -748,6 +777,96 @@ export class AlchemySignerWebClient extends BaseSignerClient<ExportWalletParams>
748
777
  ];
749
778
  }
750
779
  }
780
+
781
+ private exportAsSeedPhrase = async (stamper: ExportWalletStamper) => {
782
+ if (!this.user) {
783
+ throw new NotAuthenticatedError();
784
+ }
785
+
786
+ const { wallets } = await this.turnkeyClient.getWallets({
787
+ organizationId: this.user.orgId,
788
+ });
789
+
790
+ const walletAccountResponses = await Promise.all(
791
+ wallets.map(({ walletId }) =>
792
+ this.turnkeyClient.getWalletAccounts({
793
+ organizationId: this.user!.orgId,
794
+ walletId,
795
+ }),
796
+ ),
797
+ );
798
+ const walletAccounts = walletAccountResponses.flatMap((x) => x.accounts);
799
+
800
+ const walletAccount = walletAccounts.find(
801
+ (x) => x.address.toLowerCase() === this.user!.address.toLowerCase(),
802
+ );
803
+
804
+ if (!walletAccount) {
805
+ throw new Error(
806
+ `Could not find wallet associated with ${this.user.address}`,
807
+ );
808
+ }
809
+
810
+ const { activity } = await this.turnkeyClient.exportWallet({
811
+ organizationId: this.user.orgId,
812
+ type: "ACTIVITY_TYPE_EXPORT_WALLET",
813
+ timestampMs: Date.now().toString(),
814
+ parameters: {
815
+ walletId: walletAccount!.walletId,
816
+ targetPublicKey: stamper.publicKey()!,
817
+ },
818
+ });
819
+
820
+ const { exportBundle } = await this.pollActivityCompletion(
821
+ activity,
822
+ this.user.orgId,
823
+ "exportWalletResult",
824
+ );
825
+
826
+ const result = await stamper.injectWalletExportBundle(
827
+ exportBundle,
828
+ this.user.orgId,
829
+ );
830
+
831
+ if (!result) {
832
+ throw new Error("Failed to inject wallet export bundle");
833
+ }
834
+
835
+ return result;
836
+ };
837
+
838
+ private exportAsPrivateKey = async (stamper: ExportWalletStamper) => {
839
+ if (!this.user) {
840
+ throw new NotAuthenticatedError();
841
+ }
842
+
843
+ const { activity } = await this.turnkeyClient.exportWalletAccount({
844
+ organizationId: this.user.orgId,
845
+ type: "ACTIVITY_TYPE_EXPORT_WALLET_ACCOUNT",
846
+ timestampMs: Date.now().toString(),
847
+ parameters: {
848
+ address: this.user.address,
849
+ targetPublicKey: stamper.publicKey()!,
850
+ },
851
+ });
852
+
853
+ const { exportBundle } = await this.pollActivityCompletion(
854
+ activity,
855
+ this.user.orgId,
856
+ "exportWalletAccountResult",
857
+ );
858
+
859
+ const result = await stamper.injectKeyExportBundle(
860
+ exportBundle,
861
+ this.user.orgId,
862
+ );
863
+
864
+ if (!result) {
865
+ throw new Error("Failed to inject wallet export bundle");
866
+ }
867
+
868
+ return result;
869
+ };
751
870
  }
752
871
 
753
872
  /**
@@ -30,6 +30,8 @@ export type ExportWalletParams = {
30
30
  iframeElementId?: string;
31
31
  };
32
32
 
33
+ export type ExportWalletOutput = boolean;
34
+
33
35
  export type CreateAccountParams =
34
36
  | {
35
37
  type: "email";
package/src/version.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  // This file is autogenerated by inject-version.ts. Any changes will be
2
2
  // overwritten on commit!
3
- export const VERSION = "4.60.1";
3
+ export const VERSION = "4.61.0";