Interacting with cryptocurrency wallets is a foundational skill for building decentralized applications (dApps) on the Solana blockchain. Whether you're creating a simple frontend interface or a complex DeFi platform, understanding how users securely connect and transact through their wallets is essential. This guide walks you through the core concepts of wallet integration, focusing on software wallets like Phantom and leveraging Solana’s Wallet-Adapter library to streamline development.
Understanding Cryptocurrency Wallets
At the heart of every blockchain interaction lies cryptography — specifically, public-private key pairs. These keys allow users to prove ownership of their accounts and sign transactions without revealing sensitive information.
While the public key can be freely shared (it acts as your wallet address), the private key must remain secret. If compromised, an attacker could drain all assets from your account and perform unauthorized actions.
A wallet is any tool or device designed to securely store your private key and facilitate transaction signing. Wallets fall into two main categories:
- Hardware wallets: Physical devices (like Ledger) that store keys offline, offering high security.
- Software wallets: Applications installed on computers or mobile devices, often in the form of browser extensions.
👉 Discover how secure wallet integrations power modern dApps
Most developers building on Solana work with software wallets, especially browser-based extensions such as Phantom. These tools make it easy for websites to request user permissions, retrieve public addresses, and prompt transaction approvals — all without ever accessing the private key.
Key Interactions Between Websites and Wallets
When a dApp connects to a wallet, it can typically perform these actions:
- Read the user's public key (wallet address)
- Submit a transaction for approval
- Send the signed transaction to the Solana network
The actual signing happens inside the wallet app using the private key. The website only receives confirmation once the user approves the action.
⚠️ Never ask users to input their private keys into your application. Always rely on trusted wallet providers and standard protocols.
Introducing Phantom: A Leading Solana Wallet
Phantom is one of the most widely used software wallets in the Solana ecosystem. It supports major browsers (Chrome, Brave, Firefox, Edge) and offers mobile apps for iOS and Android. Its seamless integration with dApps makes it ideal for developers aiming to deliver smooth user experiences.
While supporting multiple wallets enhances accessibility, this guide focuses on Phantom due to its popularity and developer-friendly design.
Simplifying Wallet Integration with Solana’s Wallet-Adapter
Manually handling connections across different wallets would be time-consuming and error-prone. That’s where Solana’s Wallet-Adapter comes in — a modular suite of libraries that standardizes wallet interactions.
This adapter supports all wallets compliant with the Wallet Standard, which covers nearly every major Solana wallet today.
Core Packages You’ll Use
@solana/wallet-adapter-base– Foundational types and interfaces@solana/wallet-adapter-react– React hooks for managing connection state@solana/wallet-adapter-react-ui– Pre-built UI components (buttons, modals)@solana/wallet-adapter-wallets– Adapters for specific wallets (e.g., Phantom)
Installing Required Dependencies
To add wallet support to a React-based dApp, install the core packages:
npm install @solana/wallet-adapter-base \
@solana/wallet-adapter-react \
@solana/wallet-adapter-react-uiThese libraries enable you to manage wallet state, display connection UIs, and interact with the blockchain using clean, reusable code.
Setting Up Wallet Context Providers
To maintain consistent wallet and network connection states across your app, wrap your components with context providers.
Start by creating a WalletContextProvider.tsx file:
import { FC, ReactNode } from "react";
import { ConnectionProvider, WalletProvider } from "@solana/wallet-adapter-react";
import { WalletModalProvider } from "@solana/wallet-adapter-react-ui";
import * as web3 from "@solana/web3.js";
import { useMemo } from "react";
require("@solana/wallet-adapter-react-ui/styles.css");
const WalletContextProvider: FC<{ children: ReactNode }> = ({ children }) => {
const endpoint = web3.clusterApiUrl("devnet");
const wallets = useMemo(() => [], []);
return (
<ConnectionProvider endpoint={endpoint}>
<WalletProvider wallets={wallets}>
<WalletModalProvider>
{children}
</WalletModalProvider>
</WalletProvider>
</ConnectionProvider>
);
};
export default WalletContextProvider;This setup ensures your entire app has access to:
- A connection to the Solana Devnet
- Wallet connection status
- Modal functionality for wallet selection
Wrap your main app component with this provider to enable global access.
Adding a Connect Wallet Button
Instead of building custom buttons, use WalletMultiButton from @solana/wallet-adapter-react-ui. It automatically changes its label based on connection status ("Connect Wallet", "Disconnect", etc.).
Update your layout component (e.g., AppBar.tsx) like so:
import { WalletMultiButton } from "@solana/wallet-adapter-react-ui";
export const AppBar: FC = () => {
return (
<div>
<h2>Wallet-Adapter Example</h2>
<WalletMultiButton />
</div>
);
};Now users can click the button to select their preferred wallet (like Phantom) and connect securely.
👉 See how top dApps implement seamless wallet onboarding
Accessing User Account Information
Once connected, retrieve the user’s public key and fetch account data using useWallet and useConnection.
Here’s an example component that displays a user’s SOL balance:
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { LAMPORTS_PER_SOL } from "@solana/web3.js";
import { FC, useEffect, useState } from "react";
export const BalanceDisplay: FC = () => {
const [balance, setBalance] = useState(0);
const { connection } = useConnection();
const { publicKey } = useWallet();
useEffect(() => {
if (!connection || !publicKey) return;
// Listen for balance changes
const subscriptionId = connection.onAccountChange(
publicKey,
(updatedAccountInfo) => {
setBalance(updatedAccountInfo.lamports / LAMPORTS_PER_SOL);
},
"confirmed"
);
// Fetch initial balance
connection.getAccountInfo(publicKey).then((info) => {
if (info) setBalance(info.lamports / LAMPORTS_PER_SOL);
});
return () => {
connection.removeAccountChangeListener(subscriptionId);
};
}, [connection, publicKey]);
return <p>{publicKey ? `Balance: ${balance.toFixed(2)} SOL` : ""}</p>;
};This component updates in real time whenever the account balance changes — perfect for dashboards or trading interfaces.
Sending Transactions via Wallet Approval
To initiate a transaction (e.g., sending tokens or interacting with a smart contract), use the sendTransaction function provided by useWallet.
Example: Sending 0.1 SOL to another address:
const { publicKey, sendTransaction } = useWallet();
const { connection } = useConnection();
const sendSol = async (recipient: string) => {
if (!publicKey || !connection) return;
const transaction = new web3.Transaction();
const recipientPubKey = new web3.PublicKey(recipient);
const instruction = web3.SystemProgram.transfer({
fromPubkey: publicKey,
toPubkey: recipientPubKey,
lamports: LAMPORTS_PER_SOL * 0.1,
});
transaction.add(instruction);
try {
const signature = await sendTransaction(transaction, connection);
console.log("Transaction sent:", signature);
// Optionally link to https://explorer.solana.com/tx/${signature}
} catch (err) {
console.error("Transaction failed:", err);
}
};When called, this triggers the connected wallet (e.g., Phantom) to show a confirmation popup. The user reviews and approves — or rejects — the transaction.
Frequently Asked Questions
What is a blockchain wallet?
A blockchain wallet stores cryptographic keys and enables secure interactions with decentralized networks. It allows users to view balances, receive funds, and approve transactions without exposing private keys.
Can I build a dApp without supporting Phantom?
Yes, but Phantom dominates the Solana ecosystem. Supporting it ensures broader user adoption. However, Wallet-Adapter makes adding support for other wallets straightforward.
How does Wallet-Adapter improve security?
It abstracts direct wallet communication through standardized interfaces. Your app never handles private keys — signing occurs within the isolated environment of the wallet app itself.
Why use Devnet during development?
Devnet is a public test network where developers can test applications using free SOL. It mimics mainnet behavior without financial risk.
Is it safe to connect my wallet to any site?
Only connect to trusted dApps. Malicious sites may request excessive permissions or trick users into approving harmful transactions.
What happens if I lose my wallet?
If you lose access and don’t have a backup (like a seed phrase), you may permanently lose your assets. Always back up recovery phrases securely and never share them.
Hands-On Lab: Build a "Ping" Button for a Smart Contract
Let’s apply what we’ve learned by building a frontend that lets users trigger a "ping" on a deployed Solana program.
Step 1: Set Up Phantom in Devnet Mode
Download Phantom, create a wallet, then switch to Devnet under Developer Settings to match our test environment.
Step 2: Initialize Your Project
Use a starter Next.js template with basic structure. Install required dependencies including @solana/web3.js.
Step 3: Wrap App With Context Providers
As shown earlier, wrap your app with ConnectionProvider, WalletProvider, and WalletModalProvider.
Step 4: Add Wallet Connection UI
Replace placeholder buttons with WalletMultiButton for seamless connection flow.
Step 5: Implement the Ping Functionality
Create a button that constructs and sends a transaction to the ping program at address ChT1B39WKLS8qUrkLvFDXMhEJ4F1XZzwUNHUt4AU9aVa.
On click:
- Verify connection and public key
- Create instruction targeting the data account (
Ah9K7dQ8EHaZqcAsgBW8w37yN2eAy3koFmUn4x3CJtod) - Submit via
sendTransaction
After approval, Phantom returns a transaction signature — link it to Solana Explorer for verification.
Challenge: Build a SOL Transfer dApp
Now try building independently:
- Allow users to send SOL from their Phantom wallet to any recipient.
- Include input validation and feedback messages.
- Enhance UX by linking to transaction explorers post-send.
Use starter code or build from scratch.
👉 Explore advanced dApp patterns used by leading blockchain projects