Creating a Custom Azure Function Trigger That Listens to Ethereum Contract Events

More common than not, blockchain based systems and solutions are more than just the deployed smart contracts. There usually is a client application, and sometimes, there are additional backend components, which in some cases, listen to events raised by those deployed contracts.
One of the concepts available today when developing a system’s backend is serverless architecture. This article shows how to create an Azure Function, Microsoft’s serverless implementation, that is triggered when an event happens on an Ethereum based deployed smart contract.
TL;DR
The entire source code for this article, including a test application, is available here:
Prerequisites
As the Azure Function custom trigger will be written in C#, we will be needing an suitable editor. I chose to use Visual Studio 2019, which you can find its community edition here.
Now, because we will be needing to interact with a deployed contract, we can use the local docker based Parity deployment I described in this article, including the available wallet:
And compile the contract used in this article:
Once compiled, just use your favorite wallet to deploy the contract (such as MyCrypto).
Implementing a Trigger
To create a custom C# trigger we will need to implement the following:
- An attribute that will be used to decorate the parameter which will be receiving the data from the trigger.
- A listener that will be the actual component that polls the contract for events
- And 3 more interfaces used for configuring and wiring the attribute and the listener.
The Attribute
We will start by writing the attribute. As far as the attribute goes, there is nothing special that needs to be added to. We will just define 4 fields that we will use to gather the information required for connecting to a specific event: the Ethereum client URL (with a default of a local address of http://localhost:8545/), the contract’s ABI, the contract’s address and the event we want to poll:
The Listener
Next we will write the listener. As we are using C#, we can use Nethereum’s library to interact with Ethereum based blockchains. We will need to create a new instance of Web3
with the URL of the client we are connecting, get the contract we want to interact with by calling Eth.GetContract
on the Web3
instance with the contract’s ABI and address and finally, get the event by calling GetEvent
on the Contract
instance.
The listener itself needs to be based on the IListener
interface, which requires us to implement the Cancel
, Dispose
, StartAsync
and StopAsync
methods. We will use the StartAsync
to do our initial setup of the connection to the contract:
And then the methods that actually do the interaction work:
- execute a loop that polls the contract for changes:
- Process the list of new events:
- Extract the information of each event:
The complete listener should be similar to this:
Configuration & Wiring
Now that we are done with the attribute and the listener, we move on to the interfaces required for configuring and wiring our previous classes:
- An implementation of
ITriggerBinding
that creates an instance of the listener.
- An implementation of
ITriggerBindingProvider
that creates an instance of the implementation ofITriggerBinding
.
- And an implementation of
IExtensionConfigProvider
which we use to configure a rule that wires our attribute with the implementation ofITriggerBindingProvider
.
Testing The Trigger
To test our trigger, we will create a new empty Azure Function app project, add one function class (make sure you set the Abi
, ContractName
and EventName
constants to the values of your deployed environment):
And a startup class that initializes the app with our custom trigger:
Note that an assembly
directive indicating the startup type that needs to be used when activating the function app must be added (preferably in the Startup.cs
file just after the using
directives):
Conclusion
As this is only an example implementation, it is not “production” grade code. It’s missing things such as contract configuration information validation, extensive logging, failure recovery and more. Additionally, packaging the trigger in a Nuget package makes a lot more sense then adding a project reference.