Interface
Last updated
Last updated
In blockchain projects, it's often not practical to directly use ethers.js or web3.js to interact with MetaMask, as it can be cumbersome. To address this and facilitate faster connection and interaction with the blockchain, many excellent third-party libraries have been developed, such as web3-react, web3-modal, rainbow-kit (which is an encapsulation based on wagmi), and wagmi. To quickly build the Coin Pusher dapp, we will use the Next.js, Wagmi, Rainbow-kit, and Viem technology stack for development.
Nextjs: It is a React framework for building server-rendered and static websites and web applications.
Wagmi: It is a React Hooks library for Ethereum, designed to simplify interactions with the Ethereum blockchain and smart contracts. It supports over 40 out-of-the-box Ethereum features for accounts, wallets, contracts, transactions, signatures, ENS, and more. Wagmi also supports almost all wallets through its official connectors, EIP-6963 support, and extensible API.
Rainbow-kit: It is a React library that provides components to build a Connect Wallet UI with just a few lines of code. It supports many wallets, including Metamask, Rainbow, Coinbase Wallet, WalletConnect, and more. It is also highly customizable and comes with stunning built-in themes.
Viem: It is a low-level TypeScript interface for Ethereum that enables developers to interact with the Ethereum blockchain, including: JSON-RPC API abstraction, smart contract interactions, wallet and signature implementations, encoding/parsing utilities, and more. Wagmi Core is essentially a wrapper for Viem, providing multi-chain capabilities through Wagmi Config and automatic account management through connectors.
Final effect display
The default version of React used in the current Next.js project is version 19, but it is not very stable and may have compatibility issues with other dependencies. Therefore, I suggest changing the version of react
and react-dom
in package.json
to "^18.2.0"
, and then re-running npm install
.
Run the project in development mode.
The image below is the Next.js initialization page.
Project structure.
This is the project structure when initializing Next.js, but the contract
folder is newly created, where is store the contract's ABI and contract address. You can copy the ABI and address of the contract you just deployed.
Install RainbowKit and its peer dependencies, wagmi, viem, and @tanstack/react-query.
Note: RainbowKit is a React library.
Copy the following code snippet into the /context/Web3Provider.tsx
file.
This is the configuration file for RainbowKit. I have separated it and placed it in /context/Web3Provider.tsx
to make the project structure clearer. Configure the required chains and generate the necessary connectors. You also need to set up a wagmi configuration.
Note: Every dApp that relies on WalletConnect now needs to obtain a
projectId
from WalletConnect Cloud. This is absolutely free and only takes a few minutes.
Place the project ID in the .env
folder.
Import the Web3Provider
configuration file into app/layout.tsx
.
The Toaster
component comes from the react-hot-toast
library, which is a lightweight, customizable notification library designed for React applications.
Copy the following code snippet into the hooks/useGameStatus.ts
file.
This is a custom Hook named useGameStatus
, which is mainly used to retrieve the status of the Coin Pusher game.
Explanation:
useAccount: a Hook for getting current account.
gameStatues: This is a state declaration in a React Hook, using the useState
Hook, which stores the state of the game.
useReadContracts: useReadContracts
is a Hook provided by wagmi for querying multiple contract functions at once. We use it to query the getGameStatus
and depositOf
functions. wagmigotchiContract
contains the contract's ABI and address, which are necessary information for calling smart contracts.
isLoading and refetch: isLoading
and refetch
are both data returned from the useReadContracts
hook. isLoading
is a boolean value indicating whether the data is currently loading, and refetch
is a function used to fetch the data again.
useEffect: This is a React useEffect
Hook, used to listen for and handle updates to game status data. When the data
changes, the callback function within useEffect
is executed, and within this callback function, the data from data
is synchronized with gameStatus
.
formatUnits: formatUnits
is a utility function in viem (an Ethereum development library), primarily used to convert large on-chain values (usually represented in their smallest units) into a human-readable format.
Copy the following code snippet into the hooks/useGameDeposit.ts
file.
This is a custom Hook named useGameDeposit
, which is used to handle the deposit functionality in blockchain games.
Explanation:
useWriteContract: useWriteContract
is a Hook in Wagmi designed for executing write functions on a contract. It returns several properties, from which we extract attributes using destructuring: data
, isPending
, and writeContractAsync
. data
is the transaction hash returned after sending a transaction. isPending
is a boolean value indicating whether there is an ongoing write operation (such as a transaction); if isPending
returns true
, it means the transaction has not yet been confirmed by the blockchain. writeContractAsync
is an asynchronous function that allows you to send transactions to a smart contract.
useWriteForTransactionReceipt: useWaitForTransactionReceipt
is also a hook provided by Wagmi. The role of this hook is to listen for a transaction receipt, ensuring that the transaction has been fully confirmed. isLoading
is a property from the object returned by useWaitForTransactionReceipt
, which is renamed to isConfirming
here. This property is a boolean value indicating whether the transaction is still pending confirmation.
handleDeposit: This function accepts a flag parameter and retrieves the corresponding amount from the VALUE_BY_FLAG
array. It then uses writeContractAsync
to call the smart contract's deposit
function, passing the flag
as an argument with args: [flag]
. The value: parseEther(value)
converts the ETH amount to Wei units for the transaction.
Copy the following code snippet into the app/globals.css
file.
Copy the following code snippet into the app/page.tsx
file.
In Next.js, app/page.tsx
is a special file used to define the root page of the application, that is, the UI that is displayed when you visit the root URL of the application (usually /
).
Run npm run dev
, and then you will be able to view the page locally on port http://localhost:3000
.
Explanation:
This code snippet imports the ConnectButton
component from RainbowKit, which is primarily responsible for rendering the connect/disconnect wallet button.Then render the gameStatus
data returned from the useGameStatus()
hook onto the interface.
The handleDepositClick
function receives a flag
parameter and primarily accomplishes two operations:
setActiveDepositFlag(flag)
is a state update function used to track the deposit button currently selected by the user.
handleDeposit(flag)
is a function obtained from the useGameDeposit
custom Hook, responsible for handling the actual deposit transaction logic.
The purpose of this code is to refetch the game status using refetchGameStatus
and reset the current active deposit state when the transaction is confirmed (isConfirmed=true
).
Next, you can try playing the game.
Click the button corresponding to the amount you wish to deposit, and then the button you clicked will turn white and display 'Loading...'.
After a few seconds, the MetaMask wallet will pop up a transaction confirmation window. Click the confirm button to send a deposit transaction.
You can switch between multiple different wallet addresses to send deposit request until the total game amount reaches the encrypted target.
Note: In contract have limited each player to make only one deposit, and making multiple deposits will result in an error.
Congratulations, you have completed the development of the entire dapp.