The example application
I created an Ethereum decentralized application to make code samples below meaningful and exciting.
The idea - is a review/feedback system for superheroes.
So the user can:
- Get all superheroes.
- Get a single superhero by an ID.
- Get superhero reviews by a hero ID.
- Give a review for a superhero by the ID.
- Nominate/add a superhero to the list.
A working example is available here.
And the GitHub page is here.
Whats about WebSockets and Ethereum?
Ethereum and other blockchains are pretty slow comparing to standard backend services, which response almost immediately, not forcing users to wait. Average transaction time on the Ethereum blockchain can be up to 30–60 seconds!
We probably don’t want to drive the users of our application crazy by blocking the UI and showing 30-second loading animations. Instead, it’s better to tell the user, that their action was applied and they will be notified when changes are successful. To achieve this and make interaction with Smart Contract more dynamic, Ethereum Solidity has events. It’s possible to emit events from a Smart Contract so other Contracts or services could listen to them and respond to data changes.
Such an interaction is achieved through the WebSockets.
WebSockets API allows opening two-way interactive, dynamic session between remote programs - a client, and a server. Using this API client can send messages to a server, thus subscribing to some event, and receive the event-driven responses. The most common use cases of WebSockets are real-time dynamic applications like messaging systems (chats), monitoring tools, dashboards, online-multiplayer games, and others.
The simplest WebSocket workflow is as follows:
1. Create a new instance of WebSocket with the service URL. This action opens a connection between a client and a server.
2. Subscribe to the “open” connection. Let the client now that the server is ready to receive and send data.
3. Subscribe to the “message” event to allow your client to listen for incoming messages from the service.
4. Send the data to the service, when the connection is ready.
First - a simple way, the web3JS way
Subscription to an event with Web3JS is super easy, as it encapsulates all the WebSockets setup under the hood.
Secondly — a deep dive or the manual way
Working with Ethereum WebSockets is pretty similar to the example I showed in the 101 section. The only difference is that we need to send data in JSON-RPC format to subscribe for the desired event. All the request data we need could be found in the Contract JSON-ABI file. If following the Solidity coding conventions events are usually pascal case named.
When we found the event we need, we can take a look inside of it to find the required parameters for a request. Let’s check the NewHero event, which fires when a new hero is being created.
The request should contain:
1. id = 3. This is for client use only and can be any number.
2. method = “eth_subscribe”. This is for the Ethereum Virtual Machine (EVM), so it knows we want to listen to an event.
3. params array which contains the following elements:
- “logs” - a string value, that states that we want to listen for incoming transactions logs.
- an object with topics property what holds a unique identifier of the method we want to listen for, this one is stored in the event signature property and an address property which contains the address of the contract.
A basic subscription could look like this:
Now, when the subscription is ready, we can to listen for incoming messages. As soon as something changes, in this case, a NewHero added, we will get a message with hero data. All the results are going to be in a hexadecimal format so we have to decode them. And once more - decoding the results is not an easy topic, which requires it’s own separate discussion. I’m going to cover the encoding and decoding data between human-readable and the Ethereum hexadecimal format in the next chapter. For now, let’s simply use Web3JS decodeLog method.
All together. The subscription and the listener for a NewHero event look like this:
I hope this article was helpful for you, the code examples were meaningful, well commented, and useful.