Create your Blockchain DApp with Ethereum and VueJS – Tutorial Part 1
In this first part of the tutorial we are going to create the smart contract that handles the registration of users; then we are going to deploy the smart contract to the blockchain using Truffle.
If you missed the introduction and you want to know what this tutorial is about, please read the intro.
This part of tutorial is divided into three sections:
- Set up of the truffle environment.
- Smart contract development.
- Deploy the smart contract to the blockchain.
Note before you start: if you are using Windows you must use Power Shell as terminal.
Set up of the truffle environment
First let’s create the project folder called ethereum-vuejs-dapp
, then open the terminal in the folder just created and run the following command:
$ truffle init
This command initializes the truffle project and creates the following items:
- contracts: folder containing the smart contracts written in Solidity.
- migrations: folder containing the files that take care of the deployment.
- test: folder containing the files for testing the smart contracts.
- truffle.js: file that contains the list of blockchain networks where you can deploy your contracts.
Let’s add the details of our blockchain network to the file truffle.js
. So first start Ganache and, once it runs, check the host and the port as shown below.
Now paste the following code in truffle.js
:
module.exports = {
networks: {
ganache: {
host: "127.0.0.1",
port: 7545,
network_id: "*"
}
}
};
IMPORTANT: make sure that the host and the port of the code pasted in truffle.js
match with the settings displayed in Ganache.
Smart contract development
As described in the introduction, the main features of our dApp are:
- Let users resister their profiles.
- The owner of a profile is the only person who can edit his own information.
The following information of a user’s profile is going to be stored in the blockchain:
- Name of the owner.
- Status.
- When the profile has been created and updated.
What we need is to store the list of the users and associate each user with an account address (or wallet address).
The smart contract must provide a set of functions that:
- Let the user register his profile.
- Let the owner of a profile update his details.
- Get the list of users and their details.
- Check if the user is already registered.
Below is the code of the smart contract (you can find it on GitHub as well).
pragma solidity ^0.5.0;
contract Users {
// data structure that stores a user
struct User {
string name;
bytes32 status;
address walletAddress;
uint createdAt;
uint updatedAt;
}
// it maps the user’s wallet address with the user ID
mapping (address => uint) public usersIds;
// Array of User that holds the list of users and their details
User[] public users;
// event fired when an user is registered
event newUserRegistered(uint id);
// event fired when the user updates his status or name
event userUpdateEvent(uint id);
// Modifier: check if the caller of the smart contract is registered
modifier checkSenderIsRegistered {
require(isRegistered());
_;
}
/**
* Constructor function
*/
constructor() public
{
// NOTE: the first user MUST be emtpy: if you are trying to access to an element
// of the usersIds mapping that does not exist (like usersIds[0x12345]) you will
// receive 0, that’s why in the first position (with index 0) must be initialized
addUser(address(0x0), “", “");
// Some dummy data
addUser(address(0x333333333333), “Leo Brown", “Available");
addUser(address(0x111111111111), “John Doe", “Very happy");
addUser(address(0x222222222222), “Mary Smith", “Not in the mood today");
}
/**
* Function to register a new user.
*
* @param _userName The displaying name
* @param _status The status of the user
*/
function registerUser(string memory _userName, bytes32 _status) public
returns(uint)
{
return addUser(msg.sender, _userName, _status);
}
/**
* Add a new user. This function must be private because an user
* cannot insert another user on behalf of someone else.
*
* @param _wAddr Address wallet of the user
* @param _userName Displaying name of the user
* @param _status Status of the user
*/
function addUser(address _wAddr, string memory _userName, bytes32 _status) private
returns(uint)
{
// checking if the user is already registered
uint userId = usersIds[_wAddr];
require (userId == 0);
// associating the user wallet address with the new ID
usersIds[_wAddr] = users.length;
uint newUserId = users.length++;
// storing the new user details
users[newUserId] = User({
name: _userName,
status: _status,
walletAddress: _wAddr,
createdAt: now,
updatedAt: now
});
// emitting the event that a new user has been registered
emit newUserRegistered(newUserId);
return newUserId;
}
/**
* Update the user profile of the caller of this method.
* Note: the user can modify only his own profile.
*
* @param _newUserName The new user’s displaying name
* @param _newStatus The new user’s status
*/
function updateUser(string memory _newUserName, bytes32 _newStatus) checkSenderIsRegistered public
returns(uint)
{
// An user can modify only his own profile.
uint userId = usersIds[msg.sender];
User storage user = users[userId];
user.name = _newUserName;
user.status = _newStatus;
user.updatedAt = now;
emit userUpdateEvent(userId);
return userId;
}
/**
* Get the user’s profile information.
*
* @param _id The ID of the user stored on the blockchain.
*/
function getUserById(uint _id) public view
returns(
uint,
string memory,
bytes32,
address,
uint,
uint
) {
// checking if the ID is valid
require( (_id > 0) || (_id <= users.length) );
User memory i = users[_id];
return (
_id,
i.name,
i.status,
i.walletAddress,
i.createdAt,
i.updatedAt
);
}
/**
* Return the profile information of the caller.
*/
function getOwnProfile() checkSenderIsRegistered public view
returns(
uint,
string memory,
bytes32,
address,
uint,
uint
) {
uint id = usersIds[msg.sender];
return getUserById(id);
}
/**
* Check if the user that is calling the smart contract is registered.
*/
function isRegistered() public view returns (bool)
{
return (usersIds[msg.sender] > 0);
}
/**
* Return the number of total registered users.
*/
function totalUsers() public view returns (uint)
{
// NOTE: the total registered user is length-1 because the user with
// index 0 is empty check the contructor: addUser(address(0x0), “", “");
return users.length - 1;
}
}
Deploy the smart contract to the blockchain
It’s time to deploy the smart contract to the blockchain! Make sure that your blockchain is running and the file truffle.js
is properly set as explained before.
Go to the folder migration and create a file called 2_migrate_users.js
.
The migration filename has a number as prefix and a description as suffix. The numbered prefix is required in order to record whether the migration ran successfully and the suffix just describes what the file is about.
Copy and paste the following code inside the file 2_migrate_users.js
:
var Users = artifacts.require("./Users.sol");
module.exports = function(deployer) {
deployer.deploy(Users);
};
Now let’s open the terminal in the project folder ethereum-vuejs-dapp
and run the command:
$ truffle console ––network ganache
Once the truffle console is running, type the following command:
>> migrate ––reset ––compile-all
This command compiles all smart contracts and deploys the smart contracts to the blockchain.
If everything went fine, on the console you should see a message as follows:
Compiling .\contracts\Migrations.sol... Compiling .\contracts\Users.sol... Writing artifacts to .\build\contracts Using network 'ganache'. Running migration: 1_initial_migration.js Replacing Migrations... ... 0x18edd24941e9b7edfae4966af544d5413e31622da90cecae2d3153635a7ffba2 Migrations: 0xcac26201ab3b38d2f0f9b56f81a8897dfe036da6 Saving successful migration to network... ... 0x125c70f37e143b13acb4827dda16e8571758402db81c08a3a2ae27573910105f Saving artifacts... Running migration: 2_migrate_users.js Replacing Users... ... 0x043c2cf363da321b8a1ec06672f12fd794bf894342fa51100250bc6975806385 Users: 0x782b9ce19fe792ed3c4ccbfb439ab59ddc5369f2 Saving successful migration to network... ... 0x9e56386f94093c4f56f6b84190503376363f15a6d16661e7bfaa8fefe1b4be1f Saving artifacts... truffle(ganache)>
After the deployment you will see on Ganache some new transactions in the transaction list.
In the second part of the tutorial we will build the dApp interface using Vue JS and interact with the smart contracts through the interface.