What is Web3.js - An Introduction Into the Web3.js Libraries

What is Web3.js - An Introduction Into the Web3.js Libraries

There's been a lot of hype around web3.js.

In this article, we'll learn what the technologies web3.js and ethers.js are, and how they're used to interact with the Ethereum blockchain.

We'll also learn how to get started using the web3.js library, the main JavaScript library to interact with the Ethereum blockchain.

Overview of the article

  1. What is web3.js?

  2. Web3.js vs ethers.js.

  3. How to run JavaScript code in web3.

  4. What is web3.js used for?

Without further delay, let's dive into the world of web3.js; let's thoroughly understand what it means and how to implement it in our smart contracts programs.

What is Web3.js?

Web3.js is a collection of libraries that allow you to interact with a local or remote Ethereum node using HTTP, IPC, or WebSocket.

Web3.js allows you to develop websites or clients that interact with the blockchain. For example, it allows you to send ether from one account to another, read and write data from smart contracts, create smart contracts, and so much more!

The following documentation will guide you through installing and running web3.js, as well as providing API reference documentation with examples.

There are a few different aspects to developing blockchain applications with Ethereum:

  • Smart contract development - writing code that gets deployed to the blockchain with the Solidity programming language.

  • Developing websites or clients that interact with the blockchain - writing code that reads and writes data from the blockchain with smart contracts.

If you have a web development background, you might have used jQuery to make Ajax calls to a web server. That's a good starting point to understand the function of web3.js. Instead of using jQuery to read and write data from a web server, you can use web3.js to read and write to the Ethereum blockchain.

Below is a diagram to illustrate how web3.js interacts with the Ethereum blockchain:

web3-connect-with-ethereum-node

Image credit: iotbl.

Web3.js vs ethers.js

Both web3.js and ethers.js are Ethereum JavaScript Libraries.

Ether.js is developed and maintained by Rick Moore – A Canadian developer.

Web3.js is developed and maintained by the Ethereum Foundation. So, there is wider support for web3.js, as more developers are behind it.

One major difference between ethers.js and web3.js is how they handle key management and interaction with the Ethereum blockchain.

Web3.js assumes that there is a local node connected to the application. It's assumed that the node to stores keys, signs transactions, and reads and interacts with the Ethereum blockchain. In reality, this is not often the case — most users are not running geth locally. Metamask effectively emulates that environment through a browser application, so most web3 apps require Metamask to hold keys, sign transactions, and interact with the ethereum mainnet.

On the other hand, ethers.js takes a different approach that we believe gives developers more flexibility. Ethers.js separates the "node" into two separate roles:

  • A "wallet" that holds keys and signs transactions, and
  • A "provider" that serves as an anonymous connection to the ethereum network, checking state and sending transactions.

The 2 main advantages of ethers.js that comes to mind are:

  1. ENS names are first-class citizens.
  2. Key management and state - separation of concerns.

How to run JavaScript code in Web3.js

To run Javascript code in web3.js, you need to get web3.js into your project. This can be done using the following methods:

Dependencies

There are a few dependencies that will help you start developing with web3.js.

Node Package Manager (NPM)

The first dependency we need is Node Package Manager, or NPM, which comes with Node.js. To check if you have Node already installed, go to your terminal and type:

node -v

Web3.js Library

You can install the Web3.js library with NPM in your terminal like this:

npm install web3

Or using Yarn:

yarn add web3

Infura RPC URL

To connect to an Ethereum node with JSON RPC on the mainnet, we need access to an Ethereum node. There are a few ways you could do this.

One way you could do this is by running your own Ethereum node with Geth or Parity. But this requires you to download a lot of data from the blockchain and keep it in sync. This is a huge headache if you've never tried to do this before.

Mostly for convenience, you can use Infura to access an Ethereum node without having to run one yourself. Infura is a service that provides a remote Ethereum node for free. All you need to do is sign up, and obtain an API key and the RPC URL for the network you want to connect to. Once you've signed up, your Infura RPC URL should look like this:

https://mainnet.infura.io/YOUR_INFURA_API_KEY

What is web3.js used for?

