Configure client
A smart wallet client is the main interface used to interact with smart wallets and take actions like sending transactions, batching transactions, swapping, sponsoring gas, and more.
How It Works
The SmartWalletClient is a EIP-1193 compatible extension of viem’s Client which allows you to interact with smart wallets.
Prerequisites
Implementation
JavaScript
API
Use the createSmartWalletClient function to create a smart wallet client.
- Replace the placeholders a. API key from your Alchemy dashboard b. Policy ID from your gas policy c. Signer from authentication or your own signer
- Create the initial client using
createSmartWalletClient - Generate your smart account by calling
requestAccount() - Create the final client with your account attached
import { class LocalAccountSigner<T extends HDAccount | PrivateKeyAccount | LocalAccount>Represents a local account signer and provides methods to sign messages and transactions, as well as static methods to create the signer from mnemonic or private key.
LocalAccountSigner } from "@aa-sdk/core";
import { function alchemy(config: AlchemyTransportConfig): AlchemyTransportCreates an Alchemy transport with the specified configuration options. When sending all traffic to Alchemy, you must pass in one of rpcUrl, apiKey, or jwt. If you want to send Bundler and Paymaster traffic to Alchemy and Node traffic to a different RPC, you must pass in alchemyConnection and nodeRpcUrl.
alchemy, const sepolia: Chainsepolia } from "@account-kit/infra";
import {
function createSmartWalletClient<TAccount extends Address | undefined = undefined>(params: SmartWalletClientParams<TAccount>): SmartWalletClient<TAccount>Creates a smart wallet client that can be used to interact with a smart account.
createSmartWalletClient,
type type SmartWalletClientParams<TAccount extends Address | undefined = `0x${string}` | undefined> = {
transport: AlchemyTransport;
chain: Chain;
signer: SmartWalletSigner;
account?: `0x${string}` | TAccount | undefined;
policyId?: string | undefined;
policyIds?: never | undefined;
} | {
transport: AlchemyTransport;
chain: Chain;
signer: SmartWalletSigner;
account?: `0x${string}` | TAccount | undefined;
policyIds?: string[] | undefined;
policyId?: never | undefined;
}SmartWalletClientParams,
} from "@account-kit/wallet-client";
const const clientParams: SmartWalletClientParamsclientParams: type SmartWalletClientParams<TAccount extends Address | undefined = `0x${string}` | undefined> = {
transport: AlchemyTransport;
chain: Chain;
signer: SmartWalletSigner;
account?: `0x${string}` | TAccount | undefined;
policyId?: string | undefined;
policyIds?: never | undefined;
} | {
transport: AlchemyTransport;
chain: Chain;
signer: SmartWalletSigner;
account?: `0x${string}` | TAccount | undefined;
policyIds?: string[] | undefined;
policyId?: never | undefined;
}SmartWalletClientParams = {
transport: AlchemyTransporttransport: function alchemy(config: AlchemyTransportConfig): AlchemyTransportCreates an Alchemy transport with the specified configuration options. When sending all traffic to Alchemy, you must pass in one of rpcUrl, apiKey, or jwt. If you want to send Bundler and Paymaster traffic to Alchemy and Node traffic to a different RPC, you must pass in alchemyConnection and nodeRpcUrl.
alchemy({ apiKey: stringapiKey: "your-alchemy-api-key"}),
chain: Chainchain: const sepolia: Chainsepolia,
signer: SmartWalletSignersigner: class LocalAccountSigner<T extends HDAccount | PrivateKeyAccount | LocalAccount>Represents a local account signer and provides methods to sign messages and transactions, as well as static methods to create the signer from mnemonic or private key.
LocalAccountSigner.LocalAccountSigner<T extends HDAccount | PrivateKeyAccount | LocalAccount>.privateKeyToAccountSigner(key: Hex): LocalAccountSigner<PrivateKeyAccount>Creates a LocalAccountSigner instance using the provided private key.
privateKeyToAccountSigner("0x-your-wallet-private-key"),
policyId?: string | undefinedpolicyId: "your-policy-id",
};
const const clientWithoutAccount: SmartWalletClient<`0x${string}` | undefined>clientWithoutAccount = createSmartWalletClient<`0x${string}` | undefined>(params: SmartWalletClientParams<`0x${string}` | undefined>): SmartWalletClient<`0x${string}` | undefined>Creates a smart wallet client that can be used to interact with a smart account.
createSmartWalletClient(const clientParams: {
transport: AlchemyTransport;
chain: Chain;
signer: SmartWalletSigner;
account?: `0x${string}` | undefined;
policyId?: string | undefined;
policyIds?: never | undefined;
}clientParams);
const const account: RequestAccountResultaccount = await const clientWithoutAccount: SmartWalletClient<`0x${string}` | undefined>clientWithoutAccount.requestAccount: (params?: RequestAccountParams) => Promise<RequestAccountResult>requestAccount();
export const const client: SmartWalletClient<`0x${string}`>client = createSmartWalletClient<`0x${string}`>(params: SmartWalletClientParams<`0x${string}`>): SmartWalletClient<`0x${string}`>Creates a smart wallet client that can be used to interact with a smart account.
createSmartWalletClient({
...const clientParams: {
transport: AlchemyTransport;
chain: Chain;
signer: SmartWalletSigner;
account?: `0x${string}` | undefined;
policyId?: string | undefined;
policyIds?: never | undefined;
}clientParams,
account: `0x${string}`account: const account: RequestAccountResultaccount.address: `0x${string}`address,
});Advanced
Override default account type
By default, the Smart Wallet Client will use ModularAccountV2(MAv2). This is the cheapest and most advanced Smart Account, but you can specify other smart contract account types as needed. Learn more about the different smart accounts here.
Changing the account type will deploy a different account. If you’ve already deployed an account for a user and want to change the underlying account type, you’ll need to upgrade it. Learn how to upgrade here.
Javascript
Specify the account type when calling requestAccount using the creationHint parameter. See all parameter options.
API
Pass an accountType to creationHint when calling wallet_requestAccount.
Using 7702
To use EIP-7702, please see this guide. You’ll need to set additional parameters on the client.
Connect to an existing account address
By default, account addresses are deterministically generated from the signer address. To connect to an existing account that doesn’t match the deterministic address of your signer, specify the account address when creating the client.
Javascript
Pass the address to the createSmartWalletClient directly rather than calling requestAccount.
API
Pass the account address directly when preparing calls instead of calling wallet_requestAccount. See this guide and skip step 2.
Extend client with custom actions
Because the Smart Wallet Clients are extensions of viem’s clients, they support extensions via the .extend method. The base client already includes a number of actions by default. You can find additional details about these actions in the @aa-sdk/core documentation.
Use one client for multiple accounts
Typically, the smart account client uses the default account or the account passed into the client constructor for all of the actions you perform with the client - also known as account hositing.
If you want to manage multiple instances of an account but want to use one client for all of them, you can pass an account to the client on every action.