In this article, weโll use NextJS and Moralisโ Web3 Auth API to integrate the WalletConnect modal and QR code. As a result of following along with the steps in this article, you can have the following authentication sequence running on your dapp:
For those already familiar with NextJS and Moralisโ API, feel free to access the documentation page to get started immediately. With that said, if youโd like a free tutorial guiding you through the process and learning how to integrate the WalletConnect QR code modal, read on!
Overview
From a user perspective, itโs extremely convenient when a website or app provides the ability to log in using a simple scan of a QR code. As such convenience attracts many users, itโs not surprising to see an increase in sites and apps integrating QR code functionality. Furthermore, this type of authentication is not just popular for traditional apps but also for decentralized applications (dapps). To add this type of Web3 authentication to your dapps, you should focus on WalletConnect. Fortunately, thatโs exactly what this article focuses on. More specifically, this article explores how to integrate the WalletConnect modal and QR code!
Moving forward, youโll have a chance to follow our lead and create a simple dapp using NextJS and Moralis. After all, it is the Moralis Web3 Auth API that enables you to integrate the WalletConnect modal into any dapp without breaking a sweat. While we will focus on using the NextJS framework herein, itโs worth pointing out that Moralis is fully cross-platform interoperable. As such, you can create dapps with the WalletConnect QR code modal using a wide range of legacy dev platforms and programming languages. Accordingly, Moralis helps bridge the development gap between Web2 and Web3. Aside from the ultimate Web3 Auth API, Moralis offers the best EVM and Solana APIs. These include the NFT API, Token API, and Streams API. Whatโs more, you can use these excellent tools on all leading blockchain networks.
However, before we show you how to build a simple NextJS dapp that includes the WalletConnect modal, we need to get you all up to speed. As such, weโll first explore WalletConnectโs open-source protocol and look at what itโs used for. That said, make sure to get ready for the action-taking part of todayโs article by creating your free Moralis account now.
Exploring WalletConnectโs Open-Source Protocol
You can still hear people say that WalletConnect is a crypto wallet. However, thatโs not completely accurate. WalletConnect is an open-source protocol that establishes secure connections between crypto wallets and decentralized applications (dapps). This open-source protocol uses symmetric encryption via a shared key between two peers, which makes it one of the safest methods of Web3 authentication.
You can also think of WalletConnect as a decentralized Web3 messaging layer and a standard for connecting blockchain wallets to dapps. In addition, itโs worth pointing out that WalletConnectโs team strives to continuously expand this protocolโs interoperability. Hence, we can expect high quality and reliability from WalletConnect moving forward. As a dapp developer, you donโt want to overlook the critical infrastructure for Web3 wallets and dapps that WalletConnect supports. It achieves that by ensuring that the following core concepts are correctly implemented:
- Chain Agnostic โ WalletConnect believes in the multi-chain future of the crypto domain. As such, the WalletConnect team focuses on supporting all the leading chains. These include Ethereum, Solana, and many others. To ensure a chain-agnostic approach, WalletConnect is committed to continually adding support for emerging reputable chains.
- Multi-Chain โ WalletConnectโs users can connect any of the supported wallets to multiple chains at the same time.
- Platform Agnostic โ In addition to supporting different chains, WalletConnect also supports different platforms. Hence, the WalletConnect modal serves web, desktop, mobile, and gaming dapps.
What is WalletConnect Used For?
The above explanation should clarify that the WalletConnect modal establishes safe connections between Web3 wallets and dapps. As such, letโs explore what this process looks like. For starters, itโs worth pointing out that WalletConnect gives users two ways to establish the connection. On the one hand, users can do that by scanning a QR code with their mobile Web3 wallets โ this is the more user-friendly method and is offered by default. On the other hand, users may also use a deep link, which is particularly handy for users that do not have mobile wallets to scan the code.
However, both methods let one peer (a dapp) send out a code or link. Then, itโs up to the other peer (a crypto wallet) to scan or approve the connection. Via this method, dapps that include the WalletConnect modal and QR code enable users to easily establish safe and reliable Web3 connections.
Furthermore, WalletConnectโs impressive range of supported wallets makes this protocol extremely practical. After all, it is almost impossible to find unsupported wallets. Moreover, the official WalletConnect website currently states that their solution works with more than 170 crypto wallets. In case you want to explore what Web3 wallets WalletConnect supports, visit WalletConnectโs official website, scroll down to the โLooking for a wallet?โ section, and click on the โVIEW ALL WALLETSโ button:
The above button will take you to the โExploreโ page. There, youโll be able to see all the supported wallets:
Itโs worth pointing out that there are sixteen pages (fifteen full pages) with fifteen wallets per page (see the screenshot above). So, if we do simple math, itโs evident that WalletConnect already supports over 225 Web3 wallets.
WalletConnect Modal โ How to Integrate the WalletConnect QR Code Modal
With the basics under your belt, itโs time to build a simple dapp with the WalletConnect QR code modal. If you remember, weโll be using NextJS and Moralis to complete todayโs feat. Hence, the power of Moralisโ Auth API makes integrating the WalletConnect modal as straightforward as it gets. Moving on, weโll take you through all the steps you need to complete to end up with a simple dapp on your local server.
Also, weโll provide you with all the lines of code. As such, youโll be able to simply copy and paste the content to your instances of the required scripts. Hereโs the list of the files youโll get to create if you decide to complete todayโs challenge:
- โ.env.localโ โ In this file, youโll store all the local variables, including your Moralis Web3 API key.
- โ_app.jsxโ โ Youโll use this file to wrap your app with โWagmiConfigโ and โSessionProviderโ.
- โrequest-message.jsโ โ This file will serve as an endpoint for making requests to generate a unique message.
- โsignin.jsxโ โ Youโll use this file to create the โsigninโ page. As such, this file will contain the connector that will enable users to authenticate themselves with the WalletConnect QR code modal.
- โ[โฆnextauth].jsโ โ This is the file that youโll use to configure NextAuth.
- โuser.jsxโ โ Youโll use this file to create the โuserโ page that the successfully authenticated users will land on. For the sake of this tutorial, it will contain some basic user information.
However, before you get your hands dirty, we also want to ensure that you know exactly what youโll be building. As such, letโs do a quick demo of our example dapp.
Our Example NextJS Dapp Demo
The following screenshot shows the gist of the โsigningโ page on the client side:
As you can see, there is the โWeb3 Authenticationโ title and the โAuthenticate via WalletConnectโ button. Hence, itโs very intuitive for users to click on the button that will trigger the WalletConnect modal:
Using their mobile wallets, users get to scan the above QR code and confirm their authentication on the mobile devices:
The above image shows the confirmation on Trust Wallet; however, the process is similar for other crypto wallets.
Finally, once users connect their wallet to our dapp, they land on the โuserโ page. The latter displays some basic data related to the connected profile:
Getting Started โ Prerequisites and the Initial Setup for Your NextJS Dapp
Before completing the initial setups, make sure to get the following ready:
- Create your Moralis account.
- Install and set up Visual Studio Code (VSC).
- Create a NextJS application. Use the โCreate Next Appโ page in the NextJS docs or complete our โUsing NextJSโ tutorial if you need help with that step.
With the above prerequisites under your belt, you are ready to install the required dependencies. So, you can use one of the following commands (depending on your package manager) to install Moralis, NextAuth, and Axios:
npm install moralis next-auth axios
yarn add moralis next-auth axios
pnpm add moralis next-auth axios
Moreover, you also need to install the wagmi Web3 library using one of the following commands:
npm install wagmi ethers
yarn add wagmi ethers
pnpm add wagmi ethers
Next, create a โ.env.localโ file in your appโs root and populate it with the required environment variables:
- โAPP_DOMAINโ โ An RFC 4501 DNS authority thatโs requesting the signing.
- โMORALIS_API_KEYโ โ Your gateway to using Moralis.You can obtain the API key inside your Moralis admin area:
- โNEXTAUTH_URLโ โ Your app address. In the development stage, you want to use โhttp://localhost:3000โ or similar.
- โNEXTAUTH_SECRETโ โ A variable that will encrypt the JWT tokens of users. You may use any value here or generate one at โhttps://generate-secret.now.sh/32โ.
Nonetheless, take a look at this example that will help you better understand the above environment variables:
Note: Keep in mind that you need to restart your dapp whenever you modify your โ.env.localโ file.
Override the NextJS โAppโ Component
NextJS uses the โAppโ component to initialize pages, which you can override to take control of the page initialization. To do this, wrap your pages with โWagmiConfigโ and โSessionProviderโ. Hence, create the โ_app.jsxโ file inside the โpagesโ folder. Then, use the following lines of code to populate that file:
import { createClient, configureChains, defaultChains, WagmiConfig } from 'wagmi'; import { publicProvider } from 'wagmi/providers/public'; import { SessionProvider } from 'next-auth/react'; const { provider, webSocketProvider } = configureChains(defaultChains, [publicProvider()]); const client = createClient({ provider, webSocketProvider, autoConnect: true, }); function MyApp({ Component, pageProps }) { return ( <WagmiConfig client={client}> <SessionProvider session={pageProps.session} refetchInterval={0}> <Component {...pageProps} /> </SessionProvider> </WagmiConfig> ); } export default MyApp;
Create the โrequestMessageโ Endpoint
Start this step by creating a new API file and calling it โrequest-message.jsโ. Make sure to create that file inside the โauthโ folder. The latter should be inside โpages/apiโ. Furthermore, this endpoint will make requests to โMoralis.Authโ to generate a unique message. Later on, youโll need to sign that message on the client side. Below are the lines of code that you need to copy-paste into โrequest-message.jsโ:
import Moralis from 'moralis'; const config = { domain: process.env.APP_DOMAIN, statement: 'Please sign this message to confirm your identity.', uri: process.env.NEXTAUTH_URL, timeout: 60, }; export default async function handler(req, res) { const { address, chain, network } = req.body; await Moralis.start({ apiKey: process.env.MORALIS_API_KEY }); try { const message = await Moralis.Auth.requestMessage({ address, chain, network, ...config, }); res.status(200).json(message); } catch (error) { res.status(400).json({ error }); console.error(error); } }
Create a Sign-In Page with the WalletConnect Modal
With the initial setup completed and the โ_app.jsxโ and โrequest-message.jsโ files in place, itโs time to integrate WalletConnect. Start by creating the โsignin.jsxโ file inside the โpagesโ folder. This file will serve as a new page once you populate it according to our instructions. For starters, enter the following:
function SignIn() { return ( <div> <h3>Web3 Authentication</h3> </div> ); } export default SignIn;
Moving on, you need to create the โAuthenticate via WalletConnectโ button, as presented in the demo above. Moreover, for now, also โconsole.logโ usersโ details. Youโll achieve both of these goals by updating your โsignin.jsxโ file to look as follows:
import { useConnect } from 'wagmi'; import { InjectedConnector } from 'wagmi/connectors/injected'; import axios from 'axios'; function SignIn() { const { connectAsync } = useConnect(); const handleAuth = async () => { const { account, chain } = await connectAsync({ connector: new InjectedConnector() }); const userData = { address: account, chain: chain.id, network: 'evm' }; console.log(userData) }; return ( <div> <h3>Web3 Authentication</h3> <button onClick={() => handleAuth()}>Authenticate via WalletConnect</button> </div> ); } export default SignIn;
Extend the โhandleAuthโ Functionality
With the above lines of code in place, you already have your Web3 authentication pageโs appearance covered. Thus, itโs time to also add the actual Web3 functionality. So, start by extending the โhandleAuthโ functionality. Youโll use the latter to call the previously created โrequestMessageโ endpoint. As such, update the โsignin.jsxโ script to match the lines of code below:
import { useAccount, useConnect, useSignMessage, useDisconnect } from 'wagmi'; import { InjectedConnector } from 'wagmi/connectors/injected'; import axios from 'axios'; function SignIn() { const { connectAsync } = useConnect(); const { disconnectAsync } = useDisconnect(); const { isConnected } = useAccount(); const { signMessageAsync } = useSignMessage(); const handleAuth = async () => { // Disconnects the Web3 provider if it's already active if (isConnected) { await disconnectAsync(); } // Enabling WalletConnect const { account, chain } = await connectAsync({ connector: new WalletConnectConnector({ options: { qrcode: true, }, }), }); const userData = { address: account, chain: chain.id, network: 'evm' }; // Making a post request to our 'request-message' endpoint const { data } = await axios.post('/api/auth/request-message', userData, { headers: { 'Content-Type': 'application/json', }, }); const message = data.message; const signature = await signMessageAsync({ message }); console.log(signature) }; return ( <div> <h3>Web3 Authentication</h3> <button onClick={() => handleAuth()}>Authenticate via WalletConnect</button> </div> ); } export default SignIn;
Configure NextAuth
In order to properly configure NextAuth, create a โ[โฆnextauth].jsโ file. Also, make sure the file is inside the โauthโ folder (path: โpages/api/auth/โ). Then, add the following code to this file:
import CredentialsProvider from 'next-auth/providers/credentials'; import NextAuth from 'next-auth'; import Moralis from 'moralis'; export default NextAuth({ providers: [ CredentialsProvider({ name: 'MoralisAuth', credentials: { message: { label: 'Message', type: 'text', placeholder: '0x0', }, signature: { label: 'Signature', type: 'text', placeholder: '0x0', }, }, async authorize(credentials) { try { // "message" and "signature" are needed for authorization // We described them in "credentials" above const { message, signature } = credentials; await Moralis.start({ apiKey: process.env.MORALIS_API_KEY }); const { address, profileId } = ( await Moralis.Auth.verify({ message, signature, network: 'evm' }) ).raw; const user = { address, profileId, signature }; // Returning the user object and creating a session return user; } catch (e) { console.error(e); return null; } }, }), ], // Adding user info to the user session object callbacks: { async jwt({ token, user }) { user && (token.user = user); return token; }, async session({ session, token }) { session.user = token.user; return session; }, }, });
Secure Authentication with WalletConnect
As for the final tweak to the โsignin.jsxโ file, you need to equip it with NextAuth authentication. In addition, youโll also import โWalletConnectConnectorโ from wagmi and โuseRouterโ from Next. Furthermore, the lines of code below will also properly expand the โSignInโ function:
import { signIn } from 'next-auth/react'; import { useAccount, useConnect, useSignMessage, useDisconnect } from 'wagmi'; import { useRouter } from 'next/router'; import axios from 'axios'; import { WalletConnectConnector } from 'wagmi/connectors/walletConnect'; function SignIn() { const { connectAsync } = useConnect(); const { disconnectAsync } = useDisconnect(); const { isConnected } = useAccount(); const { signMessageAsync } = useSignMessage(); const { push } = useRouter(); const handleAuth = async () => { if (isConnected) { await disconnectAsync(); } // Added WalletConnectConnector const { account, chain } = await connectAsync({ connector: new WalletConnectConnector({ options: { qrcode: true, }, }), }); const userData = { address: account, chain: chain.id, network: 'evm' }; const { data } = await axios.post('/api/auth/request-message', userData, { headers: { 'Content-Type': 'application/json', }, }); const message = data.message; const signature = await signMessageAsync({ message }); // Redirect user after success authentication to '/user' page const { url } = await signIn('credentials', { message, signature, redirect: false, callbackUrl: '/user' }); /** * instead of using signIn(..., redirect: "/user") * we get the url from callback and push it to the router to avoid page refreshing */ push(url); }; return ( <div> <h3>Web3 Authentication</h3> <button onClick={() => handleAuth()}>Authenticate via WalletConnect</button> </div> ); } export default SignIn;
Add the User Page
In the above step, youโve completed your โsigninโ page. However, if you remember the above demo, our example dapp also has the โuserโ page. Thus, revisit the โpagesโ folder and create a new file โ โuser.jsxโ. Use the following lines of code to ensure that this page displays some basic user info and offers the โSign outโ button:
import { getSession, signOut } from 'next-auth/react'; // Gets a prop from getServerSideProps function User({ user }) { return ( <div> <h4>User session:</h4> <pre>{JSON.stringify(user, null, 2)}</pre> <button onClick={() => signOut({ redirect: '/signin' })}>Sign out</button> </div> ); } export async function getServerSideProps(context) { const session = await getSession(context); // Redirect if not authenticated if (!session) { return { redirect: { destination: '/signin', permanent: false, }, }; } return { props: { user: session.user }, }; } export default User;
The โuserโ page was the final piece of todayโs puzzle. As such, youโve now successfully created a simple NextJS dapp with the WalletConnect QR code modal. Since you were able to simply copy our code, everything should be in order. However, we still encourage you to test your dapp.
Test the WalletConnect QR Code Modal
Presuming that you used the โ3000โ port (as instructed) for your โNEXTAUTH_URLโ variable, use your browser to go to โhttp://localhost:3000/signinโ. By doing so, youโll land on the โsigninโ page of your dapp, where you can test the authentication process. Basically, you need to complete all the steps presented in the demo above. So, start by clicking on โAuthenticate via WalletConnectโ:
Nonetheless, you should land on the โuserโ page (โhttp://localhost:3000/userโ) if the WalletConnect QR code modal is functioning properly. However, if you cannot authenticate yourself, the above code will redirect you back to the โsigningโ page. If that happens, make sure to re-examine the above steps.
How to Integrate the WalletConnect Modal and QR Code โ Summary
You now know that WalletConnect is an open-source protocol designed to establish safe connections between Web3 wallets and dapps. In this article, you also learned that it supports over 225 wallets across multiple chains. Furthermore, you had a chance to follow our lead and create your own NextJS dapp with the WalletConnect modal. To make the process as frictionless as possible, we provided you with all the scripts you needed to finish this challenge. As a result, you created the following six files, which contain all the required lines of code:
- โ.env.localโ
- โ_app.jsxโ
- โrequest-message.jsโ
- โsignin.jsxโ
- โ[โฆnextauth].jsโ
- โuser.jsxโ
Moving forward, we encourage you to work on todayโs example dapp by adding additional Web3 functionalities. That way, youโll get better acquainted with the power of Moralisโ Web3 API and, in turn, build up the confidence to tackle other projects. As part of the learning process, we recommend you explore other how-to guides and tutorials in the Moralis documentation. Also, make sure to use the Moralis YouTube channel and the Moralis blog to expand your blockchain development horizons. For instance, in some of our latest articles, we focus on a Web3 JS tutorial for blockchain developers, building a Unity Web3 multiplayer game, explaining Dogechain, the Aptos and Sui chains, the ultimate blockchain tech stack, and more.
On the other hand, you might be eager to go full-time crypto as soon as possible. If thatโs the case, you should enroll in Moralis Academy and become blockchain certified. This will significantly improve your chances of landing your dream crypto job. There are many courses available; however, we recommend starting with blockchain and Bitcoin fundamentals.
Read More: moralis.io