# Framework Kit - Complete Documentation > Developer tools for Solana built on Solana Kit --- # Framework Kit URL: https://framework-kit.dev/docs > Developer tools for Solana built on Solana Kit A family of libraries for building production-ready Solana apps. Use the universal client in any JavaScript runtime, add React hooks for reactive UIs, or migrate existing web3.js code incrementally. ## Packages | Package | Description | | --- | --- | | [@solana/client](/docs/client) | Framework-agnostic client for wallets, RPC, and transactions. Works in React, Svelte, Vue, Node.js, Bun, workers, or any JavaScript runtime. | | [@solana/react-hooks](/docs/react-hooks) | React hooks and provider built on the client. Reactive state for balances, wallets, and transactions. | | [@solana/web3-compat](/docs/web3-compat) | Compatibility layer for migrating from `@solana/web3.js`. Keep using familiar APIs while adopting Solana Kit under the hood. | ## Why Framework Kit? Building Solana apps usually means wiring together RPC connections, wallet adapters, and state management yourself. Framework Kit handles this for you: - **Universal client** - One client that works everywhere: browsers, servers, edge functions, workers - **Wallet Standard support** - Auto-discover installed wallets with a unified connection API - **Real-time subscriptions** - Watch balances, accounts, and signatures with WebSocket subscriptions - **Token operations** - Built-in helpers for SOL transfers and SPL token operations - **TypeScript-first** - Full type inference and autocomplete out of the box - **Incremental adoption** - Start with web3-compat, migrate to client, add React hooks when ready ## Quick Start ### Using the Client (Any Framework) The client works in any JavaScript environment: ```ts import { autoDiscover, createClient } from "@solana/client"; const client = createClient({ cluster: "devnet", walletConnectors: autoDiscover(), }); // Connect a wallet const connectors = client.connectors.all; await client.actions.connectWallet(connectors[0].id); // Fetch balance const wallet = client.store.getState().wallet; if (wallet.status === "connected") { const balance = await client.actions.fetchBalance(wallet.session.account.address); console.log(`Balance: ${balance.toString()} lamports`); } // Send SOL const signature = await client.solTransfer.sendTransfer({ amount: 100_000_000n, // 0.1 SOL authority: wallet.session, destination: "Fg6PaFpoGXkYsidMpWFKfwtz6DhFVyG4dL1x8kj7ZJup", }); ``` ### Using React Hooks For React apps, wrap once with the provider and use hooks anywhere: ```tsx import { autoDiscover, createClient } from "@solana/client"; import { SolanaProvider, useWalletConnection, useBalance } from "@solana/react-hooks"; const client = createClient({ cluster: "devnet", walletConnectors: autoDiscover(), }); function WalletPanel() { const { connectors, connect, disconnect, wallet, status } = useWalletConnection(); const { lamports } = useBalance(wallet?.account.address); if (status === "connected") { return (

{wallet.account.address.toString()}

