# Get Started
This guide provides the essentials for adding **wallet/kit** components to your React application.
## Architecture & Multi-chain Support
**wallet/kit** is built on top of the [Wallet Standard](https://wallet-standard.github.io/wallet-standard), a chain-agnostic standard for connecting wallets to dApps. This means the core logic is **not tied to a specific blockchain**.
While we currently provide first-class support for **Solana**, the architecture is designed to support **Ethereum, Sui, and Bitcoin** in the future with minimal changes to your UI.
The `WalletProvider` abstracts the complexity of connecting to different chains, exposing a unified API for accounts and networks.
## Prerequisites
Our components are built with [Tailwind CSS v4](https://tailwindcss.com). Before you begin, make sure you have a React project set up with Tailwind CSS.
If you haven't set up shadcn/ui yet, follow the [shadcn/ui installation guide](https://ui.shadcn.com/docs/installation) first.
## Adding Components
### Configure the Registry
First, add the `@wallet-kit` registry namespace to your `components.json` file. This is required for shadcn/ui to recognize wallet/kit components.
**Note**: If you're new to shadcn/ui registries, see the [shadcn/ui registry documentation](https://ui.shadcn.com/docs/registry) for more information.
```json title="components.json"
{
"registries": {
"@wallet-kit": "https://wallet-kit.ouestlabs.xyz/r/{name}.json"
}
}
```
The `@wallet-kit` registry namespace allows you to install components using the `@wallet-kit/` prefix in shadcn CLI commands.
### Install Components
You can add components **automatically with the shadcn CLI** or **manually by copying the files**.
CLI
Manual
Install components using the `@wallet-kit` registry namespace:
```bash
npx shadcn@latest add @wallet-kit/provider @wallet-kit/connect
```
Install the runtime dependencies:
```bash
npm install @wallet-standard/react @wallet-standard/core @nanostores/react nanostores lucide-react gill @gillsdk/react @tanstack/react-query
```
**Note**: `@tanstack/react-query` is required for Solana hooks, but `SolanaWalletProvider` handles all configuration automatically. Just wrap your app with `QueryClientProvider` - no additional setup needed.
Install the required shadcn/ui primitives:
```bash
npx shadcn@latest add button dialog dropdown-menu alert avatar badge
```
Install the wallet components from the
`@wallet-kit`
registry namespace:
```bash
npx shadcn@latest add @wallet-kit/provider @wallet-kit/connect
```
Copy and paste the code into your project and update imports.
## Setup WalletProvider
The `WalletProvider` is the core component that manages wallet connections, network selection, and state persistence.
Wrap your app with `WalletProvider` at the root level and configure it using `createWalletConfig`.
### Basic Setup (Default)
The simplest setup - `SolanaWalletProvider` automatically uses the `QueryClient` from context. No additional configuration needed.
```tsx
// app/layout.tsx or _app.tsx
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import {
createWalletConfig,
WalletProvider,
} from "@/components/wallet/provider";
import { createSolanaMainnet, createSolanaDevnet } from "@/lib/chains/solana";
import { SolanaWalletProvider } from "@/lib/chains/solana/adapter";
const queryClient = new QueryClient();
export default function RootLayout({ children }) {
const config = createWalletConfig({
networks: [createSolanaMainnet(), createSolanaDevnet()],
});
return (
{children}
);
}
```
### Advanced Setup (Custom QueryClient)
For more control, you can pass a `QueryClient` instance explicitly with custom options.
```tsx
// app/layout.tsx or _app.tsx
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import {
createWalletConfig,
WalletProvider,
} from "@/components/wallet/provider";
import { createSolanaMainnet, createSolanaDevnet } from "@/lib/chains/solana";
import { SolanaWalletProvider } from "@/lib/chains/solana/adapter";
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60 * 5, // 5 minutes
refetchOnWindowFocus: false,
},
},
});
export default function RootLayout({ children }) {
const config = createWalletConfig({
networks: [createSolanaMainnet(), createSolanaDevnet()],
});
return (
{children}
);
}
```
### Use the component
```tsx
import { ConnectWallet } from "@/components/wallet/connect";
export function Header() {
return (
);
}
```
## Styling
Components are styled with a design token system defined by CSS variables and implemented with Tailwind CSS. The variables follow the same approach as shadcn/ui and are fully customizable.
For detailed information about styling, color tokens, and customization options, see the [shadcn/ui theming documentation](https://ui.shadcn.com/docs/theming).
## Working with LLMs
We structure the documentation to make the components **AI-friendly**, so language models can understand, reason about, and modify them. To support this, we include:
* A [llms.txt](/llms.txt) file that provides a map of the documentation and component structure for your AI agent.
* A [llms-full.txt](/llms-full.txt) file containing an expanded view of the docs and component sources for deeper analysis.
* A **Copy Markdown** button on every page, so you can easily share content or feed it to your AI workflows.
# Introduction
**wallet/kit** is a set of accessible and composable Wallet UI components. Built on top of [shadcn/ui](https://ui.shadcn.com/), it's designed for you to copy, paste, and own.
**This is not a component library. It is how you build your wallet component library.**
You know how most traditional component libraries work: you install a package from NPM, import the components, and use them in your app.
This approach works well until you need to customize a component to fit your design system or require one that isn't included in the library. **Often, you end up wrapping library components, writing workarounds to override styles, or mixing components from different libraries with incompatible APIs.**
This is what wallet/kit aims to solve. It is built around the following principles:
## Open Code
wallet/kit hands you the actual component code. You have full control to customize and extend the components to your needs. This means:
* **Full Transparency:** You see exactly how each component is built.
* **Easy Customization:** Modify any part of a component to fit your design and functionality requirements.
* **AI Integration:** Access to the code makes it straightforward for LLMs to read, understand, and even improve your components.
*In a typical library, if you need to change a button's behavior, you have to override styles or wrap the component. With wallet/kit, you simply edit the button code directly.*
## Composition
Every component in wallet/kit shares a common, composable interface. **If a component does not exist, we bring it in, make it composable, and adjust its style to match and work with the rest of the design system.**
*A shared, composable interface means it's predictable for both your team and LLMs. You are not learning different APIs for every new component. Even for third-party ones.*
## Beautiful Defaults
wallet/kit comes with a collection of components that have carefully chosen default styles. They are designed to look good on their own and to work well together as a consistent system:
* **Good Out-of-the-Box:** Your UI has a clean and minimal look without extra work.
* **Unified Design:** Components naturally fit with one another. Each component is built to match the others, keeping your UI consistent.
* **Easily Customizable:** If you want to change something, it's simple to override and extend the defaults.
## AI-Ready
The design of wallet/kit makes it easy for AI tools to work with your code. Its open code and consistent API allow AI models to read, understand, and even generate new components.
*An AI model can learn how your components work and suggest improvements or even create new components that integrate with your existing design.*
## Particles
We provide [particles](/particles)—pre-assembled components that combine multiple primitives into ready-to-use solutions. They're easy to customize, extend, or break apart when needed.
## Open Source
This project is open source. We welcome contributions, feedback, or improvements. Check out our [repository](https://github.com/ouestlabs/wallet-kit) on GitHub.
# Roadmap
**wallet/kit** is a modern component library for building web3 wallet interfaces in React applications. Built on top of [shadcn/ui](https://ui.shadcn.com/), we provide accessible, composable components that you can copy, paste, and customize to fit your needs.
## Current Status
We're actively building and improving `wallet/kit`. Here's what's available today:
### Components
* **Connect Button**: A customizable button to connect wallets
* **Address Display**: Formatted display for wallet addresses
* **Balance Display**: Component to show crypto balances
### Library
* **Wallet Utilities**: Helper functions for address formatting and validation
### Particles
* **Pre-assembled Patterns**: Ready-to-use wallet patterns
## What's Next
We're continuously working on improving and expanding `wallet/kit`. Here's what we're planning:
### Components
* **Transaction History**: Components to display transaction lists
* **Token List**: Display tokens and assets
* **Network Switcher**: Switch between different networks
### Documentation
* **More Examples**: Additional usage examples and patterns
* **Guides**: Best practices and advanced usage guides
* **API Reference**: Comprehensive API documentation
### Performance & Quality
* **Performance Optimizations**: Further improvements to component performance and bundle size
* **Accessibility Enhancements**: Continued focus on making all components fully accessible
* **TypeScript Improvements**: Enhanced type safety and better developer experience
## Contributing
We're building this in the open and welcome contributions! Whether it's bug reports, feature requests, or code contributions, we'd love to have you involved.
Check out our [GitHub repository](https://github.com/ouestlabs/wallet-kit) to get started.
# Wallet Balance
## Installation
CLI
Manual
```bash
npx shadcn@latest add @wallet-kit/balance
```
Install required shadcn/ui primitives:
```bash
npx shadcn@latest add skeleton
```
Install required wallet hooks:
```bash
npx shadcn@latest add @wallet-kit/use-wallet
```
Copy the component code:
## Usage
```tsx
import { WalletBalance } from "@/components/wallet/balance";
export default function Demo() {
return ;
}
```
## API Reference
### WalletBalance
Displays the connected wallet's balance. Shows a loading skeleton when no wallet is connected or while fetching balance.
#### Props
| Prop | Type | Default | Description |
| ------------ | ----------------------------- | ------- | ---------------------------------------------------------------------------- |
| `format` | `(balance: bigint) => string` | - | Custom formatter function for the balance. Receives the balance as `bigint`. |
| `showSymbol` | `boolean` | `true` | Whether to display the currency symbol (e.g., "SOL"). |
| `symbol` | `string` | `"SOL"` | The currency symbol to display. |
| `decimals` | `number` | `9` | Number of decimal places for the balance (default: 9 for Solana). |
| `className` | `string` | - | Additional CSS classes. |
Inherits all props from `div`.
#### Behavior
* **No Wallet**: Displays a loading skeleton
* **With Wallet**: Shows the formatted balance with the currency symbol
* **Custom Formatting**: Use the `format` prop to customize how the balance is displayed
## Examples
### Basic Usage
```tsx
import { WalletBalance } from "@/components/wallet/balance";
export default function BalanceDisplay() {
return (
);
}
```
### Custom Formatting
```tsx
import { WalletBalance } from "@/components/wallet/balance";
export default function CustomBalance() {
return (
{
const sol = Number(balance) / 1e9;
return sol.toLocaleString("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
}}
/>
);
}
```
### Without Symbol
```tsx
import { WalletBalance } from "@/components/wallet/balance";
export default function BalanceNoSymbol() {
return ;
}
```
* The component automatically handles loading states with a skeleton
* Default formatting uses 4 decimal places for readability
* The balance is stored as `bigint` to handle large numbers accurately
* Custom formatters should handle the conversion from `bigint` to a displayable string
* Currently displays a placeholder balance; implement blockchain-specific balance fetching in your application
# Connect Wallet
## Installation
CLI
Manual
```bash
npx shadcn@latest add @wallet-kit/connect
```
Install runtime dependencies:
```bash
npm install lucide-react
```
Install required shadcn/ui primitives:
```bash
npx shadcn@latest add button dialog button-group
```
Install required wallet components:
```bash
npx shadcn@latest add @wallet-kit/provider @wallet-kit/list @wallet-kit/onboarding @wallet-kit/error @wallet-kit/icon
```
Copy utilities:
Copy the component code:
## Usage
### ConnectWallet
The main button component that opens a dialog to select a wallet. When a wallet is connected, it displays the wallet icon and ellipsified address with a disconnect button.
```tsx
import { ConnectWallet } from "@/components/wallet/connect"
export default function Demo() {
return
}
```
### ConnectWalletPrompt
A prompt component that displays a warning message when no wallet is connected. It automatically hides when a wallet is connected.
```tsx
import { ConnectWalletPrompt } from "@/components/wallet/connect"
export default function Demo() {
return (
)
}
```
## API Reference
### ConnectWallet
A button that opens a dialog to select a wallet. If a wallet is already connected, it displays the connected wallet's address and a disconnect button.
#### Props
| Prop | Type | Default | Description |
| ----------- | ----------- | ------------------ | --------------------------------------------------------- |
| `variant` | `string` | `"default"` | The button variant style (default, outline, ghost, etc.). |
| `className` | `string` | - | Additional CSS classes. |
| `children` | `ReactNode` | `"Connect Wallet"` | Custom button text. |
Inherits all props from shadcn/ui `Button`.
#### Behavior
* **Not Connected**: Shows a button that opens a dialog with the list of available wallets
* **Connected**: Shows a `ButtonGroup` with the wallet icon, ellipsified address, and a disconnect button
* **Dialog**: Contains a toggle to show wallet onboarding information
### ConnectWalletPrompt
A prompt component that displays when no wallet is connected. Useful for gating content that requires wallet connection.
#### Props
| Prop | Type | Default | Description |
| ----------- | -------- | ----------- | ----------------------- |
| `variant` | `string` | `"outline"` | The Item variant style. |
| `className` | `string` | - | Additional CSS classes. |
Inherits all props from shadcn/ui `Item`.
#### Behavior
* **Not Connected**: Displays an alert-style item with a warning icon, message, and a `ConnectWallet` button
* **Connected**: Renders `null` (automatically hidden)
## Examples
### Basic Connection
```tsx
import { ConnectWallet } from "@/components/wallet/connect"
export default function Header() {
return (
)
}
```
### With Custom Text
```tsx
import { ConnectWallet } from "@/components/wallet/connect"
export default function Demo() {
return (
Connect Your Wallet
)
}
```
### Using the Prompt
```tsx
import { ConnectWalletPrompt } from "@/components/wallet/connect"
export default function ProtectedContent() {
return (
{/* Your protected content here */}
)
}
```
* The component automatically handles wallet connection state
* When connected, the disconnect button uses the same variant as the main button
* The dialog includes an info button that toggles wallet onboarding information
* The component uses `WalletList` internally to display available wallets
# Wallet Error
## Installation
CLI
Manual
```bash
npx shadcn@latest add @wallet-kit/error
```
Install dependencies:
```bash
npm install @wallet-standard/core
```
Install required shadcn/ui primitives:
```bash
npx shadcn@latest add alert-dialog button
```
Copy the component code:
## Usage
```tsx
import { WalletErrorDialog, NO_ERROR } from "@/components/wallet/error"
import { useState } from "react"
export default function Demo() {
const [error, setError] = useState(NO_ERROR)
return (
<>
{error !== NO_ERROR && (
setError(NO_ERROR)} />
)}
>
)
}
```
## API Reference
### WalletErrorDialog
A dialog component that displays wallet-related errors in a user-friendly format.
#### Props
| Prop | Type | Default | Description |
| --------- | ------------ | ------- | ----------------------------------------------------------------------------- |
| `error` | `symbol` | - | **Required.** The error symbol to display. Use `NO_ERROR` to hide the dialog. |
| `onClose` | `() => void` | - | **Required.** Callback fired when the dialog is closed. |
#### Behavior
* Displays error messages in a modal dialog
* Shows error name and message from Wallet Standard errors
* Provides a close button to dismiss the error
* Automatically handles error formatting
### NO\_ERROR
A constant symbol representing no error state. Use this to reset the error state.
## Examples
### Basic Error Handling
```tsx
import { WalletErrorDialog, NO_ERROR } from "@/components/wallet/error"
import { useState } from "react"
export default function WalletComponent() {
const [error, setError] = useState(NO_ERROR)
const handleWalletAction = async () => {
try {
// Wallet operation
} catch (err) {
setError(err as symbol)
}
}
return (
<>
{error !== NO_ERROR && (
setError(NO_ERROR)}
/>
)}
>
)
}
```
### With Error from Wallet Standard
```tsx
import { WalletErrorDialog, NO_ERROR } from "@/components/wallet/error"
import { WalletStandardError } from "@wallet-standard/core"
export default function Demo() {
const [error, setError] = useState(NO_ERROR)
const handleError = (walletError: WalletStandardError) => {
setError(walletError as symbol)
}
return (
<>
{error !== NO_ERROR && (
setError(NO_ERROR)}
/>
)}
>
)
}
```
* Errors are displayed using Wallet Standard error format
* The dialog uses shadcn/ui's `AlertDialog` component
* Always provide an `onClose` handler to reset the error state
* Use `NO_ERROR` constant to represent no error state
# Wallet Icon
## Installation
CLI
Manual
```bash
npx shadcn@latest add @wallet-kit/icon
```
Install runtime dependencies:
```bash
npm install @wallet-standard/react class-variance-authority
```
Install required shadcn/ui primitives:
```bash
npx shadcn@latest add avatar
```
Copy the component code:
## Usage
```tsx
import { WalletIcon } from "@/components/wallet/icon";
import { useWalletAccount } from "@/hooks/use-wallet";
export default function Demo() {
const { wallet } = useWalletAccount();
return ;
}
```
## API Reference
### WalletIcon
Displays a wallet's icon using an `Avatar` component. Falls back to the first letter of the wallet name if no icon is available.
#### Props
| Prop | Type | Default | Description |
| ----------- | -------------------------------------------- | ----------- | --------------------------------------------------------------------- |
| `wallet` | `Pick` | - | The wallet object containing `icon` (optional) and `name` (optional). |
| `size` | `"sm" \| "default" \| "lg" \| "xl" \| "2xl"` | `"default"` | The size variant of the icon. |
| `className` | `string` | - | Additional CSS classes. |
Inherits all props from shadcn/ui `Avatar`.
#### Size Variants
* **sm**: `size-6` (24px)
* **default**: `size-8` (32px)
* **lg**: `size-10` (40px)
* **xl**: `size-12` (48px)
* **2xl**: `size-16` (64px)
#### Behavior
* **With Icon**: Displays the wallet's icon image
* **Without Icon**: Falls back to the first letter of the wallet name (uppercase)
* **No Wallet**: Renders `null` if no wallet is provided
## Examples
### Basic Usage
```tsx
import { WalletIcon } from "@/components/wallet/icon";
import { useWalletAccount } from "@/hooks/use-wallet";
export default function WalletDisplay() {
const { wallet } = useWalletAccount();
return (
);
}
```
* The component uses shadcn/ui's `Avatar` component internally
* Icons are displayed with `rounded-sm` styling
* The fallback letter is always uppercase
* The component gracefully handles missing wallet data
* Size variants use `class-variance-authority` for consistent styling
# Components
# Wallet List
## Installation
CLI
Manual
```bash
npx shadcn@latest add @wallet-kit/list
```
Install runtime dependencies:
```bash
npm install lucide-react
```
Install required shadcn/ui primitives:
```bash
npx shadcn@latest add button alert badge spinner
```
Install required wallet components:
```bash
npx shadcn@latest add @wallet-kit/provider @wallet-kit/icon @wallet-kit/use-wallet
```
Copy the component code:
## Usage
```tsx
import { WalletList } from "@/components/wallet/list"
import { useWallet } from "@/hooks/use-wallet"
export default function Demo() {
const { wallets } = useWallet()
return
}
```
## API Reference
### WalletList
A scrollable list component that displays available wallets. Shows a "Connected" badge for the currently connected wallet and a spinner during connection.
#### Props
| Prop | Type | Default | Description |
| ----------- | ----------------------------------------------------- | ------- | --------------------------------------------------------------------------------------- |
| `wallets` | `UiWallet[]` | - | **Required.** Array of available wallets to display. |
| `select` | `(account: UiWalletAccount) => Promise \| void` | - | Callback fired when a wallet is selected and connected. Receives the connected account. |
| `className` | `string` | - | Additional CSS classes. |
Inherits all props from `div`.
#### Behavior
* **Empty List**: Displays `NoWalletDetected` component with a message and link to download Phantom Wallet
* **With Wallets**: Renders a scrollable list (max height 300px) of wallet buttons
* **Connected Wallet**: Shows a "Connected" badge and disables the button
* **Connecting**: Shows a spinner while connection is in progress
### NoWalletDetected
An internal component displayed when no wallets are detected. Shows an alert and a button to download Phantom Wallet.
## Examples
### Basic List
```tsx
import { WalletList } from "@/components/wallet/list"
import { useWallet } from "@/hooks/use-wallet"
export default function WalletSelector() {
const { wallets } = useWallet()
return (
{
console.log("Connected:", account.address)
}}
/>
)
}
```
### In a Dialog
```tsx
import { WalletList } from "@/components/wallet/list"
import { Dialog, DialogContent } from "@/components/ui/dialog"
import { useWallet } from "@/hooks/use-wallet"
export default function WalletDialog() {
const { wallets } = useWallet()
const [open, setOpen] = useState(false)
return (
)
}
```
* The component automatically handles wallet connection state
* Connected wallets are visually distinguished with a badge
* The list is scrollable with a maximum height of 300px
* Each wallet button shows the wallet icon, name, and connection status
# Wallet Menu
## Installation
CLI
Manual
```bash
npx shadcn@latest add @wallet-kit/menu
```
Install runtime dependencies:
```bash
npm install lucide-react sonner
```
Install required shadcn/ui primitives:
```bash
npx shadcn@latest add button dropdown-menu
```
Install required wallet components:
```bash
npx shadcn@latest add @wallet-kit/connect @wallet-kit/error @wallet-kit/icon
```
Copy utilities:
Copy the component code:
## Usage
```tsx
import { WalletMenu } from "@/components/wallet/menu"
export default function Demo() {
return
}
```
## API Reference
### WalletMenu
A dropdown menu component that provides wallet management actions. Only displays when a wallet is connected.
#### Props
| Prop | Type | Default | Description |
| ----------- | -------- | ----------- | ------------------------- |
| `variant` | `string` | `"default"` | The button variant style. |
| `className` | `string` | - | Additional CSS classes. |
Inherits all props from shadcn/ui `DropdownMenu`.
#### Behavior
* **Not Connected**: Renders `null` (hidden)
* **Connected**: Displays a dropdown menu with:
* Wallet icon and ellipsified address
* Copy address action (shows toast notification)
* Disconnect action
* Error handling for wallet operations
#### Menu Items
* **Copy Address**: Copies the connected account address to clipboard and shows a toast
* **Disconnect**: Disconnects the current wallet
## Examples
### Basic Menu
```tsx
import { WalletMenu } from "@/components/wallet/menu"
export default function Header() {
return (
)
}
```
### With Custom Variant
```tsx
import { WalletMenu } from "@/components/wallet/menu"
export default function Demo() {
return (
)
}
```
* The component automatically handles wallet connection state
* Copy action uses the browser's clipboard API
* Toast notifications are shown using `sonner`
* Error handling is integrated via `WalletErrorDialog`
# Network Control
## Installation
CLI
Manual
```bash
npx shadcn@latest add @wallet-kit/network-control
```
Install required shadcn/ui primitives:
```bash
npx shadcn@latest add badge
```
Install required wallet components:
```bash
npx shadcn@latest add @wallet-kit/provider @wallet-kit/use-wallet
```
Copy the component code:
## Usage
```tsx
import { NetworkSelect, NetworkBadge } from "@/components/wallet/network"
export default function Demo() {
return (
)
}
```
## API Reference
### NetworkSelect
A native select component that allows switching between configured networks.
#### Props
| Prop | Type | Default | Description |
| ----------- | -------- | ------- | ----------------------- |
| `className` | `string` | - | Additional CSS classes. |
Inherits all props from shadcn/ui `NativeSelect`.
#### Behavior
* Displays all networks configured in `WalletProvider`
* Automatically updates when network changes
* Uses native HTML select for accessibility
### NetworkBadge
A badge component that displays the current network name.
#### Props
| Prop | Type | Default | Description |
| ----------- | --------- | ------------ | ------------------------------------------------------------------------------ |
| `network` | `Network` | From context | Optional network object. If not provided, fetches from `WalletNetworkContext`. |
| `className` | `string` | - | Additional CSS classes. |
| `variant` | `string` | `"outline"` | Badge variant style. |
Inherits all props from shadcn/ui `Badge`.
#### Behavior
* **With Network Prop**: Displays the provided network's label
* **Without Network Prop**: Fetches network from context automatically
* **No Network**: Renders `null` if no network is available
* **SSR Safe**: Returns `null` during server-side rendering
## Examples
### Basic Usage
```tsx
import { NetworkSelect, NetworkBadge } from "@/components/wallet/network"
export default function NetworkControls() {
return (
)
}
```
### Badge Only
```tsx
import { NetworkBadge } from "@/components/wallet/network"
export default function NetworkDisplay() {
return
}
```
### With Custom Network
```tsx
import { NetworkBadge } from "@/components/wallet/network"
import { createSolanaMainnet } from "@/lib/chains/solana"
export default function Demo() {
const mainnet = createSolanaMainnet()
return
}
```
* Both components require `WalletProvider` to be in the component tree
* `NetworkBadge` can work standalone with a network prop or fetch from context
* Network changes are automatically persisted to localStorage
* The select component uses native HTML for better accessibility
# Wallet Onboarding
## Installation
CLI
Manual
```bash
npx shadcn@latest add @wallet-kit/onboarding
```
Install dependencies:
```bash
npm install motion
```
Install required shadcn/ui primitives:
```bash
npx shadcn@latest add button
```
Copy the component code:
## Usage
```tsx
import { WalletOnboarding } from "@/components/wallet/onboarding"
export default function Demo() {
return {}} />
}
```
## API Reference
### WalletOnboarding
An animated onboarding component that explains how to use crypto wallets to new users.
#### Props
| Prop | Type | Default | Description |
| --------- | ------------ | ------- | --------------------------------------------------------------------------------------------------- |
| `onClose` | `() => void` | - | **Required.** Callback fired when the user wants to close the onboarding (e.g., clicking "Got it"). |
#### Behavior
* Displays step-by-step instructions about wallets
* Uses animations (via `motion`) for smooth transitions
* Provides a "Got it" button to dismiss
* Designed to educate new users about crypto wallets
## Examples
### In a Dialog
```tsx
import { WalletOnboarding } from "@/components/wallet/onboarding"
import { Dialog, DialogContent } from "@/components/ui/dialog"
import { useState } from "react"
export default function OnboardingDialog() {
const [open, setOpen] = useState(true)
return (
)
}
```
### Toggle Onboarding
```tsx
import { WalletOnboarding } from "@/components/wallet/onboarding"
import { useState } from "react"
export default function Demo() {
const [showOnboarding, setShowOnboarding] = useState(false)
return (
<>
{showOnboarding && (
setShowOnboarding(false)} />
)}
>
)
}
```
* The component uses `motion` for animations
* Typically used inside dialogs or modals
* Provides educational content for users new to crypto wallets
* The `onClose` callback should handle hiding the component
# Wallet Provider
The `WalletProvider` is the **core component** that orchestrates all wallet interactions in your application. It must wrap your entire app (or the parts that need wallet functionality) to provide wallet state management, network selection, and account persistence.
## Why WalletProvider?
The `WalletProvider` serves as the foundation for all wallet-related functionality:
* **Multi-chain Support**: Manages multiple blockchain networks (Solana, Ethereum, Sui, etc.) through a unified API
* **State Management**: Tracks connected wallets, accounts, and network selection
* **Persistence**: Automatically saves and restores wallet connections across page reloads
* **Context Provision**: Exposes wallet state to all child components via React Context
## Installation
CLI
Manual
```bash
npx shadcn@latest add @wallet-kit/provider
```
Install runtime dependencies:
```bash
npm install @wallet-standard/react @nanostores/react nanostores @tanstack/react-query
```
Install blockchain-specific dependencies (for Solana):
```bash
npm install gill @gillsdk/react
```
Copy the provider code:
Copy the wallet hook:
Copy the chain utilities:
Copy blockchain integration (for Solana):
## Initialization
The `WalletProvider` must be initialized with a configuration object. Use `createWalletConfig` to create the configuration with your networks and settings.
### Basic Setup
```tsx
import {
createWalletConfig,
WalletProvider,
} from "@/components/wallet/provider";
import { createSolanaMainnet, createSolanaDevnet } from "@/lib/chains/solana";
export default function App({ children }) {
const config = createWalletConfig({
networks: [createSolanaMainnet(), createSolanaDevnet()],
});
return {children};
}
```
### Advanced Setup with Plugin Architecture
```tsx
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import {
createWalletConfig,
WalletProvider,
} from "@/components/wallet/provider";
import { createStorageAccount, createStorageNetwork } from "@/lib/chains/storage";
import { createSolanaMainnet, createSolanaDevnet, createSolanaTestnet } from "@/lib/chains/solana";
import { SolanaWalletProvider } from "@/lib/chains/solana/adapter";
const queryClient = new QueryClient();
// Custom storage keys (optional)
const accountStorage = createStorageAccount("my-app:account");
const networkStorage = createStorageNetwork("my-app:network");
export default function App({ children }) {
const config = createWalletConfig({
networks: [
createSolanaMainnet(),
createSolanaDevnet(),
createSolanaTestnet(),
],
accountStorage,
networkStorage,
onNetworkChange: (networkId) => {
console.log("Network changed to:", networkId);
},
});
return (
{children}
);
}
```
## Architecture
The provider initializes three main contexts that work together:
### 1. WalletNetworkContext
Manages the list of available networks and the currently selected network. It persists the selection to `localStorage`.
**Responsibilities:**
* Network selection and switching
* Network persistence
* Network validation
### 2. WalletAccountContext
Manages the currently connected account. It automatically attempts to reconnect to the last used wallet and account on mount.
**Responsibilities:**
* Account connection/disconnection
* Account persistence
* Wallet-to-account mapping
* Account validation
### 3. WalletUiContext
Exposes UI helpers like `connect`, `disconnect`, and modal state management.
**Responsibilities:**
* UI state (modals, dialogs)
* Wallet list filtering
* Connection helpers
## API Reference
### WalletProvider
The main provider component that wraps your application.
#### Props
| Prop | Type | Default | Description |
| ---------- | -------------- | ------- | --------------------------------------------------------------------------- |
| `children` | `ReactNode` | - | **Required.** The child components that will have access to wallet context. |
| `config` | `WalletConfig` | - | **Required.** Configuration object created with `createWalletConfig()`. |
### createWalletConfig
Factory function to create a wallet configuration object.
```typescript
function createWalletConfig(props: WalletConfig): WalletConfig
```
### WalletConfig
Configuration object for `WalletProvider`.
| Prop | Type | Default | Description |
| ------------------ | ------------------------------------ | ------------------------ | ------------------------------------------------------------------------------------ |
| `networks` | `Network[]` | - | **Required.** Array of network configurations. Each network must have a unique `id`. |
| `defaultNetworkId` | `Network["id"]` | First network in array | The network ID to use when no network is stored or selected. |
| `client` | `unknown` | - | Optional blockchain client instance (e.g., Solana connection object). |
| `accountStorage` | `StorageAccount` | `createStorageAccount()` | Custom storage for account persistence. |
| `networkStorage` | `StorageNetwork` | `createStorageNetwork()` | Custom storage for network persistence. |
| `onNetworkChange` | `(networkId: Network["id"]) => void` | - | Callback fired when the network changes. |
## Persistence
State is automatically persisted to `localStorage` using `nanostores`:
* **Network**: The ID of the selected network (e.g., `"solana:mainnet"`)
* **Account**: A string in the format `"walletName:accountAddress"` (e.g., `"Phantom:7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"`)
This ensures that users stay connected and on the correct network across page reloads.
## Multi-chain Support
The `WalletProvider` is designed to work with multiple blockchains using a plugin architecture. While we currently provide first-class support for Solana, you can add support for other chains by:
1. Creating network definitions using `defineNetwork()`
2. Implementing chain-specific utilities (like `formatSol` for Solana)
3. Creating chain-specific adapter providers (like `SolanaWalletProvider`)
4. Passing the networks to the provider and wrapping with chain adapters
### Plugin Architecture
The wallet kit uses a plugin-based architecture where each blockchain can provide an optional adapter:
```tsx
{/* Future: */}
{/* Future: */}
{children}
```
This allows consumers to choose which blockchains to enable. See the [Supported Networks](/docs/networks) section for blockchain-specific integrations.
* The provider must be placed at a high level in your component tree (typically in your root layout or `_app.tsx`)
* All wallet components (`ConnectWallet`, `WalletMenu`, etc.) must be children of `WalletProvider`
* Network IDs must follow the format `"chain:network"` (e.g., `"solana:mainnet"`)
* The provider automatically filters wallets based on the active network's chain namespace
# Context
The `context.ts` file defines the React Context types and providers used throughout the wallet kit for managing wallet state.
## Overview
This module exports three main contexts:
1. **WalletNetworkContext**: Manages network selection and available networks
2. **WalletAccountContext**: Manages connected wallet accounts
3. **WalletUiContext**: Manages UI state and wallet interactions
## Installation
CLI
Manual
```bash
npx shadcn@latest add @wallet-kit/context
```
Copy the context code:
## Architecture
The three contexts work together to provide complete wallet state management:
## API Reference
### WalletNetworkContext
Context for managing network state.
#### Value Type
```typescript
type WalletNetworkContextValue = {
network: Network;
networks: Network[];
setNetwork(networkId: Network["id"]): void;
}
```
* `network`: The currently active network
* `networks`: Array of all available networks
* `setNetwork`: Function to change the active network
### WalletAccountContext
Context for managing account state.
#### Value Type
```typescript
type WalletAccountState = {
account: UiWalletAccount | undefined;
accountKeys: string[];
network: Network;
setAccount: React.Dispatch>;
wallet: UiWallet | undefined;
}
```
* `account`: The currently connected account (or `undefined`)
* `accountKeys`: Array of keys used for caching/storage
* `network`: The active network
* `setAccount`: Function to set/update the connected account
* `wallet`: The wallet that owns the connected account
### WalletUiContext
Context for managing UI state and interactions.
#### Value Type
```typescript
type WalletUiContextValue = {
account?: UiWalletAccount;
accountKeys: string[];
client?: TClient;
connect: (wallet: UiWalletAccount) => void;
connected: boolean;
copy: () => void;
disconnect: () => void;
isModalOpen: boolean;
setIsModalOpen: (open: boolean) => void;
wallet?: UiWallet;
wallets: UiWallet[];
}
```
* `account`: The connected account
* `accountKeys`: Storage keys for the account
* `client`: Optional blockchain client instance
* `connect`: Function to connect a wallet account
* `connected`: Boolean indicating if a wallet is connected
* `copy`: Function to copy the account address
* `disconnect`: Function to disconnect the wallet
* `isModalOpen`: State for wallet connection modal
* `setIsModalOpen`: Function to control modal visibility
* `wallet`: The connected wallet
* `wallets`: Array of available wallets
## Usage
These contexts are typically accessed through hooks:
```tsx
import { useWalletNetwork } from "@/hooks/use-wallet"
import { useWalletAccount } from "@/hooks/use-wallet"
import { useWallet } from "@/hooks/use-wallet"
export default function MyComponent() {
const { network, setNetwork } = useWalletNetwork()
const { account, wallet } = useWalletAccount()
const { connect, disconnect, connected } = useWallet()
// Use the context values...
}
```
* These contexts are provided by `WalletProvider` - you don't need to create them manually
* All contexts are typed with TypeScript for type safety
* The contexts work together to provide a complete wallet state management solution
# Lib Placeholder
The `Placeholder` lib is a placeholder for the wallet.
## Installation
CLI
Manual
```bash
npx shadcn@latest add related packages
```
Copy and paste the following code into your project.
Update the import paths to match your project setup.
### Import
Import the placeholder lib:
```tsx
import { Placeholder } from "@/lib/lib-placeholder";
```
## Usage
```tsx
const placeholder = new Placeholder();
placeholder.placeholder();
```
## API Reference
### Placeholder
This lib is a placeholder for the wallet.
# Network
The `network.ts` file provides utilities for defining and working with blockchain networks in a type-safe way.
## Overview
This module provides:
* `Network` type: The base type for all network definitions
* `defineNetwork()`: A factory function to create network definitions
## Installation
CLI
Manual
```bash
npx shadcn@latest add @wallet-kit/network
```
Copy the network code:
## API Reference
### Network Type
```typescript
type Network = {
id: IdentifierString;
label: string;
url: string;
}
```
* `id`: A unique identifier following the format `"chain:network"` (e.g., `"solana:mainnet"`)
* `label`: Human-readable network name (e.g., `"Mainnet"`, `"Devnet"`)
* `url`: Network RPC URL or cluster identifier
### defineNetwork
A factory function that creates a network definition function.
```typescript
function defineNetwork({
id,
label,
url,
}: NetworkType) {
return (props: Partial = {}): Network => ({
id,
label,
url,
...props,
});
}
```
#### Parameters
| Parameter | Type | Description |
| --------- | ------------------ | ------------------------------------------------- |
| `id` | `IdentifierString` | The network identifier (e.g., `"solana:mainnet"`) |
| `label` | `string` | Human-readable network name |
| `url` | `string` | Network RPC URL or cluster identifier |
#### Returns
A function that returns a `Network` object, optionally with overridden properties.
## Usage
### Creating Network Definitions
```tsx
import { defineNetwork } from "@/lib/chains/network"
const createMainnet = defineNetwork({
id: "solana:mainnet",
label: "Mainnet",
url: "mainnet",
})
// Use it
const mainnet = createMainnet()
// { id: "solana:mainnet", label: "Mainnet", url: "mainnet" }
// Override properties
const customMainnet = createMainnet({ url: "https://api.mainnet-beta.solana.com" })
```
### With Type Extensions
```tsx
import { defineNetwork, type Network } from "@/lib/chains/network"
interface SolanaNetwork extends Network {
id: `solana:${string}`
url: ClusterUrl
}
const createSolanaMainnet = defineNetwork({
id: "solana:mainnet",
label: "Mainnet",
url: "mainnet",
})
```
## Network ID Format
Network IDs must follow the format: `"chain:network"`
* **Chain**: The blockchain name (e.g., `solana`, `ethereum`, `sui`)
* **Network**: The network name (e.g., `mainnet`, `devnet`, `testnet`)
Examples:
* `"solana:mainnet"`
* `"solana:devnet"`
* `"ethereum:mainnet"`
* `"sui:mainnet"`
- Network IDs must be unique within your application
- The `defineNetwork` function provides type safety and allows for property overrides
- Network definitions are typically created in blockchain-specific modules (e.g., `solana/index.ts`)
# Storage
The `storage.ts` file provides utilities for creating persistent storage atoms using [`nanostores`](https://github.com/nanostores/nanostores) that automatically sync with `localStorage`.
## Overview
This module provides:
* `Storage` class: A wrapper around `nanostores` persistent atoms
* `createStorage()`: Factory function to create storage instances
* `createStorageAccount()`: Pre-configured storage for wallet accounts
* `createStorageNetwork()`: Pre-configured storage for network IDs
## Installation
CLI
Manual
```bash
npx shadcn@latest add @wallet-kit/storage
```
Install dependencies:
```bash
npm install @nanostores/persistent nanostores
```
Copy the storage code:
## Architecture
Storage uses `nanostores` persistent atoms to automatically sync with `localStorage`:
## API Reference
### Storage Class
A generic storage class that wraps `nanostores` persistent atoms.
```typescript
class Storage {
get(): T | undefined
set(value: T | undefined): void
get value(): ReadableAtom
readonly key: string
readonly initial: T | undefined
}
```
#### Methods
| Method | Description |
| ------------ | ------------------------------------------------- |
| `get()` | Gets the current stored value |
| `set(value)` | Sets a new value (persists to localStorage) |
| `value` | Returns a reactive atom that can be subscribed to |
#### Properties
| Property | Type | Description |
| --------- | ---------------- | ------------------------- |
| `key` | `string` | The localStorage key |
| `initial` | `T \| undefined` | The initial/default value |
### createStorage
Factory function to create a storage instance.
```typescript
function createStorage(key: string, defaultValue?: T): Storage
```
#### Parameters
| Parameter | Type | Description |
| -------------- | -------------- | -------------------- |
| `key` | `string` | The localStorage key |
| `defaultValue` | `T` (optional) | The initial value |
### createStorageAccount
Creates a storage instance for wallet accounts.
```typescript
function createStorageAccount(key = "wallet-kit:account"): StorageAccount
```
Stores account data as: `"walletName:accountAddress"`
### createStorageNetwork
Creates a storage instance for network IDs.
```typescript
function createStorageNetwork(key = "wallet-kit:network"): StorageNetwork
```
Stores network data as: `"chain:network"` (e.g., `"solana:mainnet"`)
## Usage
### Basic Storage
```tsx
import { createStorage } from "@/lib/chains/storage"
const userStorage = createStorage("my-app:user", "default-user")
// Get value
const user = userStorage.get()
// Set value (automatically persists to localStorage)
userStorage.set("new-user")
// Subscribe to changes
import { useStore } from "@nanostores/react"
function MyComponent() {
const user = useStore(userStorage.value)
// Component re-renders when user changes
}
```
### Account Storage
```tsx
import { createStorageAccount } from "@/lib/chains/storage"
const accountStorage = createStorageAccount("my-app:account")
// Store account
accountStorage.set("Phantom:7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU")
// Get account
const account = accountStorage.get()
```
### Network Storage
```tsx
import { createStorageNetwork } from "@/lib/chains/storage"
const networkStorage = createStorageNetwork("my-app:network")
// Store network
networkStorage.set("solana:mainnet")
// Get network
const network = networkStorage.get()
```
### Custom Storage Keys
```tsx
import { createStorageAccount, createStorageNetwork } from "@/lib/chains/storage"
// Use custom keys to avoid conflicts
const accountStorage = createStorageAccount("my-app:wallet-account")
const networkStorage = createStorageNetwork("my-app:wallet-network")
```
## Persistence
* Values are automatically serialized to JSON and stored in `localStorage`
* Values are automatically deserialized when retrieved
* Changes are reactive - components using `useStore()` will re-render when values change
* Storage persists across page reloads and browser sessions
- Storage uses `@nanostores/persistent` under the hood
- Values are JSON-serialized, so complex objects are supported
- The storage key should be unique to avoid conflicts with other apps
- Default values are used when no stored value exists
# Supported Networks
**wallet/kit** is designed to support multiple blockchains through the Wallet Standard. This section documents the available blockchain integrations.
## Overview
The wallet kit uses a plugin-based architecture where each blockchain provides:
* Network definitions (mainnet, devnet, testnet, etc.)
* Chain-specific utilities (formatting, validation, etc.)
* Type definitions for type safety
## Available Integrations
### Solana
First-class support for Solana networks with utilities for formatting SOL amounts.
[Learn more about Solana integration →](/docs/networks/solana)
### Ethereum
Coming soon - Ethereum network support.
### Sui
Coming soon - Sui network support.
### Bitcoin
Coming soon - Bitcoin network support.
## Adding a New Blockchain
To add support for a new blockchain:
1. Create a network definition file (e.g., `lib/chains/ethereum/index.ts`)
2. Use `defineNetwork()` to create network factories
3. Export chain-specific utilities
4. Add the networks to `WalletProvider`
See the [Solana integration](/docs/networks/solana) for a complete example.
# Solana
The Solana integration provides network definitions and utilities for working with Solana blockchains.
## Overview
This module provides:
* Network factory functions for Solana networks (mainnet, devnet, testnet, localnet)
* SOL amount formatting utility (`formatSol`)
* Type-safe network definitions
* Solana client integration via `SolanaWalletProvider` plugin
## Installation
CLI
Manual
```bash
npx shadcn@latest add @wallet-kit/solana
```
Install dependencies:
```bash
npm install gill @gillsdk/react @tanstack/react-query
```
Install required wallet libs:
```bash
npx shadcn@latest add @wallet-kit/network @wallet-kit/solana-adapter
```
Copy the Solana integration code:
**Note on `@tanstack/react-query`**: This package is required for the Solana adapter to work. However, `SolanaWalletProvider` handles all the configuration automatically. You only need to wrap your app with `QueryClientProvider` - no additional setup is needed unless you want custom query options.
## Network Definitions
### createSolanaMainnet
Creates a Solana mainnet network definition.
```tsx
import { createSolanaMainnet } from "@/lib/chains/solana"
const mainnet = createSolanaMainnet()
// { id: "solana:mainnet", label: "Mainnet", url: "mainnet" }
```
### createSolanaDevnet
Creates a Solana devnet network definition.
```tsx
import { createSolanaDevnet } from "@/lib/chains/solana"
const devnet = createSolanaDevnet()
// { id: "solana:devnet", label: "Devnet", url: "devnet" }
```
### createSolanaTestnet
Creates a Solana testnet network definition.
```tsx
import { createSolanaTestnet } from "@/lib/chains/solana"
const testnet = createSolanaTestnet()
// { id: "solana:testnet", label: "Testnet", url: "testnet" }
```
### createSolanaLocalnet
Creates a Solana localnet network definition.
```tsx
import { createSolanaLocalnet } from "@/lib/chains/solana"
const localnet = createSolanaLocalnet()
// { id: "solana:localnet", label: "Localnet", url: "localnet" }
```
## Usage
### Basic Setup (Default)
The simplest setup - `SolanaWalletProvider` automatically uses the `QueryClient` from context if `QueryClientProvider` is present, or creates one internally.
```tsx
import { QueryClientProvider } from "@tanstack/react-query"
import {
createWalletConfig,
WalletProvider,
} from "@/components/wallet/provider"
import {
createSolanaMainnet,
createSolanaDevnet,
createSolanaTestnet,
} from "@/lib/chains/solana"
import { SolanaWalletProvider } from "@/lib/chains/solana/adapter"
const queryClient = new QueryClient()
export default function App({ children }) {
const config = createWalletConfig({
networks: [
createSolanaMainnet(),
createSolanaDevnet(),
createSolanaTestnet(),
],
})
return (
{children}
)
}
```
### Advanced Setup (Explicit QueryClient)
For more control, you can pass a `QueryClient` instance explicitly to `SolanaWalletProvider`. This is useful when you need to share the same `QueryClient` across multiple providers or configure it with custom options.
```tsx
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
import {
createWalletConfig,
WalletProvider,
} from "@/components/wallet/provider"
import {
createSolanaMainnet,
createSolanaDevnet,
createSolanaTestnet,
} from "@/lib/chains/solana"
import { SolanaWalletProvider } from "@/lib/chains/solana/adapter"
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60 * 5, // 5 minutes
refetchOnWindowFocus: false,
},
},
})
export default function App({ children }) {
const config = createWalletConfig({
networks: [
createSolanaMainnet(),
createSolanaDevnet(),
createSolanaTestnet(),
],
})
return (
{children}
)
}
```
### Custom Network URLs
You can override the network URL when creating networks:
```tsx
import { createSolanaMainnet } from "@/lib/chains/solana"
const customMainnet = createSolanaMainnet({
url: "https://api.mainnet-beta.solana.com"
})
```
## Utilities
### formatSol
Formats a SOL balance (in lamports) to a human-readable string.
```typescript
function formatSol({
balance: bigint;
locale?: Intl.LocalesArgument;
options?: Intl.NumberFormatOptions;
}): string
```
#### Parameters
| Parameter | Type | Default | Description |
| --------- | -------------------------- | --------- | ---------------------------------- |
| `balance` | `bigint` | - | **Required.** Balance in lamports. |
| `locale` | `string` | `"en-US"` | Locale for number formatting. |
| `options` | `Intl.NumberFormatOptions` | See below | Number formatting options. |
Default `options`:
```typescript
{
style: "decimal",
minimumFractionDigits: 2,
maximumFractionDigits: 5,
}
```
#### Examples
```tsx
import { formatSol } from "@/lib/chains/solana"
// Basic usage
const balance = formatSol({ balance: 1000000000n }) // "1.00"
// With custom locale
const balanceFR = formatSol({
balance: 1000000000n,
locale: "fr-FR"
}) // "1,00"
// With custom options
const balanceCustom = formatSol({
balance: 1000000000n,
options: {
minimumFractionDigits: 0,
maximumFractionDigits: 2,
}
}) // "1"
```
## Solana Client Integration
The Solana adapter provides a complete integration with [`@gillsdk/react`](https://github.com/gillsdk/gill), offering React hooks for fetching Solana blockchain data with automatic caching, refetching, and error handling.
### SolanaWalletProvider
Optional plugin provider that injects a Solana client into the wallet context and enables `@gillsdk/react` hooks. It automatically configures the React Query client with the necessary defaults.
**Default Behavior**: If `QueryClientProvider` is present in your component tree, `SolanaWalletProvider` will automatically use its `QueryClient`. You don't need to pass `queryClient` explicitly unless you need custom configuration.
#### Basic Usage (Default)
```tsx
import { QueryClientProvider } from "@tanstack/react-query"
import { SolanaWalletProvider } from "@/lib/chains/solana/adapter"
import { WalletProvider } from "@/components/wallet/provider"
const queryClient = new QueryClient()
export default function App({ children }) {
return (
{children}
)
}
```
#### Advanced Usage (Explicit QueryClient)
```tsx
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
import { SolanaWalletProvider } from "@/lib/chains/solana/adapter"
import { WalletProvider } from "@/components/wallet/provider"
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60 * 5,
},
},
})
export default function App({ children }) {
return (
{children}
)
}
```
#### Props
| Prop | Type | Default | Description |
| ------------- | -------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `children` | `ReactNode` | - | **Required.** Child components. |
| `url` | `SolanaClientUrlOrMoniker` | Network URL | Optional custom RPC URL or moniker (e.g., `"mainnet"`, `"devnet"`). |
| `queryClient` | `QueryClient` | From `QueryClientProvider` context | Optional React Query client. If not provided, automatically uses the client from `QueryClientProvider` context via `useQueryClient()`. The provider handles all necessary configuration internally. |
#### With Custom RPC URL
```tsx
{children}
```
### Hooks
The Solana adapter provides hooks that wrap `@gillsdk/react` hooks with automatic network detection and enabled state management.
#### useSolanaBalance
Fetch an account's balance in lamports. Automatically uses the connected account's address if no address is provided.
```tsx
import { useSolanaBalance } from "@/lib/chains/solana/adapter"
import { formatSol } from "@/lib/chains/solana"
function BalanceDisplay() {
const { balance, isLoading, isError, error } = useSolanaBalance()
if (isLoading) return
Loading...
if (isError) return
Error: {error?.message}
return
{formatSol({ balance: balance ?? 0n })} SOL
}
```
#### useSolanaAccount
Fetch account information for an address.
```tsx
import { useSolanaAccount } from "@/lib/chains/solana/adapter"
function AccountInfo({ address }: { address: string }) {
const { account, isLoading } = useSolanaAccount(address)
if (isLoading) return
Loading...
if (!account) return
Account not found
return
Owner: {account.owner}
}
```
#### useSolanaTokenMint
Fetch and decode a token mint account.
```tsx
import { useSolanaTokenMint } from "@/lib/chains/solana/adapter"
function TokenInfo({ mint }: { mint: string }) {
const { account, isLoading } = useSolanaTokenMint(mint)
if (isLoading) return
Loading...
return (
Decimals: {account?.data.decimals}
Supply: {account?.data.supply.toString()}
)
}
```
#### useSolanaTokenAccount
Fetch and decode a token account for a given mint and owner.
```tsx
import { useSolanaTokenAccount } from "@/lib/chains/solana/adapter"
function TokenBalance({ mint, owner }: { mint: string; owner: string }) {
const { account, isLoading } = useSolanaTokenAccount(mint, owner)
if (isLoading) return
Loading...
return
Amount: {account?.data.amount.toString()}
}
```
#### useSolanaProgramAccounts
Fetch all accounts owned by a program.
```tsx
import { useSolanaProgramAccounts } from "@/lib/chains/solana/adapter"
function ProgramAccounts({ program }: { program: string }) {
const { accounts, isLoading } = useSolanaProgramAccounts(program, {
commitment: "confirmed",
})
if (isLoading) return
Loading...
return (
{accounts?.map((acc, i) => (
Account: {acc.pubkey}
))}
)
}
```
#### useSolanaSignaturesForAddress
Fetch transaction signatures for an address.
```tsx
import { useSolanaSignaturesForAddress } from "@/lib/chains/solana/adapter"
function TransactionHistory({ address }: { address: string }) {
const { signatures, isLoading } = useSolanaSignaturesForAddress(address, {
limit: 10,
})
if (isLoading) return
Loading...
return (
{signatures?.map((sig) => (
{sig.signature}
))}
)
}
```
#### useSolanaSignatureStatuses
Check the status of transaction signatures.
```tsx
import { useSolanaSignatureStatuses } from "@/lib/chains/solana/adapter"
function SignatureStatus({ signatures }: { signatures: string[] }) {
const { statuses, isLoading } = useSolanaSignatureStatuses(signatures)
if (isLoading) return
Loading...
return (
{statuses?.map((status, i) => (
{status?.confirmationStatus ?? "Unknown"}
))}
)
}
```
#### useSolanaLatestBlockhash
Fetch the latest blockhash. Useful for transaction building.
```tsx
import { useSolanaLatestBlockhash } from "@/lib/chains/solana/adapter"
function BlockhashDisplay() {
const { latestBlockhash, isLoading } = useSolanaLatestBlockhash()
if (isLoading) return
Loading...
return
Blockhash: {latestBlockhash?.blockhash}
}
```
#### useSolanaClient
Get the current Solana client instance.
```tsx
import { useSolanaClient } from "@/lib/chains/solana/adapter"
function MyComponent() {
const { rpc, rpcSubscriptions } = useSolanaClient()
// Use rpc for direct RPC calls
const balance = await rpc.getBalance(address).send()
}
```
#### useSolanaWallet
Get the Solana client from wallet context or create a fallback.
```tsx
import { useSolanaWallet } from "@/lib/chains/solana/adapter"
function MyComponent() {
const client = useSolanaWallet()
// Use client for direct operations
}
```
#### useUpdateSolanaClient
Update the Solana client instance. Useful for switching RPC endpoints dynamically.
```tsx
import { useUpdateSolanaClient, useSolanaNetwork } from "@/lib/chains/solana/adapter"
import { createSolanaClient } from "gill"
function NetworkSwitcher() {
const { mutate: updateClient } = useUpdateSolanaClient()
const network = useSolanaNetwork()
const handleSwitchRPC = () => {
const newClient = createSolanaClient({
urlOrMoniker: "https://custom-rpc.com"
})
updateClient(newClient)
}
return
}
```
#### useSolanaNetwork
Get the current Solana network information.
```tsx
import { useSolanaNetwork } from "@/lib/chains/solana/adapter"
function NetworkInfo() {
const network = useSolanaNetwork()
if (!network) return
Not on Solana network
return (
Network: {network.networkId}
Cluster: {network.cluster}
)
}
```
### Hook Behavior
All hooks work out of the box with zero configuration:
* **Automatic network detection**: Hooks automatically detect if you're on a Solana network and disable queries when not
* **Smart defaults**: Use the connected account's address automatically when no address is provided
* **Safe fallbacks**: Return safe defaults (null values, no loading/error states) when conditions aren't met
* **React Query integration**: Full integration with React Query for automatic caching, background refetching, and error handling
* **No configuration needed**: Works with the default `QueryClient` from `QueryClientProvider` - no additional setup required
### Integration with @gillsdk/react
The Solana adapter is built on top of `@gillsdk/react`, which provides:
* Automatic caching with React Query
* Background refetching
* Error handling and retry logic
* Optimistic updates support
* Type-safe RPC calls
All hooks from the adapter are wrappers around `@gillsdk/react` hooks, ensuring full compatibility and feature parity.
## Types
### SolanaNetwork
Extended network type for Solana networks.
```typescript
interface SolanaNetwork extends Network {
id: SolanaNetworkId;
url: ClusterUrl;
}
```
### SolanaNetworkId
Type for Solana network IDs.
```typescript
type SolanaNetworkId = `solana:${string}`
```
## Network IDs
Solana network IDs follow the format: `solana:{network}`
* `solana:mainnet` - Mainnet
* `solana:devnet` - Devnet
* `solana:testnet` - Testnet
* `solana:localnet` - Localnet
- Network URLs use `ClusterUrl` type from `gill` package
- The `formatSol` function uses `LAMPORTS_PER_SOL` (1,000,000,000) for conversion
- All network definitions are type-safe and can be extended
- Networks can be customized by passing partial network objects to factory functions
- The `SolanaWalletProvider` automatically configures React Query with required defaults
- All hooks integrate seamlessly with `@gillsdk/react` for optimal developer experience
- The adapter handles network detection and query enabling/disabling automatically