Addons
Wallet Balance
Displays SOL balance with refresh. Requires connect-button.
Preview
"use client";import { useBalance } from "@solana/connector/react";import { RefreshCw } from "lucide-react";import { cn } from "@/lib/utils";interface WalletBalanceProps { /** Whether to auto-refresh balance (default: true) */ autoRefresh?: boolean; /** Refresh interval in milliseconds (default: 30000) */ refreshInterval?: number; /** Show refresh button (default: true) */ showRefresh?: boolean; /** Custom className */ className?: string;}export function WalletBalance({ autoRefresh = true, refreshInterval = 30000, showRefresh = true, className,}: WalletBalanceProps) { const { solBalance, isLoading, refetch } = useBalance({ autoRefresh, refreshInterval, }); return ( <div className={cn("rounded-xl border bg-muted/50 p-4", className)}> <div className="flex items-center justify-between mb-1"> <span className="text-sm text-muted-foreground">Balance</span> {showRefresh && ( <button type="button" onClick={() => refetch()} disabled={isLoading} className="p-1 hover:bg-accent rounded transition-colors disabled:opacity-50" > <RefreshCw className={cn("h-3.5 w-3.5", isLoading && "animate-spin")} /> </button> )} </div> <div className="tabular-nums text-2xl font-bold"> {isLoading ? ( <div className="h-8 w-32 bg-muted animate-pulse rounded" /> ) : solBalance !== null ? ( `${solBalance.toFixed(4)} SOL` ) : ( "-- SOL" )} </div> </div> );}Prerequisites
Complete the installation guide and install Connect Button before using this addon.
Try the Demo
Want to see it working immediately without manual wiring? Install the demo:
npx shadcn@latest add https://nitso.fun/r/wallet-balance-demo.jsonpnpm dlx shadcn@latest add https://nitso.fun/r/wallet-balance-demo.jsonyarn dlx shadcn@latest add https://nitso.fun/r/wallet-balance-demo.jsonbunx --bun shadcn@latest add https://nitso.fun/r/wallet-balance-demo.jsonThis installs wallet-balance-demo.tsx into your components/ folder. Drop it anywhere:
import { WalletBalanceDemo } from '@/components/wallet-balance-demo';
export default function Page() {
return <WalletBalanceDemo />;
}Delete it when you're ready to wire things up yourself.
Installation
npx shadcn@latest add https://nitso.fun/r/wallet-balance.jsonpnpm dlx shadcn@latest add https://nitso.fun/r/wallet-balance.jsonyarn dlx shadcn@latest add https://nitso.fun/r/wallet-balance.jsonbunx --bun shadcn@latest add https://nitso.fun/r/wallet-balance.jsonCopy the source code
"use client";import { useBalance } from "@solana/connector/react";import { RefreshCw } from "lucide-react";import { cn } from "@/lib/utils";interface WalletBalanceProps { /** Whether to auto-refresh balance (default: true) */ autoRefresh?: boolean; /** Refresh interval in milliseconds (default: 30000) */ refreshInterval?: number; /** Show refresh button (default: true) */ showRefresh?: boolean; /** Custom className */ className?: string;}export function WalletBalance({ autoRefresh = true, refreshInterval = 30000, showRefresh = true, className,}: WalletBalanceProps) { const { solBalance, isLoading, refetch } = useBalance({ autoRefresh, refreshInterval, }); return ( <div className={cn("rounded-xl border bg-muted/50 p-4", className)}> <div className="flex items-center justify-between mb-1"> <span className="text-sm text-muted-foreground">Balance</span> {showRefresh && ( <button type="button" onClick={() => refetch()} disabled={isLoading} className="p-1 hover:bg-accent rounded transition-colors disabled:opacity-50" > <RefreshCw className={cn("h-3.5 w-3.5", isLoading && "animate-spin")} /> </button> )} </div> <div className="tabular-nums text-2xl font-bold"> {isLoading ? ( <div className="h-8 w-32 bg-muted animate-pulse rounded" /> ) : solBalance !== null ? ( `${solBalance.toFixed(4)} SOL` ) : ( "-- SOL" )} </div> </div> );}Wiring
Update the file where you use <ConnectButton /> (e.g. your header or layout):
Before:
import { ConnectButton } from "@/components/nitso/connect-button/";
export function Header() {
return (
<nav>
<ConnectButton />
</nav>
);
}After:
import { ConnectButton } from "@/components/nitso/connect-button/";
import {
WalletDropdownContent,
type WalletDropdownContentProps,
} from "@/components/nitso/connect-button/";
import { WalletBalance } from "@/components/nitso/addons/wallet-balance/";
function WalletDropdownWithBalance(props: WalletDropdownContentProps) {
return (
<WalletDropdownContent {...props}> // [!code ++]
<WalletBalance /> // [!code ++]
</WalletDropdownContent>
);
}
export function Header() {
return (
<nav>
<ConnectButton /> // [!code --]
<ConnectButton dropdownContent={WalletDropdownWithBalance} /> // [!code ++]
</nav>
);
}WalletBalance plugs into the children slot of WalletDropdownContent, rendering it between the wallet header and the disconnect button.
Combining with Network Switcher
If you already have the Network Switcher wired up, add WalletBalance as a child:
import { useState } from "react";
import { ConnectButton } from "@/components/nitso/connect-button/";
import {
WalletDropdownContent,
type WalletDropdownContentProps,
} from "@/components/nitso/connect-button/";
import {
NetworkSwitcherButton,
NetworkSwitcherView,
} from "@/components/nitso/addons/network-switcher/";
import { WalletBalance } from "@/components/nitso/addons/wallet-balance/";
function WalletDropdownWithNetwork(props: WalletDropdownContentProps) {
const [view, setView] = useState<"wallet" | "network">("wallet");
if (view === "network") {
return <NetworkSwitcherView onBack={() => setView("wallet")} />;
}
return (
<WalletDropdownContent
{...props}
actions={<NetworkSwitcherButton onClick={() => setView("network")} />}
>
<WalletBalance /> // [!code ++]
</WalletDropdownContent>
);
}
export function Header() {
return (
<nav>
<ConnectButton dropdownContent={WalletDropdownWithNetwork} />
</nav>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
autoRefresh | boolean | true | Whether to auto-refresh balance in the background |
refreshInterval | number | 30000 | Interval in milliseconds between refreshes, only applies when autoRefresh is true |
showRefresh | boolean | true | Whether to show the manual refresh button |
className | string | — | Custom className for the container |
// Default — polls every 30s, manual refresh button visible
<WalletBalance />
// Disable background polling
<WalletBalance autoRefresh={false} />
// Poll every 60s
<WalletBalance autoRefresh={true} refreshInterval={60000} />
// Hide the refresh button
<WalletBalance showRefresh={false} />