Balance: {lamports?.toString() ?? "..."} lamports

); } return connectors.map((c) => ( )); } export function App() { return ( ); } ``` ### Migrating from web3.js If you have existing code using `@solana/web3.js`, swap imports to start migrating: ```diff - import { Connection, PublicKey } from "@solana/web3.js"; + import { Connection, PublicKey } from "@solana/web3-compat"; const connection = new Connection("https://api.devnet.solana.com"); const balance = await connection.getBalance(publicKey); ``` ## Next Steps - [Getting Started](/docs/getting-started) - Install and configure your first project - [Client API](/docs/client) - Core library for any JavaScript runtime - [React Hooks](/docs/react-hooks) - Reactive hooks for React apps - [Migration Guide](/docs/web3-compat) - Migrate from @solana/web3.js --- # API Reference URL: https://framework-kit.dev/docs/api-reference > Complete API reference for Framework Kit packages Quick reference for all exports. Full API docs are auto-generated from TypeScript source via [TypeDoc](https://typedoc.org/). ## @solana/client The core client library exports the following: ### Client Creation | Export | Description | | --- | --- | | `createClient(config)` | Create a new Solana client instance | | `resolveCluster(config)` | Resolve cluster endpoints from moniker or custom URLs | ### Wallet Connectors | Export | Description | | --- | --- | | `autoDiscover(options?)` | Auto-discover installed wallet extensions | | `filterByNames(...names)` | Filter wallets by name | | `phantom()` | Phantom wallet connector | | `solflare()` | Solflare wallet connector | | `backpack()` | Backpack wallet connector | | `metamask()` | MetaMask Snaps connector | | `injected(wallet)` | Generic injected wallet connector | ### Address Utilities | Export | Description | | --- | --- | | `toAddress(input)` | Convert string or PublicKey to Address | | `isAddress(value)` | Check if value is a valid Address | ### Numeric Utilities | Export | Description | | --- | --- | | `LAMPORTS_PER_SOL` | Lamports per SOL constant (1_000_000_000n) | | `lamports(value)` | Create a Lamports value | | `lamportsFromSol(sol)` | Convert SOL to lamports | | `lamportsToSolString(lamports)` | Convert lamports to SOL string | | `createTokenAmount(decimals)` | Create token amount math utilities | ### State Serialization | Export | Description | | --- | --- | | `serializeSolanaState(state)` | Serialize client state for storage | | `deserializeSolanaState(data)` | Deserialize stored state | | `applySerializableState(store, state)` | Apply serialized state to store | ### Types Key TypeScript types exported from the package: ```ts // Client configuration type SolanaClientConfig = { cluster?: ClusterMoniker; endpoint?: string; websocketEndpoint?: string; walletConnectors?: WalletConnectorFn[]; }; // Wallet state type WalletState = | { status: "disconnected" } | { status: "connecting"; connectorId: string } | { status: "connected"; session: WalletSession; connectorId: string }; // Wallet session (for signing) type WalletSession = { account: WalletAccount; signTransaction: (tx: Transaction) => Promise; signMessage: (message: Uint8Array) => Promise; }; // Cluster configuration type ClusterMoniker = "mainnet" | "mainnet-beta" | "testnet" | "devnet" | "localnet" | "localhost"; // Transaction input type TransactionInstructionInput = { programAddress: Address; accounts: AccountMeta[]; data: Uint8Array; }; ``` ## @solana/react-hooks ### Provider | Export | Description | | --- | --- | | `SolanaProvider` | Root provider component | | `SolanaQueryProvider` | Provider for query hooks with Suspense support | ### Wallet Hooks | Hook | Description | | --- | --- | | `useWalletConnection()` | Complete wallet connection management | | `useWallet()` | Access wallet state | | `useWalletSession()` | Get current session for signing | | `useWalletActions()` | Connect/disconnect actions | | `useWalletModalState()` | Modal visibility management | | `useConnectWallet()` | Connect action only | | `useDisconnectWallet()` | Disconnect action only | ### Data Hooks | Hook | Description | | --- | --- | | `useBalance(address)` | Fetch and watch balance | | `useAccount(address)` | Fetch and watch account | | `useLookupTable(address)` | Fetch lookup table | | `useNonceAccount(address)` | Fetch nonce account | | `useProgramAccounts(program)` | Query program accounts | ### Transaction Hooks | Hook | Description | | --- | --- | | `useSolTransfer()` | Send SOL | | `useSplToken(mint)` | SPL token operations | | `useWrapSol()` | Wrap/unwrap SOL | | `useSendTransaction()` | Simple transaction send | | `useTransactionPool()` | Complex transaction building | | `useSimulateTransaction(wire)` | Simulate transactions | ### Status Hooks | Hook | Description | | --- | --- | | `useSignatureStatus(signature)` | Watch signature status | | `useWaitForSignature(signature)` | Wait for confirmation | | `useClusterState()` | Current cluster info | | `useClusterStatus()` | Cluster connection status | | `useLatestBlockhash()` | Get latest blockhash | ### Utility Hooks | Hook | Description | | --- | --- | | `useClientStore(selector)` | Access Zustand store | | `useSolanaClient()` | Access client instance | ## @solana/web3-compat ### Re-exports | Export | Description | | --- | --- | | `Keypair` | Key pair for signing | | `PublicKey` | Public key representation | | `Transaction` | Legacy transaction | | `TransactionInstruction` | Transaction instruction | | `VersionedTransaction` | Versioned transaction | | `LAMPORTS_PER_SOL` | Lamports per SOL constant | ### Bridge Functions | Function | Description | | --- | --- | | `toAddress(publicKey)` | Convert PublicKey to Kit Address | | `toPublicKey(address)` | Convert Kit Address to PublicKey | | `fromWeb3Instruction(ix)` | Convert web3.js instruction to Kit | | `toWeb3Instruction(ix)` | Convert Kit instruction to web3.js | | `toKitSigner(keypair)` | Convert Keypair to Kit signer | ### Classes | Class | Description | | --- | --- | | `Connection` | web3.js-compatible RPC connection | | `SystemProgram` | System program instructions | ### Utilities | Function | Description | | --- | --- | | `sendAndConfirmTransaction` | Send and confirm a transaction | | `compileFromCompat` | Compile web3.js tx to Kit format | ## Generated Documentation Full API documentation is generated from source code and available as build artifacts: - **@solana/client**: Generated via `pnpm --filter @solana/client docs` - **JSON format**: Generated via `pnpm --filter @solana/client docs:json` The CI automatically generates and uploads API documentation on every push to main that changes the client source code. ### Building Locally To generate API docs locally: ```bash # Generate markdown docs pnpm --filter @solana/client docs # Generate JSON API spec pnpm --filter @solana/client docs:json ``` Output is written to `packages/client/docs/`. --- # @solana/client URL: https://framework-kit.dev/docs/client > Framework-agnostic client for RPC, wallets, and transactions Framework-agnostic building blocks for Solana. Works in any runtime: React, Svelte, Vue, Node.js, Bun, Deno, Cloudflare Workers, or plain browser scripts. ## Installation ```bash npm install @solana/client ``` ```bash pnpm add @solana/client ``` ```bash yarn add @solana/client ``` ```bash bun add @solana/client ``` ## Creating a Client ```ts import { autoDiscover, createClient } from "@solana/client"; const client = createClient({ endpoint: "https://api.devnet.solana.com", websocketEndpoint: "wss://api.devnet.solana.com", walletConnectors: autoDiscover(), }); ``` ## Wallet Connection ### Connect and Disconnect ```ts // Get available connectors const connectors = client.connectors.all; // Connect to a wallet await client.actions.connectWallet(connectors[0].id); // Check wallet state const wallet = client.store.getState().wallet; if (wallet.status === "connected") { console.log(wallet.session.account.address.toString()); } // Disconnect await client.actions.disconnectWallet(); ``` ### Connector IDs Connectors use **canonical IDs**: - Wallet Standard: `wallet-standard:` (example: `wallet-standard:phantom`) - Mobile Wallet Adapter: `mwa:` - WalletConnect: `walletconnect` For convenience, calls like `connectWallet("phantom")` also work (fallback-only: prefers `wallet-standard:phantom`, then `mwa:phantom`). The client persists the **canonical** ID in state for more reliable restore/auto-connect. ### Wallet Connectors Framework Kit uses the Wallet Standard for wallet discovery: ```ts import { autoDiscover, filterByNames } from "@solana/client"; // Auto-discover all installed wallets const connectors = autoDiscover(); // Filter to specific wallets const filteredConnectors = autoDiscover({ filter: filterByNames("phantom", "solflare"), }); // Custom filter function const customConnectors = autoDiscover({ filter: (wallet) => wallet.name.toLowerCase().includes("phantom"), }); ``` Built-in wallet connectors for explicit control: ```ts import { phantom, solflare, backpack, metamask, injected } from "@solana/client"; const client = createClient({ cluster: "devnet", walletConnectors: [phantom(), solflare(), backpack()], }); ``` ## ConnectorKit (optional) ConnectorKit integration is exposed as a **stable, opt-in entrypoint**: ```ts import { connectorKit } from "@solana/client/connectorkit"; import { createClient } from "@solana/client"; const walletConnectors = connectorKit({ // Pass a ConnectorKit client/config/defaultConfig (see ConnectorKit docs). defaultConfig: { /* ... */ }, }); const client = createClient({ cluster: "devnet", walletConnectors, }); ``` `@solana/connector` is an **optional peer dependency** of `@solana/client`. Install it to use `@solana/client/connectorkit`. ## Fetching Data ### Account Data ```ts import { toAddress } from "@solana/client"; const address = toAddress("Fg6PaFpoGXkYsidMpWFKfwtz6DhFVyG4dL1x8kj7ZJup"); // Fetch account const account = await client.actions.fetchAccount(address); console.log(account.lamports?.toString()); ``` ### Balance ```ts const lamports = await client.actions.fetchBalance(address); console.log(`Lamports: ${lamports.toString()}`); ``` ### Address Lookup Tables ```ts // Single lookup table const lut = await client.actions.fetchLookupTable(lutAddress); console.log(`Addresses in LUT: ${lut.addresses.length}`); // Multiple lookup tables const luts = await client.actions.fetchLookupTables([lutAddress1, lutAddress2]); ``` ### Nonce Accounts ```ts const nonce = await client.actions.fetchNonceAccount(nonceAddress); console.log(`Nonce: ${nonce.blockhash}`); console.log(`Authority: ${nonce.authority}`); ``` ## Watchers Subscribe to real-time updates: ### Watch Balance ```ts const watcher = client.watchers.watchBalance({ address }, (nextLamports) => { console.log("Updated balance:", nextLamports.toString()); }); // Clean up when done watcher.abort(); ``` ### Watch Account ```ts const watcher = client.watchers.watchAccount({ address }, (account) => { console.log("Account updated:", account); }); watcher.abort(); ``` ### Watch Signature ```ts const watcher = client.watchers.watchSignature( { signature, commitment: "confirmed" }, (notification) => console.log("Signature update:", notification), ); watcher.abort(); ``` ## Transfers ### SOL Transfer ```ts const wallet = client.store.getState().wallet; if (wallet.status !== "connected") throw new Error("Connect wallet first"); const signature = await client.solTransfer.sendTransfer({ amount: 100_000_000n, // 0.1 SOL authority: wallet.session, destination: "Ff34MXWdgNsEJ1kJFj9cXmrEe7y2P93b95mGu5CJjBQJ", }); console.log(signature.toString()); ``` ### SPL Token Transfer ```ts const usdc = client.splToken({ mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" }); // Fetch balance const balance = await usdc.fetchBalance(wallet.session.account.address); console.log(`Balance: ${balance.uiAmount}`); // Transfer const signature = await usdc.sendTransfer({ amount: 1n, authority: wallet.session, destinationOwner: "Ff34MXWdgNsEJ1kJFj9cXmrEe7y2P93b95mGu5CJjBQJ", }); ``` ### Token 2022 Support The SPL token helper supports Token 2022 (Token Extensions) mints. Use the `tokenProgram` option to specify the program: ```ts // Auto-detect program (recommended for existing mints) const token2022 = client.splToken({ mint: "2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo", // PYUSD tokenProgram: "auto", }); // Fetch balance works the same way const balance = await token2022.fetchBalance(wallet.session.account.address); // Transfer works the same way const signature = await token2022.sendTransfer({ amount: 10, authority: wallet.session, destinationOwner: recipientAddress, }); ``` You can also explicitly specify the Token 2022 program address: ```ts import { TOKEN_2022_PROGRAM_ADDRESS } from "@solana/client"; const token = client.splToken({ mint: mintAddress, tokenProgram: TOKEN_2022_PROGRAM_ADDRESS, }); ``` The `detectTokenProgram` utility is also available for manual program detection: ```ts import { detectTokenProgram } from "@solana/client"; const result = await detectTokenProgram(client.runtime, mintAddress); console.log(result.programId); // 'token' or 'token-2022' ``` ## Custom Transactions Build and send arbitrary transactions: ```ts import { getTransferSolInstruction } from "@solana-program/system"; const wallet = client.store.getState().wallet; if (wallet.status !== "connected") throw new Error("Connect wallet first"); // Prepare transaction const prepared = await client.transaction.prepare({ authority: wallet.session, instructions: [ getTransferSolInstruction({ destination: "Ff34MXWdgNsEJ1kJFj9cXmrEe7y2P93b95mGu5CJjBQJ", lamports: 10_000n, source: wallet.session.account.address, }), ], version: "auto", // 'legacy' | 0 | 'auto' }); // Serialize for inspection const wire = await client.transaction.toWire(prepared); // Send const signature = await client.transaction.send(prepared); console.log(signature.toString()); ``` ## Airdrop (Devnet/Testnet) ```ts const signature = await client.actions.requestAirdrop(address, 1_000_000_000n); // 1 SOL console.log(signature.toString()); ``` ## Cluster Configuration ### Using Monikers ```ts const client = createClient({ cluster: "mainnet", // 'devnet' | 'testnet' | 'localnet' | 'localhost' walletConnectors: autoDiscover(), }); ``` ### Custom Endpoints ```ts const client = createClient({ endpoint: "http://127.0.0.1:8899", // WebSocket inferred as ws://127.0.0.1:8900 }); ``` ### Resolve Cluster Manually ```ts import { resolveCluster } from "@solana/client"; const resolved = resolveCluster({ moniker: "testnet" }); console.log(resolved.endpoint, resolved.websocketEndpoint); ``` ## Numeric Utilities ### Lamports ```ts import { LAMPORTS_PER_SOL, lamports, lamportsFromSol, lamportsToSolString, } from "@solana/client"; const amount = lamportsFromSol(1.5); // 1_500_000_000n const sol = lamportsToSolString(amount); // "1.5" ``` ### Token Amounts ```ts import { createTokenAmount } from "@solana/client"; const tokenMath = createTokenAmount(6); // USDC has 6 decimals const parsed = tokenMath.parse("10.5"); // 10_500_000n const formatted = tokenMath.format(10_500_000n); // "10.5" ``` ## Serialization Save and restore client state: ```ts import { serializeSolanaState, deserializeSolanaState, applySerializableState, } from "@solana/client"; // Serialize current state const state = client.store.getState(); const serialized = serializeSolanaState(state); localStorage.setItem("solana-state", JSON.stringify(serialized)); // Restore state const stored = JSON.parse(localStorage.getItem("solana-state")); const deserialized = deserializeSolanaState(stored); applySerializableState(client.store, deserialized); ``` ## Store Access The client uses Zustand for state management: ```ts // Get current state const state = client.store.getState(); // Subscribe to changes const unsubscribe = client.store.subscribe((state) => { console.log("State changed:", state); }); ``` ## API Reference ### Client Actions | Action | Description | | --- | --- | | `connectWallet(id)` | Connect to a wallet by connector ID | | `disconnectWallet()` | Disconnect the current wallet | | `fetchAccount(address)` | Fetch account data | | `fetchBalance(address)` | Fetch lamport balance | | `fetchLookupTable(address)` | Fetch address lookup table | | `fetchLookupTables(addresses)` | Fetch multiple lookup tables | | `fetchNonceAccount(address)` | Fetch nonce account data | | `requestAirdrop(address, lamports)` | Request devnet/testnet airdrop | | `sendTransaction(tx)` | Send a signed transaction | | `setCluster(config)` | Change cluster/endpoint | ### Client Helpers | Helper | Description | | --- | --- | | `client.solTransfer` | SOL transfer operations | | `client.splToken({ mint })` | SPL token operations | | `client.transaction` | Transaction building and sending | ### Client Watchers | Watcher | Description | | --- | --- | | `watchAccount({ address }, callback)` | Subscribe to account changes | | `watchBalance({ address }, callback)` | Subscribe to balance changes | | `watchSignature({ signature }, callback)` | Subscribe to signature status | --- # Getting Started URL: https://framework-kit.dev/docs/getting-started > Install and configure Framework Kit in under 5 minutes Pick the packages you need and start building. | Use Case | Install | | --- | --- | | Any JS runtime (Node, Bun, Deno, browser, workers) | [`@solana/client`](/docs/client) | | React applications | [`@solana/client`](/docs/client) [`@solana/react-hooks`](/docs/react-hooks) | | Migrating from @solana/web3.js | [`@solana/web3-compat`](/docs/web3-compat) | ## Installation ### Client Only (Any Runtime) ```bash npm install @solana/client ``` ```bash pnpm add @solana/client ``` ```bash yarn add @solana/client ``` ```bash bun add @solana/client ``` ### With React Hooks ```bash npm install @solana/client @solana/react-hooks ``` ```bash pnpm add @solana/client @solana/react-hooks ``` ```bash yarn add @solana/client @solana/react-hooks ``` ```bash bun add @solana/client @solana/react-hooks ``` ### Migration Package ```bash npm install @solana/web3-compat ``` ```bash pnpm add @solana/web3-compat ``` ```bash yarn add @solana/web3-compat ``` ```bash bun add @solana/web3-compat ``` ## Requirements - Node.js 20.18.0+, Bun 1.0+, or Deno 1.40+ - TypeScript 5.3.3+ (recommended) - React 18+ (only if using `@solana/react-hooks`) ## Basic Setup ### Using the Client (Any Framework) The client works standalone in any JavaScript environment: ```ts import { autoDiscover, createClient } from "@solana/client"; const client = createClient({ cluster: "devnet", walletConnectors: autoDiscover(), // Finds installed wallet extensions }); // Connect to a wallet const connectors = client.connectors.all; await client.actions.connectWallet(connectors[0].id); // Access wallet state const wallet = client.store.getState().wallet; if (wallet.status === "connected") { console.log("Connected:", wallet.session.account.address.toString()); } // Fetch balance const balance = await client.actions.fetchBalance(wallet.session.account.address); console.log(`Balance: ${balance.toString()} lamports`); ``` ### Using React Hooks For React apps, wrap your app with the provider and use hooks: #### 1. Create a Solana Client ```tsx // lib/solana.ts import { autoDiscover, createClient } from "@solana/client"; export const client = createClient({ cluster: "devnet", walletConnectors: autoDiscover(), }); ``` #### 2. Wrap Your App with SolanaProvider ```tsx // app/providers.tsx (or your root component) import { SolanaProvider } from "@solana/react-hooks"; import { client } from "@/lib/solana"; export function Providers({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` #### 3. Use Hooks in Components ```tsx import { useWalletConnection, useBalance } from "@solana/react-hooks"; function WalletPanel() { const { connectors, connect, disconnect, wallet, status } = useWalletConnection(); const address = wallet?.account.address; const balance = useBalance(address); if (status === "connected") { return (

