---
name: wallet-integration
description: Wallet connection and transaction management for dApps using wagmi and viem. Supports multiple connectors, chain switching, EIP-712 signing, and hardware wallet integration.
allowed-tools: Read, Grep, Write, Bash, Edit, Glob, WebFetch
---
# Wallet Integration Skill
Expert wallet connection and transaction management for Web3 dApps using wagmi and viem.
## Capabilities
- **Connector Configuration**: Set up wagmi with multiple connectors
- **Connection Flows**: Implement wallet connection UX
- **Chain Management**: Handle chain switching and network errors
- **Transactions**: Execute transactions with gas estimation
- **Error Handling**: Parse and display transaction errors
- **EIP-712 Signing**: Implement typed data signing
- **Event Handling**: React to wallet events
- **Hardware Wallets**: Support Ledger, Trezor, WalletConnect
## Installation
```bash
# Install wagmi and viem
npm install wagmi viem @tanstack/react-query
# Optional UI kits
npm install @rainbow-me/rainbowkit # or
npm install @web3modal/wagmi
```
## Configuration
### Basic wagmi Config
```typescript
// config/wagmi.ts
import { createConfig, http } from "wagmi";
import { mainnet, sepolia, polygon, arbitrum } from "wagmi/chains";
import { injected, walletConnect, coinbaseWallet } from "wagmi/connectors";
export const config = createConfig({
chains: [mainnet, sepolia, polygon, arbitrum],
connectors: [
injected(),
walletConnect({
projectId: process.env.NEXT_PUBLIC_WC_PROJECT_ID!,
}),
coinbaseWallet({
appName: "My dApp",
}),
],
transports: {
[mainnet.id]: http(process.env.NEXT_PUBLIC_MAINNET_RPC),
[sepolia.id]: http(process.env.NEXT_PUBLIC_SEPOLIA_RPC),
[polygon.id]: http(process.env.NEXT_PUBLIC_POLYGON_RPC),
[arbitrum.id]: http(process.env.NEXT_PUBLIC_ARBITRUM_RPC),
},
});
```
### RainbowKit Setup
```typescript
// config/rainbowkit.ts
import "@rainbow-me/rainbowkit/styles.css";
import { getDefaultConfig } from "@rainbow-me/rainbowkit";
import { mainnet, sepolia, polygon } from "wagmi/chains";
export const config = getDefaultConfig({
appName: "My dApp",
projectId: process.env.NEXT_PUBLIC_WC_PROJECT_ID!,
chains: [mainnet, sepolia, polygon],
ssr: true,
});
```
## Provider Setup
```tsx
// app/providers.tsx
"use client";
import { WagmiProvider } from "wagmi";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { RainbowKitProvider } from "@rainbow-me/rainbowkit";
import { config } from "./config/wagmi";
const queryClient = new QueryClient();
export function Providers({ children }: { children: React.ReactNode }) {
return (
{address?.slice(0, 6)}...{address?.slice(-4)}
Error: {error.message}
}{ensName ?? `${address?.slice(0, 6)}...${address?.slice(-4)}`}
{balance?.formatted} {balance?.symbol}
Network: {chain?.name}
Current: {chain?.name ?? "Not connected"}
Error: {error.message}
}Balance: {balance ? formatUnits(balance, 18) : "0"}
; } export function TokenTransfer() { const { data: hash, writeContract, isPending } = useWriteContract(); const { isSuccess } = useWaitForTransactionReceipt({ hash }); function handleTransfer(to: string, amount: string) { writeContract({ address: TOKEN_ADDRESS, abi: erc20Abi, functionName: "transfer", args: [to as `0x${string}`, parseUnits(amount, 18)], }); } return ( ); } ``` ## EIP-712 Typed Data Signing ```tsx // components/SignTypedData.tsx import { useSignTypedData, useAccount } from "wagmi"; const domain = { name: "My dApp", version: "1", chainId: 1, verifyingContract: "0x..." as const, }; const types = { Permit: [ { name: "owner", type: "address" }, { name: "spender", type: "address" }, { name: "value", type: "uint256" }, { name: "nonce", type: "uint256" }, { name: "deadline", type: "uint256" }, ], }; export function SignPermit() { const { address } = useAccount(); const { signTypedData, data: signature, isPending } = useSignTypedData(); function handleSign() { signTypedData({ domain, types, primaryType: "Permit", message: { owner: address!, spender: "0x..." as const, value: BigInt("1000000000000000000"), nonce: BigInt(0), deadline: BigInt(Math.floor(Date.now() / 1000) + 3600), }, }); } return (Signature: {signature}
}