Check out a free preview of the full A Tour of Web 3: Ethereum & Smart Contracts with Solidity course

The "Contract Events" Lesson is part of the full, A Tour of Web 3: Ethereum & Smart Contracts with Solidity course featured in this preview video. Here's what you'd learn in this lesson:

ThePrimeagen adds a CounterInc event to the contract. When the counter is updated, the event is emitted. Any connected clients will have the event pushed to them. Additional filters like the address of the sender can be included as well.


Transcript from the "Contract Events" Lesson

>> This I know sucks, right? You don't wanna have to do this. This is the worst form of programming where you have these long running state transitions that you want to happen over time and you have to wait for something to happen and then you can do the action.

It's much better to be kind of pushed this information, right? Let's erase this transaction and just [SOUND] get it out of my sight. And we're gonna erase the set counter as well. Disgusting, right? And what we're gonna do instead is we're gonna go to our counter contract, and we're gonna add in one more item.

We're gonna add in one of the greatest parts about the solidity network. I personally think this is just something that is just so dang exciting. We'll go like this, event CounterInc, and I'm gonna pass in, that, that is it. We've just defined an event that can happen from our contract that simply has a counter or a singular value that comes out of this event.

You can have three arguments in an event and furthermore you can even index some of those items if you would like to filter on top of those. Events are not only able to be listened to in real time, you can actually go back through the blockchain and see a history of events that have happened.

In a sense, they're like cheap storage, but they're harder to use. And so they're very, very interesting. To index that you could do something like, index, I was gonna show you this, but it's just a lot of extra work, you can do that. And you can then go like, I only want to listen to events that have a counter of equal to 5.

And then it will only be notified cuz it can do a lot of live searching. Learn about events they're fantastic, but I just wanted to make sure everyone understands that they exist cuz that's the most important part about this, is that you know that events exist and that they're super useful.