Web3.js can be used in the frontend and backend to check account balances, read data from the blockchain, make transactions, and even deploy smart contracts.

1. Checking Account Balances with web3.js

Now that all of your dependencies are installed, let's walk through how you can check your account balance with web3.js. First, you should fire up the Node console in your terminal like this:

node

Now you've got the Node console open! Inside the Node console, you can require web3.js like this:

const Web3 = require('web3');

Now, you have access to a variable where you can create a new web3 connection. Before we generate a web3 connection, we must first assign the Infura URL to a variable like this:

const rpcURL = "https://mainnet.infura.io/YOUR_INFURA_API_KEY";

Make sure that you replace `` YOUR_INFURA_API_KEY "with your actual Infura API key that you obtained earlier. Now you can instantiate a Web3 connection like this:

const web3 = new Web3(rpcURL);

Now, you have a live web3 connection that will allow you to talk to the Ethereum mainnet. Let's use this connection to check the account balance for this account: 0x105cb19ba40384a8f2985816DA7883b076969cA7. We can see how much Ether this account holds by checking its balance with web3.eth.getBalance().

The first step, let's assign the address to a variable:

const address = "0x105cb19ba40384a8f2985816DA7883b076969cA7";

Let's now check the account balance like this:

 web3.eth.getBalance(address, (err, wei) => {
  balance = web3.utils.fromWei(wei, 'ether')
})

And that's it! That's how you check your account balance with web3.js.

Here is a summary of the code we wrote in this tutorial:

const Web3 = require('web3')
const rpcURL = '' // Your RPC URL goes here
const web3 = new Web3(rpcURL)
const address = '' // Your account address goes here
web3.eth.getBalance(address, (err, wei) => {
  balance = web3.utils.fromWei(wei, 'ether')
});

First, we use to check the balance by calling web3.eth.getBalance(), which accepts a callback function with two arguments, an error and the balance itself. We'll ignore the error argument for now, and reference the balance with the wei argument. Ethereum expresses balances in wei, which is the smallest subdivision of ether, kind of like a tiny penny. We can convert this balance to ether with web3.utils.fromWei(wei, 'ether');.

2. Read data from the smart contract with web3.js

In this section, we'll briefly learn how to read smart contract data from the Ethereum blockchain.

In order to read data from smart contracts with web3.js, we need two things:

  1. A JavaScript representation of the smart contract we want to interact with.
  2. A way to call the functions on the smart contract when reading the data.

We can get a JavaScript representation of an Ethereum smart contract with the "web3.eth.Contract() "function.

This function expects two arguments: one for the smart contract ABI and one for the smart contract address.

A smart contract ABI stands for "Abstract Binary Interface", and it's a JSON array that describes how a specific smart contract works.

Here is an example of an ABI:

const abi = [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_releaseTime","type":"uint256"}],"name":"mintTimelocked","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]

I know that seems like a really long, unbroken array. Don't worry if it looks overwhelming. This example is the ABI for the OmiseGo token, which implements the ERC-20 token standard. You can find more details about this token, including its ABI and address on Etherscan. We'll use this smart contract ABI for the rest of the examples.

While we're here, I'll go ahead and store the address to the OMG token from the Ethereum mainnet:

const address = "0xd26114cd6EE289AccF82350c8d8487fedB8A0C07";

Now that we have both of these values assigned, we can create a complete JavaScript representation of the OMG token smart contract like this:

const contract = new web3.eth.Contract(abi, address);

Now that the first part of this lesson is complete, we need to fulfill the second part: reading data from the smart contract by calling its functions. All of the smart contract functions are listed under the contract.methods namespace within the assigned Web3 contract. For example, we can call contract.methods.myFunction() if the contract implements myFunction().

Great! So we can theoretically call any function that the smart contract implements. But how do we know which functions it implements? For one, we could log contract.methods to the console, and see what's returned. However, since this smart contract implements the ERC-20 standard, we know that it implements several functions like totalSupply(), name(), symbol(), and balanceOf(). We can read each of those values individually, like this:

First, the total supply of all OMG tokens in existence:

