I have installed and tested everything on MacOS and Ubuntu. Installation is pretty straightforward:

On Mac:

mahesh@projectblockchain:~$ brew tap ethereum/ethereum

mahesh@projectblockchain:~$ brew install ethereum

On Ubuntu:

mahesh@projectblockchain:~$ sudo apt-get install software-properties-common

mahesh@projectblockchain:~$ sudo add-apt-repository -y ppa:ethereum/ethereum

mahesh@projectblockchain:~$ sudo apt-get update

mahesh@projectblockchain:~$ sudo apt-get install ethereum

You can find installation instructions for various platforms here: https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum

Once you have installed geth, run the below command in your command line console:

mahesh@projectblockchain:~$ geth --rinkeby --syncmode "fast" --rpc --rpcapi db,eth,net,web3,personal --cache=1024 --rpcport 8545 --rpcaddr 127.0.0.1 --rpccorsdomain "*"

This will start the Ethereum node, connect to other peer nodes and start downloading the blockchain. The time it takes to download the blockchain depends on various factors like your internet connection speed, RAM on your computer, type of hard drive etc. It took me 30–45 minutes on a machine which has 8GB RAM and 50Mbps connection.

In the console where you have geth running, you will see the output like below. Look for the block number which is in bold. When your blockchain is fully sync’d, the block number you see will be close to the block number on this page: https://rinkeby.etherscan.io/

I0130 22:18:15.116332 core/blockchain.go:1064] imported 32 blocks, 49 txs ( 6.256 Mg) in 185.716ms (33.688 Mg/s). #445097 [e1199364… / bce20913…] I0130 22:18:20.267142 core/blockchain.go:1064] imported 1 blocks, 1 txs ( 0.239 Mg) in 11.379ms (20.963 Mg/s). #445097 [b4d77c46…] I0130 22:18:21.059414 core/blockchain.go:1064] imported 1 blocks, 0 txs ( 0.000 Mg) in 7.807ms ( 0.000 Mg/s). #445098 [f990e694…] I0130 22:18:34.367485 core/blockchain.go:1064] imported 1 blocks, 0 txs ( 0.000 Mg) in 4.599ms ( 0.000 Mg/s). #445099 [86b4f29a…] I0130 22:18:42.953523 core/blockchain.go:1064] imported 1 blocks, 2 txs ( 0.294 Mg) in 9.149ms (32.136 Mg/s). #445100 [3572f223…]

2. Install the Truffle Framework

Install truffle using npm. The truffle version being used in this tutorial is 3.1.1.

npm install -g truffle@5.1.18

*Depending on your system setup, you might have to add a sudo at the beginning.

3. Set up the voting contract

First step is to set up the truffle project:

mahesh@projectblockchain:~$ mkdir voting

mahesh@projectblockchain:~$ cd voting

mahesh@projectblockchain:~/voting$ npm install -g webpack@4.42.0

mahesh@projectblockchain:~/voting$ truffle unbox webpack

mahesh@projectblockchain:~/voting$ ls

app contracts migrations test truffle-config.js

mahesh@projectblockchain:~/voting$ ls app/

node_modules package-lock.json package.json src webpack.config.js mahesh@projectblockchain:~/voting$ ls contracts/

ConvertLib.sol MetaCoin.sol Migrations.sol mahesh@projectblockchain:~/voting$ ls migrations/

1_initial_migration.js 2_deploy_contracts.js

As you can see above, truffle creates the necessary files and directories required to run a full stack dapp. Truffle also creates a sample application to get you started (we won’t be using it in this tutorial). You can safely delete the ConvertLib.sol and MetaCoin.sol files in the contracts directory for this project.

It is important to understand the contents of the migrations directory. These migration files are used to deploy the contracts to the blockchain. (If you remember, in the previous post, we used VotingContract.new to deploy the contract to the blockchain, we don’t need to do that anymore). The very first migration 1_initial_migration.js deploys a contract named Migrations to the blockchain and is used to store the latest contract you have deployed. Every time you run the migration, truffle queries the blockchain to get the last contract that has been deployed and then deploys any contracts which haven’t been deployed yet. It then updates the last_completed_migration field in the Migrations contract to indicate the latest contract deployed. You can simply think of it as a database table called Migration with a column named last_completed_migration which is kept up to date always. You can find more details on the truffle documentation page.

Let’s now update the project with all the code we wrote in the previous tutorial with few changes explained below.

First, copy over the Voting.sol from the previous tutorial to the contracts directory (there are no changes to this file).

mahesh@projectblockchain:~/voting$ ls contracts/

Migrations.sol Voting.sol

Next, replace the contents of 2_deploy_contracts.js in the migrations directory with the following:

const Voting = artifacts.require("Voting"); module.exports = function(deployer) {

deployer.deploy(Voting, ['Rama', 'Nick', 'Jose'].map(name => web3.utils.asciiToHex(name)));

}; /* As you can see above, the deployer expects the first argument to be the name of the contract followed by constructor arguments. In our case, there is only one argument which is an array of

candidates. The third argument is a hash where we specify the gas required to deploy our code. The gas amount varies depending on the size of your contract.

*/

