Skip to content

Getting Started

This guide will help you get started with Account Kit by setting up your environment, creating a smart account, and sending a UserOperation on its behalf. By the end of this guide, you'll have a basic understanding of how to use the SDK and where to look for more advanced use cases.

1. Install the Packages

In your project directory, you'll need to run the following to install the required packages:

bash
npm init es6 -y
npm install -save-dev typescript
npm install @alchemy/aa-alchemy @alchemy/aa-accounts @alchemy/aa-core viem
npm init es6 -y
npm install -save-dev typescript
npm install @alchemy/aa-alchemy @alchemy/aa-accounts @alchemy/aa-core viem
bash
yarn init -y
yarn add -D typescript
yarn add @alchemy/aa-alchemy @alchemy/aa-accounts @alchemy/aa-core viem
yarn init -y
yarn add -D typescript
yarn add @alchemy/aa-alchemy @alchemy/aa-accounts @alchemy/aa-core viem

Note

We're installing viem as well. Viem contains helpful abstractions and modules that will come in handy when using Account Kit. Additionally, many Account Kit modules use viem themselves.

Make sure your new package.json file looks something like the following. Note that we have "type": module in package.json for this example:

json
{
  "name": "account-kit-test",
  "version": "1.0.0",
  "description": "An Example Using Account Kit",
  "main": "index.ts",
  "type": "module",
  "license": "ISC",
  "devDependencies": {
    "typescript": "^5.2.2"
  },
  "dependencies": {
    "@alchemy/aa-accounts": "^1.1.0",
    "@alchemy/aa-alchemy": "^1.1.0",
    "@alchemy/aa-core": "^1.1.0",
    "viem": "^1.19.3"
  }
}
{
  "name": "account-kit-test",
  "version": "1.0.0",
  "description": "An Example Using Account Kit",
  "main": "index.ts",
  "type": "module",
  "license": "ISC",
  "devDependencies": {
    "typescript": "^5.2.2"
  },
  "dependencies": {
    "@alchemy/aa-accounts": "^1.1.0",
    "@alchemy/aa-alchemy": "^1.1.0",
    "@alchemy/aa-core": "^1.1.0",
    "viem": "^1.19.3"
  }
}

You'll also want to make sure your Node version is 18.10.0 using your version manager:

bash
nvm install 18.10.0
nvm use 18.10.0
nvm install 18.10.0
nvm use 18.10.0
bash
asdf install nodejs 18.10.0
asdf global nodejs 18.10.0
asdf reshim nodejs
asdf install nodejs 18.10.0
asdf global nodejs 18.10.0
asdf reshim nodejs

Lastly, create a file called index.ts in the project to write the code you'll see below!

2. Get Your Alchemy API Key

To read or write any data to a blockchain, you'll need an Alchemy API Key and RPC URL. Go to the Alchemy Dashboard and access your credentials from the button shown below.

Account Kit Overview

2. Query Your Smart Account Address

Using the SDK in the following example, we'll use the Account Kit to generate the address of your smart account from which to eventually send a UserOperation.

ts
import {
  LightSmartContractAccount,
  getDefaultLightAccountFactoryAddress,
} from "@alchemy/aa-accounts";
import { AlchemyProvider } from "@alchemy/aa-alchemy";
import { LocalAccountSigner, type Hex } from "@alchemy/aa-core";
import { polygonMumbai } from "viem/chains";

const chain = polygonMumbai;

// The private key of your EOA that will be the owner of Light Account
const PRIVATE_KEY = "0xYourEOAPrivateKey" as Hex;
const owner = LocalAccountSigner.privateKeyToAccountSigner(PRIVATE_KEY);

// Create a provider to send user operations from your smart account
const provider = new AlchemyProvider({
  // get your Alchemy API key at https://dashboard.alchemy.com
  apiKey: "ALCHEMY_API_KEY",
  chain,
}).connect(
  (rpcClient) =>
    new LightSmartContractAccount({
      rpcClient,
      owner,
      chain,
      factoryAddress: getDefaultLightAccountFactoryAddress(chain),
    })
);

