How to use your own Account Signer
Account Kit is designed to be flexible and allow you to use any Signer you want. If you don't want to use any Signer implementations in aa-signers
, you can either:
- Implement
SmartAccountSigner
(exported inaa-core
). - If your Signer is an EIP-1193 compliant provider, you can leverage
viem
'sWalletClient
and theWalletClientSigner
(exported inaa-core
).
Note
If you want to add your Signer implementation to Account Kit's codebase, take a look at the contibuting docs. We welcome Pull Requests onto the Github repo for aa-sdk
!
1. Implementing SmartAccountAuthenticator
or SmartAccountSigner
Smart accounts in Account Kit expect an implementation of SmartAccountSigner
to work in Account Kit. We also include a SmartAccountAuthenticator
interface that extends SmartAccountSigner
and wraps any SDKs you may wish to use as part of the implementation of your own Signer.
import type { Address } from "abitype";
import type {
Hex,
SignableMessage,
TypedData,
TypedDataDefinition,
} from "viem";
//#region SmartAccountAuthenticator
/**
* Extends the @interface SmartAccountSigner interface with authentication.
*
* @template AuthParams - the generic type of the authentication parameters
* @template AuthDetails - the generic type of the authentication details
* @template Inner - the generic type of the inner client that the signer wraps to provide functionality such as signing, etc.
*/
export interface SmartAccountAuthenticator<AuthParams, AuthDetails, Inner = any>
extends SmartAccountSigner<Inner> {
authenticate: (params: AuthParams) => Promise<AuthDetails>;
getAuthDetails: () => Promise<AuthDetails>;
}
//#endregion SmartAccountAuthenticator
//#region SmartAccountSigner
/**
* A signer that can sign messages and typed data.
*
* @template Inner - the generic type of the inner client that the signer wraps to provide functionality such as signing, etc.
*/
export interface SmartAccountSigner<Inner = any> {
signerType: string;
inner: Inner;
getAddress: () => Promise<Address>;
signMessage: (message: SignableMessage) => Promise<Hex>;
signTypedData: <
const TTypedData extends TypedData | { [key: string]: unknown },
TPrimaryType extends string = string
>(
params: TypedDataDefinition<TTypedData, TPrimaryType>
) => Promise<Hex>;
}
//#endregion SmartAccountSigner
2. Using WalletClientSigner
Viem allows you to create a WalletClient
, which can be used to wrap local or JSON RPC based wallets. You can see the complete docs for leveraging the WalletClient
here.
We support a SmartAccountSigner
implementation called WalletClientSigner
that makes it really easy to use a viem WalletClient
as a signer on your Smart Contract Account. If your Signer is EIP-1193 compliant, it is really easy to use with WalletClient
. Let's take a look at a simple example:
import {
WalletClientSigner,
sepolia,
type SmartAccountSigner,
} from "@alchemy/aa-core";
import { createWalletClient, custom } from "viem";
const externalProvider = window.ethereum; // or anyother EIP-1193 provider
const walletClient = createWalletClient({
chain: sepolia, // can provide a different chain here
transport: custom(externalProvider),
});
export const signer: SmartAccountSigner = new WalletClientSigner(
walletClient,
"json-rpc" // signerType
);