ToDo List Ethereum Dapp (Step5) | Build a smart contract client with Truffle Contract

This tutorial is part of the series ToDo List Ethereum Dapp. It is the Step 5. Tutorials already published:

In the last episode of this series we used web3 to setup a basic infrastructure to communicate with the blockchain from the frontend. That’s useful, but web3 only allow us to hit the native APIs of Ethereum.

In this tutorial we will use the Truffle Contract npm package to parse our smart contract and build a javascript object capable of calling the functions of our smart contract.

Under the hood, Truffle Contract will still use web3 to transport requests to the Ethereum blockchain.

IMPORTANT: the below instructions assume you have completed this series until step4. If that is not the case, you can simply start from the code of step4. For this, download the repo of eattheblocks, copy paste the special-episode-1/step4 folder to special-episode-1/step5 and start from there.

Fix web3 version

Unfortunately I realized that the newer versions of web3 (1.0+) have some compatibility issues with Truffle Contract, so we will downgrade it.

Install the web3 npm package as a dev dependency (you will understand why its a dev dependency in the next tutorial when we refactor with babel):

npm install -D web3@0.19.0

Now, overwrite app/vendor/web3.min.js by node_modules/web3/dist/web3.min.js.

Finally, in app/js/index.js, replace this:

web3 = new Web3('http://localhost:8545');  

By this:

web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:9545'));  

Install Truffle Contract

We are going to install a specific version of Truffle Contract which is compatible with the version of web3 we are using:

npm install -D truffle-contract@3.0.1

Then copy and paste the minified version of the source code:

cp node_modules/truffle-contract/dist/truffle-contract.min.js app/vendor

By the way, Truffle Contract used to have its own repo on Github, but it has been moved to the main repo of Truffle, following a decision of the Truffle team to adopt the monorepo approach. The old version of Truffle we installed is only available in the old repo. But with the npm installation you should not need to look there anyway.

Now add Truffle Contract to the index.html file, just below web3:

<script src="app/js/vendor/web3.min.js"></script>
<script src="app/js/vendor/truffle-contract.min.js"></script>

Import the compiled artifact of the smart contract

We need to access the compiled artifact of the smart contract from the frontend. For now we will just follow the easiest way which is to copy and paste the artifact into our javascript file. Yes, that’s not very elegant, but we will improve on that during the next video.

Let’s first start a truffle console with a local development blockchain running:

truffle develop

Then deploy the contract with the migrate command, executed inside the truffle console just started before:

migrate

Now you should have a compiled artifact in build/contract/ToDo.json. Copy this file into app/index.js, and assign the json object to a variable:

artifact = {
  "contractName": "ToDo",
  "abi": [
    {
   ...
   ...

Its critical that you copy this file AFTER running migrations, otherwise the networks key containing the address of the deployed smart contract will be empty.

Create contract abstraction

A contract abstraction is a generic object that knows about the functions a specific smart contract, and can create contract instances.

Let’s create a Truffle Contract abstraction using the artifact variable we just created. We will also set the web3 provider. Later when we will create a contract instance, this web3 provider will be the transport used to communicate with the blockchain:

abstraction = new TruffleContract(artifact);
abstraction.setProvider(web3.currentProvider);

Create a contract instance

A contract abstraction only knows about the functions of a smart contract, but it cannot communicate with any deployed instance of a smart contract. For this we need a contract instance. We will create a contract instance using:

  • the contract abstraction we just created
  • the address of the deployed smart contract.

First we need to find the address of the deployed instance of our smart contract on the blockchain. For this we will use the compiled artifact that we imported into our javascript file before. One of the entry of the json object contains all the addresses of the deployed instances of the smart contract. Let’s grab the address of the first deployed smart contract:

network = Object.keys(artifact.networks)[0];                                                                       
address = artifact.networks[network].address;  

Then we use this address to create a contract instance:

abstraction.at(address)
.then((todo) => {
  console.log(todo);
});

Then open a new terminal window and start the nodejs server that will serve the frontend:

npm start

Now, you can load the frontend in a new browser tab at http://localhost:3000.

Open the Javascript console. You should something similar to this:

TruffleContract {constructor: ƒ, abi: Array(5), contract: h, TaskCreated: ƒ, createTask: ƒ, …}

You can now delete the console.log() statement.

Test that the contract instance work

We want to make sure that the contract instance we just created is actually able to communicate with the blockchain.

For that, execute the getTaskIds() of the smart contract, using the todo variable we just created:

abstraction.at(address)
.then((todo) => {
  todo.getTaskIds()
  .then((taskIds) => {
    console.log(taskIds);
  });
});

You should see an empty array [] in the Javascript console.

Congrats, you can now call the functions of our smart contract with web3 and Truffle Contract! In the next video we will refactor our code with ES6/7 and babel.

Leave a Reply

Your email address will not be published. Required fields are marked *