September 5, 2019

During Summer 2019 (North American edition), I took part in Truffle University's inaugural cohort for two months of advanced Ethereum development education. One of the recommended assignments was to submit a pull request for an open source project of our choosing.

My contribution arose out of a personal pain point encountered while developing my decentralized dollar cost averaging dApp (Vulcan Swap) on Drizzle.

Drizzle logo

Drizzle is Truffle Suite's frontend framework for displaying content from the decentralized web. It makes use of a store and events to gracefully manage smart contract state.

The Problem: detecting a user's web3 network

At the time, there was no way for a Drizzle-built dApp to communicate to a user that their Metamask (or other provider) is connected to an unsupported network.

dApps are applications built to interact with smart contracts on a decentralized (or at least distributed) network, such as Ethereum. The thing is: there are lots of Ethereum testnets in addition to mainnet, and a developer must deploy a smart contract to each chain where they want dApps to be able to build on it.

One does not simply deploy to "Ethereum"

In addition to mainnet, there are several testnets and other chains to which a developer can deploy a smart contract. Relatively few smart contracts exist on more than a few chains.

Returning to the problem, it will often be the case - granted, for developers and super early adopters mostly - that a user opens a dApp while connected to an Ethereum chain (say Ropsten) where that dApps' smart contracts don't exist (say Rinkeby and mainnet).

In this case, there should be a way for the developer to signal to the user that they should switch to a supported network.

To combat this issue, I ended up diving deep down the Drizzle rabbit hole of Redux sagas with the help of my mentor Amal Sudama, a Drizzle core dev who has been an incredible resource and enthusiastic cheerleader to boot.


The Solution

I contributed to two separate modules of Drizzle's monorepo, one with the core logic to discriminate based on user network, and the other as a simple out-of-box sample implementation.

1. The networkWhitelist (Drizzle core functionality)

I added a new Drizzle configuration option (i.e., drizzleOptions) that allows a developer to define a networkWhitelist. This whitelist is an array of Ethereum chain IDs on which the developer wants to make their dApp available for public use.

// Signifies that the dApp is accessible on...
networkWhitelist = [
  1, // Ethereum mainnet and
  4 // Rinkeby testnet
]

If the user in this example accesses the dApp from Ropsten (chain id: 2), Drizzle will fire a Redux action that sets a networkMismatch flag in Drizzle's store. It is then up to the developer to handle how this information is relayed to the user.

Pull request: https://github.com/trufflesuite/drizzle-legacy/pull/235

2. A network-aware LoadingContainer (a Drizzle React component)

As an example of how this networkMismatch flag might be used (and to provide an out-of-box implementation), I modified the existing LoadingContainer from Drizzle's react-components module with some additional logic:

if (this.props.drizzleState.web3.networkMismatch) {
  if (this.props.networkMismatchComp) {
    return this.props.networkMismatchComp;
  }

  return (
    <main className="container network-warning">
      <div className="pure-g">
        <div className="pure-u-1-1">
          <h1>⚠️</h1>
          <p>This dapp does not support this network.</p>
        </div>
      </div>
    </main>
  );
}

This snippet allows for a developer to either display a default network mismatch message, or to optionally add their own by passing a React component to the LoadingContainer as a networkMismatchComp property.

For example, in my own Vulcan Swap dApp (a decentralized cost averaging investment tool), I provided some custom feedback formatted with Bootstrap markup to give a look more consistent with the theme:

import React from 'react';

const NetworkMismatchBlock = () =>
  <div className="networkMismatchBlock">
    <div className="alert alert-danger" role="alert">
      <div className="container">
        To "Go Long and Prosper", switch to the Rinkeby Network"
      </div>
    </div>
  </div>

export default NetworkMismatchBlock;

Pull request: https://github.com/trufflesuite/drizzle/pull/9

Network Whitelist Demo

For a quick visual run-through of the networkWhitelist functionality, check out the video below: