Skip to main content
Version: v6

Build dApps with Wagmi

Now that you've deployed your ink! smart contract, you can build a full frontend dApp using Ethereum-compatible libraries like Wagmi.

Wagmi is a popular library of React Hooks designed to work with Solidity ABI-compatible contracts — which makes it fully compatible with ink! contracts compiled using abi = "sol".

This guide walks you through building a frontend React dApp for the Flipper contract deployed on the Polkadot Hub Testnet.

Prerequisites

Before starting, ensure you have:

Project Setup

Create a new React project and install required dependencies:

npx create-next-app@latest wagmi-asset-hub
cd wagmi-asset-hub
npm install wagmi viem @tanstack/react-query

Configure Wagmi for Polkadot Hub

Create a configuration file to initialize Wagmi with Polkadot Hub. In your project, create a file named src/lib/wagmi.ts:

import { http, createConfig } from 'wagmi';

// Configure the Polkadot Hub chain
const assetHub = {
id: 420420422,
name: 'polkadot-hub-testnet',
network: 'polkadot-hub-testnet',
nativeCurrency: {
decimals: 18,
name: 'PAS',
symbol: 'PAS',
},
rpcUrls: {
default: {
http: ['https://testnet-passet-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, wrap your app with the WagmiProvider. Update your app/layout.tsx file (for Next.js app router):

// 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>
);
}

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>
);
}

Interact with Your Contract

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

info

This assumes your Flipper contract has already been deployed to the Polkadot Hub Testnet. If you haven't deployed it yet, follow the Hardhat Deployment guide first.

"use client";

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

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

export function FlipperContract() {
// Import the ABI of the contract from the flipper_evm.abi file.
const abi = [
{
"type": "constructor",
"inputs": [{"name": "init_value", "type": "bool"}],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "flip",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "get",
"inputs": [],
"outputs": [{"name": "", "type": "bool"}],
"stateMutability": "view"
}
];

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

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

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

const flip = () => {
writeContract({
address: CONTRACT_ADDRESS,
abi,
functionName: "flip",
args: [],
});
};

return (
<div>
<h2>Flipper Contract Interaction</h2>
<div>
<p>Contract Address: {CONTRACT_ADDRESS}</p>
<p>Current Value: {value?.toString() || "Loading..."}</p>
</div>

<div>
<button onClick={flip} disabled={isPending || isConfirming}>
{isPending
? "Waiting for approval..."
: isConfirming
? "Confirming..."
: "Flip Value"}
</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>
);
}

Main Application

Update your main page to combine all the components in src/app/page.tsx:

"use client";

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

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

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

Run Your dApp

Start the development server:

npm run dev

Now you have a modern frontend dApp that connects to Polkadot Hub using MetaMask and interacts with your ink! contract compiled with Solidity ABI support.

Key Features

Your dApp now supports:

  • Wallet Connection: Connect/disconnect MetaMask wallet
  • Contract Reading: Query current contract state
  • Contract Writing: Send transactions to modify state
  • Transaction Tracking: Monitor transaction status and confirmations
  • Error Handling: Display user-friendly error messages

Next Steps

With Wagmi integration complete, you can:

  • Add more complex contract interactions
  • Implement additional UI components
  • Integrate with other Ethereum-compatible libraries
  • Deploy your dApp to production

Other Libraries

Solidity ABI compatibility allows you to use a wide range of Ethereum-compatible libraries beyond Wagmi.

📚 Learn more in Explore the key libraries for interacting with smart contracts on Polkadot-based networks