
Blockchain has become a buzzword over the past few years.
In this course we will take you through the process of building your first dapp called an adoption tracking system for a pet shop!
This course, we're going to cover
Truffle, which is a
A world class development environment, testing framework for blockchains using the Ethereum Virtual Machine (EVM).
and Ganahe which is a personal blockchain for rapid Ethereum distributed application development.
Hi, I am Gaurav garg, It'll be my pleasure to bring you on this blockchain dApp journey with the Truffle and Ganache.
In this tutorial we will be covering:
Setting up the development environment
Creating a Truffle project using a Truffle Box
Writing the smart contract
Compiling and migrating the smart contract
Testing the smart contract
and Interacting with the dapp in a browser
So if you're ready to create your first dApp. lets get started.
To Create Decentralized Application or in short say dApp, you should have some knowledge using blockchain, or at least understanding the basics of what blockchain is
and how it works will help you.
This tutorial is meant for those with a basic knowledge of Ethereum and smart contracts,
who have some knowledge of HTML and JavaScript, but who are new to dapps.
You can develop your dApp on a Mac, Windows, or Linux. So the environment you use won't have any impact on creating your dApp.
There are a few technical requirements before we start writing our first dApp. We need to install the following:
Node.js v 16.14.2 LTS and npm version 8.5.0, these are the latest versions for node js and npm currently while making this tutorial.
Then we are going to install Truffle and Ganache.
so lets start with installing node js.
To install the node js, we are going to open our web browser and search for node js, we can see the link which comes with nodejs website.
we are going click this link and open the node js website. Once you enter the website click on Downloads button, and we can see here the lastest node
version is 16.14.2 and this includes npm 8.5.0, so this installer actually includes both node js and npm, we dont require here to install the npm separately.
I am using windows so I am going to install the windows installer. Once its Downloads we can left click here and then press on show in finder to go to the place
where its actually downloaded.
Now we are going to run this installer, click next, accept the license agreement, click next.
You can change the location if you want but I would recommend to install on Program Files Folder in c Drive. Then we click next.
We can see the npm package manager is here as well, we click next, next again and install. Once it done click finish.
To check if its install properly, We will use command prompt to open.
Use a shortcut, (window + R), for run prompt and type cmd to open it.
now we will type node -v, to check the version of node
we will do the same step for npm, type npm -v to check the npm version. we can see the versions here and we can say we are done with install node js and npm.
Now its time to install truffle.
To install the truffle we are going to type in command propmpt, npm install -g truffle.
It will take few mins to install the truffle, so I am going to skip the waiting time.
To verify that Truffle is installed properly, type truffle version on a command prompt
and it will show the version number of truffle, we can see here that truffle is installed with version v5.5.7
now last step is to install Ganache, we will open the web browser, and go for trufflesuite website and look for ganache.
we click on download button to download the Ganache installer.
Run the installer and
We can click on Launch after installation to check if its working.
We dont need to worry about Ganache for now, We will learn in the later lesson how to use and work with Ganache.
Now we are done with installing all requirement to start with DApp.
In the next video we are going to start creating the truffle project.
In this tutorial we are going to create a truffle project using a truffle box, so first create a directory in your development folder,
in my case i am using D drive.
use command mkdir to create a folder named pet-shop-turorial.
and then move inside it. using cd pet-shop-tutorial.
There is a special Truffle Box just for this tutorial called pet-shop, which includes the basic project structure as well as
code for the user interface. Use the `truffle unbox` command to unpack this Truffle Box.
truffle unbox pet-shop
Point to be note - Truffle can be initialized a few different ways. Another useful initialization command is
`truffle init`, which creates an empty Truffle project with no example contracts included.
Now we are going to open this folder in visual studio code using command code .
Once it open, we can see The default Truffle directory structure which contains many folders like
contracts folder which Contains the Solidity source files for our smart contracts. There is an important contract in here
called Migrations.sol, which we'll talk about later.
migrations folder, Truffle uses a migration system to handle smart contract deployments. A migration is an additional special
smart contract that keeps track of changes.
test folder which Contains both JavaScript and Solidity tests for our smart contracts
truffle-config.js file which is Truffle configuration file
The pet-shop Truffle Box has extra files and folders in it, but we won't worry about those just yet. In this next lesson we are going to write a smart contract.
We'll start our dapp by writing the smart contract that acts as the back-end logic and storage.
First we go to extenstion and search for solidity package, Install This package will help Syntax highlighting and
Snippets for solidity code in visual studio.
Now,
Create a new file named Adoption.sol in the contracts/ directory.
pragma solidity caret 0.5.0;
This is The minimum version of Solidity required is noted at the top of the contract: pragma solidity ^0.5.0;. The pragma
command means "additional information that only the compiler cares about",
while the caret symbol (^) means "the version indicated or higher".
Like JavaScript, statements are terminated with semicolons.
we will create our first contract now by writing
contract Adoption {
}
Solidity is a statically-typed language, meaning data types like strings, integers, and arrays must be defined.
Solidity has a unique type called an address. Addresses are Ethereum addresses, stored as 20 byte values.
Every account and smart contract on the Ethereum blockchain has an address and can send and receive Ether to and from this address.
we will add the variable on the next line after contract Adoption {.
address[16] public adopters;
here We've defined a single variable: adopters. This is an array of Ethereum addresses.
Arrays contain one type and can have a fixed length. In this case the type is address and the length is 16.
You'll also notice adopters is public. Public variables have automatic getter methods,
but in the case of arrays a key is required and will only return a single value.
Now, we'll write a function to fill the address in adopters array.
function adopt(uint petId) public returns (uint) {
In Solidity the types of both the function parameters and output must be specified.
In this case we'll be taking in a petId (integer) and returning an integer.
We will check to make sure petId is in range of our adopters array.
Arrays in Solidity are indexed from 0, so the ID value will need to be between 0 and 15.
We use the require() statement to ensure the ID is within range.
require(petId >= 0 && petId <= 15);
If the ID is in range, we then add the address that made the call to our adopters array.
The address of the person or smart contract who called this function is denoted by msg.sender.
adopters[petId] = msg.sender;
Finally, we return the petId provided as a confirmation.
return petId;
Now we are going to write second function, Retrieving the adopters
array getters return only a single value from a given key. Our UI needs to update all pet adoption statuses,
but making 16 API calls is not ideal. So our next step is to write a function to return the entire array
we will make function getAdopters, make it public,
The view keyword in the function declaration means that the function will not modify the state of the contract.
Since adopters is already declared, we can simply return it.
Be sure to specify the return type (in this case, the type for adopters) as address[16] memory.
memory gives the data location for the variable.
Now that we have written our smart contract, the next steps are to compile it.
Solidity is a compiled language, meaning we need to compile our Solidity to bytecode for the Ethereum Virtual Machine (EVM) to execute.
Open the terminal, and we will write truffle compile
You should see output similar to the this.
Now that we've successfully compiled our contracts, it's time to migrate them to the blockchain!
A migration is a deployment script meant to alter the state of your application's contracts, moving it from one state to the next. For the first migration, you might just be deploying new code, but over time, other migrations might move data around or replace a contract with a new one.
You'll see one JavaScript file already in the migrations/ directory: 1_initial_migration.js. This handles deploying the Migrations.sol contract to observe subsequent smart contract migrations, and ensures we don't double-migrate unchanged contracts in the future.
Now we are ready to create our own migration script. Create a new file named 2_deploy_contracts.js in the migrations/ directory.
Before we can migrate our contract to the blockchain, we need to have a blockchain running. For this tutorial, we're going to use Ganache, a personal blockchain for Ethereum development you can use to deploy contracts, develop applications, and run tests. If you haven't already, download Ganache and double click the icon to launch the application. This will generate a blockchain running locally on port 7545.
Back in our terminal, migrate the contract to the blockchain.
truffle migrate
You should see output similar to the following:
You can see the migrations being executed in order, followed by some information related to each migration. (Your information will differ.)
In Ganache, note that the state of the blockchain has changed. The blockchain now shows that the current block, previously 0, is now 4. In addition, while the first account originally had 100 ether, it is now lower, due to the transaction costs of migration. We'll talk more about transaction costs later.
You've now written your first smart contract and deployed it to a locally running blockchain. It's time to interact with our smart contract now to make sure it does what we want.
Truffle is very flexible when it comes to smart contract testing, in that tests can be written either in JavaScript or Solidity. In this tutorial, we'll be writing our tests in Javascript using the Chai and Mocha libraries.
Create a new file named testAdoption.test.js in the test/ directory.
Add the following content to the testAdoption.test.js file:
We start the contract by importing : * Adoption: The smart contract we want to test. We begin our test by importing our Adoption contract using artifacts.require.
Note: When writing this test, our callback function take the argument accounts. This provides us with the accounts available on the network when using this test.
Then, we make use of the before to provide initial setups for the following: * Adopt a pet with id 8 and assign it to the first account within the test accounts on the network. * This function later is used to check whether the petId: 8 has been adopted by accounts[0].
### Testing the adopt function
To test the adopt function, recall that upon success it returns the given adopter. We can ensure that the adopter based on given petID was returned and is compared with the expectedAdopter within the adopt function.
Add the following function within the testAdoption.test.js test file, after the declaration of before code block.
We call smart contract method adopters to see what address adopted the pet with petID 8.
Truffle imports Chai for the user so we can use the assert functions. We pass the actual value, the expected value and a failure message (which gets printed to the console if the test does not pass) to assert.equal().
### Testing retrieval of all pet owners
Since arrays can only return a single value given a single key, we create our own getter for the entire array.
Add this function below the previously added function in testAdoption.test.js.
Since adopters is an array, and we know from the first adoption test that we adopted the pet with petId 8, we are comparing the contract's address with the address that we expect to find.
Now that we've created the smart contract, deployed it to our local test blockchain and confirmed we can interact with it via the console, it's time to create a UI so that Pete has something to use for his pet shop!
Included with the pet-shop Truffle Box was code for the app's front-end. That code exists within the src/ directory.
The front-end doesn't use a build system (webpack, grunt, etc.) to be as easy as possible to get started. The structure of the app is already there; we'll be filling in the functions which are unique to Ethereum. This way, you can take this knowledge and apply it to your own front-end development.
Instantiating web3¶
Open /src/js/app.js in a text editor.
Examine the file. Note that there is a global App object to manage our application, load in the pet data in init() and then call the function initWeb3(). The web3 JavaScript library interacts with the Ethereum blockchain. It can retrieve user accounts, send transactions, interact with smart contracts, and more.
Remove the multi-line comment from within initWeb3
irst, we check if we are using modern dapp browsers or the more recent versions of MetaMask where an ethereum provider is injected into the window object. If so, we use it to create our web3 object, but we also need to explicitly request access to the accounts with ethereum.enable().
If the ethereum object does not exist, we then check for an injected web3 instance. If it exists, this indicates that we are using an older dapp browser (like Mist or an older version of MetaMask). If so, we get its provider and use it to create our web3 object.
If no injected web3 instance is present, we create our web3 object based on our local provider. (This fallback is fine for development environments, but insecure and not suitable for production.)
Now that we can interact with Ethereum via web3, we need to instantiate our smart contract so web3 knows where to find it and how it works. Truffle has a library to help with this called @truffle/contract. It keeps information about the contract in sync with migrations, so you don't need to change the contract's deployed address manually.
Still in /src/js/app.js, remove the multi-line comment from within initContract
We first retrieve the artifact file for our smart contract. Artifacts are information about our contract such as its deployed address and Application Binary Interface (ABI). The ABI is a JavaScript object defining how to interact with the contract including its variables, functions and their parameters.
Once we have the artifacts in our callback, we pass them to TruffleContract(). This creates an instance of the contract we can interact with.
With our contract instantiated, we set its web3 provider using the App.web3Provider value we stored earlier when setting up web3.
We then call the app's markAdopted() function in case any pets are already adopted from a previous visit. We've encapsulated this in a separate function since we'll need to update the UI any time we make a change to the smart contract's data.
Still in /src/js/app.js, remove the multi-line comment from markAdopted and write the following
We access the deployed Adoption contract, then call getAdopters() on that instance.
We first declare the variable adoption Instance outside of the smart contract calls so we can access the instance after initially retrieving it.
Using call() allows us to read data from the blockchain without having to send a full transaction, meaning we won't have to spend any ether.
After calling getAdopters(), we then loop through all of them, checking to see if an address is stored for each pet. Since the array contains address types, Ethereum initializes the array with 16 empty addresses. This is why we check for an empty address string rather than null or other falsey value.
Once a petId with a corresponding address is found, we disable its adopt button and change the button text to "Success", so the user gets some feedback.
Still in /src/js/app.js, remove the multi-line comment from handleAdopt and write the following:
We use web3 to get the user's accounts. In the callback after an error check, we then select the first account.
From there, we get the deployed contract as we did above and store the instance in adoptionInstance. This time though, we're going to send a transaction instead of a call. Transactions require a "from" address and have an associated cost. This cost, paid in ether, is called gas. The gas cost is the fee for performing computation and/or storing data in a smart contract. We send the transaction by executing the adopt() function with both the pet's ID and an object containing the account address, which we stored earlier in account.
The result of sending a transaction is the transaction object. If there are no errors, we proceed to call our markAdopted() function to sync the UI with our newly stored data.
Now we're ready to use our dapp!
The easiest way to interact with our dapp in a browser is through MetaMask, a browser extension for both Chrome and Firefox.
If you already use Metamask, you'll need to switch accounts. Before doing that, make sure that you have your personal secret phrase backed up, since you'll need it to log back into your personal account.
Install MetaMask in your browser.
Once installed, a tab in your browser should open displaying the following:
After clicking Getting Started, you should see the initial MetaMask screen. Click Import Wallet.
Next, you should see a screen requesting anonymous analytics. Choose to decline or agree.
In the box marked Wallet Seed, enter the mnemonic that is displayed in Ganache.
Enter a password below that and click OK.
If all goes well, MetaMask should display the Congratulations screen. Click All Done.
Now we need to connect MetaMask to the blockchain created by Ganache. Click the menu that shows "Main Network" and select Custom RPC.
In the box titled "New Network" enter http://127.0.0.1:7545, in the box titled "Chain ID" enter 1337 (Default Chain ID for Ganache) and click Save.
The network name at the top will switch to say http://127.0.0.1:7545.
Click the top-right X to close out of Settings and return to the Accounts page.
Each account created by Ganache is given 100 ether.
Configuration is now complete.
We can now start a local web server and use the dapp. We're using the lite-server library to serve our static files. This shipped with the pet-shop Truffle Box, but let's take a look at how it works.
Open bs-config.json in a text editor (in the project's root directory) and examine the contents:
This tells lite-server which files to include in our base directory. We add the ./src directory for our website files and ./build/contracts directory for the contract artifacts.
We've also added a dev command to the scripts object in the package.json file in the project's root directory. The scripts object allows us to alias console commands to a single npm command. In this case we're just doing a single command, but it's possible to have more complex configurations. Here's what yours should look like:
This tells npm to run our local install of lite-server when we execute npm run dev from the console.
npm run dev
The dev server will launch and automatically open a new browser tab containing your dapp.
A MetaMask pop-up should appear requesting your approval to allow Pete's Pet Shop to connect to your MetaMask wallet. Without explicit approval, you will be unable to interact with the dapp. Click Connect.
To use the dapp, click the Adopt button on the pet of your choice.
You'll be automatically prompted to approve the transaction by MetaMask. Click Submit to approve the transaction.
You'll see the button next to the adopted pet change to say "Success" and become disabled, just as we specified, because the pet has now been adopted.
If the button doesn't automatically change to say "Success", refreshing the app in the browser should trigger it.
And in MetaMask, you'll see the transaction listed:
You'll also see the same transaction listed in Ganache under the "Transactions" section.
Congratulations! You have taken a huge step to becoming a full-fledged dapp developer. For developing locally, you have all the tools you need to start making more advanced dapps. If you'd like to make your dapp live for others to use, stay tuned for our future tutorial on deploying to the Ropsten testnet.
This tutorial will take you through the process of building your first dapp---an adoption tracking system for a pet shop!
This tutorial is meant for those with a basic knowledge of Ethereum and smart contracts, who have some knowledge of HTML and JavaScript, but who are new to dapps.
In this tutorial we will be covering:
Setting up the development environment
Creating a Truffle project using a Truffle Box
Writing the smart contract
Compiling and migrating the smart contract
Testing the smart contract
Creating a user interface to interact with the smart contract
Interacting with the dapp in a browser.
Pete Scandlon of Pete's Pet Shop is interested in using Ethereum as an efficient way to handle their pet adoptions. The store has space for 16 pets at a given time, and they already have a database of pets. As an initial proof of concept, Pete wants to see a dapp which associates an Ethereum address with a pet to be adopted.
The website structure and styling will be supplied. Our job is to write the smart contract and front-end logic for its usage.
Truffle is a world class development environment, testing framework and asset pipeline for blockchains using the Ethereum Virtual Machine (EVM), aiming to make life as a developer easier. With Truffle, you get:
Built-in smart contract compilation, linking, deployment and binary management.
Automated contract testing for rapid development.
Scriptable, extensible deployment & migrations framework.
Network management for deploying to any number of public & private networks.
Package management with EthPM & NPM, using the ERC190 standard.
Interactive console for direct contract communication.
Configurable build pipeline with support for tight integration.
External script runner that executes scripts within a Truffle environment.