This tutorial is part of the series ToDo List Ethereum Dapp. It is the Step 5. Tutorials already published:
- Intro
- Step 1: Writing The ToDo Smart contracts- beginning
- Step 2: Writing The ToDo Smart contracts – end
- Step 3: Writing The Nodejs Backend
- Step 4: Setup the frontend and read account data
- Step 5: Build a smart contract client with Truffle Contract (This tutorial)
- Step 6: Refactor With Webpack, ES6 and truffle-solidity-loader
- Step 7: Read Contract data from Frontend
- Step 8: Create smart contract data from frontend
- Step 9: Toggle task done & keep frontend updated
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.
I have followed your tutorial for ToDo list Dapp but i got some error can you please resolve it?
truffle(develop)> migrate
TypeError: Contracts.compile is not a function
at Object.run (/home/sheetal/.nvm/versions/node/v8.0.0/lib/node_modules/truffle/build/webpack:/packages/truffle-core/lib/commands/migrate.js:167:1)
at Command.run (/home/sheetal/.nvm/versions/node/v8.0.0/lib/node_modules/truffle/build/webpack:/packages/truffle-core/lib/command.js:113:1)
at Console.interpret (/home/sheetal/.nvm/versions/node/v8.0.0/lib/node_modules/truffle/build/webpack:/packages/truffle-core/lib/console.js:139:1)
at ReplManager.interpret (/home/sheetal/.nvm/versions/node/v8.0.0/lib/node_modules/truffle/build/webpack:/packages/truffle-core/lib/repl.js:109:1)
Do you have the Migration file?
And make sure it's deploying the Todo.sol file.