{address?.toString()}

Balance: {balance.lamports?.toString() ?? "loading..."}

); } return (
{connectors.map((c) => ( ))}
); } ``` ## Next.js Setup When using Next.js with the App Router, components that use hooks must be client components. ```tsx 'use client'; import { useWalletConnection } from "@solana/react-hooks"; export function WalletButton() { const { connect, connectors } = useWalletConnection(); // ... } ``` Create the client in a separate file and import it where needed: ```tsx // lib/solana.ts import { autoDiscover, createClient } from "@solana/client"; export const client = createClient({ cluster: "devnet", walletConnectors: autoDiscover(), }); ``` ```tsx // app/providers.tsx 'use client'; import { SolanaProvider } from "@solana/react-hooks"; import { client } from "@/lib/solana"; export function Providers({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` ## Node.js / Bun Scripts The client works great for scripts, CLIs, and backend services: ```ts // scripts/check-balance.ts import { createClient, toAddress } from "@solana/client"; const client = createClient({ cluster: "mainnet", }); const address = toAddress("Fg6PaFpoGXkYsidMpWFKfwtz6DhFVyG4dL1x8kj7ZJup"); const balance = await client.actions.fetchBalance(address); console.log(`Balance: ${balance.toString()} lamports`); ``` Run with your preferred runtime: ```bash npx tsx scripts/check-balance.ts ``` ```bash pnpm dlx tsx scripts/check-balance.ts ``` ```bash yarn dlx tsx scripts/check-balance.ts ``` ```bash bun scripts/check-balance.ts ``` ## Cluster Configuration Framework Kit supports multiple Solana networks: | Moniker | Endpoint | | --- | --- | | `mainnet` / `mainnet-beta` | `https://api.mainnet-beta.solana.com` | | `testnet` | `https://api.testnet.solana.com` | | `devnet` (default) | `https://api.devnet.solana.com` | | `localnet` / `localhost` | `http://127.0.0.1:8899` | ```ts const client = createClient({ cluster: "mainnet", // or 'devnet' | 'testnet' | 'localnet' walletConnectors: autoDiscover(), }); ``` Or use a custom endpoint: ```ts const client = createClient({ endpoint: "https://my-rpc-provider.com", websocketEndpoint: "wss://my-rpc-provider.com", // optional walletConnectors: autoDiscover(), }); ``` ## Wallet Filtering Show only specific wallets in your app: ```ts import { autoDiscover, createClient, filterByNames } from "@solana/client"; const client = createClient({ cluster: "devnet", walletConnectors: autoDiscover({ filter: filterByNames("phantom", "solflare"), }), }); ``` Or use a custom filter function: ```ts const client = createClient({ cluster: "devnet", walletConnectors: autoDiscover({ filter: (wallet) => wallet.name.toLowerCase().includes("phantom"), }), }); ``` ## What's Next? - [Client API](/docs/client) - Full documentation for the framework-agnostic client - [React Hooks](/docs/react-hooks) - All available hooks for React apps - [Web3 Compatibility](/docs/web3-compat) - Migrate from @solana/web3.js --- # @solana/react-hooks URL: https://framework-kit.dev/docs/react-hooks > React hooks for wallet connection, balances, and transactions React bindings for `@solana/client`. Wrap your app once with `SolanaProvider`, then use hooks anywhere for wallets, balances, and transactions. ## Installation ```bash npm install @solana/client @solana/react-hooks ``` ```bash pnpm add @solana/client @solana/react-hooks ``` ```bash yarn add @solana/client @solana/react-hooks ``` ```bash bun add @solana/client @solana/react-hooks ``` ## Setup ### 1. Create a Client ```tsx import { autoDiscover, createClient } from "@solana/client"; const client = createClient({ endpoint: "https://api.devnet.solana.com", walletConnectors: autoDiscover(), }); ``` ### 2. Wrap with SolanaProvider ```tsx import { SolanaProvider } from "@solana/react-hooks"; export function App() { return ( {/* Your components */} ); } ``` ## Wallet Hooks ### useWalletConnection Complete wallet connection management: ```tsx function WalletPanel() { const { connectors, // Available wallet connectors connect, // Connect to a wallet disconnect, // Disconnect current wallet wallet, // Current wallet session status, // 'disconnected' | 'connecting' | 'connected' currentConnector // Current connected wallet info } = useWalletConnection(); if (status === "connected") { return (

Connected via {currentConnector?.name}

{wallet?.account.address?.toString()}

); } return connectors.map((c) => ( )); } ``` ### useWallet Access wallet state: ```tsx function WalletInfo() { const { wallet, status, connectors } = useWallet(); if (status !== "connected") return

Not connected

; return

Address: {wallet.account.address.toString()}

; } ``` ### useWalletSession Get the current wallet session for signing: ```tsx function SignButton() { const session = useWalletSession(); if (!session) return

Connect wallet first

; return

Ready to sign with {session.account.address.toString()}

; } ``` ### useWalletModalState Manage wallet modal visibility: ```tsx function WalletModal() { const { isOpen, open, close } = useWalletModalState(); return ( <> {isOpen && ( )} ); } ``` ## Data Hooks ### useBalance Auto-fetch and watch lamport balance: ```tsx function BalanceCard({ address }: { address: string }) { const { lamports, fetching, slot, error } = useBalance(address); if (fetching) return

Loading...

; if (error) return

Error loading balance

; return (

Balance: {lamports?.toString() ?? "0"} lamports (slot {slot?.toString()})

); } ``` ### useAccount Auto-fetch and watch account data: ```tsx function AccountInfo({ address }: { address: string }) { const account = useAccount(address); if (!account || account.fetching) return

Loading...

; return (

Lamports: {account.lamports?.toString() ?? "0"}

Owner: {account.owner ?? "Unknown"}

Slot: {account.slot?.toString()}

); } ``` ### useLookupTable Fetch address lookup table data: ```tsx function LookupTableInfo({ address }: { address: string }) { const { data, isLoading, error } = useLookupTable(address); if (isLoading) return

Loading...

; if (error) return

Error loading LUT

; return (

Addresses: {data?.addresses.length ?? 0}

Authority: {data?.authority ?? "None"}

); } ``` ### useNonceAccount Fetch nonce account data: ```tsx function NonceInfo({ address }: { address: string }) { const { data, isLoading, error } = useNonceAccount(address); if (isLoading) return

Loading...

; if (error) return

Error loading nonce

; return (

Nonce: {data?.blockhash}

Authority: {data?.authority}

); } ``` ## Transfer Hooks ### useSolTransfer Send SOL to an address: ```tsx function SendSol({ destination }: { destination: string }) { const { send, isSending, status, signature, error } = useSolTransfer(); return (

Status: {status}

{signature &&

Signature: {signature}

} {error &&

Error: {String(error)}

}
); } ``` ### useSplToken SPL token balance and transfers: ```tsx function TokenPanel({ mint, destinationOwner }: { mint: string; destinationOwner: string }) { const { balance, send, isSending, owner, status, error, sendError, sendSignature, resetSend, refresh, } = useSplToken(mint); if (status === "disconnected") return

Connect wallet

; if (status === "loading") return

Loading...

; if (status === "error") return

Error: {String(error)}

; return (

Owner: {owner}

Balance: {balance?.uiAmount ?? "0"}

{sendSignature &&

Signature: {sendSignature}

} {sendError && (

Error: {String(sendError)}

)}
); } ``` **Options:** | Option | Description | | --- | --- | | `commitment` | RPC commitment level | | `owner` | Override balance owner (defaults to connected wallet) | | `revalidateOnFocus` | Refresh when window regains focus | | `swr` | Additional SWR options | | `config.tokenProgram` | Token program: `'auto'` for detection, or explicit address | **Token 2022 Support:** The `useSplToken` hook supports Token 2022 mints via the `tokenProgram` config option: ```tsx function Token2022Panel({ mint }: { mint: string }) { const { balance, send } = useSplToken(mint, { config: { tokenProgram: "auto" }, // Auto-detect Token or Token 2022 }); return (

Balance: {balance?.uiAmount ?? "0"}

); } ``` ### useWrapSol Wrap and unwrap SOL to wSOL: ```tsx function WrapSolPanel() { const { wrap, unwrap, isWrapping, isUnwrapping } = useWrapSol(); return (
); } ``` ## Transaction Hooks ### useSendTransaction Simple transaction sending: ```tsx function SendPrepared({ instructions }) { const { send, isSending, status, signature, error, reset } = useSendTransaction(); return (

Status: {status}

{signature &&

Signature: {signature}

} {error &&

Error: {String(error)}

}
); } ``` ### useTransactionPool Build and manage complex transactions: ```tsx import type { TransactionInstructionInput } from "@solana/client"; function TransactionBuilder({ ix }: { ix: TransactionInstructionInput }) { const session = useWalletSession(); const { addInstruction, instructions, clearInstructions, prepareAndSend, isSending, sendSignature, sendError, latestBlockhash, reset, } = useTransactionPool(); return (

Blockhash: {latestBlockhash.blockhash ?? "loading..."}

{sendSignature &&

Signature: {sendSignature}

} {sendError &&

Error: {String(sendError)}

}
); } ``` **Available methods:** | Method | Description | | --- | --- | | `addInstruction(ix)` | Add instruction to queue | | `addInstructions(ixs)` | Add multiple instructions | | `removeInstruction(index)` | Remove instruction at index | | `clearInstructions()` | Clear all instructions | | `replaceInstructions(ixs)` | Replace instruction queue | | `prepare(opts)` | Prepare transaction without sending | | `prepareAndSend(opts)` | Prepare and send in one call | | `send(opts)` | Send prepared transaction | | `sign(opts)` | Sign without sending | | `reset()` | Reset all state | ## Signature Hooks ### useSignatureStatus Watch signature confirmation: ```tsx function SignatureInfo({ signature }: { signature: string }) { const { status, confirmations, error } = useSignatureStatus(signature); return (

Status: {status}

Confirmations: {confirmations}

{error &&

Error: {String(error)}

}
); } ``` ### useWaitForSignature Wait for specific confirmation level: ```tsx function SignatureWatcher({ signature }: { signature: string }) { const wait = useWaitForSignature(signature, { commitment: "finalized" }); if (wait.waitStatus === "error") return

Failed

; if (wait.waitStatus === "success") return

Finalized

; if (wait.waitStatus === "waiting") return

Waiting...

; return

Provide a signature

; } ``` ## Query Hooks ### useProgramAccounts Query accounts owned by a program: ```tsx import { SolanaQueryProvider, useProgramAccounts } from "@solana/react-hooks"; function ProgramAccounts({ program }: { program: string }) { const { accounts, isLoading, isError, refresh } = useProgramAccounts(program); if (isLoading) return

Loading...

; if (isError) return

Error

; return (
    {accounts.map(({ pubkey }) => (
  • {pubkey.toString()}
  • ))}
); } // Wrap with SolanaQueryProvider function ProgramAccountsSection({ program }: { program: string }) { return ( ); } ``` ### useSimulateTransaction Simulate a transaction: ```tsx function Simulation({ wire }: { wire: string }) { const { logs, isLoading, isError, refresh } = useSimulateTransaction(wire); if (isLoading) return

Simulating...

; if (isError) return

Simulation failed

; return (
{JSON.stringify(logs, null, 2)}
); } ``` ### useLatestBlockhash Get the latest blockhash: ```tsx function BlockhashInfo() { const { blockhash, lastValidBlockHeight, isLoading } = useLatestBlockhash(); if (isLoading) return

Loading...

; return (

Blockhash: {blockhash}

Valid until: {lastValidBlockHeight}

); } ``` ## Store Hook ### useClientStore Access the underlying Zustand store: ```tsx function ClusterBadge() { const cluster = useClientStore((s) => s.cluster); return

Endpoint: {cluster.endpoint}

; } function WalletStatus() { const walletStatus = useClientStore((s) => s.wallet.status); return

Status: {walletStatus}

; } ``` ## Suspense Support Enable Suspense per subtree: ```tsx import { SolanaQueryProvider, useBalance } from "@solana/react-hooks"; import { Suspense } from "react"; function BalanceDetails({ address }: { address: string }) { const balance = useBalance(address); return

Lamports: {balance.lamports?.toString() ?? "0"}

; } export function WalletPanel({ address }: { address: string }) { return ( Loading balance...

}>
); } ``` ## SWR Configuration Configure caching and revalidation: ```tsx export function App() { return ( ); } ``` **Default SWR settings:** | Option | Default | | --- | --- | | `revalidateOnFocus` | `true` | | `revalidateOnReconnect` | `true` | | `revalidateIfStale` | `true` | | `dedupingInterval` | `2000ms` | | `focusThrottleInterval` | `5000ms` | ## Hooks Reference ### Wallet Hooks | Hook | Description | | --- | --- | | `useWalletConnection` | Complete wallet connection management | | `useWallet` | Access wallet state | | `useWalletSession` | Get current session for signing | | `useWalletActions` | Connect/disconnect actions | | `useWalletModalState` | Modal visibility management | | `useConnectWallet` | Connect action only | | `useDisconnectWallet` | Disconnect action only | ### Data Hooks | Hook | Description | | --- | --- | | `useBalance` | Fetch and watch balance | | `useAccount` | Fetch and watch account | | `useLookupTable` | Fetch lookup table | | `useNonceAccount` | Fetch nonce account | | `useProgramAccounts` | Query program accounts | ### Transaction Hooks | Hook | Description | | --- | --- | | `useSolTransfer` | Send SOL | | `useSplToken` | SPL token operations | | `useWrapSol` | Wrap/unwrap SOL | | `useSendTransaction` | Simple transaction send | | `useTransactionPool` | Complex transaction building | | `useSimulateTransaction` | Simulate transactions | ### Status Hooks | Hook | Description | | --- | --- | | `useSignatureStatus` | Watch signature status | | `useWaitForSignature` | Wait for confirmation | | `useClusterState` | Current cluster info | | `useClusterStatus` | Cluster connection status | | `useLatestBlockhash` | Get latest blockhash | ### Utility Hooks | Hook | Description | | --- | --- | | `useClientStore` | Access Zustand store | | `useSolanaClient` | Access client instance | --- # @solana/web3-compat URL: https://framework-kit.dev/docs/web3-compat > Compatibility layer for migrating from @solana/web3.js Drop-in replacement for `@solana/web3.js` that uses Solana Kit under the hood. Migrate your existing code incrementally without rewriting everything at once. ## Installation ```bash npm install @solana/web3-compat ``` ```bash pnpm add @solana/web3-compat ``` ```bash yarn add @solana/web3-compat ``` ```bash bun add @solana/web3-compat ``` ## Purpose If you have existing code using `@solana/web3.js`, this package lets you: 1. Keep using familiar APIs like `Connection`, `PublicKey`, and `Transaction` 2. Gradually migrate to the new Solana Kit primitives 3. Interoperate between old and new code in the same project ## Re-exports The package re-exports core types from `@solana/web3.js`: ```ts import { Keypair, PublicKey, Transaction, TransactionInstruction, VersionedTransaction, } from "@solana/web3-compat"; ``` ## Connection The `Connection` class provides a web3.js-compatible interface backed by Solana Kit: ```ts import { Connection } from "@solana/web3-compat"; const connection = new Connection("https://api.devnet.solana.com"); // Use familiar web3.js methods const balance = await connection.getBalance(publicKey); const slot = await connection.getSlot(); const blockhash = await connection.getLatestBlockhash(); ``` ## Bridge Functions Convert between web3.js and Kit types: ### Address Conversion ```ts import { toAddress, toPublicKey } from "@solana/web3-compat"; import { PublicKey } from "@solana/web3.js"; // web3.js PublicKey to Kit Address const publicKey = new PublicKey("Fg6PaFpoGXkYsidMpWFKfwtz6DhFVyG4dL1x8kj7ZJup"); const address = toAddress(publicKey); // Kit Address to web3.js PublicKey const backToPublicKey = toPublicKey(address); ``` ### Instruction Conversion ```ts import { fromWeb3Instruction, toWeb3Instruction } from "@solana/web3-compat"; // web3.js TransactionInstruction to Kit instruction const kitInstruction = fromWeb3Instruction(web3Instruction); // Kit instruction to web3.js TransactionInstruction const web3Instruction = toWeb3Instruction(kitInstruction); ``` ### Signer Conversion ```ts import { toKitSigner } from "@solana/web3-compat"; import { Keypair } from "@solana/web3.js"; // web3.js Keypair to Kit signer const keypair = Keypair.generate(); const kitSigner = toKitSigner(keypair); ``` ## System Program The `SystemProgram` provides web3.js-compatible static methods: ```ts import { SystemProgram, PublicKey } from "@solana/web3-compat"; const instruction = SystemProgram.transfer({ fromPubkey: senderPublicKey, toPubkey: recipientPublicKey, lamports: 1000000, }); ``` ## Utilities ### Send and Confirm Transaction ```ts import { sendAndConfirmTransaction, Connection, Transaction } from "@solana/web3-compat"; const signature = await sendAndConfirmTransaction( connection, transaction, [signer], ); ``` ### Compile from Compat Convert web3.js transactions to Kit format: ```ts import { compileFromCompat } from "@solana/web3-compat"; const kitTransaction = compileFromCompat(web3Transaction); ``` ### Constants ```ts import { LAMPORTS_PER_SOL } from "@solana/web3-compat"; const solAmount = lamports / LAMPORTS_PER_SOL; ``` ## Migration Guide ### Step 1: Install the Compatibility Package ```bash npm install @solana/web3-compat @solana/client ``` ```bash pnpm add @solana/web3-compat @solana/client ``` ```bash yarn add @solana/web3-compat @solana/client ``` ```bash bun add @solana/web3-compat @solana/client ``` ### Step 2: Update Imports Replace `@solana/web3.js` imports with `@solana/web3-compat`: ```diff - import { Connection, PublicKey, Transaction } from "@solana/web3.js"; + import { Connection, PublicKey, Transaction } from "@solana/web3-compat"; ``` ### Step 3: Gradually Migrate to Kit As you update components, start using `@solana/client` directly: ```tsx // Old code using web3-compat import { Connection } from "@solana/web3-compat"; const connection = new Connection(endpoint); const balance = await connection.getBalance(publicKey); // New code using @solana/client import { createClient } from "@solana/client"; const client = createClient({ endpoint }); const balance = await client.actions.fetchBalance(address); ``` ### Step 4: Use React Hooks For React apps, migrate to hooks for cleaner code: ```tsx // Old approach const [balance, setBalance] = useState(null); useEffect(() => { connection.getBalance(publicKey).then(setBalance); }, [publicKey]); // New approach with hooks const { lamports } = useBalance(address); ``` ## Interoperability Example Mix old and new code in the same project: ```tsx import { PublicKey } from "@solana/web3-compat"; import { toAddress } from "@solana/web3-compat"; import { useBalance } from "@solana/react-hooks"; function BalanceDisplay({ publicKey }: { publicKey: PublicKey }) { // Convert web3.js PublicKey to Kit address const address = toAddress(publicKey); // Use modern hooks const { lamports } = useBalance(address); return

Balance: {lamports?.toString()}

; } ``` ## API Reference ### Re-exports from @solana/web3.js | Export | Description | | --- | --- | | `Keypair` | Key pair for signing | | `PublicKey` | Public key representation | | `Transaction` | Legacy transaction | | `TransactionInstruction` | Transaction instruction | | `VersionedTransaction` | Versioned transaction | ### Bridge Functions | Function | Description | | --- | --- | | `toAddress(publicKey)` | Convert PublicKey to Kit Address | | `toPublicKey(address)` | Convert Kit Address to PublicKey | | `fromWeb3Instruction(ix)` | Convert web3.js instruction to Kit | | `toWeb3Instruction(ix)` | Convert Kit instruction to web3.js | | `toKitSigner(keypair)` | Convert Keypair to Kit signer | ### Classes | Class | Description | | --- | --- | | `Connection` | web3.js-compatible RPC connection | | `SystemProgram` | System program instructions | ### Utilities | Function | Description | | --- | --- | | `sendAndConfirmTransaction` | Send and confirm a transaction | | `compileFromCompat` | Compile web3.js tx to Kit format | | `LAMPORTS_PER_SOL` | Lamports per SOL constant | ---