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:
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(),
},
})
Westend Asset Hub - 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. Theconnect
function initiates the connection flow with the specified connectoruseDisconnect
- provides a function to disconnect the currently connected walletuseAccount
- 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. Thewatch
parameter enables real-time updates when new blocks are mineduseBalance
- 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
//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 stateuseWriteContract
- calls a state-modifying function on your smart contract, which requires a transaction to be signed and sentuseWaitForTransactionReceipt
- 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:
-
External Advanced Wagmi
Explore Wagmi's advanced features:
-
External Wallet Integration
Connect your dApp with popular wallet providers:
-
External Testing & Development
Enhance your development workflow:
| Created: March 6, 2025