contract.methods.totalSupply().call((err, result) => { console.log(result) });
// > 140245398

Second, the name of the OMG token:

contract.methods.name().call((err, result) => { console.log(result) });
// > OMG Token

Last, we can check the balance for a given account. I looked for a OMG holder on Etherscan and found this address "0xd26114cd6EE289AccF82350c8d8487fedB8A0C07 ".

We can check the balance for this account like this:

contract.methods.balanceOf('0xd26114cd6EE289AccF82350c8d8487fedB8A0C07').call((err, result) => { console.log(result) });
// > Some large number...

And that's it! That's how easy it is to read data from smart contracts with web3.js. So far, we've been able to check the account balance from the smart contract with web3.js. Now, we have to read data from the smart contract by calling its functions. All of the smart contract functions are listed under the contract.methods namespace within the assigned web3 contract. For example, we can call contract.methods.myFunction() if the contract implements myFunction().

Great! So we can theoretically call any function that the smart contract implements. But how do we know which functions it implements? For one, we could log contract.methods to the console, and see what's returned. However, since this smart contract implements the ERC-20 standard, we know that it implements several functions like totalSupply(), name(), symbol(), and balanceOf().

We can check each of those values individually, like this:

First, the total supply of all OMG tokens in existence:

contract.methods.totalSupply().call((err, result) => { console.log(result) });
// > 140245398

Second, the name of the OMG token:

contract.methods.name().call((err, result) => { console.log(result) });
// > OMG Token

Last, we can check the balance for a given account. I looked for an OMG holder on Etherscan and found this address "0xd26114cd6EE289AccF82350c8d8487fedB8A0C07 ".

We can check the balance for this account like this:

contract.methods.balanceOf('0xd26114cd6EE289AccF82350c8d8487fedB8A0C07').call((err, result) => { console.log(result) });
// > Some large number...

And that's it! That's how you read data from smart contracts with web3.js.

Here is a summary of all the code from this section:

const Web3 = require('web3');
const rpcURL = '' // Your RCP URL goes here const web3 = new Web3(rpcURL)
const web3 = new Web3(rpcURL);
const abi = [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_releaseTime","type":"uint256"}],"name":"mintTimelocked","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]
const address = '0xd26114cd6EE289AccF82350c8d8487fedB8A0C07' ;
const contract = new web3.eth.Contract(abi, address); 
contract.methods.totalSupply().call((err, result) => { console.log(result) }); 
contract.methods.name().call((err, result) => { console.log(result) }); 
contract.methods.symbol().call((err, result) => { console.log(result) });
contract.methods.balanceOf('0xd26114cd6EE289AccF82350c8d8487fedB8A0C07').call((err, result) =>
{ console.log(result) }); // > Some large number...

3. Create an Ethereum transaction with web3.js

This section will show you how to create transactions on the Ethereum blockchain with web3.js. You'll see what happens when an Ethereum transaction is created, and how to broadcast a transaction manually to the network with web3.js.

Additionally to learning web3.js, the purpose of this article is to help you understand the fundamentals of how transactions work on the Ethereum blockchain. Whenever you create a transaction, you're writing data to the blockchain and updating its state. There are several ways to do this, like sending ether from one account to another, calling a smart contract function that writes data, and deploying a smart contract to the blockchain. We can get a greater understanding of these concepts by performing these actions with the web3.js library and observing how each step works.

In order to broadcast transactions to the network, we'll need to sign them first. I'm going to use an additional JavaScript library to do this called ethereumjs-tx. You can install this dependency from the command line like this:

 npm install ethereumjs-tx

The reason we're going to use this library is that we want to sign all of the transactions locally. If we were running our own Ethereum node locally, we could unlock an account that was stored locally and sign all of our transactions locally. If that were the case, we wouldn't necessarily need to use this library. However, we're using a remote node hosted by Infura in this tutorial. While Infura is a trustworthy service, we still want to sign the transactions locally rather than giving the remote node manage our private keys.

That's exactly what we'll do in this article. We'll create the raw transaction, sign it, then send the transaction and broadcast it to the network.

Let's start with creating a simple index.js file to run the code in this lesson, instead of doing everything in the console.

