Ethereum: Communicating with the off-chain world

Angello Pozo
4 min readJan 24, 2018

--

Ethereum Smart Contracts are wonderful, and allow for the creation of real DApps (Distributed Applications). Inevitably, your application will needs to talk to a “real world” API. This can be sending an email, querying for more data, or acting as a signal to initiate additional processing. Lets explore how to get Ethereum smart contracts talking to off-chain services.

Overview

An Ethereum DApp will more than likely be written in Solidity. If you want more development pain you can use the experimental Vyper language. In short, you make Smart Contracts emit Events while processing your transaction. Once the transaction is mined, the event data becomes available to read. In the image below, you can see that your DApp emits events, that can be retrieved from any service AKA your API.

There are two ways to get the event data.

Options 1: Use the getTransactionReceipt

Option 2: Register a listener for an event

You can use options 1 to get event data, but unfortunately this becomes problematic because the receipt is empty until the block is mined. You can poll, but that becomes difficult to mange. Plus depending on network traffic and the gasPrice set, the transaction may not be mined for some time :(. Once nice thing about this option is that you get every event that happens for your transaction.

I think the nicest solution is option 2, where you register an event listener for a specific event. This is easier to manage because unless you are using many Solidity events. Which uses gas, so try not to have too many.

Please note, that events are only emitted once they are mined into a block. That means that multiple events can be called for any one block.

Solidity Events

Creating events in solidity requires two steps: Define event, emit event.

Notice how the event Transfer was created on line 5, and then used inside the function transfer where it emits the Transfer event (line 10). The example is a bit contrived, but shows you how to use an event. If we were to call the transfer function with 0x123, and send 1 Ether from our address of 0x4444, the event trigger the Transfer event and should return [0x4444, 0x123, BigNumber(1 Ether)].

Great! Now you can emit events from Solidity!

Listening for Events

Ethereum implements their JSON RPC spec, but anyone can implement their own library in their language of choice. We are going to use Truffle and the raw web3 Javascript API. The general flow to listen to events is as follows:

  1. Load contract artifact
  2. Configure web3 and/or truffle with a provider
  3. Identify networkId
  4. Grab correct contract address from contract artifact
  5. Get a javascript contract instance
  6. call contractInstace.NAME_OF_EVENT with optional configs
  7. Listen to events!

Below we have 3 samples that use Truffle, Web3 before 1.0 beta, and Web3 after 1.0 beta.

Truffle API

Truffle is a nice wrapper around web3, that provides several convenience functions to make life easier. Take a look at the following code sample:

The first 9 lines require a few modules and setup truffle and web3 to talk to the correct network. Lines 12–19 are there as a hack to make it work with web3 and can be ignored. The work starts on line 21 with contract.deployed(). This is a nice truffle helper functions that selects the correct contract address from the artifact that gets created and saved to ./build/contracts. With contractInstance returned (line 23), we “create” the event by calling contractInstance.NAME_OF_EVENT. More options exist and can be found here. I selected from block of 0, because its our own testrpc. For you contracts, it would be best to select a block number closer to when the contract was created.

Raw Web3 (0.20.4 and below)

For this second example we will use Web3 directly. Aside from the hack in the previous example, the code flow is similar.

The big difference are lines 9–12 where we are manually grabbing the correct network from the artifact. We do not have the nice truffle .deployed function to make this one step. Now we do the exact same thing we did before in the truffle example and create the event by calling contract.NAME_OF_EVENT. In this version I did not put a block number, but you can pass the exact same thing as the truffle version.

Raw Web3 1.0.0 beta

Web3 does bring a large number of changes to the API. One big change is the that we must use the webSockProvider to register events instead of the httpProvider.

Additionally, getting the networkId has also been updated. But the process is the same. We grab the networkId with web3.eth.net.getId(), and then select the correct contract address from the Artifact. Initializing the contract is now a class constructor with a capital C in web3.eth.Contract. Then lastly, we create the event listener. We must now handled the ‘data’, ‘changed’, and ‘error’ events ourselves. Before it was wrapped in the watch function from the previous 2 examples.

Tutorial

Looking over the code samples above should be helpful in getting you started on your own services. If not, I also created a repo where you can test out the code yourself! Just click here and follow the examples. Its a derivative of the tutorial token examples.

Conclusion

You should understand how to connect your offchain services to onchain events. This means you can now integrate the blockchain into your existing infrastructure. If you have any issues or comments please leave them! You can also communicate with me on twitter https://twitter.com/angellopozo

To keep up with the latest HelloSugoi news as it’s happening, we invite you join our mailing list, message us on Discord, follow us on Twitter @HelloSugoi, and visit our website hellosugoi.com.

--

--

Angello Pozo

Co-Founder of HelloSugoi. Hacking away on Ethereum (blockchain) DApps. Follow me on https://twitter.com/angellopozo