Documentation Index
Fetch the complete documentation index at: https://seilabs-docs-evm-reference-and-sei-js-examples.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Wagmi + React
Wagmi is the standard React library for EVM wallet connections and contract interactions. This page covers the essential patterns for a Sei frontend: configuration, wallet connect/disconnect, reading balances, and writing to contracts.
For Node.js scripts and backend services, see the viem Quickstart instead.
Install
npm install wagmi viem @sei-js/precompiles @tanstack/react-query
Configuration
Configure Wagmi with the Sei chain and your preferred wallet connectors:
// wagmi.config.ts
import { createConfig, http } from 'wagmi';
import { injected, walletConnect } from 'wagmi/connectors';
import { sei, seiTestnet } from '@sei-js/precompiles/viem';
export const config = createConfig({
chains: [sei, seiTestnet],
connectors: [
injected(),
walletConnect({ projectId: 'YOUR_WALLETCONNECT_PROJECT_ID' }),
],
transports: {
[sei.id]: http(),
[seiTestnet.id]: http(),
},
});
Provider Setup
Wrap your app with WagmiProvider and QueryClientProvider:
// App.tsx
import { WagmiProvider } from 'wagmi';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { config } from './wagmi.config';
const queryClient = new QueryClient();
export function App() {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<YourApp />
</QueryClientProvider>
</WagmiProvider>
);
}
Connecting a Wallet
import { useConnect, useDisconnect, useAccount } from 'wagmi';
export function WalletButton() {
const { connectors, connect } = useConnect();
const { disconnect } = useDisconnect();
const { address, isConnected } = useAccount();
if (isConnected) {
return (
<div>
<span>{address}</span>
<button onClick={() => disconnect()}>Disconnect</button>
</div>
);
}
return (
<div>
{connectors.map((connector) => (
<button key={connector.id} onClick={() => connect({ connector })}>
Connect {connector.name}
</button>
))}
</div>
);
}
Reading the Native SEI Balance
import { useBalance, useAccount } from 'wagmi';
import { formatEther } from 'viem';
export function SeiBalance() {
const { address } = useAccount();
const { data: balance } = useBalance({ address });
if (!balance) return null;
return (
<p>Balance: {formatEther(balance.value)} SEI</p>
);
}
Reading a Contract
import { useReadContract } from 'wagmi';
import { parseAbi } from 'viem';
const ERC20_ABI = parseAbi([
'function balanceOf(address owner) view returns (uint256)',
'function symbol() view returns (string)',
]);
export function TokenBalance({ tokenAddress, owner }: { tokenAddress: `0x${string}`; owner: `0x${string}` }) {
const { data: balance } = useReadContract({
address: tokenAddress,
abi: ERC20_ABI,
functionName: 'balanceOf',
args: [owner],
});
const { data: symbol } = useReadContract({
address: tokenAddress,
abi: ERC20_ABI,
functionName: 'symbol',
});
if (balance === undefined) return null;
return <p>{balance.toString()} {symbol}</p>;
}
Writing to a Contract
Use useWriteContract for transactions that mutate state, and useWaitForTransactionReceipt to track confirmation:
import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi';
import { parseAbi, parseUnits } from 'viem';
const ERC20_ABI = parseAbi([
'function transfer(address to, uint256 amount) returns (bool)',
]);
export function TransferButton({ tokenAddress }: { tokenAddress: `0x${string}` }) {
const { writeContract, data: hash, isPending } = useWriteContract();
const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({ hash });
function handleTransfer() {
writeContract({
address: tokenAddress,
abi: ERC20_ABI,
functionName: 'transfer',
args: ['0xRecipient', parseUnits('10', 18)],
});
}
return (
<div>
<button onClick={handleTransfer} disabled={isPending || isConfirming}>
{isPending ? 'Confirm in wallet...' : isConfirming ? 'Confirming...' : 'Transfer'}
</button>
{isSuccess && <p>Transfer confirmed.</p>}
</div>
);
}
Sei has instant finality —
useWaitForTransactionReceipt resolves as soon as the transaction is included in a block. A single confirmation is final. See
Finality.
Watching the Connected Chain
import { useChainId, useSwitchChain } from 'wagmi';
import { sei, seiTestnet } from '@sei-js/precompiles/viem';
export function NetworkSwitcher() {
const chainId = useChainId();
const { switchChain } = useSwitchChain();
return (
<div>
<p>Connected to chain {chainId}</p>
{chainId !== sei.id && (
<button onClick={() => switchChain({ chainId: sei.id })}>
Switch to Sei Mainnet
</button>
)}
</div>
);
}