Wallet connection
Wire onchain-ui components to a connected wallet with wagmi.
Most onchain-ui components display addresses, amounts, and metadata passed as props. This recipe uses wagmi to connect an EVM wallet and read its account, balance, and chain.
onchain-ui targets EVM chains. Address components accept viem Address values, and the identity resolvers support ENS names and Basenames.
Setup
npm install wagmi viem @tanstack/react-queryThese examples target wagmi 3. In wagmi 2, use useAccount for account state, useConnect().connectors for connectors, and useSwitchChain().chains for chains. Call mutation functions directly, such as connect({ connector }), rather than through mutate. Only ConnectWallet and useAvailableConnectors import wagmi. Other registry components take props and do not depend on the wagmi version.
Create the wagmi config and wrap your app with the providers below. Wagmi uses TanStack Query for caching, so you can reuse the same QueryClient for the Data fetching recipe.
// app/providers.tsx
"use client"
import { WagmiProvider, createConfig, http } from "wagmi"
import { base, mainnet } from "wagmi/chains"
import { injected } from "wagmi/connectors"
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
const config = createConfig({
chains: [mainnet, base],
connectors: [injected()],
transports: {
[mainnet.id]: http("https://your-rpc-provider.example/mainnet"),
[base.id]: http("https://your-rpc-provider.example/base"),
},
})
const queryClient = new QueryClient()
export function Providers({ children }: { children: React.ReactNode }) {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</WagmiProvider>
)
}Connect a wallet
Install Connect wallet to add a wallet picker and connected account menu:
npx shadcn add @onchain-ui/connect-wallet"use client"
import { ConnectWallet } from "@/components/ui/connect-wallet"
export function Header() {
return <ConnectWallet />
}ConnectWallet lists available wallets, connects to the user's selection, and shows the address or resolved name. Its account menu includes a disconnect action. The setup above uses injected() and EIP-6963 to discover browser wallets without an extra SDK or project ID.
To build your own layout, use the items included in the install. ConnectorList and WalletButton accept props, and useAvailableConnectors returns the available wagmi connectors.
When you need more than injected wallets
For QR codes, mobile deep links, or other sign-in methods, add a connector that supports them and install its required dependencies. See wagmi's connector list. ConnectWallet lists remote connectors from your config without probing them for an injected provider.
Reown AppKit, RainbowKit, Privy, and Dynamic provide their own connection UI. Check a kit's wagmi peer dependency range before adding it to this setup.
Account chip
For a custom account button, pass the address from useConnection to AddressIdentity. It resolves a Basename or ENS name and avatar, with a truncated address as the fallback.
npx shadcn add button card @onchain-ui/address-identity"use client"
import { useConnection, useConnect, useDisconnect } from "wagmi"
import { injected } from "wagmi/connectors"
import { Button } from "@/components/ui/button"
import { Card } from "@/components/ui/card"
import { AddressIdentity } from "@/components/ui/address-identity"
export function AccountChip() {
const { address, isConnected } = useConnection()
const connect = useConnect()
const disconnect = useDisconnect()
if (!isConnected || !address) {
return (
<Button onClick={() => connect.mutate({ connector: injected() })}>
Connect wallet
</Button>
)
}
return (
<Card size="sm" className="flex-row items-center gap-3 px-3">
<AddressIdentity address={address} />
<Button variant="ghost" size="sm" onClick={() => disconnect.mutate()}>
Disconnect
</Button>
</Card>
)
}Native balance
useBalance returns a bigint value. Format it with viem's formatUnits and pass the result to TokenBalance.
"use client"
import { useBalance, useConnection } from "wagmi"
import { formatUnits } from "viem"
import { TokenBalance } from "@/components/ui/token-balance"
export function GasBalance() {
const { address } = useConnection()
const { data: balance } = useBalance({ address })
return (
<TokenBalance
amount={balance ? formatUnits(balance.value, balance.decimals) : null}
symbol={balance?.symbol}
/>
)
}Reuse wagmi's clients for identity resolution
AddressIdentity accepts viem clients through resolverOptions. Use usePublicClient to get the clients from wagmi's transports config:
"use client"
import { usePublicClient } from "wagmi"
import { base, mainnet } from "wagmi/chains"
import { AddressIdentity } from "@/components/ui/address-identity"
import type { Address } from "viem"
export function ResolvedIdentity({ address }: { address: Address }) {
const mainnetClient = usePublicClient({ chainId: mainnet.id })
const baseClient = usePublicClient({ chainId: base.id })
return (
<AddressIdentity
address={address}
resolverOptions={{ mainnetClient, baseClient }}
/>
)
}Components using the same client instances and resolver settings share cached lookups. See identity caching.