Skip links

Creating a Web3 wallet connect with Web3Modal, Wagmi and NextJS 13

jeyprox

SHARE

Trying to build your first Web3 dapp can be a daunting challenge. An essential part of those apps is often an option to be able to log in with your wallet. An easy way to achieve this, is with the upcoming Web3Modal 2.0 release.

What are Web3Modal and Wagmi

Simply put, they are libraries to make it easier for us developers to interact with the blockchain and connect users to your dapp.

Setting up the application

We’ll start with creating our new NextJS 13 app with TS and ESLint.

npx create-next-app --experimental-app

Once in the project, we can install all the libraries we need in order to get started.

npm i @web3modal/react @web3modal/ethereum wagmi

With this out the way, we can begin with the setup of the Web3Modal client.

Getting a ProjectID from WalletConnect

To properly use Web3Modal, you need to create a project on WalletConnect.
After creating an account, simply click on New Project, pick a suitable name and then click Create.
You can now navigate into the project and find your own ProjectID.

Now that we have the ID, we need to add it to a .env file, so that we can use it inside the application. To do this, create a .env.local file at the root of your app and add the following variable. Don’t forget to insert your personal project id that you just copied. 🙂

NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=<your-project-id>

Creating the Web3Modal client

In NextJS 13 the layout.tsx is a server component by default, which is why we can’t use the required WagmiConfig Provider out of the box.
So we first need to create a web3-provider.tsx in the apps directory of our application with the following code.

"use client";

import { mainnet, configureChains, createClient, WagmiConfig } from "wagmi";
import {
  EthereumClient,
  modalConnectors,
  walletConnectProvider,
} from "@web3modal/ethereum";
import { Web3Modal } from "@web3modal/react";

const chains = [mainnet];

// Wagmi client
const { provider } = configureChains(chains, [
  walletConnectProvider({
    projectId: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID!,
  }),
]);
const wagmiClient = createClient({
  autoConnect: true,
  connectors: modalConnectors({ appName: "web3Modal", chains }),
  provider,
});

// Web3Modal Ethereum Client
const ethereumClient = new EthereumClient(wagmiClient, chains);

export default function Web3ModalProvider({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <>
      <WagmiConfig client={wagmiClient}>{children}</WagmiConfig>
      <Web3Modal
        projectId={process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID}
        ethereumClient={ethereumClient}
      />
    </>
  );
}

The "use client" tells NextJS that the component should be rendered client side.
Afterwards, we configure the Web3Modal Provider by defining the chains that should be used by wagmi and passing them into the configureChains function together with the WalletConnect provider.
This returns a provider object that we can use to create our wagmiClient .
We also need an EthereumClient to pass to the Web3Modal component.

This shiny new Web3 Provider can now be imported inside the root layout.tsx file and wrapped around the children object like this.

import Web3ModalProvider from "./web3-provider";
import "./globals.css";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <head />
      <body>
        <Web3ModalProvider>{children}</Web3ModalProvider>
      </body>
    </html>
  );
}

Now our application is fully set up to work with Web3Modal and wagmi.
The only thing left is to create the connect button for your wallet.

Adding a connect button

Inside the index page.tsx all the content inside the <main></main> tags can be removed as we don’t need it for this dapp.
The @Web3Modal/react package provides a connect button out of the box that allows for some customisation. For this you can simply use the following code. Again, don’t forget that it’s a client side component with "use client";

"use client";

import { Web3Button } from "@web3modal/react";

export default function Home() {
  return (
    <main>
      <Web3Button />
    </main>
  );
}

This completes everything we set out to do.
We can now connect our wallet to our dapp and use it as e.g. user authentication or just to fetch the wallet address.

However, we can go one step further and create a fully custom connect button.
For this we’ll use TailwindCSS as our CSS framework to have some more options with the styling.

npm i -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

The new page.tsx in the app folder could be rewritten as:

"use client";

import { useWeb3Modal } from "@web3modal/react";
import { useAccount, useDisconnect, useBalance } from "wagmi";

export default function Home() {
  const { address } = useAccount();
  const { data, isLoading } = useBalance({ address });
  const { open } = useWeb3Modal();
  const { disconnect } = useDisconnect();
  return (
    <main className="absolute inset-0 grid place-content-center">
      <div className="space-y-3 rounded-3xl bg-gray-800 px-8 py-6 shadow-xl">
        <h1 className="font-mono text-3xl font-bold">Wallet Connect</h1>
        {address ? (
          <div className="space-y-8">
            <div className="space-y-2">
              <div className="space-y-0.5">
                <h2>your address</h2>
                <p className="rounded bg-gradient-to-tr from-indigo-500 to-violet-700 px-2 py-1">
                  {address}
                </p>
              </div>
              <div className="space-y-0.5">
                <h2>your balance</h2>
                <p className="rounded bg-gradient-to-tl from-indigo-500 to-violet-700 px-2 py-1">
                  {isLoading
                    ? "loading..."
                    : `${data?.formatted} ${data?.symbol}`}
                </p>
              </div>
            </div>
            <div className="flex w-full justify-end">
              <button
                type="button"
                className="rounded-lg border-2 border-red-500 px-3 py-1.5 transition-colors hover:bg-gray-600/25"
                onClick={() => disconnect()}
              >
                disconnect
              </button>
            </div>
          </div>
        ) : (
          <button
            type="button"
            onClick={() => open()}
            className="w-full rounded-xl bg-gradient-to-tr from-indigo-500 to-violet-700 px-4 py-2 text-center"
          >
            connect wallet
          </button>
        )}
      </div>
    </main>
  );
}

And with some styling in our globals.css :

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
html,
body {
@apply bg-gray-900 text-gray-100;
}
}

It would look something like this:

website with connect wallet button
custom connect button
website after logging in with the connect button
custom “user information” after logging in with the wallet

The final file tree should look something like this:

app/
- globals.css
- head.tsx
- layout.tsx
- page.tsx
- web3-provider.tsx

This concludes this tutorial on how to implement the functionality to connect your wallet with your dapp.
I hope you learned something along the way and were able to use this guide in your own project.

You can find the example project on my GitHub under the name web3modal-blog.

You might also like

This website uses cookies to improve your web experience.
Explore
Drag