Skip to content

Examples

Reference implementations and common patterns for Mini App development.

Common patterns

Wallet Connection Pattern

Complete wallet connection setup:

tsx
// hooks/useAutoConnect.ts
import { useEffect } from "react";
import { useConnect, useConnectors } from "wagmi";

export function useAutoConnect() {
  const connectors = useConnectors();
  const { connect } = useConnect();

  useEffect(() => {
    if (connectors.length > 0) {
      connect({ connector: connectors[0] });
    }
  }, [connectors, connect]);
}

// App.tsx
import { WagmiProvider } from "wagmi";
import { config } from "./wagmi";
import { useAutoConnect } from "./hooks/useAutoConnect";

function AppContent() {
  useAutoConnect();
  return <div>My Mini App</div>;
}

function App() {
  return (
    <WagmiProvider config={config}>
      <AppContent />
    </WagmiProvider>
  );
}

Token balance pattern

Fetch and display token balance (Wagmi v3: use useConnection() for address):

tsx
import { useConnection, useReadContracts } from "wagmi";
import { erc20Abi, formatUnits, type Hex } from "viem";

const USDC_ADDRESS = "0xcebA9300f2b948710d2653dD7B07f33A8B32118C";

function TokenBalance() {
  const { address } = useConnection();

  const { data: results, isLoading } = useReadContracts({
    contracts: [
      {
        address: USDC_ADDRESS,
        abi: erc20Abi,
        functionName: "balanceOf",
        args: [address as Hex],
      },
      {
        address: USDC_ADDRESS,
        abi: erc20Abi,
        functionName: "decimals",
      },
      {
        address: USDC_ADDRESS,
        abi: erc20Abi,
        functionName: "symbol",
      },
    ],
    query: {
      enabled: !!address,
    },
  });

  if (isLoading) return <div>Loading...</div>;

  const [balance, decimals, symbol] = results || [];
  const formatted = balance && decimals ? formatUnits(balance, decimals) : "0";

  return (
    <div>
      <p>
        {formatted} {symbol}
      </p>
    </div>
  );
}

Send transaction pattern

Send tokens with full status tracking (Wagmi v3: use useConnection() for address):

tsx
import { useSendTransaction, useWaitForTransactionReceipt, useConnection } from "wagmi";
import { encodeFunctionData, erc20Abi, parseUnits } from "viem";

const USDC_ADDRESS = "0xcebA9300f2b948710d2653dD7B07f33A8B32118C";
const USDC_ADAPTER = "0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B";
const USDC_DECIMALS = 6; // USDC uses 6 decimals; you can also read from the token contract with useReadContract + decimals()

function SendUSDC({ to, amount }: { to: `0x${string}`; amount: string }) {
  const { address } = useConnection();
  const {
    sendTransaction,
    data: hash,
    isPending,
    error,
  } = useSendTransaction();
  const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({
    hash,
  });

  const handleSend = () => {
    const data = encodeFunctionData({
      abi: erc20Abi,
      functionName: "transfer",
      args: [to, parseUnits(amount, USDC_DECIMALS)],
    });

    sendTransaction({
      to: USDC_ADDRESS,
      data,
      feeCurrency: USDC_ADAPTER,
    });
  };

  return (
    <div>
      <button
        onClick={handleSend}
        disabled={isPending || isConfirming || !address}
      >
        {isPending
          ? "Preparing..."
          : isConfirming
            ? "Confirming..."
            : "Send USDC"}
      </button>

      {error && <div>Error: {error.message}</div>}
      {isSuccess && <div>Transaction confirmed!</div>}
      {hash && <div>Tx: {hash}</div>}
    </div>
  );
}

Contract Interaction Pattern

Read and write to a custom contract:

tsx
import {
  useReadContract,
  useWriteContract,
  useWaitForTransactionReceipt,
} from "wagmi";
import type { Address } from "viem";

const CONTRACT_ABI = [
  {
    inputs: [],
    name: "getValue",
    outputs: [{ name: "", type: "uint256" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [{ name: "value", type: "uint256" }],
    name: "setValue",
    outputs: [],
    stateMutability: "nonpayable",
    type: "function",
  },
] as const;

const CONTRACT_ADDRESS = "0x..." as Address;

function ContractInteraction() {
  const { data: value, isLoading } = useReadContract({
    address: CONTRACT_ADDRESS,
    abi: CONTRACT_ABI,
    functionName: "getValue",
  });

  const { writeContract, data: hash, isPending } = useWriteContract();
  const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({
    hash,
  });

  const handleSetValue = () => {
    writeContract({
      address: CONTRACT_ADDRESS,
      abi: CONTRACT_ABI,
      functionName: "setValue",
      args: [BigInt(100)],
    });
  };

  if (isLoading) return <div>Loading...</div>;

  return (
    <div>
      <p>Current Value: {value?.toString()}</p>
      <button onClick={handleSetValue} disabled={isPending || isConfirming}>
        {isPending
          ? "Preparing..."
          : isConfirming
            ? "Confirming..."
            : "Set Value"}
      </button>
      {isSuccess && <div>Value updated!</div>}
    </div>
  );
}

Chain-Aware Pattern

Handle different chains and addresses:

tsx
import { useChainId } from "wagmi";
import { celo, celoSepolia } from "wagmi/chains";
import type { Address } from "viem";

const TOKEN_ADDRESSES: Record<number, Address> = {
  [celo.id]: "0x..." as Address, // Mainnet
  [celoSepolia.id]: "0x..." as Address, // Testnet
};

function useTokenAddress() {
  const chainId = useChainId();
  return TOKEN_ADDRESSES[chainId];
}

function ChainAwareComponent() {
  const tokenAddress = useTokenAddress();
  const chainId = useChainId();

  if (!tokenAddress) {
    return <div>Token not available on this network</div>;
  }

  return (
    <div>
      <p>Network: {chainId === celo.id ? "Mainnet" : "Testnet"}</p>
      <p>Token: {tokenAddress}</p>
    </div>
  );
}

Use Cases

Payment App

Send token payments (e.g. USDC) between users. Use the same pattern as the Send transaction pattern above: encode an ERC20 transfer with encodeFunctionData and call sendTransaction with the token contract as to and the encoded data. Validate the recipient address before sending.

Token Swap

To swap tokens, call a DEX contract (e.g. a router with swapExactTokensForTokens or similar) with encoded calldata — pass token addresses, amounts, and deadline. Use encodeFunctionData with the DEX ABI and then sendTransaction. For contract interaction patterns, see Smart contracts. Check your DEX’s documentation for the exact function and parameters.

Custom contracts (e.g. NFTs)

For custom contract interactions such as NFTs, use the same patterns as in Smart contracts: useReadContract / useReadContracts for reads and useWriteContract with your contract ABI for writes.

Next Steps