(async () => {
  // Fund your account address with ETH to send for the user operations
  // (e.g. Get Sepolia ETH at https://sepoliafaucet.com)
  console.log("Smart Account Address: ", await provider.getAddress()); // Log the smart account address
})();
import {
  LightSmartContractAccount,
  getDefaultLightAccountFactoryAddress,
} from "@alchemy/aa-accounts";
import { AlchemyProvider } from "@alchemy/aa-alchemy";
import { LocalAccountSigner, type Hex } from "@alchemy/aa-core";
import { polygonMumbai } from "viem/chains";

const chain = polygonMumbai;

// The private key of your EOA that will be the owner of Light Account
const PRIVATE_KEY = "0xYourEOAPrivateKey" as Hex;
const owner = LocalAccountSigner.privateKeyToAccountSigner(PRIVATE_KEY);

// Create a provider to send user operations from your smart account
const provider = new AlchemyProvider({
  // get your Alchemy API key at https://dashboard.alchemy.com
  apiKey: "ALCHEMY_API_KEY",
  chain,
}).connect(
  (rpcClient) =>
    new LightSmartContractAccount({
      rpcClient,
      owner,
      chain,
      factoryAddress: getDefaultLightAccountFactoryAddress(chain),
    })
);

(async () => {
  // Fund your account address with ETH to send for the user operations
  // (e.g. Get Sepolia ETH at https://sepoliafaucet.com)
  console.log("Smart Account Address: ", await provider.getAddress()); // Log the smart account address
})();

Copy the above into index.ts. To run the script, do:

bash
npx tsx index.ts
npx tsx index.ts

You'll get a response like this on your terminal:

Smart Account Address: 0xYOUR_SMART_ACCOUNT_ADDRESS
Smart Account Address: 0xYOUR_SMART_ACCOUNT_ADDRESS

3. Fund Your Smart Account

To deploy the smart account and send UserOperations on its behalf, you'll need to add native token to your smart account.

At scale, you might consider using our Gas Manager to sponsor UserOperations for smart accounts. But for the purpose of this example, and because we're using a testnet, let's fund the account using the Alchemy Faucet. Make sure to log in with Alchemy to receive your testnet tokens.

Account Kit Overview

4. Send a User Operation Using Account Kit

Finally, let's deploy the newly funded smart account and send a UserOperation on its behalf.

ts
import {
  LightSmartContractAccount,
  getDefaultLightAccountFactoryAddress,
} from "@alchemy/aa-accounts";
import { AlchemyProvider } from "@alchemy/aa-alchemy";
import { Address, LocalAccountSigner, type Hex } from "@alchemy/aa-core";
import { polygonMumbai } from "viem/chains";

const chain = polygonMumbai;

// The private key of your EOA that will be the owner of Light Account
const PRIVATE_KEY = "0xYourEOAPrivateKey" as Hex;
const owner = LocalAccountSigner.privateKeyToAccountSigner(PRIVATE_KEY);

// Create a provider to send user operations from your smart account
const provider = new AlchemyProvider({
  // get your Alchemy API key at https://dashboard.alchemy.com
  apiKey: "ALCHEMY_API_KEY",
  chain,
}).connect(
  (rpcClient) =>
    new LightSmartContractAccount({
      rpcClient,
      owner,
      chain,
      factoryAddress: getDefaultLightAccountFactoryAddress(chain),
    })
);


(async () => {
  // Fund your account address with ETH to send for the user operations
  // (e.g. Get Sepolia ETH at https://sepoliafaucet.com)
  console.log("Smart Account Address: ", await provider.getAddress()); // Log the smart account address

  const vitalikAddress =
    "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" as Address;
  // Send a user operation from your smart account to Vitalik that does nothing
  const { hash: uoHash } = await provider.sendUserOperation({
    target: vitalikAddress, // The desired target contract address
    data: "0x", // The desired call data
    value: 0n, // (Optional) value to send the target contract address
  });

  console.log("UserOperation Hash: ", uoHash); // Log the user operation hash

  // Wait for the user operation to be mined
  const txHash = await provider.waitForUserOperationTransaction(uoHash);

  console.log("Transaction Hash: ", txHash); // Log the transaction hash
})();
import {
  LightSmartContractAccount,
  getDefaultLightAccountFactoryAddress,
} from "@alchemy/aa-accounts";
import { AlchemyProvider } from "@alchemy/aa-alchemy";
import { Address, LocalAccountSigner, type Hex } from "@alchemy/aa-core";
import { polygonMumbai } from "viem/chains";