You can also set the gas value as a global setting in truffle-config.js. Go ahead and add the gas option like below so in the future if you forget to set the gas in specific migration file, it will by default use the global value. Also add other arguments as shown.

require('babel-register') module.exports = {

networks: {

develop: {

port: 8545,

host: 'localhost',

network_id: '*',

gas: 6700000

}

},

compilers: {

solc: {

version: "0.6.4"

//Uncomment and update the solc version as shown here }

} }

Replace the contents of app/src/index.js with the contents below.

Replace the contents of app/src/index.html with the following. Even this file is pretty much the same as last chapter except the js file included is index.js at the end of the file.

4. Deploy the contract to Rinkeby test network

Before we can deploy the contract, we will need an account and some ether. When we used ganache, it created 10 test accounts and came preloaded with 100 test ethers. But for testnet and mainnet we have to create the account and add some ether ourselves.

Skip this step if you are using ganache

In your command line terminal, do the following:

mahesh@projectblockchain:~/voting$ truffle console truffle(default)> web3.personal.newAccount('verystrongpassword')

'0x95a94979d86d9c32d1d2ab5ace2dcc8d1b446fa1' truffle(default)> web3.eth.getBalance('0x95a94979d86d9c32d1d2ab5ace2dcc8d1b446fa1')

{ [String: '0'] s: 1, e: 0, c: [ 0 ] } truffle(default)> web3.personal.unlockAccount('0x95a94979d86d9c32d1d2ab5ace2dcc8d1b446fa1', 'verystrongpassword', 15000) // Replace 'verystrongpassword' with a good strong password.

// The account is locked by default, make sure to unlock it before using the account for deploying and interacting with the blockchain.

In the previous post, we started a node console and initialized the web3 object. When we execute truffle console, all of that is done for us and we get a web3 object ready to use. We now have an account with address ‘0x95a94979d86d9c32d1d2ab5ace2dcc8d1b446fa1’ (you will have a different address in your case) and the balance will be 0.

You can get some test ether for Rinkeby network through the faucet here: https://faucet.rinkeby.io/. Try web3.eth.getBalance again to make sure you have ether. You can also enter your address on rinkeby.etherscan.io to see your account balance. If you can see a non-zero balance on rinkeby.etherscan.io but if web3.eth.getBalance still shows 0, it means your sync hasn’t completed. You just have to wait for your local blockchain to sync and catch up.

Now that you have some ether, go ahead and compile and deploy the contract to the blockchain. Below is the command to run and the output you will see if everything goes well.

* Do not forget to unlock the account before deploying your contract.

mahesh@projectblockchain:~/voting$ truffle migrate --network develop

[Network name should be whatever you have in your truffle-config.js] Compiling Migrations.sol... Compiling Voting.sol... Writing artifacts to ./build/contracts Running migration: 1_initial_migration.js Deploying Migrations... Migrations: 0x3cee101c94f8a06d549334372181bc5a7b3a8bee Saving successful migration to network... Saving artifacts... Running migration: 2_deploy_contracts.js Deploying Voting... Voting: 0xd24a32f0ee12f5e9d233a2ebab5a53d4d4986203 Saving successful migration to network... Saving artifacts... mahesh@projectblockchain:~/voting$

On my machine, it took about 70–80 seconds to deploy the contracts.

5. Interacting with the voting contract

If you were able to deploy the contract successfully, you should now be able to fetch the vote count and also vote through truffle console.

mahesh@projectblockchain:~/voting$ truffle console --network develop truffle(develop)> instance = await Voting.deployed()

truffle(develop)> await instance.voteForCandidate(web3.utils.asciiToHex('Rama')) // After a few seconds, you should see a transaction receipt like this: receipt: { blockHash: '0x7229f668db0ac335cdd0c4c86e0394a35dd471a1095b8fafb52ebd7671433156', blockNumber: 469628, contractAddress: null,

....

.... truffle(develop)> result = await instance.totalVotesFor(web3.utils.asciiToHex('Rama'))

truffle(develop)> result.toString()

'1'

If you are able to do this, it’s a success, your contract is live and functional! Now, go ahead and start the the server

mahesh@projectblockchain:~/voting$ npm run dev

You should see the voting page at localhost:8080 (open the page in incognito window in your browser to avoid any conflict with wallets you might have installed) and be able to vote and see the vote counts of all the candidates. Since we are dealing with a real blockchain, every write to the blockchain (voteForCandidate) will take a few seconds (The miners have to include your transaction in a block and the block to the blockchain).

If you see this page and are able to vote, you have a built a full fledged Ethereum application on the public test network, congratulations!

Since all your transactions are public, you can look at them here: https://rinkeby.etherscan.io/. Just enter your account address and it will show you all your transactions with timestamp.

Hopefully you were able to follow along and get the application working. You can find the all the files in the github repo here. If you run into issues getting the application working, feel free to DM me on twitter @zastrinlab.