Appendix A: web3.js tutorial

Description

This tutorial is based on web3@1.0.0-beta.29 web3.js. It is intended as an introduction to web3.js.

The web3.js JavaScript library is a collection of modules which contain specific functionality for the Ethereum ecosystem, and an Ethereum compatible JavaScript API, which implements the Generic JSON RPC spec.

To run this script you don’t need to run your own local node, because it uses the Infura services.

web3.js contract basic interaction in a non-blocked (async) fashion

Check you have a valid npm version:

$ npm -v
5.6.0

If you haven’t initialize npm:

$ npm init

Install basic dependences:

npm i command-line-args
npm i web3
npm i node-rest-client-promise

This will update your package.json configuration file with your new dependences.

Node.js script execution

Basic execution

code/web3js/web3-contract-basic-interaction.js

Use your own Infura Token

code/web3js/web3-contract-basic-interaction.js --infuraFileToken /path/to/file/with/infura_token

or

code/web3js/web3-contract-basic-interaction.js /path/to/file/with/infura_token

Reviewing the demo script

Next, let’s review our demo script web3-contract-basic-interaction.

We use the Web3 object to obtain a basic web3 provider:

var web3 = new Web3(infura_host);

Next, let’s interact with web3 and try some basic functions. Let’s see the protocol version:

web3.eth.getProtocolVersion().then(function(protocolVersion) {
      console.log(`Protocol Version: ${protocolVersion}`);
  })

Now let’s look at the current gas price:

web3.eth.getGasPrice().then(function(gasPrice) {
      console.log(`Gas Price: ${gasPrice}`);
  })

Whats the last mined block in the current chain?

web3.eth.getBlockNumber().then(function(blockNumber) {
      console.log(`Block Number: ${blockNumber}`);
  })

Contract interaction

Now let’s try some basic interactions with a contract.

First, let’s initialize our contract address:

var our_contract_address = "0xd0A1E359811322d97991E03f863a0C30C2cF029C";

Let’s see its balance:

web3.eth.getBalance(our_contract_address).then(function(balance) {
      console.log(`Balance of ${our_contract_address}: ${balance}`);
})

Now let’s see its byte code:

web3.eth.getCode(our_contract_address).then(function(code) {
      console.log(code);
})

We prepare our environment to interact with the Etherscan explorer API.

Let’s initialize our contract url in the Etherscan explorer API for the Kovan chain:

var etherscan_url = `https://kovan.etherscan.io/api?module=contract&action=getabi&address=${our_contract_address}`

And let’s initialize a REST client to interact with the Etherscan API:

var client = require('node-rest-client-promise').Client();

Let’s get a client promise:

client.getPromise(etherscan_url)

Once we’ve got a valid client promise, we can get our contract ABI from the Etherscan API:

.then((client_promise) => {
  our_contract_abi = JSON.parse(client_promise.data.result);

And now we create our contract object as a promise to consume later.

  return new Promise((resolve, reject) => {
      var our_contract = new web3.eth.Contract(our_contract_abi, our_contract_address);
      try {
        // If all goes well
        resolve(our_contract);
      } catch (ex) {
        // If something goes wrong
        reject(ex);
      }
    });
})

If our contract promise returns successfully we can start interacting with it:

.then((our_contract) => {

Let’s see our contract address:

console.log(`Our Contract address:  ${our_contract._address}`);

or alternatively:

console.log(`Our Contract address in other way:  ${our_contract.options.address}`);

Now let’s query our contract abi:

console.log("Our contract abi: " + JSON.stringify(our_contract.options.jsonInterface));

Now let’s see our contract total supply using a callback:

our_contract.methods.totalSupply().call(function(err, totalSupply) {
    if (!err) {
        console.log(`Total Supply with a callback:  ${totalSupply}`);
    } else {
        console.log(err);
    }
});

Or we can use the returned Promise instead of passing in the callback:

our_contract.methods.totalSupply().call().then(function(totalSupply){
    console.log(`Total Supply with a promise:  ${totalSupply}`);
}).catch(function(err) {
    console.log(err);
});

Asynchronous operation with await

Now that you’ve seen the basic tutorial, we can try the same interactions using an asynchronous await construct. Review the web3-contract-basic-interaction-async-await.js script in code/web3js and compare it to this tutorial to see how they differ. Async-await is easier to read, as it makes the asynchronous interaction behave more like a sequence of blocking calls.