And so now that we've done that, we need to do one other thing which I forgot to do last night while practicing and it took me 20 minutes to figure out what was going wrong. I'm gonna go like, this emit Counter Inc(counter, there we go. At this point I want to make sure everybody knows, hey, this count has happened and here's the new value.

There's something very important now, which is what do we have to do? Can someone tell me the steps in here that we have to do to get everything working for our website? Does anyone remember the steps we have to do? Deploy it. Updater and take down Webpack relaunch it, right, kind of sucks.

It is what it is, but we got to do those things. I really wanted to make this part super painful because I really want you to be excited for part four. So this is just me making it so painful, you're like, my gosh, just stop doing this already.

No, we're gonna keep on doing this cuz it has to hurt. It has to hurt to make something super sweet. I think what was it, Mellencamp that said something like that? I can't remember, anyways, that joke fell flat. Let it go. Just let the joke go. All right, so now that we have that, let's go back and let's relaunch our contract, right?

We do have one question.
>> Yeah, so at a higher level what is an event then? Is it something that's persisted somewhere?
>> Yes, so every transaction will actually have a log field associated with it in which you can put data into it. And so when that transaction happens, you'll know about the log.

And not only that, but the provider has a way to listen to the network as it produces blocks and read through the logs. If you've told the provider, hey, I want to be able to listen to these specific events, even filtered on this specific set of data, it will do all that for you.

It kind of feels like magic, and in the end, you simply get out a callback. If that makes sense. Yeah, it's pretty much 200 IQ. So we've just deployed a new counter that now has our event. So again, copy out the address, go to the end. Delete the address, paste it in, go to Webpack, take down Webpack, put it back up.

I know, I feel so good at this at this point it's like a video game. I'm pretty much cranking 90s and Fortnight except for it's with Webpack and updating, environment variables. All right, now we said that out loud. I'm going to refresh it and notice that our increment is back at one.

But we haven't done anything to the front end yet. So let's go back to our code, and let's go to index.ts. So we need to change something, right? I don't want to have to try to call this at the right time. I want something to call me when it's time.

So let's do this. Let's go counter, which the name of our contract, on, which is a convenience method for us to be able to do that. Now we need to provide it a filter. In the JavaScript world obviously you do something like this on counter Inc. That's just not how it's gonna work here.

Instead, we have to do this. We have to go counter, filters, CounterInc. Remember how ethers generates all these magic functions for us? It also generates magic filters for us to listen for our events. It's really actually kind of a fantastic library. So this name, CounterInc, is the name, that's within our contract.

So it just generates it for us. And so now that we've done that, we can have a function, which takes in the arguments from our contract. So I'll have count, right, cuz that gets passed through. And now I can take that, and I can set counter, and I wanna just pass them account will jump up to counter.

We'll take an account, right now make a little question mark in there and I'll just do a little count, or do that, fantastic, right? We just made it all work out fantastically, right? And so now every single time this gets called, we can then do whatever, I don't know, I think people call it top down render, whatever they do.

They can do some sort of fantastic updating of all of your UI, cuz you have all of your events in here. And so you can hook that into all of your state transformation, all the stuff you need to do, but it's now abstracted away from an action that a user takes.

We just simply listen for that event. Which means that if we opened up a second browser, theoretically, we should be able to have both those browsers update at the same time, right? So we will try that as well. But for now we've done this. Let's go back to this.

Let's refresh it and my goodness, what just happened? Everything broke, right? Again, [LAUGH] first try on this breaking, it really intentionally did this. All right, scroll to the top, counters filters CounterInc is not a function. But I thought I just told you that, right? We just created this event.

Why isn't it not that? Well remember, again, go back to our code. What did we tell ethers was our interface? We didn't tell it about this event. So instead of doing this anymore, let's delete that. I just really wanted you to know that you can just simply create an inline interface, we don't need to do an in line interface anymore.

Let's erase that, let's go to the tippity top and let's import contract or it was called counter, we'll call counter from, go back to artifacts, oopsies, that happens every now and then. Import, contract or I call a counter from, it's like Groundhog's Day. Let's go to artifacts, contracts, counter.sol, counter.json.

Now remember, it's French, there you go. You have this nice counter right here and now we have that file that I showed you earlier inside of our front end, that's why I had that TS config resolved json modules. And so that we can really get out this. Now notice what's different about our ABI, which stands for Application Binary Interface, but it doesn't really look very binary to me.

It has no indexes. It has a name. It has a type. It has the name of our event and its type event. So really is gonna tell ethers everything it needs to properly construct our contract object. So now it's going to add that filters method to ethers, so we'll be able to use that.

So now all we need to do is go back, go down to where we initialized it and just simply do counter.abi. That will be the abi we need to pass in and now this will always work as we make updates to counter it will pick up all those changes.

We don't need to manually specify it. It is beautiful. All right, I mean, I think it's beautiful. Now the reason you use hardhat, hardhat saves all this information out for you and it saves it in such a way that it works nicely with ethers, right, which I think is pretty fantastic.

So now that we've done that, we should be able to go back to our website, and we should be able to see these changes. So let's go back here. Let's refresh. All right, we're back. We have it, fantastic. Let's increment it. It'll do the same thing. Hey, do you wanna do this?

Yes, we wanna do this. Now, my goodness, we're waiting. Is it gonna happen? Looks like we have the longer wait here. I'm so excited because it's gonna happen in 3, 2, 1, now. I nailed it, but wait, what the heck it didn't quite update where's the update, there it is.

Our event got called, look at that and now says number two. That is pretty awesome, right? Now we're actually really interacting with Etherium and we're actually getting data back out. And, really we should be able to go in here and go to 69. 69, I actually haven't done this yet.

We'll update it from a second browser tab, make it happen. It's gonna go off, it's gonna now do a nice little event at the exact same time. And theoretically we should be able to see both of these go off at the same time cuz they're both listening to the same source which is our network.

It's no different than if you did it, there you go we got one updated. I don't, there it is, we got them both. They both actually worked out. For me this was really, really cool because this is like a whole new level of things you can do. Your contract can have all these state changes happening not even from the person that's using it and you can listen to only the ones you want.

Say you only wanted to listen to changes that that individual person has made, the person that's calling the count. I could also add in message.sender, which is just saying, hey, here is the address of the person who's called this function. And then inside of here, I can simply put address and since I want to filter on it, index, and I can go, ader, and there we go.

Now we've made events that I can listen to that only I have done. And so you can do all these really cool tricky things that just make it super nice.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now