How to Make a Solana Wallet: A Technical Guide
Author: Usman Asim
In the past few years, Solana has exploded onto the scene as one of the most active blockchain networks, averaging over 1.2 million daily active users and 60M+ transactions (non-voting) per day. That activity is driven by DeFi, DePIN, institutions, enterprises, and more, all happening at lightning speed and at fractions of a penny per transaction.
If you're looking to build on Solana and tap into the the hot and growing ecosystem, then starting with a wallet is a great entry point. Wallets are the gateway to interacting with any chain: signing transactions, holding assets, and powering apps.
In this guide, we'll walk you through creating both regular and smart wallets using our tools at Alchemy. We've built out reliable RPC endpoints for seamless network connections and an SDK for account abstraction to make wallet building straightforward and scalable. Let's dive in and get you set up, starting on devnet so you can test things out without spending real SOL.
Wallets on Solana: The Basics
On Solana, wallets aren't quite like what you might be used to on Ethereum. Instead of a strict split between user controlled externally owned accounts (EOAs) and smart contracts, Solana treats everything as accounts, which are data storage units on the blockchain. A "wallet" here is often just a keypair (public and private keys) that lets you control one or more of these accounts. Accounts can hold SOL tokens, other assets, or even executable code for programs (Solana's version of smart contracts).
This uniform approach opens the door to cool features like program derived addresses (PDAs), where programs can generate addresses and even sign transactions on behalf of users without needing their private keys.
It's a more flexible setup than Ethereum's model, where EOAs are purely for signing and contracts handle the logic separately. For more on Solana's account model, check out the official Solana docs on accounts and wallets.
Solana wallets generally fall into two camps:
Regular wallets (keypair based): These are your straightforward cryptographic keypairs for signing transactions and managing accounts. They're great for scripts or testing, but you'll handle keys and fees manually.
Smart wallets (with account abstraction): These level up the experience by hiding away the nitty gritty details like key management. Smart wallets support things like social authentication (e.g., signing in with email or passkeys instead of seed phrases), gas/rent sponsorship (where someone else pays transaction fees), batched transactions (multiple actions in one go), and even automated behaviors powered by programmable logic. Solana's design makes these especially potent for apps, going beyond Ethereum's ERC-4337 focus on UX tweaks. Dive deeper into Solana's account abstraction in the Solana Cookbook on wallet management and the deep dive of ERC-4337 on Solana.
In this tutorial, we'll build both of these types of wallets using Alchemy's tools. Our RPC endpoints give you reliable access to the Solana network without spinning up your own node, and our Smart Accounts (in beta for Solana as of late 2025) handle the wallet magic. Head over to our Solana Smart Wallets getting started guide for the latest on the SDK.
Prerequisites: Setting Up Your Devnet Environment
Before we jump into the code, let's make sure you're ready. This tutorial assumes you're comfortable with basic JavaScript, but we'll explain concepts along the way so everyone can keep up. Here's what you'll need:
Node.js (v16 or higher) and npm/yarn: This is your runtime for running JS code outside the browser. You can download it from nodejs.org if you haven't already.
A code editor like VS Code or Cursor: Somewhere to write and debug your code. VS Code is free and has great extensions for blockchain development. You can get set up here. Cursor is like a cooler, AI-enabled version of VS Code. You can check it out here.
Basic JavaScript knowledge; React for smart wallet parts: We'll use React hooks in the smart wallet section, but if you're not using React, dont worry, we will cover adaptations to other frameworks later. Need React basics? Check out React's quick start.
An Alchemy account: Sign up for free at dashboard.alchemy.com. Create a new app, select Solana (devnet for testing, mainnet for production), and grab your API key. While you're there, enable an EVM chain like Sepolia if you want hybrid support – it's handy for cross-chain apps.
For regular wallets: Install the Solana web3.js library, which handles key generation, connections, and transactions. This library is the go to for interacting with Solana programs.
npm install @solana/web3.jsFor smart wallets: Install Alchemy's Account Kit packages, plus Solana web3.js for compatibility. The Account Kit is our SDK for embedded wallets across chains. See our soical auth integration docs for more info.
yarn add @account-kit/infra @account-kit/react @solana/web3.js
Pro tip: Build everything on devnet first. It's the main test environment that mimics deploying on mainnet perfectly and allows you to test your contracts, run through your flows, make sure everything works. Once you're confident, have deployed to testnet and thoroughly tested everything, deploying to mainnet is as simple as swapping the RPC URL. No code changes needed: just flip the switch.
Understanding Solana's Wallet Structure
Before we generate a wallet, let’s back up and give some quick context on how Solana wallets work. This will help you grasp why the steps we're about to take make sense, especially if you're coming from Ethereum.
Accounts vs. wallets: In Solana, a wallet is essentially a keypair that owns accounts. Accounts are like buckets for data: they can store your SOL balance, tokens, or program code. Unlike Ethereum, where EOAs (user addresses) are distinct from contract addresses, Solana blurs the lines: everything is an account. This means you can create accounts on the fly, fund them separately, and even have programs control them via PDAs. No automatic account creation on key gen; you fund to initialize. For a deeper dive, see Solana's core concepts.
Rent instead of dynamic gas fees: Solana doesn't use Ethereum style gas for every computation unit: transactions have flat fees (super low, like $0.00025 on average as of 2025) but accounts pay "rent" to keep their data stored on the chain if your balance dips below a threshold (about 0.00089 SOL per KB). It's like a storage deposit: pay upfront or maintain enough SOL to exempt it. This keeps the network lean by pruning inactive accounts. Transactions still cost fees, but rent is the unique twist for persistence. You can compare it to Ethereum's gas, which hits you per operation and can spike during congestion. Solana's model prioritizes speed instead. Read more in Solana's rent docs.
PDAs and programmability: Programs can derive "program derived addresses" that look like regular addresses but are controlled by code, not keys, which allows smart wallet features like automated signing. It's more baked in to the core Solana Architecture than Ethereum's contract wallets.
Grasping these concepts helps you see why Solana wallets feel more "programmable" out of the box. It all comes back to that concept of flexible accounts.
How to Make a Regular Solana Wallet: Step-by-Step
Regular wallets are your entry level setup: a simple keypair for signing transactions. They're perfect for backend scripts, testing, or when you want full control without abstractions. In this tutorial, we'll use @solana/web3.js to generate a keypair.
Then we will use Alchemy's RPC to connect to the network; without a RPC connection, your wallet can't query balances or send transactions.
Step 1: Generate a Keypair
Generating a wallet on Solana means creating a fresh cryptographic keypair, essentially a pair of mathematically linked keys that work together. The public key becomes your wallet address on Solana, which you can share freely with anyone who needs to send you funds or interact with your account. The private key (also called the secret key) is what proves you own that address and allows you to sign transactions.
Here's an important distinction from Ethereum: on Ethereum, when you generate an Externally Owned Account (EOA), it's immediately "ready" and exists on the blockchain. On Solana, generating a keypair just creates the cryptographic keys, the actual account on the blockchain doesn't exist until someone funds that address. This is part of Solana's account model where accounts need rent exemption balance to persist on chain.
Create a new JS file (say, regular-wallet.js) and run this snippet:
import { Keypair } from '@solana/web3.js';
const wallet = Keypair.generate();
console.log('Public Key (Wallet Address):', wallet.publicKey.toString());
console.log('Secret Key:', wallet.secretKey); // Secure this immediately! Never log in production.Run this script with node.js and boom: you've got a wallet.
Here's what you should have gotten returned:
Public Key (Wallet Address): This is a base58-encoded string that looks something like
7xj9WkvP6Az8vG5nXJh4Fq3qY8kPqT9wXVZN2xMqGnD4. This is what you'll share with others when you want to receive funds, and it's what you'll use when connecting to dApps or checking your balance. Think of it like your bank account number, it's safe to share publicly.Secret Key: This is returned as a
Uint8Array(an array of 64 bytes). This is your private key and is the cryptographic proof that you control this wallet. Anyone with access to this secret key can sign transactions and move funds from your wallet. Never, ever share this or commit it to version control.
Critical security practices for the secret key:
Never log it in production: The
console.login our example is fine for local testing, but remove it before deploying any real application.Use environment variables: Store it in a
.envfile that's added to your.gitignore. Access it withprocess.env.PRIVATE_KEYin your code.Consider hardware wallets: For production applications handling significant value, integrate hardware wallets like Ledger or Trezor that keep private keys isolated in secure hardware.
Encrypt if storing: If you must store the secret key in a database or file, encrypt it first using strong encryption libraries.
For security best practices, check Solana's security guide.
Step 2: Connect to the Network via Alchemy RPC
Now, connect your wallet to Solana's devnet using an RPC endpoint. This "connection" object lets your code talk to the blockchain, fetch balances, submit transactions, etc. Alchemy's RPC is like a supercharged proxy to Solana nodes, handling load balancing so your app stays responsive.
Add this to your script (replace <YOUR_API_KEY> with your key from the Alchemy dashboard):
import { Connection } from '@solana/web3.js';
const connection = new Connection(
'https://solana-devnet.g.alchemy.com/v2/<YOUR_API_KEY>', // Devnet for testing
'confirmed' // Commitment level: 'confirmed' for speed with some finality
);
async function checkBalance(publicKey) {
const balance = await connection.getBalance(publicKey);
console.log('Balance:', balance / 1e9, 'SOL'); // Convert lamports (1 SOL = 1e9 lamports)
}
await checkBalance(wallet.publicKey);This connection enables you to check whether you wallet is funded and to interact with apps. Run the script; if unfunded, the response will show 0 SOL. For full RPC methods, see Solana's RPC docs or our Alchemy Solana RPC guide.
Step 3: Fund and Interact with Your Wallet
With the connection live, let's interact onchain. This is where the fun starts: funding via airdrop (devnet only), signing transactions, etc. These basics let you transfer SOL, call programs, or build simple tools.
Request an Airdrop (Funding on Devnet)
Devnet gives free SOL for testing, allowing you to fund your account if it's empty, but be mindful that you are limited to ~24 SOL/day per IP address.
You’ll need to fund your account for rent exemptions in fees. This method also only works for devnet. In production, where fees are paid in real SOL (and not test SOL), you will need to buy/fund your account via an exchange like Coinbase. See Solana's Devnet Sol Guide.
const airdropSignature = await connection.requestAirdrop(
wallet.publicKey,
1e9 // 1 SOL in lamports
);
await connection.confirmTransaction(airdropSignature);
console.log('Airdrop complete! Check balance again.');Here's what's happening:
Request the airdrop:
connection.requestAirdrop()asks the devnet for test SOL. It takes your wallet's public key and the amount in lamports (1e9= 1 SOL), then returns a transaction signature, a unique identifier for this transaction.Confirm the transaction:
await connection.confirmTransaction()waits for the network to process your airdrop. This is crucial, without waiting for confirmation, your balance might still show 0 SOL even though the airdrop was requested. Solana processes transactions asynchronously, so you need to wait.Success: Once confirmed, run
checkBalance()again and you should see 1 SOL in your wallet.
Sign and Send a Transaction
Let's transfer 0.1 SOL to another address. This example demonstrates transaction signing, where your private key cryptographically authorizes the transaction, proving you own the sending wallet. We'll build a transaction, sign it with your keypair, and broadcast it to the network via RPC. Transaction fees (around 0.000005 SOL) are deducted automatically from your balance. For more complex operations like multi-instruction transactions or program calls, explore Solana's transaction basics documentation.
Run this code to send SOL:
import { Transaction, SystemProgram, PublicKey, sendAndConfirmTransaction } from '@solana/web3.js';
const recipient = new PublicKey('recipient_address_here'); // Replace with a real address`
const tx = new Transaction().add(
SystemProgram.transfer({
fromPubkey: wallet.publicKey,
toPubkey: recipient,
lamports: 1e8 // 0.1 SOL
})
);
// Simplest approach - handles blockhash and confirmation automatically
const signature = await sendAndConfirmTransaction(
connection,
tx,
[wallet] // Signers
);
console.log('Transfer signature:', signature);Here's what's happening:
Create the recipient:
new PublicKey()converts a base58-encoded address string into a PublicKey object that Solana can work with. Replace'recipient_address_here'with an actual Solana address (you could even use your own wallet's public key to test sending to yourself).Build the transaction:
new Transaction().add()creates a transaction and adds a transfer instruction. TheSystemProgram.transfer()call specifies the sender (fromPubkey), recipient (toPubkey), and amount in lamports (1e8 = 0.1 SOL).Send and confirm:
sendAndConfirmTransaction()is a helper function that handles three steps in one: it fetches the latest blockhash (required for all Solana transactions), signs the transaction with your wallet keypair, sends it to the network, and waits for confirmation. The[wallet]array contains all signers, in this case, just your wallet.Transaction signature: The returned signature is your proof of execution, a unique identifier for this specific transaction on the blockchain.
Security Tip: Never hardcode secret keys. Instead use
process.env.PRIVATE_KEY. For production, integrate hardware wallets to alleviate any other points of attack. For more on secure key management, view our best practices for key management & security.
And if all went well, you should have gotten a successful transaction signature back! That signature is your proof the transaction was processed on Solana's blockchain. You can look it up on Solana Explorer to see the full details: sender, recipient, fee paid, and block confirmation.
That's the essence of interacting with a simple Solana wallet on devnet: generate a keypair, connect via RPC, fund it, and sign transactions. These building blocks: keypair generation, network connection, balance checks, and transaction signing are the foundation for any Solana development work.
These regular keypair based wallets we just interacted with are perfect for backend scripts that need programmatic control, testing and development, for folks who prefer direct management of their keys, and simple uses cases like basic transfers and program interactions. However, you can see they come with their own trade offs: users must manage their own keys, pay their own fees, and handle the technical complexity of blockchain interactions. For consumer facing apps where UX matters, this friction can be a dealbreaker.
That's where smart wallets come in. They abstract away the complexity while giving you powerful features like social login, gasless transactions, and session keys. Let's explore how to build smart wallets on Solana that make Web3 feel like Web2.
How to Make a Smart Solana Wallet: Leveling Up with Account Abstraction
Smart wallets take the regular accounts we learned about and add account abstraction magic, making any app feel more like a Web2 app. No more seed phrases; instead, users log in socially (email, phone number, etc), and features like fee sponsorship mean users don’t need to provide SOL upfront in order to take actions. Alchemy Smart Wallets, simplifies this for Solana, It's great for user facing apps where UX matters, think onboarding newbies without wallet friction.
Here’s how to set up a smart wallet on Solana:
Step 1: Configure the SDK
First, we need to configure the Account Kit SDK. This configuration tells the SDK how to connect to Solana, which networks to use, and what policies to apply (like who pays for gas). Think of this as setting up the communication channel between your app and the blockchain.
The SDK needs config to know your chains and connection details. This sets up the "transport" for Solana interactions. Create a config.ts (or .js) file in your project root – assuming you have a React app set up (if not, start one with npx create-react-app my-solana-app for basics).
import { cookieStorage, createConfig } from "@account-kit/react";
import { Connection } from "@solana/web3.js";
import { sepolia } from "@account-kit/infra"; // EVM chain for hybrid AA support
export const config = createConfig({
// Other options like transport for EVM if needed
chain: sepolia, // Example EVM chain; adjust as needed
solana: {
connection: new Connection(
"https://solana-devnet.g.alchemy.com/v2/<YOUR_API_KEY>",
{
wsEndpoint: "wss://api.devnet.solana.com", // WebSocket for real-time updates
commitment: "confirmed",
}
),
policyId: "<YOUR_POLICY_ID>", // Optional: For gas sponsorship policies from Alchemy dashboard
},
ssr: true, // Enable server-side rendering if your app uses it
storage: cookieStorage, // Stores session data securely in browser cookies
});Let's break down what's happening here:
connection: This creates the link to Solana's devnet through Alchemy's RPC endpoint. Replace
<YOUR_API_KEY>with your actual API key from the Alchemy dashboard.wsEndpoint: This WebSocket connection enables real-time updates, so your app can instantly reflect transaction confirmations and account changes without constant polling.
commitment: Set to "confirmed" for a balance between speed and finality, transactions are highly unlikely to be reversed at this level.
policyId: This is where the magic of gas sponsorship happens. You can create policies in your Alchemy dashboard that define rules for when your app will pay transaction fees on behalf of users. This is optional but powerful for UX.
storage: Using cookie storage keeps user sessions secure and persistent across page refreshes.
chain: If you're building a cross-chain app that works on both Solana and EVM chains (like Ethereum), you can specify an EVM chain here. This enables hybrid functionality.
Now that we have our configuration, we need to make it available throughout our entire React application. We do this by wrapping our app with the AccountKitProvider component. This is similar to how React's Context API works, it creates a "context" that any component in your app can access.
Why is this important? Once wrapped, any component in your app can use Account Kit's hooks to access wallet functionality, authenticate users, sign transactions, and more. Without this wrapper, those features wouldn't be available.
Open your src/App.js (or src/App.tsx) file and modify it like this:
import { AccountKitProvider } from "@account-kit/react";
import { config } from "./config"; // Import the config file we just created
function App() {
return (
<AccountKitProvider config={config}>
/* Your app's components go here */
/** Any component inside this provider can now use Account Kit hooks */
</AccountKitProvider>
);
}
export default App;This provider does several things behind the scenes:
It initializes the connection to Solana using your configuration
It manages the user's authentication state across your entire app
It provides hooks like
useSigner(),useAuthenticate(), anduseUser()to all child componentsIt handles session persistence so users stay logged in between visits
Important note for non React developers: If you're building a Node.js backend, a vanilla JavaScript app, or using a different framework, you won't use this provider pattern. Instead, you can import and use SolanaSigner directly from the SDK. Check out our documentation on different frameworks for implementation details on using Account Kit outside of React.
Step 2: Create and Use the Wallet with Hooks
Now that we've configured the SDK and wrapped our app with the provider, we can start actually using the smart wallet in our components. React hooks are functions that let us "hook into" React features like state and lifecycle methods. In this case, we'll use Account Kit's custom hooks to interact with the user's Solana smart wallet.
The useSolanaSigner hook is your main interface to the wallet. It returns a signer object that represents the user's smart wallet: this is what you'll use to get their address, sign transactions, and interact with the blockchain. The beauty here is that all the complex key management, account creation, and signing logic is handled automatically behind the scenes.
Create a new component file called WalletComponent.js in your components folder:
import { useSolanaSigner } from "@account-kit/react";
function WalletComponent() {
const { data: signer, isLoading } = useSolanaSigner({});
if (isLoading) return <div>Loading wallet...</div>;
if (!signer) return <div>No signer available – check login</div>;
return <div>Solana Address: {signer.address}</div>;
}
export default WalletComponent;Let's break down what's happening in this component:
The useSolanaSigner hook: This hook does the heavy lifting. When called, it checks if the user has an authenticated session. If they do, it returns their smart wallet signer. If not, it returns null. The hook also provides an isLoading state so you can show loading indicators while the wallet is being initialized.
Loading state: While the SDK is initializing the wallet connection or checking for an existing session, isLoading will be true. This is when you want to show a spinner or loading message to your users. Good UX means never leaving users wondering what's happening.
No signer scenario: If signer is null or undefined, it means the user hasn't logged in yet or their session has expired. This is your cue to either redirect them to a login flow or display authentication options. We'll cover the authentication piece in the next step.
The signer object: Once you have a valid signer, it contains everything you need to interact with the blockchain on behalf of the user. The most immediately useful property is signer.address, which is the user's Solana public key (their wallet address). You can display this to users, use it to query their balances, or include it in transactions.
What else can you do with the signer? Beyond just displaying the address, the signer object is what you'll pass to transaction functions. For example, if you want to send SOL or interact with a Solana program, you'll use hooks like useSolanaSendTransaction and pass the signer to them. The signer handles all the cryptographic signing without the user ever seeing or managing private keys.
A key point about smart wallets: Notice how we never generated a keypair, never asked the user to back up a seed phrase, and never handled private keys? That's the account abstraction magic at work. The user's authentication (which we'll set up next via social login) is what controls access to this wallet, but the actual key management happens securely in the background, often using techniques like multi-party computation (MPC) or secure enclaves.
For complete examples of sending transactions, interacting with programs, or checking balances using the signer, check out our Solana transactions guide in the Account Kit documentation.
Step 3: Leverage Advanced Features
Smart wallets shine when it comes to advanced features. Each builds on account abstraction to improve UX and reduce barriers, perfect for apps where users hate fumbling with wallets. Those advanced features include things like:
Social login: Let users sign in with email, Google, or passkeys instead of managing their own account keys. This creates a PDA based wallet on first login, without needing seed phrases. This slashes onboarding drop off: new users just click "Sign in with Google" and are done, dramatically simplifying the onboarding process. You can integrate this with the SDK’s auth methods. See an example in Alchemy's social login docs.
Sponsorship (gas/rent coverage): Sponsors (the app or a 3rd party provider) pay user fees via a policy ID, so users go gasless (simplifying their UX). On Solana, this sponsorship covers transaction fees and rent. This can boost conversions in free to play games or airdrops because users don’t have to handle SOL prompts to fund wallets to handle fees or set their own fee rates. Learn more in sponsorship gas and rent setup.
Batching transactions: Bundles multiple instructions (e.g. transfers or program calls) into a single transaction. Instead of separate sends, this enables things like handling swaps + stakes atomically. This can save on transaction fees and ensures all or nothing execution. You can use the SDK's
useSendTransactionwith an array of instructions. See batching examples.Non-React adaptation: If you're in vanilla JS or another framework, export the signer from the config and use it directly (e.g.,
const signer = getSolanaSigner(config)). This keeps AA portable. For details, check out non-React SDK usage.
The SDK ties it all together, abstracting Solana's quirks into a clean API. Test on devnet, and you're ready for production grade UX.
Regular vs. Smart Wallets: A Quick Comparison
To help you decide what you need for your use case, here's a table breaking down the key differences in wallet types on Solana. This highlights when to use each in your projects.

Best Practices: Tips to Keep in Mind While Building
As you craft your Solana wallet, here are some best practices and tips to ensure it's secure, scalable, and user-friendly.
Security first: For regular wallets, always use hardware wallets (like Ledger or Trezor) for mainnet to keep keys offline. With smart wallets, lean on the SDK's passkeys or multi-factor auth to reduce phishing risks by avoiding seed phrases. Never expose secrets in code; use encrypted storage. Audit your setup with tools like Solana's security guide.
Test thoroughly: Always start on devnet or testnet to iterate without costs. Use Alchemy's dashboard to monitor RPC usage, transaction failures, and performance metrics. It's like a built in debugger for your blockchain calls. Simulate edge cases like network congestion to ensure retries work.
Error handling and reliability: Wrap RPC calls in try-catch blocks and add exponential backoff retries (e.g., via libraries like p-retry). Solana's speed can lead to race conditions, so confirm transactions with 'finalized' commitment for max safety. This keeps your app robust, especially for high-volume apps.
Scalability considerations: Alchemy's infrastructure auto-scales for high loads, so you won't bottleneck on RPC. For smart wallets, batch where possible to minimize transactions. Monitor rent exemptions to avoid surprise costs. Tools like Solscan explorer help track this.
Resources for deeper dives: Stay updated with Alchemy's Solana docs for SDK changes, and explore Solana's official react wallet adapters for UI integrations.
Wrapping Up: Time to Build on Solana
There you have it – you've now got the know how on how to spin up regular and smart Solana wallets with Alchemy's help. Whether you're scripting simple transfers or building a killer dApp with gasless logins, Solana's ecosystem is primed for innovation. Now's the time to jump in and start experimenting. For more, check out our full Solana developer resources and the Solana docs. Happy building – if you run into questions, hit us up on Discord or support. Let's make some onchain magic!
Alchemy Newsletter
Be the first to know about releases
Related articles
How to Use a Blockchain API
Discover the basics of blockchain APIs, from the fundamentals to practical implementation steps.
How to Use AI Tools in Crypto App Development
Unlock your app's full potential and start coding with AI.

Priority Blockspace for Humans on World Chain: Mainnet-Ready with Alchemy
World Chain launches Priority Blockspace for Humans. Verified humans now get priority transactions over bots. Deep dive into the technical implementation and collaboration behind this milestone.