Skip to content

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 choose not use our signer, you can either:

  1. Use a 3rd party library as a Signer that integrates with Account Kit.
  2. Implement SmartAccountSigner (exported in @aa-sdk/core).
  3. If your Signer is an EIP-1193 compliant provider, you can leverage viem's WalletClient and the WalletClientSigner (exported in @aa-sdk/core).

Then you can use your Signer as an owner on Smart Contracts exported from @account-kit/smart-contracts and with our infra Smart Account Clients exported from @account-kit/infra.

Third Party SDKs

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.

types.ts
import type { Address } from "abitype";
import type {
  Hex,
  SignableMessage,
  TypedData,
  TypedDataDefinition,
} from "viem";
 
/**
 * 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>;
}
 
/**
 * 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 | Record<string, unknown>,
    TPrimaryType extends keyof TTypedData | "EIP712Domain" = keyof TTypedData
  >(
    params: TypedDataDefinition<TTypedData, TPrimaryType>
  ) => Promise<Hex>;
}

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:

wallet-client-signer.ts
import { WalletClientSigner, type SmartAccountSigner } from "@aa-sdk/core";
import { createWalletClient, custom } from "viem";
import { sepolia } from "viem/chains";
 
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
);