Skip to content
Alchemy Logo

Wallet APIs SDK Quickstart

@alchemy/wallet-apis (v5.x.x) is the recommended SDK. If you're still on v4.x.x, see the migration guide.

You're going to need @alchemy/wallet-apis and viem.

npm install @alchemy/wallet-apis viem

This quickstart uses a local private key as an example. You can use any viem-compatible signer, including providers like Privy.

import { createSmartWalletClient, alchemyWalletTransport } from "@alchemy/wallet-apis";
import { arbitrumSepolia } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
 
const client = createSmartWalletClient({
  transport: alchemyWalletTransport({
    apiKey: "YOUR_API_KEY",
  }),
  chain: arbitrumSepolia,
  signer: privateKeyToAccount("0xYOUR_PRIVATE_KEY" as const),
  paymaster: {
    policyId: "YOUR_POLICY_ID",
  },
});

The client defaults to EIP-7702, so your EOA will be delegated to a smart wallet to enable gas sponsorship, batching, and more. The SDK handles delegation automatically on the first transaction.

import { zeroAddress } from "viem";
 
const { id } = await client.sendCalls({
  calls: [{ to: zeroAddress, value: BigInt(0) }],
});

const status = await client.waitForCallsStatus({ id });
console.log(`Call ID: ${id}`);
console.log(`Status: ${status.status}`);

The call ID is an opaque identifier. Don't parse it or depend on its format, which may change without notice. Only pass it back to Alchemy APIs such as waitForCallsStatus.

Using @account-kit/wallet-client (v4)?

The examples on this page use @alchemy/wallet-apis (v5). If you're using @account-kit/wallet-client (v4), the client setup looks like this:

client.ts (v4)
import { LocalAccountSigner } from "@aa-sdk/core";
import { createSmartWalletClient } from "@account-kit/wallet-client";
import { alchemy, sepolia } from "@account-kit/infra";
 
const signer = LocalAccountSigner.privateKeyToAccountSigner("0xYOUR_PRIVATE_KEY" as const);
 
export const client = createSmartWalletClient({
  transport: alchemy({ apiKey: "YOUR_API_KEY" }),
  chain: sepolia,
  signer,
  account: signer.address, // can also be passed per action as `from` or `account`
  // Optional: sponsor gas for your users (see "Sponsor gas" guide)
  policyId: "YOUR_POLICY_ID", 
});

Key v4 differences:

  • Account address must be specified on the client or per action (from or account). In v5, the client automatically uses the owner's address as the account address via EIP-7702.
  • Chain imports come directly from @account-kit/infra instead of viem/chains.
  • Numeric values use hex strings: value: "0x0" instead of value: BigInt(0).
  • In v4, the paymaster capability on prepareCalls or sendCalls is called paymasterService instead of paymaster, or you can set the policyId directly on the client.
  • Owners use LocalAccountSigner / WalletClientSigner from @aa-sdk/core. In v5, a viem LocalAccount or WalletClient is used directly.

See the full migration guide for a complete cheat sheet.

Was this page helpful?