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:
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
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:
{
"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:
nvm install 18.10.0
nvm use 18.10.0
nvm install 18.10.0
nvm use 18.10.0
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.

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
.
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:
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 UserOperation
s 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.

4. Send a User Operation Using Account Kit
Finally, let's deploy the newly funded smart account and send a UserOperation
on its behalf.
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:
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:
- "precheck failed: maxFeePerGas is XXX but must be at least XXX, which is based on the current block base fee"
- "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.
To learn more about the different packages and their use cases, check out the "Packages Overview" page.
To learn about the end-to-end process of integrating smart accounts in your applications, check out the section on Smart Accounts.
To learn about the
owner
field on your smart account, check out the section on Choosing a Signer to own the smart account.To learn more about different User Operations you can send with different
target
anddata
fields in thesendUserOperation
function above, look at our How to Send a User Operation guide for an example using NFT mints.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.
To see Account Kit in action, check out our Demos.