Viem and Wagmi Integration with OperaMini

Viem and Wagmi Integration with OperaMini
Written By: Bishakh Neogi

Problem Statement

Integrating a Next.js application with MiniPay in today’s fast-paced world poses numerous challenges, particularly in achieving seamless integration with blockchain wallets and providing a smooth user experience. Developers often struggle with the complexities of Ethereum libraries, efficient wallet connections, and ensuring compatibility across various devices and browsers. The need for a robust solution becomes even more critical with the growing user base of mobile browsers like Opera Mini, which boasts over 100 million users.


With the technological boom, the technical jargons are also growing exponentially, especially for blockchain. Most developers, after just reading the term blockchain, get overwhelmed. Are you also looking to work with blockchain but afraid of this 10-letter word?

Say no to complexities and big technical terms. We’re in this together! This story will help you understand the integration in no time. So let’s jump into this together!

Imagine blockchain as a digital party. Viem is the host ensuring everything runs smoothly. Wagmi is the DJ, keeping the music (or transactions) flowing. And MiniPay? It’s the VIP guest list, ensuring only the right people get in.

So, grab your virtual party hat, and let’s dive into the world of blockchain integration. Who knew coding could be this fun?

Goal

A passionate team of developers is determined to create a revolutionary DApp called MicroCredit. Their vision is to offer microloans to underserved communities, enabling financial inclusion for millions. However, they face a significant hurdle: integrating their DApp with the MiniPay wallet, a rapidly expanding wallet on the Celo blockchain embedded in the Opera Mini browser. This integration is crucial for reaching their target audience primarily using mobile devices.

Despite their enthusiasm, the team encounters several roadblocks:

  1. Complexity of Existing Libraries: The low-level TypeScript Ethereum libraries are difficult to work with, causing delays and frustration.
  2. Efficient Wallet Integration: Ensuring a smooth connection with the MiniPay wallet while maintaining security and reliability is challenging.
  3. Compatibility Issues: The DApp needs to be compatible with the Opera Mini browser on Android devices, which requires meticulous configuration.

Determined to overcome these challenges, the team leverages two powerful tools: Viem and Wagmi.

Tools required for the integration are:

1.Wagmi (a.k.a. DJ): wagmi is a React Hooks library that provides a streamlined way to interact with Ethereum. It is designed to make working with Ethereum within React applications easier by offering a set of hooks for common blockchain operations.

2.Viem (a.ka. host): The Wagmi users needed help working with the existing low-level TypeScript Ethereum libraries. So here the view came into the picture by creating a TypeScript Interface for Ethereum that provides low-level stateless primitives for interacting with Ethereum.
Viem is an alternative to ethers.js and web3.js with better reliability, efficiency, and excellent developer experience.

3.Minipay (a.k.a. VIP Guest List): MiniPay, a rapidly expanding wallet developed by Opera on the Celo blockchain, aims to offer a seamless user experience for interacting with decentralized applications (DApps). Integrated into the Opera Mini browser on Android devices, MiniPay provides DApp developers access to a vast user base of 100 million people, facilitating broad distribution and adoption.

Flow-diagram of integrating Viem and Wagmi with Minipay wallet


Steps to integrate Viem and Wagmi with Minipay

Folder structure for integration:
(In the steps below we are using Nextjs 14.1.4 with Page router)

blockchain
  |
  config
    |
    index.ts
  chains.ts
pages
  |
  __app.tsx

Creation of wagmiClient
(blockchain/config/index.ts)

import { http, createConfig } from "wagmi";
import { createConfig as createCoreConfig } from "@wagmi/core";
import { celo } from "wagmi/chains";
import { injected } from "wagmi/connectors";
import { cookieStorage, createStorage } from "wagmi";

export const wagmiClient = createConfig({
  chains: [celo],
  connectors: [injected()],
  transports: {
    [celo.id]: http(),
  },
  ssr: true,
  storage: createStorage({
    storage: cookieStorage,
  }),
});

export const wagmiCoreClient = createCoreConfig({
  chains: [celo],
  transports: {
    [celo.id]: http(),
  },
});
injected is the type of connector for connecting EIP-1193 Ethereum Providers.

1. Chains (Celo): The Navigator

Chains, also known as Celo, is the wise navigator of the Tech Tribe. Celo knows the way around the vast blockchain landscape and ensures the Tribe stays on the right path. Whenever the Tribe starts a new journey, Celo charts the course by defining which blockchain networks they will traverse. In this adventure, Celo is guiding them through the Celo blockchain.

chains: [celo],

2. Connectors (Injected): The Connector

Injected, the energetic connector, has a knack for building bridges. Whenever the Tribe encounters a new device or browser, Injected steps in to establish a secure connection. With Injected’s help, the Tribe can link their application to various Ethereum providers, making sure their DApp is accessible from different platforms.

connectors: [injected()],

3. SSR (Server-Side Rendering): The Stealthy Agent

SSR, the stealthy agent, ensures that everything runs smoothly behind the scenes. SSR is a master of disguise, making sure the Tribe’s DApp performs optimally whether users are on the client-side or server-side. By enabling SSR, the Tribe can deliver a seamless user experience, regardless of where the request comes from.

ssr: true,

4. Transports (HTTP): The Messenger

Transports, the reliable messenger, is responsible for carrying important information back and forth. In this quest, Transports uses the HTTP protocol to communicate with the blockchain. Whenever the Tribe needs to send or receive data, Transports ensures it gets delivered accurately and efficiently.

transports: {
  [celo.id]: http(),
},

5. Storage (Cookie Storage): The Keeper of Secrets

Storage, the meticulous keeper of secrets, ensures that all important data is stored safely. Using cookie storage, Storage keeps track of crucial information such as user sessions and preferences. This way, the Tribe can easily retrieve and use the data whenever needed, ensuring a personalized and consistent experience for their users.

Using the WagmiProvider with the created WagmiClient
(pages/_app.tsx)

import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { wagmiClient } from "@/blockchain/config";
import { WagmiProvider } from "wagmi";
import "@/styles/globals.css";
import type { AppProps } from "next/app";
import Head from "next/head";

export default function App({ Component, pageProps }: AppProps) {
  return (
    
      <Head>
        <title>MicroCredit</title>
      </Head>

      <WagmiProvider config={wagmiClient}>
        <AppQueryClientProvider>
          <AppWrapper>
            <main className={`${generalSans.className}  mx-auto`}>
              <Component {...pageProps} />
            </main>
          </AppWrapper>
          <ReactQueryDevtools initialIsOpen={false} />
        </AppQueryClientProvider>
      </WagmiProvider>
  );
}

Configuring the Chain-id and Gas-fees estimation
(blockchain/chain.ts)

import { celo, Chain } from "viem/chains";

export const MainChain = celo;

export function gasEstimationWorks(chainId: Chain["id"]) {
  return chainId !== celo.id;
}
Flow-diagram explaining the chain.ts


Now we are all set with the chain-id, gas-fees and the Wagmi-client to be used in our application.

The destructured value used for the integration:

By destructuring the object we can get the wallet-address and the connection status of the wallet from the useConnect() hook provided by Wagmi.

 const {
    address,
    status,
    isConnecting,
    isConnected,
    isDisconnected
  } = useAccount();

if(isConnecting)
{
  return <Loader/>
}
if(isConnected)
{
  //return required connected component screens
}

Thank you for coming this far, I hope the integration was interesting and at the same time fun to know how things work under the hood.