Building Your First dApp: A No-Nonsense Guide
The goal of this tutorial is to help you write and deploy your first fully fledged decentralized application on the Ethereum Blockchain without any frills, such as a beautiful and dynamic front end.
The application in question lets you submit and retrieve a number. This may sound pretty simple, but as the old Latin saying goes:
when you are steeped in little things, you shall safely attempt great things
This tutorial assumes that you’re using a computer running Mac OS. If you are not running Mac OS, almost all the packages and tools presented should be available for Windows and Linux environments. Any exceptions will be noted for your convenience.
Part 1: Getting your Tools
There are a couple of tools you’ll need to get your dApp off the ground so let’s go ahead and set them up. If you already have any of the tools already installed, go to the next step of installation instructions until you have everything you need.
brew
brew is a package manager for Mac OS only that will help in the installation of each tool. If you are using a Linux system, you will be installing most components using your distributions package manager. If you are using Windows, the products are stored and retrieved using tar.gz and zip file formats. You can install it by following the commands here in your terminal:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
npm
or “node package manager” is a command line tool designed to let you install other command line tools.
With brew
installed, getting npm installed is just one command away:
brew install npm
If you have a Windows or Linux machine installation for npm shouldn’t be too difficult either but you won’t be able to use brew
.
Make sure you have npm
properly installed by running the following commands in your terminal (this applies to all operating system platforms):
node -v
npm -v
Truffle
Truffle is an Ethereum smart contract development environment. It lets you write test cases for contracts and makes deploying your contracts fast and easy.
It can be installed through npm
like so:
npm install -g truffle
http-server
Just like its name, http-server is a tool that creates an http server on your computer. It’ll be used later in the tutorial to let you access your dApp from your computer’s directory.
It can be installed through npm
like so:
npm install -g http-server
Ganache
Made by the same people that made Truffle, Ganache acts as a simulated Ethereum blockchain that automatically creates accounts loaded with Ether for development purposes. It also comes with a built-in blockchain explorer so you can really see whats going on when you’re fiddling with your contract.
Ganache can be installed below:
MetaMask
MetaMask is a browser plug-in that lets you interact with dApps without having to host a full Ethereum node yourself. It also makes testing dApps on different networks from your personal computer incredibly easy.
MetaMask can be installed below:
Setting up your Development Environment
With all the above tools installed you’re finally ready to get your development environment up and running for this dApp.
Your project will need two directories: one to develop, debug, and deploy your smart contract code with Truffle and another to develop your dApp UI. Although the UI for this contract is just a single file (one HTML file with some embedded JavaScript), keeping everything in separate directories ensures things stay organized as the project grows larger. It also makes working with the http-server tool you install previously a lot easier as you’ll see later.
For the sake of simplicity, make two directories with the commands below in your terminal:
mkdir show_num
mkdir show_num_ui
show_num
is where we’ll use Truffle for smart contract work while show_num_ui
is where we’ll put the HTML file we need.
Go ahead and navigate into your newly made show_num
directory like so:
cd show_num
Truffle will set up a localized development environment within the folder like so:
truffle init
If it ran successfully, you should see something like this in your terminal:
Congratulations! You’ve set up your smart contract development environment. If you type ls
(which lists all the files and directories within your current folder) you should see something like this:
contracts is where you’ll actually be storing and writing all the code for the smart contract behind your dApp
migrations holds special configuration files that let you tell Truffle how to deploy your contract
test can hold programs for testing your contracts before deployment, whether it be through Solidity or JavaScript.
truffle.js and truffle-config.js give instructions to Truffle on where to deploy your contract, whether it be a local environment for the purposes of this tutorial or the actual mainnet. However, the files can also do a lot more to customize your environment. For the purposes of this tutorial, we only care about the location for contract deployment.
There’s one last thing we have to do before we consider the development environment complete: tell Truffle where the contract should go when you deploy it.
As mentioned previously truffle.js and truffle-config.js are the places to go to set this up properly. You’ll need to edit truffle.js for Mac; if you’re a Windows user, you’ll need to edit truffle-config.js. Go ahead and fire up your favorite text editor and open the file to edit it. If you do not have one, the option used by most developers is Sublime Text with a Solidity syntax tool. If you need the full directory of where the file is, the pwd
command is your friend, it’ll tell you exactly where you are.
I’m partial to the Vim text editor so the following screenshots will all be in Vim but you can still follow along with your favorite text editor.
Your truffle.js file should look like this by default:
You’ll want to focus on the part that says module.exports
. Go ahead and remove that section and replace it with the following code:
module.exports = {
networks: {
development: {
host: "127.0.0.1",
port: 8545,
network_id: "*" // Match any network id
}
}
};
This tells Truffle is that we want to push our contract to Ganache, our Ethereum blockchain simulator. If you’d like to make sure the information is accurate and aligns properly with your Ganache installation, or change any values, you can launch Ganache and go to the Preferences panel to see the host, port, and network ID information for yourself:
For our purposes, the Network ID won’t be any problem as Truffle has the wildcard option set and will connect to any Network ID. If your Network ID isn’t the same as the one in the picture, you can safely ignore it. For the example above, I have it set to “8888” which isn’t the default but you can tweak it as you wish.
Part 2: Creating and Deploying your Smart Contract
With the development environment now successfully set up, we can really get into the nitty-gritty of writing the code for our contract.
Go ahead and open your text editor and make a file in the contracts
directory called show_num.sol
. It should be noted that all smart contracts for Ethereum end with .sol
.
You might notice that there is another file already in the contracts
called Migrations.sol
. DO NOT REMOVE OR CHANGE THIS FILE! Truffle uses it to convert your smart contract into a more machine ready format that can be run by Web3 or Ganache.
Copy and paste the code below:
As promised, the dApp in question lets you submit and retrieve a number.
All Ethereum contracts start with pragma
followed by the version of the compiler used. This prevents the file from failed to be compiled by future compilers should future compilers introduce incompatible changes.
All contracts start with the contract
keyword followed by the name of the contract and enclosing curly brackets. Note how the name of the contract must match the name of file. This is a bit of a technicality with how Truffle works, but a good habit to practice nonetheless.
uint num
declares an unsigned integer within the contract. function set_num(uint x) public
declares a function that is publicly accessible and takes a uint
as its argument. function reveal_num () public view returns (uint)
declares a function that is publicly accessible and which returns a uint. The view
keyword states that the function does not change the state of the contract ( it doesn’t modify any data ). This is opposed to our set_num
function which does.
After saving your show_num.sol
file with the code above we can finally get around to compiling and deploying the smart contract code!
Making sure that you’re still in the environment we set up with Truffle, run the command below:
truffle compile
Your terminal should say something like this:
With your contract all compiled, we have to tell Truffle how to properly migrate your contract to Ganache. truffle.js already tells Truffle the where but what Truffle needs is the how. That’s where the migrations
directory comes in handy.
You can go up a directory (out of contracts
) like so:
cd ..
typing ls
just to confirm you’re out of the contracts
directory your files should now look like this:
One of the things you should see is a new directory called build
. This holds the compiled contract code as well as other necessary code for bridging our contract to our UI, making our fully fledged dApp.
For now go ahead and enter your migrations
directory like so:
cd migrations
If you do an ls
, you’ll notice that there’s one file already present there, 1_initial_migration.js
. This goes hand-in-hand with the previous Migrations.sol
file you saw in the contracts
directory. Make sure you, like Migrations.sol
DO NOT tamper or remove the file as this can ruin the migration process
Make a new file called 2_show_num_deploy.js
and make its contents the following:
Note the "./show_num.sol"
which tells Truffle to get compiled contract code for show_num
. The following lines just tell Truffle to migrate the contract but just Truffle also offers a number of other ways to customize your migration to more complex needs which we won’t be exploring today for the sake of simplicity.
Go ahead and save the file. Now, launch your installation of Ganache, letting it run in the background. Run the following command:
truffle migrate
If all goes well you should see something in your terminal like the following:
If you open up your Ganache instance running the background, you can tell that your contracts have been deployed because a quick glance at your accounts show that you’ve spent some Ethereum for deployment….
…and that you have 4 new generated blocks, which Ganache created automatically from its automining feature which only mines when it detects any intended interaction (calling/deploying a contract)
If you want to be doubly sure that your contract has been deployed, you can click the yellow buttons to the right for each block which give you more details about each block.
Some of the blocks (1 and 3 in our case) will be labelled with a “contract creation” indicator
If you look at the TX HASH field in Ganache and the output from truffle migrate
you’ll notice that they match up as well:
Hooray! Our smart contract now lives on our simulated Ethereum blockchain. With that out of the way, it’s time to concern ourselves with the front-end for our dApp
Part 3: Creating your Front-End
A dApp consists of smart contracts and a UI. We’ve already taken care of the smart contract part now it’s just a matter of putting a UI on top.
In order for our UI to communicate with your contract, there has to be some kind of bridge to do so. Luckily, web3
is a JavaScript API that lets you communicate with an Ethereum node, giving easy access to the Ethereum network and hence, your smart contract. Usually, you’d have to import the web3
JavaScript library into your project. That’s where the MetaMask browser plugin is so useful. MetaMask, as mentioned before, acts like a node so you don’t have to go through running your own Ethereum node just to access a dApp. MetaMask will automatically inject web3
into our page, allowing your dApp to work with any other browser that also has MetaMask installed.
However, web3
alone isn’t enough by itself. You’ll need to tell web3
where and how to talk to your contract. There are two critical pieces of information that you need to find and talk to your contract through web3
: The address of your contract and the ABI or Application Binary Interface, which encodes/decodes information to and from the Ethereum Virtual Machine.
Truffle makes it very easy to find this information. If you go to your show_num
directory and go into your build
directory, you’ll see a contracts
directory. Go ahead and go into that directory. You should see two files, Migrations.json
and show_num.json
. The names correspond to each of the migrated contracts. Opening up show_num.json
you should see something like this:
Right off the bat you can see an "abi"
section followed by some stuff enclosed with a pair of square brackets. If you scroll or search “address” in your text editor, you’ll find the address of your contract
Where this information goes is shown in the code for our UI file, show_num.html
, below:
As promised, our UI is very bare bones, with a simple entry field to get a number, a button to submit it, and another button to retrieve the number.
The line web3.eth.defaultAccounts = web3.eth.accounts[0]
just takes the first account that MetaMask provides as the one to use for interacting with the smart contract.
You can go ahead and make a show_num.html
file and then save it in your show_num_ui
folder which we made in the very beginning of the tutorial.
Particular attention should be paid to these lines:
const contract_abi = abi_from_Truffle_here....
const contract_address = "0xb421a6223b29b6791ad231bb1788ad9a38115834"
To get the contract_abi
into a nice, singular, string, you can use a “minifier” like the one below:
Just copy and paste the ABI from the show_num.json
file and copy the resulting output, replacing the ABI after contract_abi
if needed.
To create a contract instance that you can then call functions from, you do it like so:
var contract_inst = web3.eth.contract(contract_abi).at(contract_address);
Now you can call the contract via contract_inst
Something that should be noted, especially for people (like me) who are unfamiliar with JavaScript, is that web3
forces you to use callbacks, which are functions that are executed after another function has executed. The reason for this is that JavaScript is an event-driven language, meaning that JavaScript will not wait for a function to provide a response, instead it will execute other functions while awaiting a response.
Hence, a call to the reveal_num
function looks like this using web3
:
contract_inst.reveal_num((err, res) =>
{
if(!err)
{
document.getElementById("num_out").innerText = res;
console.log(res);
}
else
console.error(err);});
Where the call will either return some value for an error err
or result res
and each must be subsequently dealt with.
Testing and Playing with your dApp
Now that our UI and our smart contract are in place, it’s time to give the whole thing a spin.
First, make sure you’ve set up your MetaMask account and wallet. Clicking on MetaMask, following the provided instructions. Ensure that you properly store your password as well as the wallet passphrase. Losing the passphrase means a total inability to recover funds, should you use MetaMask to store any actual Ether. Luckily, we’ll just be using the Ether that Ganache provides us with.
After setting up MetaMask, you’ll want to connect to Ganache. MetaMask provides the option to connect to multiple testnets, “Localhost 8545” being the default Ganache port. Go ahead and click on that.
Now we’ll want to fund your account with some Ether so you can interact with your dApp. If you go back to the show_num
directory where you first created and migrated your contract, run the following command:
truffle console
This lets you interact with Ganache via the command line.
To transfer Ether from Ganache to your MetaMask wallet, execute this command:
web3.eth.sendTransaction({from:web3.eth.coinbase, to: your_metamask_wallet, value: web3.toWei(10, "ether") })
Where your_metamask_wallet should be the address of your MetaMask account as a string (encapsulated in ''
or ""
). in web3.toWei()
you can change 10
to any number of Ether and the "ether"
argument denotes the denomination of Ether, so you could send smaller amounts if you’d like.
If the transaction happens properly, you’ll see the transaction hash in the terminal. You can exit the Truffle console by hitting Ctrl+C twice.
Your wallet balance should appear like this in MetaMask:
And to be doubly certain, Ganache will also happily indicate that a value transfer occurred in its latest block:
With some Ether in your pocket, its time to launch that UI! Unfortunately, you can’t just double-click on the HTML file and start clicking away. You’ll have to access it from a server.
Now http-server comes to the rescue. Navigate to the show_num_ui
directory, where you saved the show_num.html
file and and run the following command:
http-server
You’ll see a prompt pop up asking if you want to grant “node” access. Go ahead and grant it. Your terminal show look like this:
http-server also lets you customize which port you’d like to access it from and a bunch of other neat settings, all of which are ignored for the sake of simplicity.
If you type localhost:8080
into your browser, you’ll be greeted by something like the page below:
Click on show_num.html
and you’ll be greeted by the (rather ugly but very usable) UI of our dApp!
Now for the real test. Go ahead and type a number into the field, and then hit the Send Number to Contract button. MetaMask will immediately ask your permission in using Ether to cover the action:
Go ahead and hit Confirm. MetaMask will notify you that a transaction occurred and you can see it in Ganache as well as a new block labelled “Contract Call” will appear:
If you hit the Show Number button, you should see the number you assigned come appear:
Congratulations! You’ve built your first dApp!
What Next?
Now that you’ve learned the basic workflow for developing dApps, you’re free to play with JavaScript frameworks like React and Angular to make your dApp look a lot better. Solidity isn’t just restricted to setting and getting data. You can launch your own tokens and build more useful dApps.
I intentionally kept details related to Truffle and the Solidity programming language sparse but I highly encourage those still interested to consult the documentation below:
If you’re looking for inspiration, you can consult this neat website:
I hope you’ve enjoyed this tutorial. If there are any errors in explanation or code, please feel free state them in the comments where they will be fixed promptly.
Best of luck with developing your own dApps and keep up the good work!