Build your Ethereum DApp on Windows with Truffle, Ganache and Metamask (Beginners Guide)

Filza Tariq

In this tutorial I am going to show you that how simply you can develop an ethereum dapp from scratch using Truffle, Metamask and Ganache. To setup your system with necessary dependencies refer to my previous article and setup your system to begin developing your first dapp.

Before we dive into the development, let me give you an overview about the architecture of Ethereum Dapp we are going to develop and how different puzzles are going to fit into the picture. So let’s start the journey to build your Ethereum DApp.


What are Ethereum Dapps?

Dapps are the decentralized applications that runs on a peer-to-peer network unlike traditional web apps that runs on centralized servers. When these dapps are built over ethereum network, these are known as “ethereum dapps”. In decentralized apps, all the users’ data is stored on immutable distributed ledger and every participating nodes have a copy of that ledger. These dapps logic that runs on the blockchain nodes is written in solidity language and traditionally called as “smart contracts”.

Architecture of our Ethereum Dapp:

Client’s Browser: It is just like a normal browser of any web application written in html, css and javascript.

Web3.js: Web3.js is a collection of libraries that enables your browser to interact with blockchain. It enables you to read and write data from smart contracts, transfer ethers between accounts and much more.

Web3 Provider: Ethereum network contains nodes and all nodes share the same copy of data. Setting a “web3 provider” in web3.js tells our code that which node we are going to read and write data from. We are using Metamask in our implementation that injects its web3 provider in the browser. Metamask is a browser extension for Chrome and Firefox that lets users securely manage their Ethereum accounts and private keys, and use these accounts to interact with websites that are using Web3.js.

Ethereum Virtual Machine: Every ethereum node in ethereum network runs their own EVM implementation and responsible for running the same instructions of smart contracts over the ethereum network.

Ok that’s all about the theory, to wake you up let’s start with the development.


What we are going to develop?

We are going to develop a simple decentralized newsfeed system. News publisher can post news on blockchain with their account addresses. These news will be immutable and displayed in the same order as they are posted.

Our Final Dapp will look something like this:

You can refer to the code at GitHub anytime you face issues. But I urge you to code each step yourself along with me.

Step 1: Setting up the Structure

I presume that you have set the development environment already. In command prompt create a new directory and unbox “truffle-box” in that respective directory to get the structure of project.

mkdir postnews

cd postnews

truffle unbox pet-shop

This will set up the following basic structure in your folder:

Let’s examine the project structure Truffle Box gave us.

Contracts: As obvious with the name, here all our smart contracts will reside.

Migrations: Includes Migration files to migrate smart contracts to blockchain.

Node_modules: Contains all node dependencies

Src: Home for all client side application code

Test: Where we write tests for our smart contract either in solidity or javascript. We are not going to write any tests in our implementation because we are building a basic implementation of Dapp. But tests are important to write when you are working on commercial projects, because each migration of smart contract on blockchain causes gas cost. Thus, you want to make sure that your smart contracts are bug free and perform the intended functionality.


Step 2: Writing Smart Contract

Create a new file news.sol in contract folder and write the following code in it.

pragma solidity >=0.4.0 <=0.6.0;

contract news{

struct newsfeed{

address publisher;

string newsdesc;

}

mapping(uint => newsfeed) public newsfeeds;

uint public newsCount;

function addnews(string memory newsdesc) public {

newsCount++;

newsfeeds[newsCount].publisher = msg.sender;

newsfeeds[newsCount].newsdesc = newsdesc;

}

}

Let me explain this code. First we specify that the current code is runnable on the solidity compiler version greater than 0.4.0 and smaller than 0.6.0 with “pragma solidity”. Then we initialized the contract and initialized the structure of our newsfeed containing address of publisher (initialized with address data type) and news itself (initialized with string data type).

To store this created structure we have created mapping that is just like a key value pair. The key to mapping is an unsigned integer and the value is the “newsfeed struct”.

“newscount” keeps track of the number of posted news and initially 0. Addnews function will store publisher address and news in the struct referenced by the key value. “msg.sender” gets the address of account which has called the contract.

Simple. Isn’t it? Now let’s compile this smart contract to see if it runs properly. To do this, navigate to your project folder in console and write

truffle compile

Now lets migrate our current smart contract on Ganache. To do this, create a new file in Migration folder named “2_deploy_contracts.js”. Paste the following code in that file to migrate your contract:

var news = artifacts.require(“./news.sol”);

module.exports = function(deployer) {

deployer.deploy(news);

};

Save it and in console type:

truffle migrate

Make sure that Ganache is open and running while you migrate your contract. And hurrah! Your contract is successfully migrated to Ganache.

Step 3: Developing Client-side application to interact with contract

Go to your index.html file and paste the following code:

<!DOCTYPE html>

<html lang=”en”>

<head>

<meta charset=”utf-8">

<meta http-equiv=”X-UA-Compatible” content=”IE=edge”>

<meta name=”viewport” content=”width=device-width, initial-scale=1">

<! — The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags →

<title>Decentralized Newsfeed</title>

<! — Bootstrap →

<link href=”css/bootstrap.min.css” rel=”stylesheet”>

<! — HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries →

<! — WARNING: Respond.js doesn’t work if you view the page via file:// →

<! — [if lt IE 9]>

<script src=”https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>

<script src=”https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>

<![endif] →

</head>

<body>

<div class=”container”>

<div class=”row”>

<div class=”col-xs-12 col-sm-8 col-sm-push-2">

<h1 class=”text-center”>Decentralized Newsfeed</h1>

<hr/>

<br/>

</div>

</div>

<div id=”newsRow” class=”row”>

<! — NEWS LOAD HERE →

</div>

