WagmiΒΆ
IntroductionΒΆ
Wagmi is a collection of React Hooks for interacting with Ethereum-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 Polkadot 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:
Install DependenciesΒΆ
Install Wagmi v3 and its peer dependencies:
Configure Wagmi for Polkadot HubΒΆ
Create a configuration file to initialize Wagmi with Polkadot Hub. In your project, create a file named app/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 Polkadot 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(),
},
})
Example Polkadot Hub TestNet Configuration
import { http, createConfig } from 'wagmi';
// Configure the Polkadot Hub chain
const assetHub = {
id: 420420417,
name: 'polkadot-hub-testnet',
network: 'polkadot-hub-testnet',
nativeCurrency: {
decimals: 18,
name: 'PAS',
symbol: 'PAS',
},
rpcUrls: {
default: {
http: ['https://services.polkadothub-rpc.com/testnet'],
},
},
} 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, useConnection, useDisconnect } from "wagmi";
import { injected } from "wagmi/connectors";
export function ConnectWallet() {
const { connect } = useConnect();
const { address, isConnected } = useConnection();
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. Theconnectfunction initiates the connection flow with the specified connector.useDisconnect: Provides a function to disconnect the currently connected wallet.useConnection: Returns data about the connected account, including the address and connection status. In Wagmi v3,useAccounthas been renamed touseConnection.
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, useConnection } from "wagmi";
export function BlockchainInfo() {
const { address } = useConnection();
// 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. Thewatchparameter 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 the Polkadot Hub TestNet. 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 =
"INSERT_CONTRACT_ADDRESS" 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 { useConnection } from "wagmi";
export default function Home() {
const { isConnected } = useConnection();
return (
<main>
<h1>Wagmi - Polkadot 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 Polkadot 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: June 11, 2025