Server wallets

Server wallets are in early access and we’d love to hear how you’re using them! Contact us at [email protected] - we’d love to help you get up and running.

Server wallets can be programmatically controlled using access keys. This enables backend applications to sign transactions and messages on behalf of users without requiring interactive authentication.

Prerequisites

Get your API key by creating a new app in your Alchemy Dashboard. Make sure your desired network is enabled for your app under the Networks tab.

Step 1: Generate an Access Key

Generate a secure access key for authentication. This key will never be sent to our servers - we’ll derive a public key from it when interacting with Alchemy.

Critical: Save your access key securely!

This access key is required to control your server wallet and cannot be recovered if lost. Make sure to store it in a secure location.

evm.ts
1import { generateAccessKey } from "@account-kit/signer";
2
3// Generate a random access key
4const accessKey = generateAccessKey();
5console.log("Access key:", accessKey);
6
7// Store this securely - you'll need it to control the server signer

Step 2: Create the Server Signer

Before we can send transactions we need a way to sign them. Let’s create a server signer using the access key you just created to handle this:

evm.ts
1import { createServerSigner } from "@account-kit/signer";
2
3const signer = await createServerSigner({
4 auth: {
5 accessKey: "your-access-key-here",
6 },
7 connection: {
8 apiKey: "your-alchemy-api-key",
9 },
10});
11
12console.log("Signer address:", await signer.getAddress());

Want to use the same access key to control multiple server signers? Check out the example below to learn how to use auth.accountId to create multiple signers that you can control with the same access key.

1import { createServerSigner } from "@account-kit/signer";
2
3const businessSigner = await createServerSigner({
4 auth: {
5 accessKey: "your-access-key-here",
6 accountId: "business",
7 },
8 connection: {
9 apiKey: "your-alchemy-api-key",
10 },
11});
12
13const personalSigner = await createServerSigner({
14 auth: {
15 accessKey: "your-access-key-here", // same access key
16 accountId: "personal", // different account ID
17 },
18 connection: {
19 apiKey: "your-alchemy-api-key",
20 },
21});
22
23// These will have different addresses despite using the same access key
24console.log("Business address:", await businessSigner.getAddress());
25console.log("Personal address:", await personalSigner.getAddress());

Step 3: Send a Transaction

We can now send transactions using the Smart Account Client:

evm.ts
1import { createSmartWalletClient } from "@account-kit/wallet-client";
2import { alchemy, baseSepolia } from "@account-kit/infra";
3
4// Create Smart Account Client using the signer from Step 2
5const client = createSmartWalletClient({
6 transport: alchemy({
7 apiKey: "your-alchemy-api-key",
8 }),
9 chain: baseSepolia,
10 signer,
11 policyId: "your-sponsor-gas-policy-id", // Make sure enabled on Base Sepolia
12});
13
14// Retrieve account
15const account = await client.requestAccount();
16console.log("Smart account address:", account.address);
17
18// Send a transaction
19const { preparedCallIds } = await client.sendCalls({
20 calls: [
21 {
22 to: "0x1234567890123456789012345678901234567890",
23 value: "0x0",
24 data: "0x",
25 },
26 ],
27 from: account.address,
28});
29console.log("Transaction sent:", preparedCallIds[0]);

Solana Support

Server wallet can also easily be used on Solana. To start sending sponsored transactions on Solana, set up a Solana sponsor gas policy in our dashboard and follow the guide below.

solana.ts
1import { createServerSigner } from "@account-kit/signer";
2import { Connection, SystemProgram, PublicKey } from "@solana/web3.js";
3
4// Set up Solana connection
5const connection = new Connection(
6 `https://solana-devnet.g.alchemy.com/v2/your-alchemy-api-key`,
7);
8
9const signer = await createServerSigner({
10 auth: { accessKey: "your-access-key" },
11 connection: { apiKey: "your-alchemy-api-key" },
12});
13
14// Convert the signer to a Solana-compatible signer
15const solanaSigner = signer.toSolanaSigner();
16
17// Build transaction instructions
18const instructions = [
19 SystemProgram.transfer({
20 fromPubkey: new PublicKey(solanaSigner.address),
21 toPubkey: new PublicKey(solanaSigner.address),
22 lamports: 0,
23 }),
24];
25
26// Add sponsorship
27const tx = await solanaSigner.addSponsorship(
28 instructions,
29 connection,
30 "your-solana-sponsorship-policy-id", // Make sure enabled on Solana devnet
31);
32
33// Sign the transaction
34await solanaSigner.addSignature(tx);
35
36// Send the transaction
37const hash = await connection.sendTransaction(tx);
38console.log("Transaction sent:", hash);