<! — <button class=”btn btn-default” type=”button” class=”aaaaaddProd”>Add Product</button> →

<! — Button trigger modal →

<button type=”button” style=”align:center;” class=”btn btn-primary” data-toggle=”modal” data-target=”#exampleModalCenter”>

Add News

</button>

</div>

<! — Modal →

<div class=”modal fade” id=”exampleModalCenter” tabindex=”-1" role=”dialog” aria-labelledby=”exampleModalCenterTitle” aria-hidden=”true”>

<div class=”modal-dialog modal-dialog-centered” role=”document”>

<! — Modal Content →

<div class=”modal-content”>

<! — Modal Header →

<div class=”modal-header”>

<h5 class=”modal-title” id=”exampleModalCenterTitle”>Add News</h5>

<button type=”button” class=”close” data-dismiss=”modal” aria-label=”Close”>

<span aria-hidden=”true”>&times;</span>

</button>

</div>

<! — Modal Body →

<div class=”modal-body”>

<form>

<div class=”form-group”>

<textarea class=”form-control postbox” id=”post” placeholder=”Add you story Here…” rows=”5"></textarea>

</div>

<button type=”submit” data-dismiss=”modal” class=”btn btn-primary addNews”>Post News</button>

</form>

</div>

<div class=”modal-footer”>

<button type=”button” class=”btn btn-secondary” data-dismiss=”modal”>Close</button>

</div>

</div>

</div>

</div>

<div id=”postTemplate” style=”display: none;”>

<div class=”col-md-12">

<div class=”panel panel-default panel-pet”>

<div class=”panel-heading”>

<strong>Publisher Address</strong> <h3 class=”panel-title”> Account Address </h3>

</div>

<div class=”panel-body”>

<strong>Descrition</strong>: <span class=”desc”> </span><br/>

</div>

</div>

</div>

</div>

<! — jQuery (necessary for Bootstrap’s JavaScript plugins) →

<script src=”https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<! — Include all compiled plugins (below), or include individual files as needed →

<script src=”js/bootstrap.min.js”></script>

<script src=”js/web3.min.js”></script>

<script src=”js/truffle-contract.js”></script>

<script src=”js/app.js”></script>

</body>

</html>

Ok! Don’t scare yourself it’s just some simple html. Let me go through it. Add News Button is navigating to the model that opens a dialogue for adding news. “posttemplate” contains the layout of how your posts will be displayed on screen.

To make this code in action lets write some code in app.js and see how it is going to link up with our smart contract.

In your app.js file first add the following code to setup the web3 provider for web3.js in browser.

App = {

web3Provider: null,

contracts: {},

initWeb3: async function() {

// Modern dapp browsers…

if (window.ethereum) {

App.web3Provider = window.ethereum;

try {

// Request account access

await window.ethereum.enable();

} catch (error) {

// User denied account access…

console.error(“User denied account access”)

}

}

// Legacy dapp browsers…

else if (window.web3) {

App.web3Provider = window.web3.currentProvider;

}

// If no injected web3 instance is detected, fall back to Ganache

else {

App.web3Provider = new Web3.providers.HttpProvider(‘http://localhost:7545');

}

// App.web3Provider = new Web3.providers.HttpProvider(‘http://localhost:8545');

web3 = new Web3(App.web3Provider);

return App.initContract();

},

Extend app.js with the following code:

initContract: function() {

$.getJSON(‘news.json’, function(data) {

// Get the necessary contract artifact file and instantiate it with truffle-contract

App.contracts.news = TruffleContract(data);

// Set the provider for our contract

App.contracts.news.setProvider(App.web3Provider);

return App.init();

});

return App.AddNewsButton();

},

When we compile our contract “news.json” is created in build folder. Truffle has a library called “TruffleContract” that keeps information about the contract. So using this library we set web3 provider for our contract. This enables our client side application to interact with our smart contract deployed on blockchain.

Move forward and add the following code in app.js:

AddNewsButton: function() {

$(document).on(‘click’, ‘.addNews’, App.AddNews);

},

AddNews:function(event){

var post = document.getElementById(‘post’).value

var postInstance;

App.contracts.news.deployed().then(function(instance){

postInstance = instance;

return postInstance.addnews(post);

});

console.log(“News posted”);

},

};

This code will take the user entered news and pass it to our add news function in smart contract. Smart contract will write the publisher address and news on blockchain using mapping.

Finally add the following code in app.js to render the html template with data on every page reload so your news will be displayed.

init: async function() {

// Load News

var postInstance;

App.contracts.news.deployed().then(function(instance){

postInstance = instance;

return postInstance.newsCount();

}).then(function(result){

var counts = result.c[0];

console.log(“Total News : “+counts);

for (var i = 1; i <= counts; i ++) {

postInstance.newsfeeds(i).then(function(result)

{

console.log(“Publisher Address:” +result[0]);

console.log(“News:” +result[1]);

var newsRow = $(‘#newsRow’);

var postTemplate = $(‘#postTemplate’);

postTemplate.find(‘.panel-title’).text(result[0]);

postTemplate.find(‘.desc’).text(result[1]);

newsRow.append(postTemplate.html());

});

}

});

‘i’ initialized with 1 is passed as a key to newsfeeds mapping. This will fetch the structure details on index i. Structure details are just like an array having “publisher address” at 0 index and “newsdesc” at 1 index. This data will be retrieved from smart contract and append to “postTemplate” in index.html.

Now in your console type “npm run dev” to run your dapp.

This will open up the dapp in your browser. Make sure you are logged in with metamask and its running on port 7545.

Kudos! You have successfully developed your Dapp. Happy Coding!

Filza Tariq

Written by

Currently working at NCCS Blockchain Security Lab. Passionate about emerging technologies and love to explain complex terms and technologies in easy fun way.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade