Building a Coin Flip Game on Ethereum (Part 1) - Web3 Email Onboarding

Emmanuel Oaikhenan
Emmanuel Oaikhenan
Technical Writer
This tutorial walks through implementing Web3 email onboarding using Particle Auth for authentication and the Biconomy SDK for handling blockchain transactions.

Account Abstraction is premised on the ease of user onboarding into Web3. Users can be onboarded without the need to understand how to manage Wallet Keys, as is typical of Web3 onboarding. In this guide, Web3 email onboarding refers to authenticating users using their email addresses within a decentralized application (dApp). This tutorial walks developers through the steps of implementing Web3 email onboarding using Particle Auth for authentication and the Biconomy SDK for handling blockchain transactions.

This guide is part one of a three part series on how to build and deploy a coin flip game on Ethereum, but it can also be used on its own!

Prerequisites

Before starting with the implementation, make sure you have the following:

  1. Node.js and npm are installed on your machine.

  2. A basic understanding of React.js and Next.js.

  3. Access to a Biconomy API key and Particle Auth credentials.

Tutorial: Integrating Particle Auth and Biconomy SDK in Next.js for Email Onboarding

1

Create a Next.js Project

Create a new Next.js project and navigate to the project directory:

npx create-next-app web3-onboarding-demo
cd web3-onboarding-demo
2

Install Dependencies

Install the required dependencies for Particle Auth, Biconomy SDK, and other packages:
Particle Auth is a simple self-custodial auth infra for Web3 apps and wallets. It supports mobile numbers and email login and provides users a simple onboarding experience.
The @biconomy/particle-auth is a library to import the particle-auth for the web directly from Biconomy SDK.
npm install @biconomy/particle-auth @biconomy/account @particle-network/chains  viem ethers
3

UI Setup

Open the pages/index.js file and replace its content with the following code. Update the placeholders with your actual credentials:
import { Inter } from "next/font/google";
export default function Home() {
return (
    <div
      className={`flex min-h-screen flex-col p-24 ${inter.className}`}
    >
      <p>Hello}</p>
    <button
       className="mt-6 flex justify-center items-center w-64 cursor-pointer border-2 border-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
          >
            Login
          </button>
      </>    
    </div>
    
  );
}
3.1
Run the application using the following command:
npm run dev
3.2
Visit http://localhost:3000 in your browser to see the page.
4

Set Up Biconomy

Import the dependencies in the index.tsx file:
import { createSmartAccountClient } from "@biconomy/account";
import { ParticleAuthModule, ParticleProvider } from "@biconomy/particle-auth";
import { PolygonMumbai } from "@particle-network/chains";
import { ethers } from "ethers";
4.1
In the Home component, we will set up the particle class by getting the required credentials from Particle Auth.
…
  const particle = new ParticleAuthModule.ParticleNetwork({
    projectId: "YOUR_PROJECT_ID",
    clientKey: "YOUR_CLIENT_KEY",
    appId: "YOUR_APP_ID",
chainName: PolygonMumbai.name, //optional: current chain name, default Ethereum.
  chainId: 80001,
    wallet: {
      displayWalletEntry: true,
      defaultWalletEntryPosition: ParticleAuthModule.WalletEntryPosition.BR,
      uiMode: "dark",
      supportChains: [
        { id: 11155111, name: "Sepolia" },
      ],
      customStyle: {},
    },
  });
4.2
In the code above, we initialize a class using ParticleAuthModule. The variable particle, which holds the credentials, will be parsed as a provider, which will be used to create a signer that will then be parsed to the Biconomy SDK.
First, let’s add some State:
const [scw, setSCW] = useState<String>("")
const [SmartAccount, setSmartAccount] = useState<any>(null)
4.3
Create a function to handle the creation of the Smart Contract Wallet using the particle instance and the Biconomy SDK. The particle has a method particle.auth that is parsed to the EthersJS provider instance BrowserProvider which is used to create the Provider for instantiating a Signer object that enables the created wallet to give permissions to sign UserOperations (transactions).
const fetchSmartAccount = async () => {
    const particleProvider = new ParticleProvider(particle.auth);
    const web3Provider = new ethers.BrowserProvider(
      particleProvider,
      "any"
    );
    const signer = await web3Provider.getSigner()
      const smartAccountValue = await createSmartAccountClient({
        signer,
        bundlerUrl: "<https://bundler.biconomy.io/api/v2/80001/nJPK7B3ru.dd7f7861-190d-41bd-af80-6877f74b8f44>",
        biconomyPaymasterApiKey: "YOUR_BICONOMY_API_KEY",
        rpcUrl: "<https://rpc.ankr.com/polygon_mumbai>"
      });
      setSmartAccount(smartAccountValue);
      console.log(smartAccountValue)
      const address = await smartAccountValue.getAccountAddress();
      setSCW(address);
      console.log(address)
    };
5

Login

The next step is to implement the login into the application. We will create a Login function. Particle Auth has a method login that initializes a Modal where users can log in via their email.
5.1
The login is also called the fetchSmartAccount to create the Smart Contract Wallet upon login. It is important to note that the Particle Auth login function creates a User Object with credentials returned, such as email and wallets (an array). Note that the address created by Particle Auth is an EOA used to create the smart contract wallet by Biconomy SDK.
const login = async () => {
  try {
     const userInfo = await particle.auth.login();
     console.log("Logged in user:", userInfo);
     await fetchSmartAccount();
  } catch (error) {
     console.error(error);
  }
};
5.2
To see the login method in action, the next step is to update the button in the return statement. Also, at this point we use a unary operator to mount the state and demonstrate that the user is logged in:
 return (
    <div
      className={`flex min-h-screen flex-col p-24 ${inter.className}`}
    >
      {scw ? 
      <>
 <p>Hello {scw}</p>
  </>
      :
      <>
      <p>Hello {scw}</p>
    <button
            onClick={login}
            className="mt-6 flex justify-center items-center w-64 cursor-pointer border-2 border-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
          >
            Login
          </button>
      </>
    }
    </div>
  );
5.3
Run the application using the following command:
npm run dev
5.4
Visit http://localhost:3000 in your browser to view the Web3 email onboarding application.

Complete Code Base

// Import necessary packages import { useState, useEffect } from "react"; import { createSmartAccountClient } from "@biconomy/account"; import { ParticleAuthModule, ParticleProvider } from "@biconomy/particle-auth"; import { PolygonMumbai } from "@particle-network/chains"; import { ethers } from "ethers"; // Define the Home component export default function Home() { // State variables const [scw, setSCW] = useState<String>(""); const [SmartAccount, setSmartAccount] = useState<any>(null); // Initialize Particle Auth const particle = new ParticleAuthModule.ParticleNetwork({ projectId: "YOUR_PROJECT_ID", clientKey: "YOUR_CLIENT_KEY", appId: "YOUR_APP_ID", chainName: PolygonMumbai.name, //optional: current chain name, default Ethereum. chainId: 80001, wallet: { displayWalletEntry: true, defaultWalletEntryPosition: ParticleAuthModule.WalletEntryPosition.BR, uiMode: "dark", supportChains: [ { id: 80001, name: "Mumbai" }, ], customStyle: {}, }, }); // Connect function for authentication const connect = async () => { try { const userInfo = await particle.auth.login(); console.log("Logged in user:", userInfo); const address = await SmartAccount.getAccountAddress(); console.log(address); setSCW(address); } catch (error) { console.error(error); } }; // Fetch Smart Account on component mount useEffect(() => { const fetchSmartAccount = async () => { const particleProvider = new ParticleProvider(particle.auth); const web3Provider = new ethers.BrowserProvider( particleProvider, "any" ); const signer = await web3Provider.getSigner(); const smartAccountValue = await createSmartAccountClient({ signer, bundlerUrl: "<https://bundler.biconomy.io/api/v2/11155111/nJPK7B3ru.dd7f7861-190d-41bd-af80-6877f74b8f44>", biconomyPaymasterApiKey: "YOUR_BICONOMY_PAYMASTER_API_KEY", rpcUrl: "<https://rpc.ankr.com/polygon_mumbai>", }); setSmartAccount(smartAccountValue); console.log(SmartAccount); }; fetchSmartAccount(); }, []); // Render UI return ( <div className={`flex min-h-screen flex-col p-24`}> {scw ? ( <> <p>Hello {scw}</p> </> ) : ( <> <p>Hello {scw}</p> <button onClick={connect} className="mt-6 flex justify-center items-center w-64 cursor-pointer border-2 border-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" > Login </button> </> )} </div> ); }

Conclusion

This tutorial covers the integration of Particle Auth and Biconomy SDK for Web3 email onboarding in a Next.js application. Feel free to customize and extend the code to fit your specific requirements. Refer to Particle Auth and Biconomy documentation for more advanced features and configurations.

Read more