Skip to content

Drizzle and Contract Events

Drizzle is ideal for synchronizing contract state with a user interface, but as dapps grow in complexity we foresee growing demand for coordination with off-chain services.

The code in this section may be small, but it opens up a powerful mechanism to enable that coordination. Imagine your dapp needs to send a message whenever a contract event is generated. Lets see how to make this happen.

This tutorial demonstrates how to use Drizzle to subscribe to smart contract events.

The finished dapp.

We'll use react-toastify to alert the user whenever a SimpleStorage contract event is emitted. We have to declare a component and invoke toast.success() when an event is detected. We'll touch MyComponent and the event reducer respectively.

A Complete example is available at the following repo.

Prerequisite: You should be familiar with Truffle, Drizzle, React and Redux. If you need an introduction please consult the following resources:
  1. Truffle Quickstart
  2. Getting Started with Drizzle and React
  3. Tutorial: Intro to React
  4. Redux Basic Tutorial
  5. Redux Saga
  6. Redux Middleware

Unbox Drizzle

Let's use truffle unbox to bootstrap a project and then wire up a contract event to a display component by creating a reducer and hook it up to Drizzle's EVENT_FIRED action.

Note: More Drizzle actions are listed in our Drizzle Actions documentation.

First create an empty directory, navigate to it, and unbox Drizzle.

// In the project directory...
$ truffle unbox drizzle

Now let's start the truffle develop console (which runs a Ganache test blockchain in the background):

$ truffle develop

Finally, in our Truffle develop console, let's compile and migrate our smart contracts.

truffle(develop)> compile

# some output here...

truffle(develop)> migrate

Now that we have a test chain running and our smart contracts deployed, let's add a toast notification to the UI.

Listen for Contract Events

We want to listen for the SimpleStorage contract's StorageSet event and show a toast notification once it fires.

The front end code is located under the app folder. Lets add the notification library react-toastify to simulate an external interaction.

$ cd app
$ npm install react-toastify

For the sake of simplicity, we will work in one file, ./app/src/middleware/index.js.

$ mkdir ./src/middleware
$ touch ./src/middleware/index.js

Import EventActions and generateStore from Drizzle as well as toast from react-toastify, and drizzleOptions.

// ./app/middleware/index.js
import { generateStore, EventActions } from '@drizzle/store'
import drizzleOptions from '../drizzleOptions'
import { toast } from 'react-toastify'

The action EventActions.EVENT_FIRED is emitted whenever a contract event is detected in a Block. We will gain access to it by registering a custom middleware with the Redux store. As you know, Redux middleware comprises a set of functions executed in a sequence that processes each dispatched actions before passing them to Reducers.

const contractEventNotifier = store => next => action => {
  if (action.type === EventActions.EVENT_FIRED) {
    const contract = action.name
    const contractEvent = action.event.event
    const message = action.event.returnValues._message
    const display = `${contract}(${contractEvent}): ${message}`

    toast.success(display, { position: toast.POSITION.TOP_RIGHT })
  }
  return next(action)
}

Now lets register this middleware with Drizzle. generateStore will return a Redux store that you can use anywhere you can use a store. We will export it to be used by DrizzleProvider.

const appMiddlewares = [ contractEventNotifier ]

export default generateStore({
  drizzleOptions,
  appMiddlewares,
  disableReduxDevTools: false  // enable ReduxDevTools!
})

Connect the Store

Send the store as a prop to DrizzleProvider

// App.js
...
import store from './middleware'
...
const drizzle = new Drizzle(drizzleOptions, store);
...

Hook up Display

Modify MyComponent.js to import ReactToastify.css and configure ToastContainer

...
import { ToastContainer } from 'react-toastify'
import 'react-toastify/dist/ReactToastify.css'
...

export default ({ accounts }) => (
  <div className="App">
    <ToastContainer />
  ...
  </div>

A Quick Test

  • Things often go south during development so a pretest check is in order.

    1. MetaMask should NOT be on Main net! Do not run this if you're on main net!
    2. Is MetaMask listening on the correct port defined above? Metamask should have ETH funds. Something is amiss if it doesn't.
    3. Are the smart contracts deployed from the correct directory?
  • Fire up the app.

    $ npm run start
    

  • Change SimpleStorage's stored Value Change SimpleStorage value!

  • You'll be rewarded with a toast notification when the transaction is completed. Toast

The dapp is now a consumer of Drizzle's EVENT_FIRED action item and can coordinate with other services to implement its business logic.

More Drizzle actions are listed in our Drizzle Actions documentation.