Skip to content

Wagmi

Introduction

Wagmi is a collection of React Hooks for interacting with EVM-compatible blockchains, focusing on developer experience, feature richness, and reliability.

This guide demonstrates how to use Wagmi to interact with and deploy smart contracts to Asset Hub, providing a seamless frontend integration for your dApps.

Set Up the Project

To start working with Wagmi, create a new React project and initialize it by running the following commands in your terminal:

# Create a new React project using Next.js
npx create-next-app@latest wagmi-asset-hub
cd wagmi-asset-hub

Install Dependencies

Install Wagmi and its peer dependencies:

# Install Wagmi and its dependencies
npm install wagmi viem @tanstack/react-query

Configure Wagmi for Asset Hub

Create a configuration file to initialize Wagmi with Asset Hub. In your project, create a file named src/lib/wagmi.ts and add the code below. Be sure to replace INSERT_RPC_URL, INSERT_CHAIN_ID, INSERT_CHAIN_NAME, INSERT_NETWORK_NAME, INSERT_CHAIN_DECIMALS, INSERT_CURRENCY_NAME, and INSERT_CURRENCY_SYMBOL with your specific values.

import { http, createConfig } from 'wagmi'

// Configure the Asset Hub chain
const assetHub = {
  id: INSERT_CHAIN_ID,
  name: 'INSERT_CHAIN_NAME',
  network: 'INSERT_NETWORK_NAME',
  nativeCurrency: {
    decimals: INSERT_CHAIN_DECIMALS,
    name: 'INSERT_CURRENCY_NAME',
    symbol: 'INSERT_CURRENCY_SYMBOL',
  },
  rpcUrls: {
    default: {
      http: ['INSERT_RPC_URL'],
    },
  },
} as const;

// Create Wagmi config
export const config = createConfig({
  chains: [assetHub],
  transports: {
    [assetHub.id]: http(),
  },
})
For example, to connect to Westend Asset Hub, you can use the following configuration:

Westend Asset Hub - wagmi.ts
wagmi.ts
import { http, createConfig } from 'wagmi';

// Configure the Asset Hub chain
const assetHub = {
  id: 420420421,
  name: 'westend-asset-hub',
  network: 'westend',
  nativeCurrency: {
    decimals: 18,
    name: 'WND',
    symbol: 'WND',
  },
  rpcUrls: {
    default: {
      http: ['https://westend-asset-hub-eth-rpc.polkadot.io'],
    },
  },
} as const;

// Create wagmi config
export const config = createConfig({
  chains: [assetHub],
  transports: {
    [assetHub.id]: http(),
  },
});

Set Up the Wagmi Provider

To enable Wagmi in your React application, you need to wrap your app with the WagmiProvider. Update your app/layout.tsx file (for Next.js app router) with the following code:

// For app router (src/app/layout.tsx)
"use client";

import { WagmiProvider } from "wagmi";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { config } from "./lib/wagmi";

// Create a query client
const queryClient = new QueryClient();

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <WagmiProvider config={config}>
          <QueryClientProvider client={queryClient}>
            {children}
          </QueryClientProvider>
        </WagmiProvider>
      </body>
    </html>
  );
}

Note

If you are using a Next.js pages router, you should modify the src/pages/_app.tsx instead.

Connect a Wallet

Create a component to connect wallets to your dApp. Create a file named app/components/ConnectWallet.tsx:

"use client";

import React from "react";
import { useConnect, useAccount, useDisconnect } from "wagmi";
import { injected } from "wagmi/connectors";

export function ConnectWallet() {
  const { connect } = useConnect();
  const { address, isConnected } = useAccount();
  const { disconnect } = useDisconnect();

  if (isConnected) {
    return (
      <div>
        <div>Connected to {address}</div>
        <button onClick={() => disconnect()}>Disconnect</button>
      </div>
    );
  }

  return (
    <button onClick={() => connect({ connector: injected() })}>
      Connect Wallet
    </button>
  );
}

This component uses the following React hooks:

  • useConnect - provides functions and state for connecting the user's wallet to your dApp. The connect function initiates the connection flow with the specified connector
  • useDisconnect - provides a function to disconnect the currently connected wallet
  • useAccount - returns data about the connected account, including the address and connection status

Fetch Blockchain Data

Wagmi provides various hooks to fetch blockchain data. Here's an example component that demonstrates some of these hooks:

"use client";

import { useBlockNumber, useBalance, useAccount } from "wagmi";

export function BlockchainInfo() {
  const { address } = useAccount();
  // Get the latest block number
  const { data: blockNumber } = useBlockNumber({ watch: true });

  // Get balance for the connected wallet
  const { data: balance } = useBalance({
    address,
  });

  return (
    <div>
      <h2>Blockchain Information</h2>
      <div>
        <p>Current Block: {blockNumber?.toString() || "Loading..."}</p>

        {address && balance && (
          <p>
            Balance:{" "}
            {(
              BigInt(balance.value) / BigInt(10 ** balance.decimals)
            ).toLocaleString()}{" "}
            {balance.symbol}
          </p>
        )}
      </div>
    </div>
  );
}

