220ml of dark roasted full bodied coffee brewed in french press accompanied by a banana while listening to Liquid Tension Experiment

tl;dr: You can go ahead and clone this repo, it’s got the end result of this in-depth tutorial below.

Here’s what we will be doing to become smart-contract heroes! – Install the dev environment plus MetaMask. – Develop a very simple voting smart contract. – Develop a front-end for our DAPP using React and Redux. – Configure and deploy our contract to Ropsten.

If you don’t know what Solidity is, please go check it out. There’s an awesome video library you can watch to get a firm grasp on developing smart contracts with Solidity. This is not a requisite for this blog post; I just thought it was important to share the videos, since their content is pretty solid.

The Dev Environment

We need to install our dev environment, so we’re going to install truffle, which will help us get started quickly:

1

$npm install-gtruffle

And now, there are several ways to run a local blockchain for our development environment, but the easiest is to download Ganache. Once you’ve downloaded and executed it, you’ll have a fully functional blockchain ethereum network for you to deploy and test your contracts.

Note your network ID and RPC Server Port; typically the network ID is 5777 and the server hosted in 127.0.0.1:7545.

Let’s Start Playing!

We don’t have to start from scratch to develop our app; we’re going to use truffle boxes, which are boilerplate projects that include a bunch of functionalities already built in to bootstrap our DAPP ideas:

In order to get the environment started the right way, add a file to the root of the application folder called .env:

1

2

NODE_PATH=src/

REACT_APP_LOCAL_BLOCKCHAIN_PORT=7545

The first bit will allow our React application to import modules using an absolute path instead of a relative one; this will avoid the typical import foo from ‘../../../../foo’, which are hard to read and maintain. The second one lets you configure which local network blockchain port to use; it’s set up to use the default Ganache network port.

Now, in the package.json file, let’s edit the scripts section so it looks like this:

1

2

3

4

5

"scripts":{

"start":"env-cmd ./.env node scripts/start.js",

"build":"env-cmd ./.env node scripts/build.js",

"test":"env-cmd ./.env node scripts/test.js --env=jsdom"

},

Once we’ve set up the dependencies and scripts, lets go ahead and delete the contracts/SimpleStorage.sol file and create our own contracts/Voting.sol:

The next part is developing the front-end app, and because it’s an app with React + Redux + React-Router, there’s a whole bunch of files; so instead of copying/pasting every file, type these commands in the terminal (inside your project root of course):

That should create a backup of the src folder, and then download and unzip the source code of the voting-dapp front-end.

However, I’m going to explain some key files so you understand how to communicate with your smart contracts. For instance, in the build/contracts/ folder, you’ll find several .json files, one per contract; those files are known as ABI, which stands for Application Binary Interface, and they hold all of the information regarding each contract.

These ABI files are made when you truffle compile, and if you open src/contracts-api/VotingContract.js:

You can see in the constructor (from lines 11 to 14) where we’re getting a reference to the Web3 provider instance; then, we create a contract using the ABI file and set its provider.

After that, it becomes super easy to operate on the contract; we get an instance reference of the deployed contract using async/await and then just call the function we’re interested in and then return the value of said function. Truffle-contract already abstracts all of the complexity for you and gives you a nice API to use.

This file acts as an abstraction layer for each function’s custom behavior.

This leads me to the other important aspect, the src/modules/candidates/candidates.actions.js file:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

import{

GET_CANDIDATES,

VOTE,

NEW_CANDIDATE,

}from'./candidates.constants'

import{VotingContract}from'contracts-api'

export constgetCandidates=()=&gt;{

return{

type:GET_CANDIDATES,

payload:(newVotingContract()).getAllCandidates(),

}

}

export constpostulateNewCandidate=()=&gt;{

return{

type:NEW_CANDIDATE,

payload:(newVotingContract())

.proposeCandidate({type:'random'})

.then(()=&gt;(newVotingContract()).getAllCandidates()),

}

}

export constvote=(candidateName)=&gt;{

return{

type:VOTE,

payload:(newVotingContract())

.castVote(candidateName)

.then(()=&gt;(newVotingContract()).getAllCandidates()),

}

}

These are pretty standard redux action creator functions, but they’re using redux-promise-middleware, which makes the actions look a lot simpler. You can see how easy it is to call each contract function using our custom abstraction layer.

Also, you can listen to events being published by your contract; there’s an event called UpdateCandidates, and if you take a peek at src/modules/candidates/candidates.event-listeners.js file:

1

2

3

4

5

6

7

8

9

import{getCandidates}from'modules/candidates'

import{VotingContract}from'contracts-api'

export defaultasync(dispatch,getState)=&gt;{

await(newVotingContract())

.updateCandidatesEventListener((error,candidateList)=&gt;{

dispatch(getCandidates())

})

}

This is a very simple function that is called from the src/store.js file in line 36:

applyCandidatesEventListeners(store.dispatch, store.getState);

It gets the dispatch and getState functions passed from the store instance, and that’s how it dispatches actions when events are called.

And that’s about it; everything else is a pretty standard react application. Now, we can go ahead and start our brand new front-end:

1

$npm start

_Note: While in development mode, it’s better to deactivate MetaMask if you already have it installed; it has some nasty bugs regarding events and synchronization with local RPC servers (like Ganache) _

Success! You should have been presented with something like the picture above; you should be able to hit the plus fab button and the app should be creating new “candidates” each time. While you’re at it, go ahead and take a look at the Transactions and Blocks tabs in Ganache; you’ll see that each time you either vote or create a new candidate, a transaction is made and a block is added.

Deployment to Ropsten network

We will need MetaMask installed; this will keep things nice and easy. We’ll use MetaMask to create ourselves an Ethereum account and fill it with free ETH (using a faucet) so we can deploy our smart contracts to the Ropsten network (that’s a testing network, so that’s why we can get ETH for free).

First, create yourself a secure password:

Then, copy the 12 word mnemonic you’ve been given somewhere safe:

Copy them somewhere safe; seriously, they’re important. Now you can go to Infura.io to get your API key by signing up. Once you do, put those 12 words and the Infura API key in their respective places in your truffle.js file:

1

2

3

4

5

//...

varinfuraApiKey='YOUR GENERATED INFURA API KEY';

varmnemonic='YOUR 12 WORDS MNEMONIC';

//...

Then, on your MetaMask UI, select the Ropsten network:

Last thing—go to the MetaMask faucet and request some ether for your account, you’ll need it to deploy your contracts:

Wait for the transaction to finish, and then that’s it! Now, let’s deploy to Ropsten:

1

2

$truffle compile

$truffle migrate--network ropsten

Done. You’re now officially on Ropsten; now you only need your MetaMask pointing towards Ropsten Network (like you already have), and you can interact with your deployed smart contract using your local react app (at least while your MetaMask is pointing towards the Ropsten Network).

If you want to deploy your app as a real distributed application, you can use IPFS.io, which will help you deploy your application in a P2P protocol static hosting. In case you want to deploy your front-end in a typical centralized way, surge.sh is pretty good for that and super easy to use.

That’s it for this tutorial; hope you enjoyed the music and the snack! You can find a presentation here and the source code for this application is at this repo; should you have any questions about implementations or the code in general, feel free to create issues on the Github repo or post them as comments below.

Daniel Prado is a Web Development Practice Lead for Gorilla Logic. He previously taught frontend technologies and data structures at some of Costa Rica’s most prestigious universities. Daniel enjoys open water swimming, go-cart racing, and listen to music - especially 80s heavy metal bands.