Skip to content
Alchemy Logo

Wallets API Quickstart (SDK)

Learn to interact with Wallet APIs using the Wallet Client SDK

You're going to need @account-kit/wallet-client, @account-kit/infra, optionally @aa-sdk/core if you use a LocalAccountSigner, and optionally viem if you want to verify a signed message.

npm install @account-kit/wallet-client @account-kit/infra @aa-sdk/core

Given a signer (e.g. a LocalAccountSigner imported from @aa-sdk/core or an Alchemy Signer), all you need to do is follow a few simple steps to start sending user ops with Wallet APIs!

import { createSmartWalletClient } from "@account-kit/wallet-client";
import { alchemy, arbitrumSepolia } from "@account-kit/infra";
import { LocalAccountSigner } from "@aa-sdk/core";
 
const signer = LocalAccountSigner.privateKeyToAccountSigner(PRIVATE_KEY); // we use a private key signer as an example here
 
const transport = alchemy({
  apiKey: ALCHEMY_API_KEY, // use your Alchemy app api key here!
});
 
const client = createSmartWalletClient({
  transport,
  chain: arbitrumSepolia, // use any chain imported from @account-kit/infra here!
  signer,
});

Use your signer address directly as the from field to enable EIP-7702 by default. This first transaction will delegate your account.

import { zeroAddress } from "viem";
 
const signerAddress = await signer.getAddress();
 
const preparedCalls = await client.prepareCalls({
  calls: [{ to: zeroAddress, value: "0x0" }], // callData is optional in a "data" parameter
  from: signerAddress,
  // "capabilities" is a data structure that hold gas manager data (as seen below) or permission data
  capabilities: {
    paymasterService: {
      policyId: GAS_MANAGER_POLICY_ID, // put your gas manager policy ID here
    },
  },
});
 
// Sign the calls (handles both authorization and user operation if account isn't delegated yet)
const signedCalls = await client.signPreparedCalls(preparedCalls);
 
// Send the userOp
const result = await client.sendPreparedCalls(signedCalls);
 
// Check calls status.
const status = await client.getCallsStatus(result.id);

Once your account is delegated, you can sign messages.

import { createPublicClient } from "viem";
 
const signerAddress = await signer.getAddress();
 
const message = "we are so back";
 
const signature = await client.signMessage({ message, account: signerAddress });
 
const publicClient = createPublicClient({
  chain: arbitrumSepolia,
  transport: transport,
});
 
const isValid = await publicClient.verifyMessage({
  address: signerAddress,
  message,
  signature,
});

// assuming you have a typedData variable
const signature = await client.signTypedData({ typedData, account: signerAddress });
 
const isValid = await publicClient.verifyTypedData({
  address: signerAddress,
  ...typedData,
  signature,
});
Was this page helpful?