This component uses the following React hooks:

  • useBlockNumber - fetches the current block number of the connected chain. The watch parameter enables real-time updates when new blocks are mined
  • useBalance - retrieves the native token balance for a specified address, including value, symbol, and decimals information

Interact with Deployed Contract

This guide uses a simple Storage contract already deployed to Westend Asset Hub (0xabBd46Ef74b88E8B1CDa49BeFb5057710443Fd29). The code of that contract is:

Storage.sol
Storage.sol
//SPDX-License-Identifier: MIT

// Solidity files have to start with this pragma.
// It will be used by the Solidity compiler to validate its version.
pragma solidity ^0.8.9;

contract Storage {
    // Public state variable to store a number
    uint256 public storedNumber;

    /**
    * Updates the stored number.
    *
    * The `public` modifier allows anyone to call this function.
    *
    * @param _newNumber - The new value to store.
    */
    function setNumber(uint256 _newNumber) public {
        storedNumber = _newNumber;
    }
}

Create a component to interact with your deployed contract. Create a file named app/components/StorageContract.tsx:

"use client";

import { useState } from "react";
import {
  useReadContract,
  useWriteContract,
  useWaitForTransactionReceipt,
} from "wagmi";

const CONTRACT_ADDRESS =
  "0xabBd46Ef74b88E8B1CDa49BeFb5057710443Fd29" as `0x${string}`;

export function StorageContract() {
  const [number, setNumber] = useState<string>("42");

  // Contract ABI (should match your compiled contract)
  const abi = [
    {
      inputs: [],
      name: "storedNumber",
      outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [
        { internalType: "uint256", name: "_newNumber", type: "uint256" },
      ],
      name: "setNumber",
      outputs: [],
      stateMutability: "nonpayable",
      type: "function",
    },
  ];

  // Read the current stored number
  const { data: storedNumber, refetch } = useReadContract({
    address: CONTRACT_ADDRESS,
    abi,
    functionName: "storedNumber",
  });

  // Write to the contract
  const { writeContract, data: hash, error, isPending } = useWriteContract();

  // Wait for transaction to be mined
  const { isLoading: isConfirming, isSuccess: isConfirmed } =
    useWaitForTransactionReceipt({
      hash,
    });

  const handleSetNumber = () => {
    writeContract({
      address: CONTRACT_ADDRESS,
      abi,
      functionName: "setNumber",
      args: [BigInt(number)],
    });
  };

  return (
    <div>
      <h2>Storage Contract Interaction</h2>
      <div>
        <p>Contract Address: {CONTRACT_ADDRESS}</p>
        <p>Current Stored Number: {storedNumber?.toString() || "Loading..."}</p>
      </div>

      <div>
        <input
          type="number"
          value={number}
          onChange={(e) => setNumber(e.target.value)}
          disabled={isPending || isConfirming}
        />
        <button onClick={handleSetNumber} disabled={isPending || isConfirming}>
          {isPending
            ? "Waiting for approval..."
            : isConfirming
            ? "Confirming..."
            : "Set Number"}
        </button>
      </div>

      {error && <div className="error-message">Error: {error.message}</div>}

      {isConfirmed && (
        <div className="success-message">
          Successfully updated!{" "}
          <button onClick={() => refetch()}>Refresh</button>
        </div>
      )}
    </div>
  );
}

This component demonstrates how to interact with a smart contract using Wagmi's hooks:

  • useReadContract - calls a read-only function on your smart contract to retrieve data without modifying the blockchain state
  • useWriteContract - calls a state-modifying function on your smart contract, which requires a transaction to be signed and sent
  • useWaitForTransactionReceipt - tracks the status of a transaction after it's been submitted, allowing you to know when it's been confirmed

The component also includes proper state handling to:

  • Show the current value stored in the contract
  • Allow users to input a new value
  • Display transaction status (pending, confirming, or completed)
  • Handle errors
  • Provide feedback when a transaction is successful

Integrate Components

Update your main page to combine all the components. Create or update the file src/app/page.tsx:

"use client";

import { BlockchainInfo } from "./components/BlockchainInfo";
import { ConnectWallet } from "./components/ConnectWallet";
import { StorageContract } from "./components/StorageContract";
import { useAccount } from "wagmi";

export default function Home() {
  const { isConnected } = useAccount();

  return (
    <main>
      <h1>Wagmi - Asset Hub Smart Contracts</h1>
      <ConnectWallet />
      {isConnected ? <BlockchainInfo /> : <span>Connect your wallet</span>}
      {isConnected ? <StorageContract /> : <span>Connect your wallet</span>}
    </main>
  );
}

Where to Go Next

Now that you have the foundational knowledge to use Wagmi with Asset Hub, consider exploring:

Last update: March 6, 2025
| Created: March 6, 2025