Inside the index.js file, we'll first require the newly installed library like this:

const Tx = require('ethereumjs-tx')

Next, we'll set up a web3 connection as we did in the previous section:

const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/YOUR_INFURA_API_KEY')

Notice that we're using the Ropsten test network, which is different from the Ethereum mainnet that we used in the previous section. We'll use a test network because all transactions cost gas in the form of ether. We can use fake ether on the Ropsten test net without worrying about spending any money. You can obtain fake ether from a faucet on the Ropsten test network, or the Metamask faucet.

We are going to create a transaction that sends fake ether from one account to another. In order to do this, we'll need two accounts and their private keys.

You can actually create new accounts with web3.js like this:

web3.eth.accounts.create()
// > {
//    address: "0xb8CE9ab6943e0eCED004cDe8e3bBed6568B2Fa01",
//    privateKey: "0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709",
//    signTransaction: function(tx){...},
//    sign: function(data){...},
//    encrypt: function(password){...}
// };

Once you have created both of these accounts, make sure you load them up with fake ether from a faucet. Now, we'll assign their public keys to variables in our script like this:

const account1 = '0xb8CE9ab6943e0eCED004cDe8e3bBed6568B2Fa01';
const account2 = '0xb8CE9ab6943e0eCED004cDe8e3bBed6568B2Fa02';

Note: Be sure to use the accounts you generated, as these accounts won't work for this lesson. Now, let's save the private keys to the environment like this:

const privateKey1 = Buffer.from(process.env.PRIVATE_KEY_1); 
const privateKey1 = Buffer.from(process.env.PRIVATE_KEY_2);

We have now got all of our variables set up. I know some of this might be a little confusing at this point. Stick with me, it will all make sense shortly.

From this point, we want to do a few things:

  1. Build a transaction object.
  2. Sign the transaction.
  3. Broadcast the transaction to the network.

We can build the transaction object like this:

const txObject = {
    nonce:    web3.utils.toHex(txCount),
    to:       account2,
    value:    web3.utils.toHex(web3.utils.toWei('0.1', 'ether')),
    gasLimit: web3.utils.toHex(21000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei'))
  };

In this code, we're building an object that has all the values needed to generate a transaction, like nonce, to, value, gasLimit, and gasPrice.

Let's break down each of these values:

  • nonce - this is the previous transaction count for the given account. We'll assign the value of this variable momentarily. We also must convert this value to hexadecimal. We can do this with the web3.js utility web3.utils.toHex().

  • to - the account we're sending ether to.

  • value - the amount of ether we want to send. This value must be expressed in wei and converted to hexadecimal. We can convert the value to wei with the web3.js utility web3.utils.toWei().

  • gasLimit - this is the maximum amount of gas consumed by the transaction. A basic transaction like this always costs 21000 units of gas, so we'll use that for the value here.

  • gasPrice - this is the amount we want to pay for each unit of gas. I'll use 10 Gwei here.

Note, that there is no form field in this transaction object. That will be inferred whenever we sign this transaction with account1's private key.

Now let's assign the value for the nonce variable. We can get the transaction nonce with web3.eth.getTransactionCount() function. We'll wrap all of our code inside a callback function like this:

web3.eth.getTransactionCount(account1, (err, txCount) => {
  const txObject = {
    nonce:    web3.utils.toHex(txCount),
    to:       account2,
    value:    web3.utils.toHex(web3.utils.toWei('0.1', 'ether')),
    gasLimit: web3.utils.toHex(21000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei'))
  }
})

Like this, we've finished building the transaction object! Now we're going to sign the transaction. We can do that like this:

const tx = new Tx(txObject)
tx.sign(privateKey1)

const serializedTx = tx.serialize()
const raw = '0x' + serializedTx.toString('hex')

Here we used the etheremjs-tx library to create a new "Tx object ". We also use this library to sign the transaction with "privateKey1 ". Next, we serialize the transaction and convert it to a hexadecimal string so that it can be passed to web3. Finally, we send this signed serialized transaction to the test network with the web3.eth.sendSignedTransaction() function like this:

web3.eth.sendSignedTransaction(raw, (err, txHash) => {
  console.log('txHash:', txHash)
});

This is the final step of this lesson that sends the transaction and broadcasts it to the network. At this point, your completed index.js file should look like this:

var Tx     = require('ethereumjs-tx')
const Web3 = require('web3')
const web3 = new Web3('https://ropsten.infura.io/YOUR_INFURA_API_KEY')

const account1 = '' // Your account address 1
const account2 = '' // Your account address 2

const privateKey1 = Buffer.from('YOUR_PRIVATE_KEY_1', 'hex')
const privateKey2 = Buffer.from('YOUR_PRIVATE_KEY_2', 'hex')

web3.eth.getTransactionCount(account1, (err, txCount) => {
  // Build the transaction
  const txObject = {
    nonce:    web3.utils.toHex(txCount),
    to:       account2,
    value:    web3.utils.toHex(web3.utils.toWei('0.1', 'ether')),
    gasLimit: web3.utils.toHex(21000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei'))
  }

  // Sign the transaction
  const tx = new Tx(txObject)
  tx.sign(privateKey1)

  const serializedTx = tx.serialize()
  const raw = '0x' + serializedTx.toString('hex')

  // Broadcast the transaction
  web3.eth.sendSignedTransaction(raw, (err, txHash) => {
    console.log('txHash:', txHash)
    // Now go check etherscan to see the transaction!
  })
});

You can then run the index.js file from your terminal with NodeJS like this:

node index.js

Or SImply run:

node index

Web3.js Utilities

There are some cool tips and tricks that you might not know about web3.js. Let's go ahead and set up the index.js and jump into taking a look at these tips. Let's connect to the Ethereum mainnet like this:

const Web3 = require('web3')
const web3 = new Web3('https://mainnet.infura.io/YOUR_INFURA_API_KEY')

First, you can actually get the average gas price currently for the network like this:

web3.eth.getGasPrice().then((result) => {
  console.log(web3.utils.fromWei(result, 'ether')
});

Let's say you've developed on the blockchain before, you have probably dealt with hashing functions. Web3.js has a lot of built-in helpers for using hashing functions.

You have direct access to the sha3 function like this:

console.log(web3.utils.sha3('Hashnode blog'));

Or as keccack256 :

console.log(web3.utils.keccak256('Hashnode blog'));

You can also handle (pseudo) randomness by generating a 32-byte random hex like this:

console.log(web3.utils.randomHex(32));

In any case, have you ever found yourself trying to perform an action on a JavaScript array or object, and needed the help of an external library? Thankfully, web3.js ships with the underscoreJS library:

const _ = web3.utils._
_.each({ key1: 'value1', key2: 'value2' }, (value, key) => {
  console.log(key)
});

And that's it! Those are some fancy tips and tricks you can use with web3.js. Here is the complete tutorial code for this lesson:

const Web3 = require('web3')
const web3 = new Web3('https://mainnet.infura.io/YOUR_INFURA_API_KEY')

// Get average gas price in wei from last few blocks median gas price
web3.eth.getGasPrice().then((result) => {
  console.log(web3.utils.fromWei(result, 'ether')
})

// Use sha256 Hashing function
console.log(web3.utils.sha3('Hashnode blog'))

// Use keccak256 Hashing function (alias)
console.log(web3.utils.keccak256('Dapp University'))

// Get a Random Hex
console.log(web3.utils.randomHex(32))

// Get access to the underscore JS library
const _ = web3.utils._

_.each({ key1: 'value1', key2: 'value2' }, (value, key) => {
  console.log(key)
});

Now you can run the index.js file from your terminal with NodeJS like this:

node index.js

Or SImply run:

node index

Conclusion

In this article, we learned what the web3.js library is all about. We had an introduction to web3.js and ethers.js, their differences and what they're used for.

We also learned how we can use web3.js to check account balances, read data from smart contracts, and how use web3.js to create Ethereum transactions.

We also briefly took a look at some web3.js tips and tricks.

To learn more about NFTs, dApps, the blockchain and other web3 content, check out Hashnode’s web3 blog.