@account-kit/signer 4.0.0-beta.3 → 4.0.0-beta.4
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/esm/base.d.ts +33 -1
- package/dist/esm/base.js +81 -7
- package/dist/esm/base.js.map +1 -1
- package/dist/esm/client/base.d.ts +28 -5
- package/dist/esm/client/base.js +25 -1
- package/dist/esm/client/base.js.map +1 -1
- package/dist/esm/client/index.d.ts +78 -5
- package/dist/esm/client/index.js +211 -6
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/client/types.d.ts +25 -0
- package/dist/esm/client/types.js.map +1 -1
- package/dist/esm/oauth.d.ts +18 -0
- package/dist/esm/oauth.js +29 -0
- package/dist/esm/oauth.js.map +1 -0
- package/dist/esm/session/manager.d.ts +3 -2
- package/dist/esm/session/manager.js +28 -15
- package/dist/esm/session/manager.js.map +1 -1
- package/dist/esm/session/types.d.ts +1 -1
- package/dist/esm/session/types.js.map +1 -1
- package/dist/esm/signer.d.ts +39 -7
- package/dist/esm/signer.js.map +1 -1
- package/dist/esm/utils/typeAssertions.d.ts +1 -0
- package/dist/esm/utils/typeAssertions.js +4 -0
- package/dist/esm/utils/typeAssertions.js.map +1 -0
- 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 +33 -1
- package/dist/types/base.d.ts.map +1 -1
- package/dist/types/client/base.d.ts +28 -5
- package/dist/types/client/base.d.ts.map +1 -1
- package/dist/types/client/index.d.ts +78 -5
- package/dist/types/client/index.d.ts.map +1 -1
- package/dist/types/client/types.d.ts +25 -0
- package/dist/types/client/types.d.ts.map +1 -1
- package/dist/types/oauth.d.ts +19 -0
- package/dist/types/oauth.d.ts.map +1 -0
- package/dist/types/session/manager.d.ts +3 -2
- package/dist/types/session/manager.d.ts.map +1 -1
- package/dist/types/session/types.d.ts +1 -1
- package/dist/types/session/types.d.ts.map +1 -1
- package/dist/types/signer.d.ts +39 -7
- package/dist/types/signer.d.ts.map +1 -1
- package/dist/types/utils/typeAssertions.d.ts +2 -0
- package/dist/types/utils/typeAssertions.d.ts.map +1 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +3 -3
- package/src/base.ts +80 -10
- package/src/client/base.ts +31 -3
- package/src/client/index.ts +244 -12
- package/src/client/types.ts +26 -0
- package/src/oauth.ts +38 -0
- package/src/session/manager.ts +45 -19
- package/src/session/types.ts +1 -1
- package/src/signer.ts +15 -1
- package/src/utils/typeAssertions.ts +3 -0
- package/src/version.ts +1 -1
package/dist/esm/base.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type SmartAccountAuthenticator } from "@aa-sdk/core";
|
|
2
2
|
import { type CustomSource, type Hex, type LocalAccount, type SignableMessage, type TypedData, type TypedDataDefinition } from "viem";
|
|
3
3
|
import type { BaseSignerClient } from "./client/base";
|
|
4
|
-
import type { User } from "./client/types";
|
|
4
|
+
import type { OauthConfig, User } from "./client/types";
|
|
5
5
|
import { type SessionManagerParams } from "./session/manager.js";
|
|
6
6
|
import type { AuthParams } from "./signer";
|
|
7
7
|
import { type AlchemySignerEvents } from "./types.js";
|
|
@@ -36,6 +36,36 @@ export declare abstract class BaseAlchemySigner<TClient extends BaseSignerClient
|
|
|
36
36
|
* @returns {() => void} a function to remove the listener
|
|
37
37
|
*/
|
|
38
38
|
on: <E extends keyof AlchemySignerEvents>(event: E, listener: AlchemySignerEvents[E]) => () => void;
|
|
39
|
+
/**
|
|
40
|
+
* Prepares the config needed to use popup-based OAuth login. This must be
|
|
41
|
+
* called before calling `.authenticate` with params `{ type: "oauth", mode:
|
|
42
|
+
* "popup" }`, and is recommended to be called on page load.
|
|
43
|
+
*
|
|
44
|
+
* This method exists because browsers may prevent popups from opening unless
|
|
45
|
+
* triggered by user interaction, and so the OAuth config must already have
|
|
46
|
+
* been fetched at the time a user clicks a social login button.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* import { AlchemyWebSigner } from "@account-kit/signer";
|
|
51
|
+
*
|
|
52
|
+
* const signer = new AlchemyWebSigner({
|
|
53
|
+
* client: {
|
|
54
|
+
* connection: {
|
|
55
|
+
* rpcUrl: "/api/rpc",
|
|
56
|
+
* },
|
|
57
|
+
* iframeConfig: {
|
|
58
|
+
* iframeContainerId: "alchemy-signer-iframe-container",
|
|
59
|
+
* },
|
|
60
|
+
* },
|
|
61
|
+
* });
|
|
62
|
+
*
|
|
63
|
+
* await signer.preparePopupOauth();
|
|
64
|
+
* ```
|
|
65
|
+
* @returns {Promise<OauthConfig>} the config which must be loaded before
|
|
66
|
+
* using popup-based OAuth
|
|
67
|
+
*/
|
|
68
|
+
preparePopupOauth: () => Promise<OauthConfig>;
|
|
39
69
|
/**
|
|
40
70
|
* Authenticate a user with either an email or a passkey and create a session for that user
|
|
41
71
|
*
|
|
@@ -316,5 +346,7 @@ export declare abstract class BaseAlchemySigner<TClient extends BaseSignerClient
|
|
|
316
346
|
toViemAccount: () => LocalAccount;
|
|
317
347
|
private authenticateWithEmail;
|
|
318
348
|
private authenticateWithPasskey;
|
|
349
|
+
private authenticateWithOauth;
|
|
350
|
+
private handleOauthReturn;
|
|
319
351
|
private registerListeners;
|
|
320
352
|
}
|
package/dist/esm/base.js
CHANGED
|
@@ -6,6 +6,7 @@ import { createStore } from "zustand/vanilla";
|
|
|
6
6
|
import { NotAuthenticatedError } from "./errors.js";
|
|
7
7
|
import { SessionManager, } from "./session/manager.js";
|
|
8
8
|
import { AlchemySignerStatus, } from "./types.js";
|
|
9
|
+
import { assertNever } from "./utils/typeAssertions.js";
|
|
9
10
|
/**
|
|
10
11
|
* Base abstract class for Alchemy Signer, providing authentication and session management for smart accounts.
|
|
11
12
|
* Implements the `SmartAccountAuthenticator` interface and handles various signer events.
|
|
@@ -70,10 +71,45 @@ export class BaseAlchemySigner {
|
|
|
70
71
|
case "statusChanged":
|
|
71
72
|
return this.store.subscribe(({ status }) => status, listener, { fireImmediately: true });
|
|
72
73
|
default:
|
|
73
|
-
throw new Error(`
|
|
74
|
+
throw new Error(`Unknown event type ${event}`);
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
});
|
|
78
|
+
/**
|
|
79
|
+
* Prepares the config needed to use popup-based OAuth login. This must be
|
|
80
|
+
* called before calling `.authenticate` with params `{ type: "oauth", mode:
|
|
81
|
+
* "popup" }`, and is recommended to be called on page load.
|
|
82
|
+
*
|
|
83
|
+
* This method exists because browsers may prevent popups from opening unless
|
|
84
|
+
* triggered by user interaction, and so the OAuth config must already have
|
|
85
|
+
* been fetched at the time a user clicks a social login button.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* import { AlchemyWebSigner } from "@account-kit/signer";
|
|
90
|
+
*
|
|
91
|
+
* const signer = new AlchemyWebSigner({
|
|
92
|
+
* client: {
|
|
93
|
+
* connection: {
|
|
94
|
+
* rpcUrl: "/api/rpc",
|
|
95
|
+
* },
|
|
96
|
+
* iframeConfig: {
|
|
97
|
+
* iframeContainerId: "alchemy-signer-iframe-container",
|
|
98
|
+
* },
|
|
99
|
+
* },
|
|
100
|
+
* });
|
|
101
|
+
*
|
|
102
|
+
* await signer.preparePopupOauth();
|
|
103
|
+
* ```
|
|
104
|
+
* @returns {Promise<OauthConfig>} the config which must be loaded before
|
|
105
|
+
* using popup-based OAuth
|
|
106
|
+
*/
|
|
107
|
+
Object.defineProperty(this, "preparePopupOauth", {
|
|
108
|
+
enumerable: true,
|
|
109
|
+
configurable: true,
|
|
110
|
+
writable: true,
|
|
111
|
+
value: () => this.inner.initOauth()
|
|
112
|
+
});
|
|
77
113
|
/**
|
|
78
114
|
* Authenticate a user with either an email or a passkey and create a session for that user
|
|
79
115
|
*
|
|
@@ -106,10 +142,19 @@ export class BaseAlchemySigner {
|
|
|
106
142
|
configurable: true,
|
|
107
143
|
writable: true,
|
|
108
144
|
value: async (params) => {
|
|
109
|
-
|
|
110
|
-
|
|
145
|
+
const { type } = params;
|
|
146
|
+
switch (type) {
|
|
147
|
+
case "email":
|
|
148
|
+
return this.authenticateWithEmail(params);
|
|
149
|
+
case "passkey":
|
|
150
|
+
return this.authenticateWithPasskey(params);
|
|
151
|
+
case "oauth":
|
|
152
|
+
return this.authenticateWithOauth(params);
|
|
153
|
+
case "oauthReturn":
|
|
154
|
+
return this.handleOauthReturn(params);
|
|
155
|
+
default:
|
|
156
|
+
assertNever(type, `Unknown auth type: ${type}`);
|
|
111
157
|
}
|
|
112
|
-
return this.authenticateWithPasskey(params);
|
|
113
158
|
}
|
|
114
159
|
});
|
|
115
160
|
/**
|
|
@@ -468,16 +513,17 @@ export class BaseAlchemySigner {
|
|
|
468
513
|
value: async (params) => {
|
|
469
514
|
if ("email" in params) {
|
|
470
515
|
const existingUser = await this.getUser(params.email);
|
|
516
|
+
const expirationSeconds = Math.floor(this.sessionManager.expirationTimeMs / 1000);
|
|
471
517
|
const { orgId } = existingUser
|
|
472
518
|
? await this.inner.initEmailAuth({
|
|
473
519
|
email: params.email,
|
|
474
|
-
expirationSeconds
|
|
520
|
+
expirationSeconds,
|
|
475
521
|
redirectParams: params.redirectParams,
|
|
476
522
|
})
|
|
477
523
|
: await this.inner.createAccount({
|
|
478
524
|
type: "email",
|
|
479
525
|
email: params.email,
|
|
480
|
-
expirationSeconds
|
|
526
|
+
expirationSeconds,
|
|
481
527
|
redirectParams: params.redirectParams,
|
|
482
528
|
});
|
|
483
529
|
this.sessionManager.setTemporarySession({ orgId });
|
|
@@ -499,9 +545,10 @@ export class BaseAlchemySigner {
|
|
|
499
545
|
this.store.setState({ status: AlchemySignerStatus.DISCONNECTED });
|
|
500
546
|
throw new Error("Could not find email auth init session!");
|
|
501
547
|
}
|
|
502
|
-
const user = await this.inner.
|
|
548
|
+
const user = await this.inner.completeAuthWithBundle({
|
|
503
549
|
bundle: params.bundle,
|
|
504
550
|
orgId: temporarySession.orgId,
|
|
551
|
+
connectedEventName: "connectedEmail",
|
|
505
552
|
});
|
|
506
553
|
return user;
|
|
507
554
|
}
|
|
@@ -540,6 +587,33 @@ export class BaseAlchemySigner {
|
|
|
540
587
|
return user;
|
|
541
588
|
}
|
|
542
589
|
});
|
|
590
|
+
Object.defineProperty(this, "authenticateWithOauth", {
|
|
591
|
+
enumerable: true,
|
|
592
|
+
configurable: true,
|
|
593
|
+
writable: true,
|
|
594
|
+
value: async (args) => {
|
|
595
|
+
const params = {
|
|
596
|
+
...args,
|
|
597
|
+
expirationSeconds: Math.floor(this.sessionManager.expirationTimeMs / 1000),
|
|
598
|
+
};
|
|
599
|
+
if (params.mode === "redirect") {
|
|
600
|
+
return this.inner.oauthWithRedirect(params);
|
|
601
|
+
}
|
|
602
|
+
else {
|
|
603
|
+
return this.inner.oauthWithPopup(params);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
Object.defineProperty(this, "handleOauthReturn", {
|
|
608
|
+
enumerable: true,
|
|
609
|
+
configurable: true,
|
|
610
|
+
writable: true,
|
|
611
|
+
value: ({ bundle, orgId, }) => this.inner.completeAuthWithBundle({
|
|
612
|
+
bundle,
|
|
613
|
+
orgId,
|
|
614
|
+
connectedEventName: "connectedOauth",
|
|
615
|
+
})
|
|
616
|
+
});
|
|
543
617
|
Object.defineProperty(this, "registerListeners", {
|
|
544
618
|
enumerable: true,
|
|
545
619
|
configurable: true,
|
package/dist/esm/base.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/base.ts"],"names":[],"mappings":"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","sourcesContent":["import { takeBytes, type SmartAccountAuthenticator } from \"@aa-sdk/core\";\nimport {\n hashMessage,\n hashTypedData,\n keccak256,\n serializeTransaction,\n type CustomSource,\n type Hex,\n type LocalAccount,\n type SignableMessage,\n type TypedData,\n type TypedDataDefinition,\n} from \"viem\";\nimport { toAccount } from \"viem/accounts\";\nimport type { Mutate, StoreApi } from \"zustand\";\nimport { subscribeWithSelector } from \"zustand/middleware\";\nimport { createStore } from \"zustand/vanilla\";\nimport type { BaseSignerClient } from \"./client/base\";\nimport type { User } from \"./client/types\";\nimport { NotAuthenticatedError } from \"./errors.js\";\nimport {\n SessionManager,\n type SessionManagerParams,\n} from \"./session/manager.js\";\nimport type { AuthParams } from \"./signer\";\nimport {\n AlchemySignerStatus,\n type AlchemySignerEvent,\n type AlchemySignerEvents,\n} from \"./types.js\";\n\nexport interface BaseAlchemySignerParams<TClient extends BaseSignerClient> {\n client: TClient;\n sessionConfig?: Omit<SessionManagerParams, \"client\">;\n}\n\ntype AlchemySignerStore = {\n user: User | null;\n status: AlchemySignerStatus;\n};\n\ntype InternalStore = Mutate<\n StoreApi<AlchemySignerStore>,\n [[\"zustand/subscribeWithSelector\", never]]\n>;\n\n/**\n * Base abstract class for Alchemy Signer, providing authentication and session management for smart accounts.\n * Implements the `SmartAccountAuthenticator` interface and handles various signer events.\n */\nexport abstract class BaseAlchemySigner<TClient extends BaseSignerClient>\n implements SmartAccountAuthenticator<AuthParams, User, TClient>\n{\n signerType: string = \"alchemy-signer\";\n inner: TClient;\n private sessionManager: SessionManager;\n private store: InternalStore;\n\n /**\n * Initializes an instance with the provided client and session configuration.\n * This function sets up the internal store, initializes the session manager,\n * registers listeners and initializes the session manager to manage session state.\n *\n * @param {BaseAlchemySignerParams<TClient>} param0 Object containing the client and session configuration\n * @param {TClient} param0.client The client instance to be used internally\n * @param {SessionConfig} param0.sessionConfig Configuration for managing sessions\n */\n constructor({ client, sessionConfig }: BaseAlchemySignerParams<TClient>) {\n this.inner = client;\n this.store = createStore(\n subscribeWithSelector(\n () =>\n ({\n user: null,\n status: AlchemySignerStatus.INITIALIZING,\n } satisfies AlchemySignerStore)\n )\n );\n // NOTE: it's important that the session manager share a client\n // with the signer. The SessionManager leverages the Signer's client\n // to manage session state.\n this.sessionManager = new SessionManager({\n ...sessionConfig,\n client: this.inner,\n });\n this.store = createStore(\n subscribeWithSelector(\n () =>\n ({\n user: null,\n status: AlchemySignerStatus.INITIALIZING,\n } satisfies AlchemySignerStore)\n )\n );\n // register listeners first\n this.registerListeners();\n // then initialize so that we can catch those events\n this.sessionManager.initialize();\n }\n\n /**\n * Allows you to subscribe to events emitted by the signer\n *\n * @param {AlchemySignerEvent} event the event to subscribe to\n * @param {AlchemySignerEvents[AlchemySignerEvent]} listener the function to run when the event is emitted\n * @returns {() => void} a function to remove the listener\n */\n on = <E extends AlchemySignerEvent>(\n event: E,\n listener: AlchemySignerEvents[E]\n ) => {\n // NOTE: we're using zustand here to handle this because we are able to use the fireImmediately\n // option which deals with a possible race condition where the listener is added after the event\n // is fired. In the Client and SessionManager we use EventEmitter because it's easier to handle internally\n switch (event) {\n case \"connected\":\n return this.store.subscribe(\n ({ status }) => status,\n (status) =>\n status === AlchemySignerStatus.CONNECTED &&\n (listener as AlchemySignerEvents[\"connected\"])(\n this.store.getState().user!\n ),\n { fireImmediately: true }\n );\n case \"disconnected\":\n return this.store.subscribe(\n ({ status }) => status,\n (status) =>\n status === AlchemySignerStatus.DISCONNECTED &&\n (listener as AlchemySignerEvents[\"disconnected\"])(),\n { fireImmediately: true }\n );\n case \"statusChanged\":\n return this.store.subscribe(\n ({ status }) => status,\n listener as AlchemySignerEvents[\"statusChanged\"],\n { fireImmediately: true }\n );\n default:\n throw new Error(`Uknown event type ${event}`);\n }\n };\n\n /**\n * Authenticate a user with either an email or a passkey and create a session for that user\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * const result = await signer.authenticate({\n * type: \"email\",\n * email: \"foo@mail.com\",\n * });\n * ```\n *\n * @param {AuthParams} params - undefined if passkey login, otherwise an object with email and bundle to resolve\n * @returns {Promise<User>} the user that was authenticated\n */\n authenticate: (params: AuthParams) => Promise<User> = async (params) => {\n if (params.type === \"email\") {\n return this.authenticateWithEmail(params);\n }\n\n return this.authenticateWithPasskey(params);\n };\n\n /**\n * Clear a user session and log them out\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * await signer.disconnect();\n * ```\n *\n * @returns {Promise<void>} a promise that resolves when the user is logged out\n */\n disconnect: () => Promise<void> = async () => {\n await this.inner.disconnect();\n };\n\n /**\n * Gets the current logged in user\n * If a user has an ongoing session, it will use that session and\n * try to authenticate\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * // throws if not logged in\n * const user = await signer.getAuthDetails();\n * ```\n *\n * @throws if there is no user logged in\n * @returns {Promise<User>} the current user\n */\n getAuthDetails = async (): Promise<User> => {\n const sessionUser = await this.sessionManager.getSessionUser();\n if (sessionUser != null) {\n return sessionUser;\n }\n\n return this.inner.whoami();\n };\n\n /**\n * Retrieves the address of the current user by calling the `whoami` method on `this.inner`.\n *\n * @returns {Promise<string>} A promise that resolves to the address of the current user.\n */\n getAddress: () => Promise<`0x${string}`> = async () => {\n const { address } = await this.inner.whoami();\n\n return address;\n };\n\n /**\n * Signs a raw message after hashing it.\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * const signature = await signer.signMessage(\"Hello, world!\");\n * ```\n *\n * @param {string} msg the message to be hashed and then signed\n * @returns {Promise<string>} a promise that resolves to the signed message\n */\n signMessage: (msg: SignableMessage) => Promise<`0x${string}`> = async (\n msg\n ) => {\n const messageHash = hashMessage(msg);\n\n return this.inner.signRawMessage(messageHash);\n };\n\n /**\n * Signs a typed message by first hashing it and then signing the hashed message using the `signRawMessage` method.\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * const signature = await signer.signTypedData({\n * domain: {},\n * types: {},\n * primaryType: \"\",\n * message: {},\n * });\n * ```\n *\n * @param {TypedDataDefinition<TTypedData, TPrimaryType>} params The parameters for the typed message to be hashed and signed\n * @returns {Promise<any>} A promise that resolves to the signed message\n */\n signTypedData: <\n const TTypedData extends TypedData | Record<string, unknown>,\n TPrimaryType extends keyof TTypedData | \"EIP712Domain\" = keyof TTypedData\n >(\n params: TypedDataDefinition<TTypedData, TPrimaryType>\n ) => Promise<Hex> = async (params) => {\n const messageHash = hashTypedData(params);\n\n return this.inner.signRawMessage(messageHash);\n };\n\n /**\n * Serializes a transaction, signs it with a raw message, and then returns the serialized transaction with the signature.\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * const tx = await signer.signTransaction({\n * to: \"0x1234\",\n * value: \"0x1234\",\n * data: \"0x1234\",\n * });\n * ```\n *\n * @param {Transaction} tx the transaction to be serialized and signed\n * @param {{serializer?: SerializeTransactionFn}} args options for serialization\n * @param {() => Hex} [args.serializer] an optional serializer function. If not provided, the default `serializeTransaction` function will be used\n * @returns {Promise<string>} a promise that resolves to the serialized transaction with the signature\n */\n signTransaction: CustomSource[\"signTransaction\"] = async (tx, args) => {\n const serializeFn = args?.serializer ?? serializeTransaction;\n const serializedTx = serializeFn(tx);\n const signatureHex = await this.inner.signRawMessage(\n keccak256(serializedTx)\n );\n\n const signature = {\n r: takeBytes(signatureHex, { count: 32 }),\n s: takeBytes(signatureHex, { count: 32, offset: 32 }),\n v: BigInt(takeBytes(signatureHex, { count: 1, offset: 64 })),\n };\n\n return serializeFn(tx, signature);\n };\n\n /**\n * Unauthenticated call to look up a user's organizationId by email\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * const result = await signer.getUser(\"foo@mail.com\");\n * ```\n *\n * @param {string} email the email to lookup\n * @returns {Promise<{orgId: string}>} the organization id for the user if they exist\n */\n getUser: (email: string) => Promise<{ orgId: string } | null> = async (\n email\n ) => {\n const result = await this.inner.lookupUserByEmail(email);\n\n if (result.orgId == null) {\n return null;\n }\n\n return {\n orgId: result.orgId,\n };\n };\n\n /**\n * Adds a passkey to the user's account\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * const result = await signer.addPasskey()\n * ```\n *\n * @param {CredentialCreationOptions | undefined} params optional parameters for the passkey creation\n * @returns {Promise<string[]>} an array of the authenticator ids added to the user\n */\n addPasskey: (params?: CredentialCreationOptions) => Promise<string[]> =\n async (params) => {\n return this.inner.addPasskey(params ?? {});\n };\n\n /**\n * Used to export the wallet for a given user\n * If the user is authenticated with an Email, this will return a seed phrase\n * If the user is authenticated with a Passkey, this will return a private key\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * // the params passed to this are different based on the specific signer\n * const result = signer.exportWallet()\n * ```\n *\n * @param {unknown} params export wallet parameters\n * @returns {boolean} true if the wallet was exported successfully\n */\n exportWallet: (\n params: Parameters<(typeof this.inner)[\"exportWallet\"]>[0]\n ) => Promise<boolean> = async (params) => {\n return this.inner.exportWallet(params);\n };\n\n /**\n * This method lets you adapt your AlchemySigner to a viem LocalAccount, which\n * will let you use the signer as an EOA directly.\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * const account = signer.toViemAccount();\n * ```\n *\n * @throws if your signer is not authenticated\n * @returns {LocalAccount} a LocalAccount object that can be used with viem's wallet client\n */\n toViemAccount = (): LocalAccount => {\n // if we want this method to be synchronous, then we need to do this check here\n // otherwise we can use the sessionManager to get the user\n if (!this.inner.getUser()) {\n throw new NotAuthenticatedError();\n }\n\n return toAccount({\n address: this.inner.getUser()!.address,\n signMessage: (msg) => this.signMessage(msg.message),\n signTypedData: <\n const typedData extends TypedData | Record<string, unknown>,\n primaryType extends keyof typedData | \"EIP712Domain\" = keyof typedData\n >(\n typedDataDefinition: TypedDataDefinition<typedData, primaryType>\n ) => this.signTypedData<typedData, primaryType>(typedDataDefinition),\n signTransaction: this.signTransaction,\n });\n };\n\n private authenticateWithEmail = async (\n params: Extract<AuthParams, { type: \"email\" }>\n ): Promise<User> => {\n if (\"email\" in params) {\n const existingUser = await this.getUser(params.email);\n\n const { orgId } = existingUser\n ? await this.inner.initEmailAuth({\n email: params.email,\n expirationSeconds: this.sessionManager.expirationTimeMs,\n redirectParams: params.redirectParams,\n })\n : await this.inner.createAccount({\n type: \"email\",\n email: params.email,\n expirationSeconds: this.sessionManager.expirationTimeMs,\n redirectParams: params.redirectParams,\n });\n\n this.sessionManager.setTemporarySession({ orgId });\n this.store.setState({ status: AlchemySignerStatus.AWAITING_EMAIL_AUTH });\n\n // We wait for the session manager to emit a connected event if\n // cross tab sessions are permitted\n return new Promise<User>((resolve) => {\n const removeListener = this.sessionManager.on(\n \"connected\",\n (session) => {\n resolve(session.user);\n removeListener();\n }\n );\n });\n } else {\n const temporarySession = params.orgId\n ? { orgId: params.orgId }\n : this.sessionManager.getTemporarySession();\n\n if (!temporarySession) {\n this.store.setState({ status: AlchemySignerStatus.DISCONNECTED });\n throw new Error(\"Could not find email auth init session!\");\n }\n\n const user = await this.inner.completeEmailAuth({\n bundle: params.bundle,\n orgId: temporarySession.orgId,\n });\n\n return user;\n }\n };\n\n private authenticateWithPasskey = async (\n args: Extract<AuthParams, { type: \"passkey\" }>\n ) => {\n let user: User;\n const shouldCreateNew = async () => {\n if (\"email\" in args) {\n const existingUser = await this.getUser(args.email);\n return existingUser == null;\n }\n\n return args.createNew;\n };\n\n if (await shouldCreateNew()) {\n const result = await this.inner.createAccount(\n args as Extract<\n AuthParams,\n { type: \"passkey\" } & ({ email: string } | { createNew: true })\n >\n );\n // account creation for passkeys returns the whoami response so we don't have to\n // call it again after signup\n user = {\n address: result.address!,\n userId: result.userId!,\n orgId: result.orgId,\n };\n } else {\n user = await this.inner.lookupUserWithPasskey();\n if (!user) {\n this.store.setState({ status: AlchemySignerStatus.DISCONNECTED });\n throw new Error(\"No user found\");\n }\n }\n\n return user;\n };\n\n private registerListeners = () => {\n this.sessionManager.on(\"connected\", (session) => {\n this.store.setState({\n user: session.user,\n status: AlchemySignerStatus.CONNECTED,\n });\n });\n\n this.sessionManager.on(\"disconnected\", () => {\n this.store.setState({\n user: null,\n status: AlchemySignerStatus.DISCONNECTED,\n });\n });\n\n this.sessionManager.on(\"initialized\", () => {\n this.store.setState((state) => ({\n status: state.user\n ? AlchemySignerStatus.CONNECTED\n : AlchemySignerStatus.DISCONNECTED,\n }));\n });\n\n this.inner.on(\"authenticating\", () => {\n this.store.setState({ status: AlchemySignerStatus.AUTHENTICATING });\n });\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/base.ts"],"names":[],"mappings":"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","sourcesContent":["import { takeBytes, type SmartAccountAuthenticator } from \"@aa-sdk/core\";\nimport {\n hashMessage,\n hashTypedData,\n keccak256,\n serializeTransaction,\n type CustomSource,\n type Hex,\n type LocalAccount,\n type SignableMessage,\n type TypedData,\n type TypedDataDefinition,\n} from \"viem\";\nimport { toAccount } from \"viem/accounts\";\nimport type { Mutate, StoreApi } from \"zustand\";\nimport { subscribeWithSelector } from \"zustand/middleware\";\nimport { createStore } from \"zustand/vanilla\";\nimport type { BaseSignerClient } from \"./client/base\";\nimport type { OauthConfig, OauthParams, User } from \"./client/types\";\nimport { NotAuthenticatedError } from \"./errors.js\";\nimport {\n SessionManager,\n type SessionManagerParams,\n} from \"./session/manager.js\";\nimport type { AuthParams } from \"./signer\";\nimport {\n AlchemySignerStatus,\n type AlchemySignerEvent,\n type AlchemySignerEvents,\n} from \"./types.js\";\nimport { assertNever } from \"./utils/typeAssertions.js\";\n\nexport interface BaseAlchemySignerParams<TClient extends BaseSignerClient> {\n client: TClient;\n sessionConfig?: Omit<SessionManagerParams, \"client\">;\n}\n\ntype AlchemySignerStore = {\n user: User | null;\n status: AlchemySignerStatus;\n};\n\ntype InternalStore = Mutate<\n StoreApi<AlchemySignerStore>,\n [[\"zustand/subscribeWithSelector\", never]]\n>;\n\n/**\n * Base abstract class for Alchemy Signer, providing authentication and session management for smart accounts.\n * Implements the `SmartAccountAuthenticator` interface and handles various signer events.\n */\nexport abstract class BaseAlchemySigner<TClient extends BaseSignerClient>\n implements SmartAccountAuthenticator<AuthParams, User, TClient>\n{\n signerType: string = \"alchemy-signer\";\n inner: TClient;\n private sessionManager: SessionManager;\n private store: InternalStore;\n\n /**\n * Initializes an instance with the provided client and session configuration.\n * This function sets up the internal store, initializes the session manager,\n * registers listeners and initializes the session manager to manage session state.\n *\n * @param {BaseAlchemySignerParams<TClient>} param0 Object containing the client and session configuration\n * @param {TClient} param0.client The client instance to be used internally\n * @param {SessionConfig} param0.sessionConfig Configuration for managing sessions\n */\n constructor({ client, sessionConfig }: BaseAlchemySignerParams<TClient>) {\n this.inner = client;\n this.store = createStore(\n subscribeWithSelector(\n () =>\n ({\n user: null,\n status: AlchemySignerStatus.INITIALIZING,\n } satisfies AlchemySignerStore)\n )\n );\n // NOTE: it's important that the session manager share a client\n // with the signer. The SessionManager leverages the Signer's client\n // to manage session state.\n this.sessionManager = new SessionManager({\n ...sessionConfig,\n client: this.inner,\n });\n this.store = createStore(\n subscribeWithSelector(\n () =>\n ({\n user: null,\n status: AlchemySignerStatus.INITIALIZING,\n } satisfies AlchemySignerStore)\n )\n );\n // register listeners first\n this.registerListeners();\n // then initialize so that we can catch those events\n this.sessionManager.initialize();\n }\n\n /**\n * Allows you to subscribe to events emitted by the signer\n *\n * @param {AlchemySignerEvent} event the event to subscribe to\n * @param {AlchemySignerEvents[AlchemySignerEvent]} listener the function to run when the event is emitted\n * @returns {() => void} a function to remove the listener\n */\n on = <E extends AlchemySignerEvent>(\n event: E,\n listener: AlchemySignerEvents[E]\n ) => {\n // NOTE: we're using zustand here to handle this because we are able to use the fireImmediately\n // option which deals with a possible race condition where the listener is added after the event\n // is fired. In the Client and SessionManager we use EventEmitter because it's easier to handle internally\n switch (event) {\n case \"connected\":\n return this.store.subscribe(\n ({ status }) => status,\n (status) =>\n status === AlchemySignerStatus.CONNECTED &&\n (listener as AlchemySignerEvents[\"connected\"])(\n this.store.getState().user!\n ),\n { fireImmediately: true }\n );\n case \"disconnected\":\n return this.store.subscribe(\n ({ status }) => status,\n (status) =>\n status === AlchemySignerStatus.DISCONNECTED &&\n (listener as AlchemySignerEvents[\"disconnected\"])(),\n { fireImmediately: true }\n );\n case \"statusChanged\":\n return this.store.subscribe(\n ({ status }) => status,\n listener as AlchemySignerEvents[\"statusChanged\"],\n { fireImmediately: true }\n );\n default:\n throw new Error(`Unknown event type ${event}`);\n }\n };\n\n /**\n * Prepares the config needed to use popup-based OAuth login. This must be\n * called before calling `.authenticate` with params `{ type: \"oauth\", mode:\n * \"popup\" }`, and is recommended to be called on page load.\n *\n * This method exists because browsers may prevent popups from opening unless\n * triggered by user interaction, and so the OAuth config must already have\n * been fetched at the time a user clicks a social login button.\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * await signer.preparePopupOauth();\n * ```\n * @returns {Promise<OauthConfig>} the config which must be loaded before\n * using popup-based OAuth\n */\n preparePopupOauth = (): Promise<OauthConfig> => this.inner.initOauth();\n\n /**\n * Authenticate a user with either an email or a passkey and create a session for that user\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * const result = await signer.authenticate({\n * type: \"email\",\n * email: \"foo@mail.com\",\n * });\n * ```\n *\n * @param {AuthParams} params - undefined if passkey login, otherwise an object with email and bundle to resolve\n * @returns {Promise<User>} the user that was authenticated\n */\n authenticate: (params: AuthParams) => Promise<User> = async (params) => {\n const { type } = params;\n switch (type) {\n case \"email\":\n return this.authenticateWithEmail(params);\n case \"passkey\":\n return this.authenticateWithPasskey(params);\n case \"oauth\":\n return this.authenticateWithOauth(params);\n case \"oauthReturn\":\n return this.handleOauthReturn(params);\n default:\n assertNever(type, `Unknown auth type: ${type}`);\n }\n };\n\n /**\n * Clear a user session and log them out\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * await signer.disconnect();\n * ```\n *\n * @returns {Promise<void>} a promise that resolves when the user is logged out\n */\n disconnect: () => Promise<void> = async () => {\n await this.inner.disconnect();\n };\n\n /**\n * Gets the current logged in user\n * If a user has an ongoing session, it will use that session and\n * try to authenticate\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * // throws if not logged in\n * const user = await signer.getAuthDetails();\n * ```\n *\n * @throws if there is no user logged in\n * @returns {Promise<User>} the current user\n */\n getAuthDetails = async (): Promise<User> => {\n const sessionUser = await this.sessionManager.getSessionUser();\n if (sessionUser != null) {\n return sessionUser;\n }\n\n return this.inner.whoami();\n };\n\n /**\n * Retrieves the address of the current user by calling the `whoami` method on `this.inner`.\n *\n * @returns {Promise<string>} A promise that resolves to the address of the current user.\n */\n getAddress: () => Promise<`0x${string}`> = async () => {\n const { address } = await this.inner.whoami();\n\n return address;\n };\n\n /**\n * Signs a raw message after hashing it.\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * const signature = await signer.signMessage(\"Hello, world!\");\n * ```\n *\n * @param {string} msg the message to be hashed and then signed\n * @returns {Promise<string>} a promise that resolves to the signed message\n */\n signMessage: (msg: SignableMessage) => Promise<`0x${string}`> = async (\n msg\n ) => {\n const messageHash = hashMessage(msg);\n\n return this.inner.signRawMessage(messageHash);\n };\n\n /**\n * Signs a typed message by first hashing it and then signing the hashed message using the `signRawMessage` method.\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * const signature = await signer.signTypedData({\n * domain: {},\n * types: {},\n * primaryType: \"\",\n * message: {},\n * });\n * ```\n *\n * @param {TypedDataDefinition<TTypedData, TPrimaryType>} params The parameters for the typed message to be hashed and signed\n * @returns {Promise<any>} A promise that resolves to the signed message\n */\n signTypedData: <\n const TTypedData extends TypedData | Record<string, unknown>,\n TPrimaryType extends keyof TTypedData | \"EIP712Domain\" = keyof TTypedData\n >(\n params: TypedDataDefinition<TTypedData, TPrimaryType>\n ) => Promise<Hex> = async (params) => {\n const messageHash = hashTypedData(params);\n\n return this.inner.signRawMessage(messageHash);\n };\n\n /**\n * Serializes a transaction, signs it with a raw message, and then returns the serialized transaction with the signature.\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * const tx = await signer.signTransaction({\n * to: \"0x1234\",\n * value: \"0x1234\",\n * data: \"0x1234\",\n * });\n * ```\n *\n * @param {Transaction} tx the transaction to be serialized and signed\n * @param {{serializer?: SerializeTransactionFn}} args options for serialization\n * @param {() => Hex} [args.serializer] an optional serializer function. If not provided, the default `serializeTransaction` function will be used\n * @returns {Promise<string>} a promise that resolves to the serialized transaction with the signature\n */\n signTransaction: CustomSource[\"signTransaction\"] = async (tx, args) => {\n const serializeFn = args?.serializer ?? serializeTransaction;\n const serializedTx = serializeFn(tx);\n const signatureHex = await this.inner.signRawMessage(\n keccak256(serializedTx)\n );\n\n const signature = {\n r: takeBytes(signatureHex, { count: 32 }),\n s: takeBytes(signatureHex, { count: 32, offset: 32 }),\n v: BigInt(takeBytes(signatureHex, { count: 1, offset: 64 })),\n };\n\n return serializeFn(tx, signature);\n };\n\n /**\n * Unauthenticated call to look up a user's organizationId by email\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * const result = await signer.getUser(\"foo@mail.com\");\n * ```\n *\n * @param {string} email the email to lookup\n * @returns {Promise<{orgId: string}>} the organization id for the user if they exist\n */\n getUser: (email: string) => Promise<{ orgId: string } | null> = async (\n email\n ) => {\n const result = await this.inner.lookupUserByEmail(email);\n\n if (result.orgId == null) {\n return null;\n }\n\n return {\n orgId: result.orgId,\n };\n };\n\n /**\n * Adds a passkey to the user's account\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * const result = await signer.addPasskey()\n * ```\n *\n * @param {CredentialCreationOptions | undefined} params optional parameters for the passkey creation\n * @returns {Promise<string[]>} an array of the authenticator ids added to the user\n */\n addPasskey: (params?: CredentialCreationOptions) => Promise<string[]> =\n async (params) => {\n return this.inner.addPasskey(params ?? {});\n };\n\n /**\n * Used to export the wallet for a given user\n * If the user is authenticated with an Email, this will return a seed phrase\n * If the user is authenticated with a Passkey, this will return a private key\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * // the params passed to this are different based on the specific signer\n * const result = signer.exportWallet()\n * ```\n *\n * @param {unknown} params export wallet parameters\n * @returns {boolean} true if the wallet was exported successfully\n */\n exportWallet: (\n params: Parameters<(typeof this.inner)[\"exportWallet\"]>[0]\n ) => Promise<boolean> = async (params) => {\n return this.inner.exportWallet(params);\n };\n\n /**\n * This method lets you adapt your AlchemySigner to a viem LocalAccount, which\n * will let you use the signer as an EOA directly.\n *\n * @example\n * ```ts\n * import { AlchemyWebSigner } from \"@account-kit/signer\";\n *\n * const signer = new AlchemyWebSigner({\n * client: {\n * connection: {\n * rpcUrl: \"/api/rpc\",\n * },\n * iframeConfig: {\n * iframeContainerId: \"alchemy-signer-iframe-container\",\n * },\n * },\n * });\n *\n * const account = signer.toViemAccount();\n * ```\n *\n * @throws if your signer is not authenticated\n * @returns {LocalAccount} a LocalAccount object that can be used with viem's wallet client\n */\n toViemAccount = (): LocalAccount => {\n // if we want this method to be synchronous, then we need to do this check here\n // otherwise we can use the sessionManager to get the user\n if (!this.inner.getUser()) {\n throw new NotAuthenticatedError();\n }\n\n return toAccount({\n address: this.inner.getUser()!.address,\n signMessage: (msg) => this.signMessage(msg.message),\n signTypedData: <\n const typedData extends TypedData | Record<string, unknown>,\n primaryType extends keyof typedData | \"EIP712Domain\" = keyof typedData\n >(\n typedDataDefinition: TypedDataDefinition<typedData, primaryType>\n ) => this.signTypedData<typedData, primaryType>(typedDataDefinition),\n signTransaction: this.signTransaction,\n });\n };\n\n private authenticateWithEmail = async (\n params: Extract<AuthParams, { type: \"email\" }>\n ): Promise<User> => {\n if (\"email\" in params) {\n const existingUser = await this.getUser(params.email);\n const expirationSeconds = Math.floor(\n this.sessionManager.expirationTimeMs / 1000\n );\n\n const { orgId } = existingUser\n ? await this.inner.initEmailAuth({\n email: params.email,\n expirationSeconds,\n redirectParams: params.redirectParams,\n })\n : await this.inner.createAccount({\n type: \"email\",\n email: params.email,\n expirationSeconds,\n redirectParams: params.redirectParams,\n });\n\n this.sessionManager.setTemporarySession({ orgId });\n this.store.setState({ status: AlchemySignerStatus.AWAITING_EMAIL_AUTH });\n\n // We wait for the session manager to emit a connected event if\n // cross tab sessions are permitted\n return new Promise<User>((resolve) => {\n const removeListener = this.sessionManager.on(\n \"connected\",\n (session) => {\n resolve(session.user);\n removeListener();\n }\n );\n });\n } else {\n const temporarySession = params.orgId\n ? { orgId: params.orgId }\n : this.sessionManager.getTemporarySession();\n\n if (!temporarySession) {\n this.store.setState({ status: AlchemySignerStatus.DISCONNECTED });\n throw new Error(\"Could not find email auth init session!\");\n }\n\n const user = await this.inner.completeAuthWithBundle({\n bundle: params.bundle,\n orgId: temporarySession.orgId,\n connectedEventName: \"connectedEmail\",\n });\n\n return user;\n }\n };\n\n private authenticateWithPasskey = async (\n args: Extract<AuthParams, { type: \"passkey\" }>\n ): Promise<User> => {\n let user: User;\n const shouldCreateNew = async () => {\n if (\"email\" in args) {\n const existingUser = await this.getUser(args.email);\n return existingUser == null;\n }\n\n return args.createNew;\n };\n\n if (await shouldCreateNew()) {\n const result = await this.inner.createAccount(\n args as Extract<\n AuthParams,\n { type: \"passkey\" } & ({ email: string } | { createNew: true })\n >\n );\n // account creation for passkeys returns the whoami response so we don't have to\n // call it again after signup\n user = {\n address: result.address!,\n userId: result.userId!,\n orgId: result.orgId,\n };\n } else {\n user = await this.inner.lookupUserWithPasskey();\n if (!user) {\n this.store.setState({ status: AlchemySignerStatus.DISCONNECTED });\n throw new Error(\"No user found\");\n }\n }\n\n return user;\n };\n\n private authenticateWithOauth = async (\n args: Extract<AuthParams, { type: \"oauth\" }>\n ): Promise<User> => {\n const params: OauthParams = {\n ...args,\n expirationSeconds: Math.floor(\n this.sessionManager.expirationTimeMs / 1000\n ),\n };\n if (params.mode === \"redirect\") {\n return this.inner.oauthWithRedirect(params);\n } else {\n return this.inner.oauthWithPopup(params);\n }\n };\n\n private handleOauthReturn = ({\n bundle,\n orgId,\n }: Extract<AuthParams, { type: \"oauthReturn\" }>): Promise<User> =>\n this.inner.completeAuthWithBundle({\n bundle,\n orgId,\n connectedEventName: \"connectedOauth\",\n });\n\n private registerListeners = () => {\n this.sessionManager.on(\"connected\", (session) => {\n this.store.setState({\n user: session.user,\n status: AlchemySignerStatus.CONNECTED,\n });\n });\n\n this.sessionManager.on(\"disconnected\", () => {\n this.store.setState({\n user: null,\n status: AlchemySignerStatus.DISCONNECTED,\n });\n });\n\n this.sessionManager.on(\"initialized\", () => {\n this.store.setState((state) => ({\n status: state.user\n ? AlchemySignerStatus.CONNECTED\n : AlchemySignerStatus.DISCONNECTED,\n }));\n });\n\n this.inner.on(\"authenticating\", () => {\n this.store.setState({ status: AlchemySignerStatus.AUTHENTICATING });\n });\n };\n}\n"]}
|
|
@@ -2,7 +2,7 @@ import { type ConnectionConfig } from "@aa-sdk/core";
|
|
|
2
2
|
import { TurnkeyClient, type TSignedRequest } from "@turnkey/http";
|
|
3
3
|
import EventEmitter from "eventemitter3";
|
|
4
4
|
import type { Hex } from "viem";
|
|
5
|
-
import type { AlchemySignerClientEvents, CreateAccountParams, EmailAuthParams, GetWebAuthnAttestationResult, SignerBody, SignerResponse, SignupResponse, User } from "./types.js";
|
|
5
|
+
import type { AlchemySignerClientEvents, CreateAccountParams, EmailAuthParams, GetWebAuthnAttestationResult, OauthConfig, OauthParams, SignerBody, SignerResponse, SignupResponse, User } from "./types.js";
|
|
6
6
|
export interface BaseSignerClientParams {
|
|
7
7
|
stamper: TurnkeyClient["stamper"];
|
|
8
8
|
connection: ConnectionConfig;
|
|
@@ -23,12 +23,19 @@ export declare abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
23
23
|
protected turnkeyClient: TurnkeyClient;
|
|
24
24
|
protected rootOrg: string;
|
|
25
25
|
protected eventEmitter: EventEmitter<AlchemySignerClientEvents>;
|
|
26
|
+
protected oauthConfig: OauthConfig | undefined;
|
|
26
27
|
/**
|
|
27
28
|
* Create a new instance of the Alchemy Signer client
|
|
28
29
|
*
|
|
29
30
|
* @param {BaseSignerClientParams} params the parameters required to create the client
|
|
30
31
|
*/
|
|
31
32
|
constructor(params: BaseSignerClientParams);
|
|
33
|
+
/**
|
|
34
|
+
* Asynchronously fetches and sets the OAuth configuration.
|
|
35
|
+
*
|
|
36
|
+
* @returns {Promise<OauthConfig>} A promise that resolves to the OAuth configuration
|
|
37
|
+
*/
|
|
38
|
+
initOauth: () => Promise<OauthConfig>;
|
|
32
39
|
protected get user(): User | undefined;
|
|
33
40
|
protected set user(user: User | undefined);
|
|
34
41
|
/**
|
|
@@ -53,13 +60,21 @@ export declare abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
53
60
|
abstract initEmailAuth(params: Omit<EmailAuthParams, "targetPublicKey">): Promise<{
|
|
54
61
|
orgId: string;
|
|
55
62
|
}>;
|
|
56
|
-
abstract
|
|
63
|
+
abstract completeAuthWithBundle(params: {
|
|
57
64
|
bundle: string;
|
|
58
65
|
orgId: string;
|
|
66
|
+
connectedEventName: keyof AlchemySignerClientEvents;
|
|
59
67
|
}): Promise<User>;
|
|
68
|
+
abstract oauthWithRedirect(args: Extract<OauthParams, {
|
|
69
|
+
mode: "redirect";
|
|
70
|
+
}>): Promise<never>;
|
|
71
|
+
abstract oauthWithPopup(args: Extract<OauthParams, {
|
|
72
|
+
mode: "popup";
|
|
73
|
+
}>): Promise<User>;
|
|
60
74
|
abstract disconnect(): Promise<void>;
|
|
61
75
|
abstract exportWallet(params: TExportWalletParams): Promise<boolean>;
|
|
62
76
|
abstract lookupUserWithPasskey(user?: User): Promise<User>;
|
|
77
|
+
protected abstract getOauthConfig(): Promise<OauthConfig>;
|
|
63
78
|
protected abstract getWebAuthnAttestation(options: CredentialCreationOptions, userDetails?: {
|
|
64
79
|
username: string;
|
|
65
80
|
}): Promise<GetWebAuthnAttestationResult>;
|
|
@@ -129,7 +144,7 @@ export declare abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
129
144
|
* @param {SignerBody<R>} body The request body containing the data to be sent
|
|
130
145
|
* @returns {Promise<SignerResponse<R>>} A promise that resolves to the response from the signer
|
|
131
146
|
*/
|
|
132
|
-
request: <R extends "/v1/signup" | "/v1/whoami" | "/v1/auth" | "/v1/lookup" | "/v1/sign-payload">(route: R, body: SignerBody<R>) => Promise<SignerResponse<R>>;
|
|
147
|
+
request: <R extends "/v1/signup" | "/v1/whoami" | "/v1/auth" | "/v1/lookup" | "/v1/sign-payload" | "/v1/prepare-oauth">(route: R, body: SignerBody<R>) => Promise<SignerResponse<R>>;
|
|
133
148
|
private exportAsSeedPhrase;
|
|
134
149
|
private exportAsPrivateKey;
|
|
135
150
|
protected pollActivityCompletion: <T extends "createOrganizationResult" | "createAuthenticatorsResult" | "createUsersResult" | "createPrivateKeysResult" | "createInvitationsResult" | "acceptInvitationResult" | "signRawPayloadResult" | "createPolicyResult" | "disablePrivateKeyResult" | "deleteUsersResult" | "deleteAuthenticatorsResult" | "deleteInvitationResult" | "deleteOrganizationResult" | "deletePolicyResult" | "createUserTagResult" | "deleteUserTagsResult" | "signTransactionResult" | "deleteApiKeysResult" | "createApiKeysResult" | "createPrivateKeyTagResult" | "deletePrivateKeyTagsResult" | "setPaymentMethodResult" | "activateBillingTierResult" | "deletePaymentMethodResult" | "createApiOnlyUsersResult" | "updateRootQuorumResult" | "updateUserTagResult" | "updatePrivateKeyTagResult" | "createSubOrganizationResult" | "updateAllowedOriginsResult" | "createPrivateKeysResultV2" | "updateUserResult" | "updatePolicyResult" | "createSubOrganizationResultV3" | "createWalletResult" | "createWalletAccountsResult" | "initUserEmailRecoveryResult" | "recoverUserResult" | "setOrganizationFeatureResult" | "removeOrganizationFeatureResult" | "exportPrivateKeyResult" | "exportWalletResult" | "createSubOrganizationResultV4" | "emailAuthResult" | "exportWalletAccountResult">(activity: Awaited<ReturnType<(typeof this.turnkeyClient)["getActivity"]>>["activity"], organizationId: string, resultKey: T) => Promise<NonNullable<{
|
|
@@ -236,7 +251,11 @@ export declare abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
236
251
|
privateKeys: {
|
|
237
252
|
privateKeyId?: string | undefined;
|
|
238
253
|
addresses?: {
|
|
239
|
-
format?: "ADDRESS_FORMAT_UNCOMPRESSED" | "ADDRESS_FORMAT_COMPRESSED" | "ADDRESS_FORMAT_ETHEREUM" | "ADDRESS_FORMAT_SOLANA" | "ADDRESS_FORMAT_COSMOS" | undefined;
|
|
254
|
+
format?: "ADDRESS_FORMAT_UNCOMPRESSED" | "ADDRESS_FORMAT_COMPRESSED" | "ADDRESS_FORMAT_ETHEREUM" | "ADDRESS_FORMAT_SOLANA" | "ADDRESS_FORMAT_COSMOS" | undefined; /**
|
|
255
|
+
* Returns the current user or null if no user is set.
|
|
256
|
+
*
|
|
257
|
+
* @returns {User | null} the current user object or null if no user is available
|
|
258
|
+
*/
|
|
240
259
|
address?: string | undefined;
|
|
241
260
|
}[] | undefined;
|
|
242
261
|
}[];
|
|
@@ -252,7 +271,11 @@ export declare abstract class BaseSignerClient<TExportWalletParams = unknown> {
|
|
|
252
271
|
privateKeys: {
|
|
253
272
|
privateKeyId?: string | undefined;
|
|
254
273
|
addresses?: {
|
|
255
|
-
format?: "ADDRESS_FORMAT_UNCOMPRESSED" | "ADDRESS_FORMAT_COMPRESSED" | "ADDRESS_FORMAT_ETHEREUM" | "ADDRESS_FORMAT_SOLANA" | "ADDRESS_FORMAT_COSMOS" | undefined;
|
|
274
|
+
format?: "ADDRESS_FORMAT_UNCOMPRESSED" | "ADDRESS_FORMAT_COMPRESSED" | "ADDRESS_FORMAT_ETHEREUM" | "ADDRESS_FORMAT_SOLANA" | "ADDRESS_FORMAT_COSMOS" | undefined; /**
|
|
275
|
+
* Returns the current user or null if no user is set.
|
|
276
|
+
*
|
|
277
|
+
* @returns {User | null} the current user object or null if no user is available
|
|
278
|
+
*/
|
|
256
279
|
address?: string | undefined;
|
|
257
280
|
}[] | undefined;
|
|
258
281
|
}[];
|
package/dist/esm/client/base.js
CHANGED
|
@@ -3,6 +3,7 @@ import { TurnkeyClient } from "@turnkey/http";
|
|
|
3
3
|
import EventEmitter from "eventemitter3";
|
|
4
4
|
import { NotAuthenticatedError } from "../errors.js";
|
|
5
5
|
import { base64UrlEncode } from "../utils/base64UrlEncode.js";
|
|
6
|
+
import { assertNever } from "../utils/typeAssertions.js";
|
|
6
7
|
/**
|
|
7
8
|
* Base class for all Alchemy Signer clients
|
|
8
9
|
*/
|
|
@@ -43,6 +44,26 @@ export class BaseSignerClient {
|
|
|
43
44
|
writable: true,
|
|
44
45
|
value: void 0
|
|
45
46
|
});
|
|
47
|
+
Object.defineProperty(this, "oauthConfig", {
|
|
48
|
+
enumerable: true,
|
|
49
|
+
configurable: true,
|
|
50
|
+
writable: true,
|
|
51
|
+
value: void 0
|
|
52
|
+
});
|
|
53
|
+
/**
|
|
54
|
+
* Asynchronously fetches and sets the OAuth configuration.
|
|
55
|
+
*
|
|
56
|
+
* @returns {Promise<OauthConfig>} A promise that resolves to the OAuth configuration
|
|
57
|
+
*/
|
|
58
|
+
Object.defineProperty(this, "initOauth", {
|
|
59
|
+
enumerable: true,
|
|
60
|
+
configurable: true,
|
|
61
|
+
writable: true,
|
|
62
|
+
value: async () => {
|
|
63
|
+
this.oauthConfig = await this.getOauthConfig();
|
|
64
|
+
return this.oauthConfig;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
46
67
|
// #endregion
|
|
47
68
|
// #region PUBLIC METHODS
|
|
48
69
|
/**
|
|
@@ -377,11 +398,14 @@ export class BaseSignerClient {
|
|
|
377
398
|
* @returns {Promise<boolean>} A promise that resolves to true if the export is successful
|
|
378
399
|
*/
|
|
379
400
|
exportWalletInner(params) {
|
|
380
|
-
|
|
401
|
+
const { exportAs } = params;
|
|
402
|
+
switch (exportAs) {
|
|
381
403
|
case "PRIVATE_KEY":
|
|
382
404
|
return this.exportAsPrivateKey(params.exportStamper);
|
|
383
405
|
case "SEED_PHRASE":
|
|
384
406
|
return this.exportAsSeedPhrase(params.exportStamper);
|
|
407
|
+
default:
|
|
408
|
+
assertNever(exportAs, `Unknown export mode: ${exportAs}`);
|
|
385
409
|
}
|
|
386
410
|
}
|
|
387
411
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/client/base.ts"],"names":[],"mappings":"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","sourcesContent":["import { ConnectionConfigSchema, type ConnectionConfig } from \"@aa-sdk/core\";\nimport { TurnkeyClient, type TSignedRequest } from \"@turnkey/http\";\nimport EventEmitter from \"eventemitter3\";\nimport type { Hex } from \"viem\";\nimport { NotAuthenticatedError } from \"../errors.js\";\nimport { base64UrlEncode } from \"../utils/base64UrlEncode.js\";\nimport type {\n AlchemySignerClientEvent,\n AlchemySignerClientEvents,\n CreateAccountParams,\n EmailAuthParams,\n GetWebAuthnAttestationResult,\n SignerBody,\n SignerResponse,\n SignerRoutes,\n SignupResponse,\n User,\n} from \"./types.js\";\n\nexport interface BaseSignerClientParams {\n stamper: TurnkeyClient[\"stamper\"];\n connection: ConnectionConfig;\n rootOrgId?: string;\n rpId?: string;\n}\n\nexport type ExportWalletStamper = TurnkeyClient[\"stamper\"] & {\n injectWalletExportBundle(bundle: string): Promise<boolean>;\n injectKeyExportBundle(bundle: string): Promise<boolean>;\n publicKey(): string | null;\n};\n\n/**\n * Base class for all Alchemy Signer clients\n */\nexport abstract class BaseSignerClient<TExportWalletParams = unknown> {\n private _user: User | undefined;\n private connectionConfig: ConnectionConfig;\n protected turnkeyClient: TurnkeyClient;\n protected rootOrg: string;\n protected eventEmitter: EventEmitter<AlchemySignerClientEvents>;\n\n /**\n * Create a new instance of the Alchemy Signer client\n *\n * @param {BaseSignerClientParams} params the parameters required to create the client\n */\n constructor(params: BaseSignerClientParams) {\n const { stamper, connection, rootOrgId } = params;\n\n this.rootOrg = rootOrgId ?? \"24c1acf5-810f-41e0-a503-d5d13fa8e830\";\n this.eventEmitter = new EventEmitter<AlchemySignerClientEvents>();\n this.connectionConfig = ConnectionConfigSchema.parse(connection);\n this.turnkeyClient = new TurnkeyClient(\n { baseUrl: \"https://api.turnkey.com\" },\n stamper\n );\n }\n\n protected get user() {\n return this._user;\n }\n\n protected set user(user: User | undefined) {\n if (user && !this._user) {\n this.eventEmitter.emit(\"connected\", user);\n } else if (!user && this._user) {\n this.eventEmitter.emit(\"disconnected\");\n }\n\n this._user = user;\n }\n\n /**\n * Sets the stamper of the TurnkeyClient.\n *\n * @param {TurnkeyClient[\"stamper\"]} stamper the stamper function to set for the TurnkeyClient\n */\n protected setStamper(stamper: TurnkeyClient[\"stamper\"]) {\n this.turnkeyClient.stamper = stamper;\n }\n\n /**\n * Exports wallet credentials based on the specified type, either as a SEED_PHRASE or PRIVATE_KEY.\n *\n * @param {object} params The parameters for exporting the wallet\n * @param {ExportWalletStamper} params.exportStamper The stamper used for exporting the wallet\n * @param {\"SEED_PHRASE\" | \"PRIVATE_KEY\"} params.exportAs Specifies the format for exporting the wallet, either as a SEED_PHRASE or PRIVATE_KEY\n * @returns {Promise<boolean>} A promise that resolves to true if the export is successful\n */\n protected exportWalletInner(params: {\n exportStamper: ExportWalletStamper;\n exportAs: \"SEED_PHRASE\" | \"PRIVATE_KEY\";\n }): Promise<boolean> {\n switch (params.exportAs) {\n case \"PRIVATE_KEY\":\n return this.exportAsPrivateKey(params.exportStamper);\n case \"SEED_PHRASE\":\n return this.exportAsSeedPhrase(params.exportStamper);\n }\n }\n\n // #region ABSTRACT METHODS\n\n public abstract createAccount(\n params: CreateAccountParams\n ): Promise<SignupResponse>;\n\n public abstract initEmailAuth(\n params: Omit<EmailAuthParams, \"targetPublicKey\">\n ): Promise<{ orgId: string }>;\n\n public abstract completeEmailAuth(params: {\n bundle: string;\n orgId: string;\n }): Promise<User>;\n\n public abstract disconnect(): Promise<void>;\n\n public abstract exportWallet(params: TExportWalletParams): Promise<boolean>;\n\n public abstract lookupUserWithPasskey(user?: User): Promise<User>;\n\n protected abstract getWebAuthnAttestation(\n options: CredentialCreationOptions,\n userDetails?: { username: string }\n ): Promise<GetWebAuthnAttestationResult>;\n\n // #endregion\n\n // #region PUBLIC METHODS\n\n /**\n * Listen to events emitted by the client\n *\n * @param {AlchemySignerClientEvent} event the event you want to listen to\n * @param {AlchemySignerClientEvents[AlchemySignerClientEvent]} listener the callback function to execute when an event is fired\n * @returns {() => void} a function that will remove the listener when called\n */\n public on = <E extends AlchemySignerClientEvent>(\n event: E,\n listener: AlchemySignerClientEvents[E]\n ) => {\n this.eventEmitter.on(event, listener as any);\n\n return () => this.eventEmitter.removeListener(event, listener as any);\n };\n\n /**\n * Handles the creation of authenticators using WebAuthn attestation and the provided options. Requires the user to be authenticated.\n *\n * @param {CredentialCreationOptions} options The options used to create the WebAuthn attestation\n * @returns {Promise<string[]>} A promise that resolves to an array of authenticator IDs\n * @throws {NotAuthenticatedError} If the user is not authenticated\n */\n public addPasskey = async (options: CredentialCreationOptions) => {\n if (!this.user) {\n throw new NotAuthenticatedError();\n }\n const { attestation, challenge } = await this.getWebAuthnAttestation(\n options\n );\n\n const { activity } = await this.turnkeyClient.createAuthenticators({\n type: \"ACTIVITY_TYPE_CREATE_AUTHENTICATORS_V2\",\n timestampMs: Date.now().toString(),\n organizationId: this.user.orgId,\n parameters: {\n userId: this.user.userId,\n authenticators: [\n {\n attestation,\n authenticatorName: `passkey-${Date.now().toString()}`,\n challenge: base64UrlEncode(challenge),\n },\n ],\n },\n });\n\n const { authenticatorIds } = await this.pollActivityCompletion(\n activity,\n this.user.orgId,\n \"createAuthenticatorsResult\"\n );\n\n return authenticatorIds;\n };\n\n /**\n * Retrieves the current user or fetches the user information if not already available.\n *\n * @param {string} [orgId] optional organization ID, defaults to the user's organization ID\n * @returns {Promise<User>} A promise that resolves to the user object\n * @throws {Error} if no organization ID is provided when there is no current user\n */\n public whoami = async (orgId = this.user?.orgId): Promise<User> => {\n if (this.user) {\n return this.user;\n }\n\n if (!orgId) {\n throw new Error(\"No orgId provided\");\n }\n\n const stampedRequest = await this.turnkeyClient.stampGetWhoami({\n organizationId: orgId,\n });\n\n const user = await this.request(\"/v1/whoami\", {\n stampedRequest,\n });\n\n const credentialId = (() => {\n try {\n return JSON.parse(stampedRequest?.stamp.stampHeaderValue)\n .credentialId as string;\n } catch (e) {\n return undefined;\n }\n })();\n\n this.user = {\n ...user,\n credentialId,\n };\n\n return this.user;\n };\n\n /**\n * 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.\n * 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\n * 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\n * belong to the user who created it.\n *\n * @returns {Promise<TSignedRequest>} a promise that resolves to the \"whoami\" information for the logged in user\n * @throws {Error} if no organization ID is provided\n */\n public stampWhoami = async (): Promise<TSignedRequest> => {\n if (!this.user) {\n throw new Error(\"User must be authenticated to stamp a whoami request\");\n }\n\n return await this.turnkeyClient.stampGetWhoami({\n organizationId: this.user.orgId,\n });\n };\n\n /**\n * Looks up information based on an email address.\n *\n * @param {string} email the email address to look up\n * @returns {Promise<any>} the result of the lookup request\n */\n public lookupUserByEmail = async (email: string) => {\n return this.request(\"/v1/lookup\", { email });\n };\n\n /**\n * This will sign a message with the user's private key, without doing any transformations on the message.\n * For SignMessage or SignTypedData, the caller should hash the message before calling this method and pass\n * that result here.\n *\n * @param {Hex} msg the hex representation of the bytes to sign\n * @returns {Promise<Hex>} the signature over the raw hex\n */\n public signRawMessage = async (msg: Hex): Promise<Hex> => {\n if (!this.user) {\n throw new NotAuthenticatedError();\n }\n\n const stampedRequest = await this.turnkeyClient.stampSignRawPayload({\n organizationId: this.user.orgId,\n type: \"ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2\",\n timestampMs: Date.now().toString(),\n parameters: {\n encoding: \"PAYLOAD_ENCODING_HEXADECIMAL\",\n hashFunction: \"HASH_FUNCTION_NO_OP\",\n payload: msg,\n signWith: this.user.address,\n },\n });\n\n const { signature } = await this.request(\"/v1/sign-payload\", {\n stampedRequest,\n });\n\n return signature;\n };\n\n /**\n * Returns the current user or null if no user is set.\n *\n * @returns {User | null} the current user object or null if no user is available\n */\n public getUser = (): User | null => {\n return this.user ?? null;\n };\n\n /**\n * Sends a POST request to the given signer route with the specified body and returns the response.\n * Not intended to be used directly, use the specific methods instead on the client instead.\n *\n * @param {SignerRoutes} route The route to which the request should be sent\n * @param {SignerBody<R>} body The request body containing the data to be sent\n * @returns {Promise<SignerResponse<R>>} A promise that resolves to the response from the signer\n */\n public request = async <R extends SignerRoutes>(\n route: R,\n body: SignerBody<R>\n ): Promise<SignerResponse<R>> => {\n const url = this.connectionConfig.rpcUrl ?? \"https://api.g.alchemy.com\";\n const basePath = \"/signer\";\n\n const headers = new Headers();\n headers.append(\"Content-Type\", \"application/json\");\n if (this.connectionConfig.apiKey) {\n headers.append(\"Authorization\", `Bearer ${this.connectionConfig.apiKey}`);\n } else if (this.connectionConfig.jwt) {\n headers.append(\"Authorization\", `Bearer ${this.connectionConfig.jwt}`);\n }\n\n const response = await fetch(`${url}${basePath}${route}`, {\n method: \"POST\",\n body: JSON.stringify(body),\n headers,\n });\n\n if (!response.ok) {\n throw new Error(await response.text());\n }\n\n const json = await response.json();\n\n return json as SignerResponse<R>;\n };\n\n // #endregion\n\n // #region PRIVATE METHODS\n private exportAsSeedPhrase = async (stamper: ExportWalletStamper) => {\n if (!this.user) {\n throw new NotAuthenticatedError();\n }\n\n const { wallets } = await this.turnkeyClient.getWallets({\n organizationId: this.user.orgId,\n });\n\n const walletAccounts = await Promise.all(\n wallets.map(({ walletId }) =>\n this.turnkeyClient.getWalletAccounts({\n organizationId: this.user!.orgId,\n walletId,\n })\n )\n ).then((x) => x.flatMap((x) => x.accounts));\n\n const walletAccount = walletAccounts.find(\n (x) => x.address === this.user!.address\n );\n\n if (!walletAccount) {\n throw new Error(\n `Could not find wallet associated with ${this.user.address}`\n );\n }\n\n const { activity } = await this.turnkeyClient.exportWallet({\n organizationId: this.user.orgId,\n type: \"ACTIVITY_TYPE_EXPORT_WALLET\",\n timestampMs: Date.now().toString(),\n parameters: {\n walletId: walletAccount!.walletId,\n targetPublicKey: stamper.publicKey()!,\n },\n });\n\n const { exportBundle } = await this.pollActivityCompletion(\n activity,\n this.user.orgId,\n \"exportWalletResult\"\n );\n\n const result = await stamper.injectWalletExportBundle(exportBundle);\n\n if (!result) {\n throw new Error(\"Failed to inject wallet export bundle\");\n }\n\n return result;\n };\n\n private exportAsPrivateKey = async (stamper: ExportWalletStamper) => {\n if (!this.user) {\n throw new NotAuthenticatedError();\n }\n\n const { activity } = await this.turnkeyClient.exportWalletAccount({\n organizationId: this.user.orgId,\n type: \"ACTIVITY_TYPE_EXPORT_WALLET_ACCOUNT\",\n timestampMs: Date.now().toString(),\n parameters: {\n address: this.user.address,\n targetPublicKey: stamper.publicKey()!,\n },\n });\n\n const { exportBundle } = await this.pollActivityCompletion(\n activity,\n this.user.orgId,\n \"exportWalletAccountResult\"\n );\n\n const result = await stamper.injectKeyExportBundle(exportBundle);\n\n if (!result) {\n throw new Error(\"Failed to inject wallet export bundle\");\n }\n\n return result;\n };\n\n // eslint-disable-next-line eslint-rules/require-jsdoc-on-reexported-functions\n protected pollActivityCompletion = async <\n T extends keyof Awaited<\n ReturnType<(typeof this.turnkeyClient)[\"getActivity\"]>\n >[\"activity\"][\"result\"]\n >(\n activity: Awaited<\n ReturnType<(typeof this.turnkeyClient)[\"getActivity\"]>\n >[\"activity\"],\n organizationId: string,\n resultKey: T\n ): Promise<\n NonNullable<\n Awaited<\n ReturnType<(typeof this.turnkeyClient)[\"getActivity\"]>\n >[\"activity\"][\"result\"][T]\n >\n > => {\n if (activity.status === \"ACTIVITY_STATUS_COMPLETED\") {\n return activity.result[resultKey]!;\n }\n\n const {\n activity: { status, id, result },\n } = await this.turnkeyClient.getActivity({\n activityId: activity.id,\n organizationId,\n });\n\n if (status === \"ACTIVITY_STATUS_COMPLETED\") {\n return result[resultKey]!;\n }\n\n if (\n status === \"ACTIVITY_STATUS_FAILED\" ||\n status === \"ACTIVITY_STATUS_REJECTED\" ||\n status === \"ACTIVITY_STATUS_CONSENSUS_NEEDED\"\n ) {\n throw new Error(\n `Failed to get activity with with id ${id} (status: ${status})`\n );\n }\n\n // TODO: add ability to configure this + add exponential backoff\n await new Promise((resolve) => setTimeout(resolve, 500));\n\n return this.pollActivityCompletion(activity, organizationId, resultKey);\n };\n // #endregion\n}\n"]}
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/client/base.ts"],"names":[],"mappings":"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","sourcesContent":["import { ConnectionConfigSchema, type ConnectionConfig } from \"@aa-sdk/core\";\nimport { TurnkeyClient, type TSignedRequest } from \"@turnkey/http\";\nimport EventEmitter from \"eventemitter3\";\nimport type { Hex } from \"viem\";\nimport { NotAuthenticatedError } from \"../errors.js\";\nimport { base64UrlEncode } from \"../utils/base64UrlEncode.js\";\nimport type {\n AlchemySignerClientEvent,\n AlchemySignerClientEvents,\n CreateAccountParams,\n EmailAuthParams,\n GetWebAuthnAttestationResult,\n OauthConfig,\n OauthParams,\n SignerBody,\n SignerResponse,\n SignerRoutes,\n SignupResponse,\n User,\n} from \"./types.js\";\nimport { assertNever } from \"../utils/typeAssertions.js\";\n\nexport interface BaseSignerClientParams {\n stamper: TurnkeyClient[\"stamper\"];\n connection: ConnectionConfig;\n rootOrgId?: string;\n rpId?: string;\n}\n\nexport type ExportWalletStamper = TurnkeyClient[\"stamper\"] & {\n injectWalletExportBundle(bundle: string): Promise<boolean>;\n injectKeyExportBundle(bundle: string): Promise<boolean>;\n publicKey(): string | null;\n};\n\n/**\n * Base class for all Alchemy Signer clients\n */\nexport abstract class BaseSignerClient<TExportWalletParams = unknown> {\n private _user: User | undefined;\n private connectionConfig: ConnectionConfig;\n protected turnkeyClient: TurnkeyClient;\n protected rootOrg: string;\n protected eventEmitter: EventEmitter<AlchemySignerClientEvents>;\n protected oauthConfig: OauthConfig | undefined;\n\n /**\n * Create a new instance of the Alchemy Signer client\n *\n * @param {BaseSignerClientParams} params the parameters required to create the client\n */\n constructor(params: BaseSignerClientParams) {\n const { stamper, connection, rootOrgId } = params;\n this.rootOrg = rootOrgId ?? \"24c1acf5-810f-41e0-a503-d5d13fa8e830\";\n this.eventEmitter = new EventEmitter<AlchemySignerClientEvents>();\n this.connectionConfig = ConnectionConfigSchema.parse(connection);\n this.turnkeyClient = new TurnkeyClient(\n { baseUrl: \"https://api.turnkey.com\" },\n stamper\n );\n }\n\n /**\n * Asynchronously fetches and sets the OAuth configuration.\n *\n * @returns {Promise<OauthConfig>} A promise that resolves to the OAuth configuration\n */\n public initOauth = async (): Promise<OauthConfig> => {\n this.oauthConfig = await this.getOauthConfig();\n return this.oauthConfig;\n };\n\n protected get user() {\n return this._user;\n }\n\n protected set user(user: User | undefined) {\n if (user && !this._user) {\n this.eventEmitter.emit(\"connected\", user);\n } else if (!user && this._user) {\n this.eventEmitter.emit(\"disconnected\");\n }\n\n this._user = user;\n }\n\n /**\n * Sets the stamper of the TurnkeyClient.\n *\n * @param {TurnkeyClient[\"stamper\"]} stamper the stamper function to set for the TurnkeyClient\n */\n protected setStamper(stamper: TurnkeyClient[\"stamper\"]) {\n this.turnkeyClient.stamper = stamper;\n }\n\n /**\n * Exports wallet credentials based on the specified type, either as a SEED_PHRASE or PRIVATE_KEY.\n *\n * @param {object} params The parameters for exporting the wallet\n * @param {ExportWalletStamper} params.exportStamper The stamper used for exporting the wallet\n * @param {\"SEED_PHRASE\" | \"PRIVATE_KEY\"} params.exportAs Specifies the format for exporting the wallet, either as a SEED_PHRASE or PRIVATE_KEY\n * @returns {Promise<boolean>} A promise that resolves to true if the export is successful\n */\n protected exportWalletInner(params: {\n exportStamper: ExportWalletStamper;\n exportAs: \"SEED_PHRASE\" | \"PRIVATE_KEY\";\n }): Promise<boolean> {\n const { exportAs } = params;\n switch (exportAs) {\n case \"PRIVATE_KEY\":\n return this.exportAsPrivateKey(params.exportStamper);\n case \"SEED_PHRASE\":\n return this.exportAsSeedPhrase(params.exportStamper);\n default:\n assertNever(exportAs, `Unknown export mode: ${exportAs}`);\n }\n }\n\n // #region ABSTRACT METHODS\n\n public abstract createAccount(\n params: CreateAccountParams\n ): Promise<SignupResponse>;\n\n public abstract initEmailAuth(\n params: Omit<EmailAuthParams, \"targetPublicKey\">\n ): Promise<{ orgId: string }>;\n\n public abstract completeAuthWithBundle(params: {\n bundle: string;\n orgId: string;\n connectedEventName: keyof AlchemySignerClientEvents;\n }): Promise<User>;\n\n public abstract oauthWithRedirect(\n args: Extract<OauthParams, { mode: \"redirect\" }>\n ): Promise<never>;\n\n public abstract oauthWithPopup(\n args: Extract<OauthParams, { mode: \"popup\" }>\n ): Promise<User>;\n\n public abstract disconnect(): Promise<void>;\n\n public abstract exportWallet(params: TExportWalletParams): Promise<boolean>;\n\n public abstract lookupUserWithPasskey(user?: User): Promise<User>;\n\n protected abstract getOauthConfig(): Promise<OauthConfig>;\n\n protected abstract getWebAuthnAttestation(\n options: CredentialCreationOptions,\n userDetails?: { username: string }\n ): Promise<GetWebAuthnAttestationResult>;\n\n // #endregion\n\n // #region PUBLIC METHODS\n\n /**\n * Listen to events emitted by the client\n *\n * @param {AlchemySignerClientEvent} event the event you want to listen to\n * @param {AlchemySignerClientEvents[AlchemySignerClientEvent]} listener the callback function to execute when an event is fired\n * @returns {() => void} a function that will remove the listener when called\n */\n public on = <E extends AlchemySignerClientEvent>(\n event: E,\n listener: AlchemySignerClientEvents[E]\n ) => {\n this.eventEmitter.on(event, listener as any);\n\n return () => this.eventEmitter.removeListener(event, listener as any);\n };\n\n /**\n * Handles the creation of authenticators using WebAuthn attestation and the provided options. Requires the user to be authenticated.\n *\n * @param {CredentialCreationOptions} options The options used to create the WebAuthn attestation\n * @returns {Promise<string[]>} A promise that resolves to an array of authenticator IDs\n * @throws {NotAuthenticatedError} If the user is not authenticated\n */\n public addPasskey = async (options: CredentialCreationOptions) => {\n if (!this.user) {\n throw new NotAuthenticatedError();\n }\n const { attestation, challenge } = await this.getWebAuthnAttestation(\n options\n );\n\n const { activity } = await this.turnkeyClient.createAuthenticators({\n type: \"ACTIVITY_TYPE_CREATE_AUTHENTICATORS_V2\",\n timestampMs: Date.now().toString(),\n organizationId: this.user.orgId,\n parameters: {\n userId: this.user.userId,\n authenticators: [\n {\n attestation,\n authenticatorName: `passkey-${Date.now().toString()}`,\n challenge: base64UrlEncode(challenge),\n },\n ],\n },\n });\n\n const { authenticatorIds } = await this.pollActivityCompletion(\n activity,\n this.user.orgId,\n \"createAuthenticatorsResult\"\n );\n\n return authenticatorIds;\n };\n\n /**\n * Retrieves the current user or fetches the user information if not already available.\n *\n * @param {string} [orgId] optional organization ID, defaults to the user's organization ID\n * @returns {Promise<User>} A promise that resolves to the user object\n * @throws {Error} if no organization ID is provided when there is no current user\n */\n public whoami = async (orgId = this.user?.orgId): Promise<User> => {\n if (this.user) {\n return this.user;\n }\n\n if (!orgId) {\n throw new Error(\"No orgId provided\");\n }\n\n const stampedRequest = await this.turnkeyClient.stampGetWhoami({\n organizationId: orgId,\n });\n\n const user = await this.request(\"/v1/whoami\", {\n stampedRequest,\n });\n\n const credentialId = (() => {\n try {\n return JSON.parse(stampedRequest?.stamp.stampHeaderValue)\n .credentialId as string;\n } catch (e) {\n return undefined;\n }\n })();\n\n this.user = {\n ...user,\n credentialId,\n };\n\n return this.user;\n };\n\n /**\n * 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.\n * 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\n * 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\n * belong to the user who created it.\n *\n * @returns {Promise<TSignedRequest>} a promise that resolves to the \"whoami\" information for the logged in user\n * @throws {Error} if no organization ID is provided\n */\n public stampWhoami = async (): Promise<TSignedRequest> => {\n if (!this.user) {\n throw new Error(\"User must be authenticated to stamp a whoami request\");\n }\n\n return await this.turnkeyClient.stampGetWhoami({\n organizationId: this.user.orgId,\n });\n };\n\n /**\n * Looks up information based on an email address.\n *\n * @param {string} email the email address to look up\n * @returns {Promise<any>} the result of the lookup request\n */\n public lookupUserByEmail = async (email: string) => {\n return this.request(\"/v1/lookup\", { email });\n };\n\n /**\n * This will sign a message with the user's private key, without doing any transformations on the message.\n * For SignMessage or SignTypedData, the caller should hash the message before calling this method and pass\n * that result here.\n *\n * @param {Hex} msg the hex representation of the bytes to sign\n * @returns {Promise<Hex>} the signature over the raw hex\n */\n public signRawMessage = async (msg: Hex): Promise<Hex> => {\n if (!this.user) {\n throw new NotAuthenticatedError();\n }\n\n const stampedRequest = await this.turnkeyClient.stampSignRawPayload({\n organizationId: this.user.orgId,\n type: \"ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2\",\n timestampMs: Date.now().toString(),\n parameters: {\n encoding: \"PAYLOAD_ENCODING_HEXADECIMAL\",\n hashFunction: \"HASH_FUNCTION_NO_OP\",\n payload: msg,\n signWith: this.user.address,\n },\n });\n\n const { signature } = await this.request(\"/v1/sign-payload\", {\n stampedRequest,\n });\n\n return signature;\n };\n\n /**\n * Returns the current user or null if no user is set.\n *\n * @returns {User | null} the current user object or null if no user is available\n */\n public getUser = (): User | null => {\n return this.user ?? null;\n };\n\n /**\n * Sends a POST request to the given signer route with the specified body and returns the response.\n * Not intended to be used directly, use the specific methods instead on the client instead.\n *\n * @param {SignerRoutes} route The route to which the request should be sent\n * @param {SignerBody<R>} body The request body containing the data to be sent\n * @returns {Promise<SignerResponse<R>>} A promise that resolves to the response from the signer\n */\n public request = async <R extends SignerRoutes>(\n route: R,\n body: SignerBody<R>\n ): Promise<SignerResponse<R>> => {\n const url = this.connectionConfig.rpcUrl ?? \"https://api.g.alchemy.com\";\n\n const basePath = \"/signer\";\n\n const headers = new Headers();\n headers.append(\"Content-Type\", \"application/json\");\n if (this.connectionConfig.apiKey) {\n headers.append(\"Authorization\", `Bearer ${this.connectionConfig.apiKey}`);\n } else if (this.connectionConfig.jwt) {\n headers.append(\"Authorization\", `Bearer ${this.connectionConfig.jwt}`);\n }\n\n const response = await fetch(`${url}${basePath}${route}`, {\n method: \"POST\",\n body: JSON.stringify(body),\n headers,\n });\n\n if (!response.ok) {\n throw new Error(await response.text());\n }\n\n const json = await response.json();\n\n return json as SignerResponse<R>;\n };\n\n // #endregion\n\n // #region PRIVATE METHODS\n private exportAsSeedPhrase = async (stamper: ExportWalletStamper) => {\n if (!this.user) {\n throw new NotAuthenticatedError();\n }\n\n const { wallets } = await this.turnkeyClient.getWallets({\n organizationId: this.user.orgId,\n });\n\n const walletAccounts = await Promise.all(\n wallets.map(({ walletId }) =>\n this.turnkeyClient.getWalletAccounts({\n organizationId: this.user!.orgId,\n walletId,\n })\n )\n ).then((x) => x.flatMap((x) => x.accounts));\n\n const walletAccount = walletAccounts.find(\n (x) => x.address === this.user!.address\n );\n\n if (!walletAccount) {\n throw new Error(\n `Could not find wallet associated with ${this.user.address}`\n );\n }\n\n const { activity } = await this.turnkeyClient.exportWallet({\n organizationId: this.user.orgId,\n type: \"ACTIVITY_TYPE_EXPORT_WALLET\",\n timestampMs: Date.now().toString(),\n parameters: {\n walletId: walletAccount!.walletId,\n targetPublicKey: stamper.publicKey()!,\n },\n });\n\n const { exportBundle } = await this.pollActivityCompletion(\n activity,\n this.user.orgId,\n \"exportWalletResult\"\n );\n\n const result = await stamper.injectWalletExportBundle(exportBundle);\n\n if (!result) {\n throw new Error(\"Failed to inject wallet export bundle\");\n }\n\n return result;\n };\n\n private exportAsPrivateKey = async (stamper: ExportWalletStamper) => {\n if (!this.user) {\n throw new NotAuthenticatedError();\n }\n\n const { activity } = await this.turnkeyClient.exportWalletAccount({\n organizationId: this.user.orgId,\n type: \"ACTIVITY_TYPE_EXPORT_WALLET_ACCOUNT\",\n timestampMs: Date.now().toString(),\n parameters: {\n address: this.user.address,\n targetPublicKey: stamper.publicKey()!,\n },\n });\n\n const { exportBundle } = await this.pollActivityCompletion(\n activity,\n this.user.orgId,\n \"exportWalletAccountResult\"\n );\n\n const result = await stamper.injectKeyExportBundle(exportBundle);\n\n if (!result) {\n throw new Error(\"Failed to inject wallet export bundle\");\n }\n\n return result;\n };\n\n // eslint-disable-next-line eslint-rules/require-jsdoc-on-reexported-functions\n protected pollActivityCompletion = async <\n T extends keyof Awaited<\n ReturnType<(typeof this.turnkeyClient)[\"getActivity\"]>\n >[\"activity\"][\"result\"]\n >(\n activity: Awaited<\n ReturnType<(typeof this.turnkeyClient)[\"getActivity\"]>\n >[\"activity\"],\n organizationId: string,\n resultKey: T\n ): Promise<\n NonNullable<\n Awaited<\n ReturnType<(typeof this.turnkeyClient)[\"getActivity\"]>\n >[\"activity\"][\"result\"][T]\n >\n > => {\n if (activity.status === \"ACTIVITY_STATUS_COMPLETED\") {\n return activity.result[resultKey]!;\n }\n\n const {\n activity: { status, id, result },\n } = await this.turnkeyClient.getActivity({\n activityId: activity.id,\n organizationId,\n });\n\n if (status === \"ACTIVITY_STATUS_COMPLETED\") {\n return result[resultKey]!;\n }\n\n if (\n status === \"ACTIVITY_STATUS_FAILED\" ||\n status === \"ACTIVITY_STATUS_REJECTED\" ||\n status === \"ACTIVITY_STATUS_CONSENSUS_NEEDED\"\n ) {\n throw new Error(\n `Failed to get activity with with id ${id} (status: ${status})`\n );\n }\n\n // TODO: add ability to configure this + add exponential backoff\n await new Promise((resolve) => setTimeout(resolve, 500));\n\n return this.pollActivityCompletion(activity, organizationId, resultKey);\n };\n // #endregion\n}\n"]}
|