Events are great, listening for events and doing something is one of the core uses of JavaScript on the frontend. It's what allows us to see some amazing interactions happen in our web applications.
It's fun to listen for clicks and whenever we press a key but it's even more fun when we can listen for events that happen somewhere else completely. This allows us to create real time applications and if you're building on the blockchain it can be done with just a few lines of code!
The code we're going to be discussing below was built while I was taking a course all about building Smart Contracts at BuildSpace. If you're interested in really diving into the things I'm going to discuss I highly recommend checking out their courses which are all cohort based and free!
The Project I built here was a little concept Pokemon Battle Simulator where anyone can jump in and have a Pokemon perform an action in battle against another. Almost like a crowd sourced Pokemon battle on the blockchain. A quick demo of it can be found on this tweet.
Let's start by taking a look at some Solidity code. Solidity is a language you can use to build Smart Contracts which is code that helps you interact with the Ethereum Blockchain. Here's some code from a smart contract I've written below:
event NewAction(
address indexed from,
uint256 timestamp,
string message,
uint256 lugiahp,
uint256 zardhp
);
struct Action {
address trainer;
string message;
uint256 timestamp;
uint256 lugiahp;
uint256 zardhp;
}
Action[] actions;
This isn't the full smart contract but we're just going to be focused on the parts that enable us to have real time interactions with the block chain. Now remember how I was talking about events at the start of this post? With Solidity you can actually create events to listen for. In this case I am listening for an event that I have named NewAction. That is going to be whenever and Action struct is added to the actions Array.
If you're coming from JavaScript you can think of this as an actions object being added to an array of actions. Now let's take a look at a function from my smart contract:
function attack(string memory _message) public {
totalDamage += charizardAttack;
totalHp -= charizardAttack;
charizardDamage += lugiaAttack;
charizardHp -= lugiaAttack;
console.log("%s has attacked the shadow Lugia!", msg.sender);
console.log("%s was attacked back by shadow Lugia!", msg.sender);
actions.push(
Action(msg.sender, _message, block.timestamp, totalHp, charizardHp)
);
emit NewAction(
msg.sender,
block.timestamp,
_message,
totalHp,
charizardHp
);
}
This function is taking care of an attack sequence between Charizard and Lugia with both dealing some damage to each other. At the end of the function you will notice I have this
emit NewAction(
msg.sender,
block.timestamp,
_message,
totalHp,
charizardHp
);
Remember I created the NewAction event earlier? Calling emit is what allows me to say ok this event is now taking place and a new action struct is being created with the information passed in and added to the array of actions.
That's all we need on the Solidity side of things to make sure an event is there to be listened for but how do we actually listen for this on the front end?
During the time I spent building this, our awesome instructor Farza introduced us to using ethers js with React to interact with the blockchain. One of the awesome things about this course that I really enjoyed is that there are some bonus concepts like events that he introduces and lets us explore for ourselves.
So while searching google and hunting through some documentation I was able to discover the code needed to listen for this event on the frontend. Check out this useEffect hook below from one of my components:
const listener = (block) => {
console.log("new action emited")
console.log(block)
getAllActions()
}
React.useEffect(() => {
lugiaBattleContract.on("NewAction", listener)
return () => {
lugiaBattleContract.off("NewAction", listener)
}
},[])
A little context: the getAllActions function is getting the data from the actions Array in my smart contract, sanitizing it a bit, then updating some state with that data. In my useEffect hook I am using some functionality given to us by ethers js in order to listen for an event named "NewAction" which if you recall I defined in my smart contract. Now anytime anyone performs an attack - everyone else will also know because the action will be updated for everyone in real time!
A quick note: always make sure that if you're using some type of listener function in React - put it in a useEffect and return a function for cleaning it up. Otherwise you'll end up like me trying to debug why your component is re-rendering several hundred times when the event only happens once.
Here is a quick demo below of this in action:
It's a large gif 😬 so once it loads you'll see that Charizard is attacking in one browser but the actions logs update in both browsers!
I've done some real time stuff before and this is just amazing to see that I can do this so easily on the Ethereum blockchain!
If you would like to play with the demo yourself you can do so here.
You will need to have the metamask chrome extension set up and you'll need some test ETH on the Rinkeby Test Network.
I've been on a journey to learn web3 for a while now in hopes of getting into the space eventually as a developer advocate. If you want to join me on this journey give me a follow on Twitter!
Top comments (0)