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 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.
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.
- MetaMask should NOT be on Main net! Do not run this if you're on main net!
- Is MetaMask listening on the correct port defined above? Metamask should have ETH funds. Something is amiss if it doesn't.
- Are the smart contracts deployed from the correct directory?
-
Fire up the app.
$ npm run start
-
Change SimpleStorage's
stored Value
-
You'll be rewarded with a toast notification when the transaction is completed.
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.