Ethereum State Management with Drizzle

Mollie Elisabeth Stein

September 12, 2018

Build

**This post assumes base knowledge of blockchain technology and Solidity contracts.

Giant Machines recently developed a DApp (decentralized app) for the Ethereum blockchain, and in the spirit of helping other developers and supporting Truffle, we are sharing some internal notes and comments on our experience with Drizzle. This post addresses the documentation gaps and issues we ran into when initializing Truffle’s new(ish) state management library, Drizzle.

Tools We Used

For our DApp we used React on the front end, Drizzle for state management, and MetaMask as the web3 provider. For our dev environment we used Truffle Develop to create a local blockchain and deploy contracts via the command line. Everything here applies to Drizzle v1.1.0, Drizzle-React v1.1.1, and React v15.4.2.

Initializing Drizzle

Drizzle uses WebSockets and web3, and works on top of Redux with additional methods like cacheCall and cacheSend to sync up the store and contract. We saved time by not having to instantiate a web3 connection when making contract calls or polling for changes made to the contract.

In our experience, the Drizzle docs do not reflect what is required to run Drizzle out of the box. The drizzleOptions object is inflexible and must be configured in a fairly specific way for Drizzle to start. In fact, the drizzleOptions default did not instantiate Drizzle for us. The drizzleOptions object must include four properties: web3contractspolls, and events.

Ours looked like this after some trial and error:

drizzleOptions = {
web3: {
block: false,
fallback: {
type: ‘ws’,
url: ‘ws://127.0.0.1:9545’,
},
},
contracts: [
ContractName,
],
polls: {
accounts: IntervalInMilliseconds,
},
events: {},
};
  • web3.fallback provides a type and url for the web3 connection if a provider, such as MetaMask, is not available
  • web3.fallback.type only accepts ws as its value
  • web3.fallback.url must have ws in the protocol identifier instead of http
  • polls and events should be present as empty objects even if they are not needed
  • polls indicates how often Drizzle will ping the blockchain for changes in state
  • By default, polls is { blocks: 3000 }, which will poll every 3 seconds, but we found that Drizzle only triggered a re-render with the polls set as { accounts: 3000 }

To connect to Drizzle, wrap the main application component with the DrizzleProvider from the drizzle-react library and pass drizzleOptions through the options prop. DrizzleProvider will generate its own store, but we recommend creating custom actions and reducers on top of what the drizzle library provides. The Drizzle Truffle Box provides an example of how to generate the store with custom reducers.

Drizzle’s React Components

Drizzle has a few of its own React components through the drizzle-react-components library. The LoadingContainer component from Drizzle wraps the app just below DrizzleProvider to create a loading page while Drizzle connects to web3. The LoadingContainer was useful, but the ContractFormContractData, and AccountData components were not flexible enough for practical use. We did, however, use these other components for reference on how to use cacheCall and cacheSend.

In the Application

The main application component has this structure:

ReactDOM.render(
(
<DrizzleProvider options={drizzleOptions} store={store}
<LoadingContainer>
<BrowserRouter>
<App />
</BrowserRouter>
</LoadingContainer>
</DrizzleProvider>
),
document.getElementById('root'),
);

The Drizzle state and contract instances are accessible through React’s Context API within the App component. To enable context where the contract is needed, pass context as an argument through the constructor() of a component:

constructor(props, context) {
super(props);
this.drizzleState = context.drizzle;
this.contractInstance = context.drizzle.contracts.SimpleStorage;
}

To add Drizzle to the context, add the following code to the component, like you did with propTypes:

ComponentName.contextTypes = {
drizzle: PropTypes.object,
};

The Drizzle state was added to the main application component, and the objects that contained contract methods, web3, and events were passed down separately.

The contractInstance is required to make calls to the backend and can be passed through props. See the Drizzle docs for how cacheCall and cacheSend work with the contract and Drizzle store. They are asynchronous and do not return a promise. Calls can still be made through web3’s call and send methods, and these should be used when the result of a promise is required.

A benefit of using Drizzle is that it provides access to a transaction’s status. Pending transactions may take a while to complete, and the transactions object in the Drizzle state is only updated when cacheSend is used. This allows the developers to craft a more elegant front-end experience.

Takeaways

It was difficult getting started with Drizzle. If you plan to use any of the Truffle libraries, we highly recommend checking out Truffle boxes before getting started. The Drizzle box will greatly accelerate your configuration of Drizzle.

We’re excited to see more from Truffle! 🙂

About the author

Mollie Elisabeth Stein

Software Engineer

SHARE VIA

Stay in the loop

Keep up to date with our newest products and all the latest
in technology and design.
Keep up to date with our newest products
and all the latest
in technology and design.

Other blog posts

Building With ChatGPT & LLMs: Two Common Pitfalls & One Way To Win

What does it mean for your organization? Should AI materially change your headcount projections? Could AI help your team work more effectively and efficiently? Most importantly, is the AI good enough? Should you trust it?

That’s what Giant Machines aimed to figure out when we launched our own AI/ML project in early 2023.

The Opportunity Gap and its $160 Billion Impact

At Giant Machines, we believe making tech that matters includes creating opportunities, cultivating talent, and making spaces for everyone.

Improve Your Debugging Approach for Better Software Applications (& Sounder Sleep 😴)

In the process of developing applications, bugs will inevitably be introduced (“I code, therefore I create bugs” ~ Descartes, probably). Bugs can be introduced for a variety of reasons, such as logical errors, misunderstanding of requirements, lack of tests, tight deadlines, or something as simple as having an off day as a fallible human. However, knowing that bugs are inevitable, we can arm ourselves with tools to quickly identify and address software bugs before they are released in the wild.

Company

Learn more about us here at Giant Machines and how you can work with us.

What we do

We leverage best-in-class talent to create leading edge digital solutions.
services

Innovate

Know your next move

Build

Develop beautiful products

Learn

Enrich your tech knowledge

Our work

Learn more about our partnerships and collaborations.

Our perspective

Stay up to date with the latest in technology and design.

SUBSCRIBE