const chain = polygonMumbai;

// The private key of your EOA that will be the owner of Light Account
const PRIVATE_KEY = "0xYourEOAPrivateKey" as Hex;
const owner = LocalAccountSigner.privateKeyToAccountSigner(PRIVATE_KEY);

// Create a provider to send user operations from your smart account
const provider = new AlchemyProvider({
  // get your Alchemy API key at https://dashboard.alchemy.com
  apiKey: "ALCHEMY_API_KEY",
  chain,
}).connect(
  (rpcClient) =>
    new LightSmartContractAccount({
      rpcClient,
      owner,
      chain,
      factoryAddress: getDefaultLightAccountFactoryAddress(chain),
    })
);


(async () => {
  // Fund your account address with ETH to send for the user operations
  // (e.g. Get Sepolia ETH at https://sepoliafaucet.com)
  console.log("Smart Account Address: ", await provider.getAddress()); // Log the smart account address

  const vitalikAddress =
    "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" as Address;
  // Send a user operation from your smart account to Vitalik that does nothing
  const { hash: uoHash } = await provider.sendUserOperation({
    target: vitalikAddress, // The desired target contract address
    data: "0x", // The desired call data
    value: 0n, // (Optional) value to send the target contract address
  });

  console.log("UserOperation Hash: ", uoHash); // Log the user operation hash

  // Wait for the user operation to be mined
  const txHash = await provider.waitForUserOperationTransaction(uoHash);

  console.log("Transaction Hash: ", txHash); // Log the transaction hash
})();

Copy the above to replace what's in index.ts. To run the full example script above, do:

bash
npx tsx index.ts
npx tsx index.ts

And that's it! You should see the following on your terminal:

Smart Account Address: 0xYOUR_SMART_ACCOUNT_ADDRESS
UserOperation Hash: 0xYOUR_UO_HASH
Transaction Hash: 0xYOUR_TXN_HASH
Smart Account Address: 0xYOUR_SMART_ACCOUNT_ADDRESS
UserOperation Hash: 0xYOUR_UO_HASH
Transaction Hash: 0xYOUR_TXN_HASH

Note

The UserOperation Hash is what our Bundler returns once it submits the UserOperation to the Blockchain on behalf of your smart account.

To know when the UserOperation is mined on a blockchain in order query information about it, you'll want to use the Transaction Hash.

Handling Errors

When running the above script, you might see the following errors:

  1. "precheck failed: maxFeePerGas is XXX but must be at least XXX, which is based on the current block base fee"
  2. "Failed to find transaction for User Operation"

These are due to increase network activity at that time, and are fleeting issues. Running the script again will resolve them naturally.

Since this "Getting Started" example is a simple script, you'll need to consider how Account Kit can work in various applications. Check out our Demos to see how.

5. Dive Deeper

In this guide, we initialized an AlchemyProvider with the aa-alchemy package to send a UserOperation. However, you can do a lot more with Account Kit and its many packages.

  1. To learn more about the different packages and their use cases, check out the "Packages Overview" page.

  2. To learn about the end-to-end process of integrating smart accounts in your applications, check out the section on Smart Accounts.

  3. To learn about the owner field on your smart account, check out the section on Choosing a Signer to own the smart account.

  4. To learn more about different User Operations you can send with different target and data fields in the sendUserOperation function above, look at our How to Send a User Operation guide for an example using NFT mints.

  5. To explore more ways to use Account Kit, check out the many step-by-step guides, such as How to Sponsor Gas for a User Operation or How to Fetch Smart Account Data.

  6. To see Account Kit in action, check out our Demos.