Building a Coin Flip Game on Ethereum (Part 3) - Interacting with the Contract
Introduction
Welcome to the third installment of our tutorial series focused on interacting with smart contracts using a user interface. In this guide, we will delve into a practical example involving a CoinFlip smart contract.
The contract features two primary write methods: createMatch
and joinMatch
. Each function plays a crucial role in allowing users to engage with the game, by creating and joining matches respectively.
Our goal today is to build the necessary UI components that will call these methods and handle their responses effectively. This hands-on approach will not only reinforce your understanding of Ethereum smart contracts but also sharpen your skills in integrating these contracts with a front-end interface. Whether you're a seasoned developer or just starting out, this guide will provide you with the tools and knowledge needed to build dynamic dApps.
Prerequisites
Check out the previous instalments of this series here:
Building a Coin Flip Game on Ethereum (Part 1) - Web3 Email Onboarding.
Building a Coin Flip Game on Ethereum (Part 2) - Deploying the Contract.
Tutorial: Interacting with the CoinFlip Smart Contract
First, we will create form components to interact with the different methods.
1
Create Match
createMatch
method allows users to create matches. It takes only one argument, and that is the amount that the user is staking for the session of the game, and it returns an ID. In the joinMatch
method, users can then call the ID and play the particular game. Here is the code:Code Breakdown
const createMatch = async () => {
await
to handle promises calling the Smart Contract.const encodedCall = new ethers.Interface({
inputs: [],
name: "createMatch",
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
stateMutability: "payable",
type: "function",
});
const newAmount = ethers.parseEther(amount);
const data = encodedCall.encodeFunctionData("createMatch", []);
- An instance of
ethers.Interface
is created with the ABI method that describes calling thecreateMatch
via the UI. ethers.parseEther(amount)
converts the amount to the correct String for the transaction.encodedCall.encodeFunctionData("createMatch", [])
encodes the function callcreateMatch
along with any parameters it may have, in this case, it's an empty array[]
.
const transaction = {
to: "0xb27C9567E84606faBE6955a17ba71fFc9B93B46b",
value: newAmount.toString(),
data,
};
to
) which is the deploy Smart Contract available on the Polygon Mumbai Chain, value (value
), and encoded data (data
).const userOp = await SmartAccount.buildUserOp([transaction]);
const userOpResponse = await SmartAccount.sendUserOp(userOp);
SmartAccount.buildUserOp([transaction])
constructs a user operation object by parsing the transaction to the BiconomybuildUserOp
method.SmartAccount.sendUserOp(userOp)
sends the constructed user operation to the Bundler.
const { receipt } = await userOpResponse.wait(1);
userOpResponse
) to be confirmed on the blockchain. The await
function is used to await for the transaction to be included in a block and for the return (a promise) to be resolved. The 1
parameter specifies the number of block confirmations to wait for before resolving. Once confirmed, the function returns a receipt object containing information about the transaction.console.log(receipt);
2
Form UI
createMatch
we will build a Form UI. Paste the following code before the Login Button:2.1
createMatch
method we will declare a state to handle form input, in this case “amount’ and also variables to handle input and submit events.createMatch
to send the amount to the Smart Contract and create a Game session.2.2
3
Join Match
joinMatch
method is not different from the createMatch
method. The principal difference is that while createMatch
does not take in any arguments, the joinMatch
takes one argument. This difference is highlighted in the ABI call:encodedCall.encodeFunctionData("joinMatch", [newMatchID])
encodes the function calljoinMatch
with the newMatchID as a parameter.
createMatch
.3.1
matchId
from joinMatch
, and also form elements:3.2
createMatch
, but, it has two input fields:matchId
as an actual Id of a created match. You can look up the deployed Smart Contract to find Matches. Once the transaction is successful, it will log the transactionHash
to the Console.4
Checking Total Matches
totalMatches
method.getContract
from Viem.js to read the contract information. You can parse it to the UI. For example, as a paragraph under “Hello”:<p>{totalMatches}</p>
Conclusion
Congratulations on completing this tutorial! By now, you should have a functional understanding of how to interact with smart contracts through a user interface. We have covered how to create and join game matches using the createMatch
and joinMatch
methods of the CoinFlip smart contract. You've also learned to handle form inputs and manage state in a React application, which are essential skills for any aspiring dApp developer.
Remember, the key to mastering smart contract interactions is practice and experimentation. Feel free to modify the code, try different approaches, and explore other functions within the smart contract. As you continue your journey in blockchain development, always keep learning and stay updated with the latest in Ethereum and smart contract technologies. Happy coding!