© Wei-Meng Lee 2019
W.-M. LeeBeginning Ethereum Smart Contracts Programminghttps://doi.org/10.1007/978-1-4842-5086-0_8

8. Using the web3.js APIs

Wei-Meng Lee1 
(1)
Ang Mo Kio, Singapore
 

In the previous chapters, you have learned the basics of Smart Contracts and how to deploy them onto the blockchain. So far, all interactions with the Smart Contracts have been through the Remix IDE. While the Remix IDE provides an easy way for developers to test their Smart Contracts, it is not suitable for use by end users. To allow end users to interact with your Smart Contracts, you need to build front end that hides the complexity of interacting with the Smart Contracts in the back end. For this purpose, you need an API.

In this chapter, you will learn how to interact with Smart Contracts using the web3.js APIs. Using the web3.js APIs, you can build front ends (such as web pages, Node.js applications, etc.) to interact with Smart Contracts.

What Is web3.js?

The web3.js is a collection of libraries that allow you to interact with a local or remote Ethereum node, using HTTP, WebSocket, or IPC. Through the web3.js APIs, your front end can then interact with the Smart Contracts. The web3.js APIs contain the following modules:
  • web3-eth – For the Ethereum blockchain and smart contracts

  • web3-shh – For the whisper protocol to communicate p2p and broadcast

  • web3-bzz – For the swarm protocol, the decentralized file storage

  • web3-utils – Contains useful helper functions for DApp developers.

For this book, we will only focus on the first module, the web3-eth.

Installing web3.js

Installing web3.js requires Node.js. Specifically, you will make use of npm to download the web3.js APIs onto your local computer.

Tip

For more information on installing Node.js, check out the following page: https://nodejs.org/en/download/ .

For this chapter, we shall create a folder named web3projects to store the web3.js APIs. In Terminal, type the following commands:
$ cd ~
$ mkdir web3projects
$ cd web3projects
Before you download the web3.js APIs, you want to create an empty Node.js project:
$ npm init --yes
The preceding command creates a file named package.json. This file contains the dependencies required by a Node.js application. To download the web3.js APIs, type the following command:
$ npm install [email protected] --save

Tip

Creating the package.json file will prevent npm from showing pages of warning and error messages when you install web3.js.

The --save option informs npm to modify the package.json file and add the web3.js as a dependency for the application.

The web3projects folder should now have a folder named node_modules. Within this node_modules folder, you will see a number of folders, all of which make up the suites of APIs that is web3.js.

Testing the web3.js Using MetaMask

With the web3.js downloaded, let’s now test it and understand how it works. Create a text file named TestWeb3.html and save it in the web3projects folder. Populate it as follows:
<!DOCTYPE html>
<html lang="en">
<script src="./node_modules/web3/dist/web3.min.js"></script>
<body>
    <script>
        if (typeof web3 !== 'undefined') {
            // this statement is executed if you are using
            // MetaMask
            async function enableAccounts() {
                await ethereum.enable();
                .then((account) => {
                    alert("Account: " + account + " " +
                       "Provider Name: " +
                       web3.currentProvider.constructor.name);
                })
            }
            enableAccounts();
        } else {
            // set the provider you want from Web3.providers
            web3 = new Web3(
                new Web3.providers.HttpProvider(
                "http://localhost:8545"));
            alert("Account: " + web3.eth.accounts[0] + " " +
                "Provider Name: " +
                web3.currentProvider.constructor.name);
        }
    </script>
</body>
</html>
In Terminal, type the following command:
$ npm install -g serve

Tip

Installing the serve application globally using the -g option may require sudo permission. Alternatively, you can also install it locally within the current directory without using the -g option.

The preceding command installs a web server on the local computer. Typing the serve command in any directory will enable the directory to serve its content through the web server.

In the web3projects folder, type the following command:
$ serve

Using the Chrome browser (with MetaMask installed), load the following URL: http://localhost:5000/TestWeb3.html.

You will see the alert shown in Figure 8-1. Click Connect.
../images/471881_1_En_8_Chapter/471881_1_En_8_Fig1_HTML.jpg
Figure 8-1

You need to give permission to the page to allow it to access your MetaMask account(s)

You should now see the alert as shown in Figure 8-2.
../images/471881_1_En_8_Chapter/471881_1_En_8_Fig2_HTML.jpg
Figure 8-2

The web3 object connecting to MetaMask

Let’s now understand how this works. First, in your JavaScript code, you first check if web3 is undefined:
        if (typeof web3 !== 'undefined') {
            // this statement is executed if you are using
            // MetaMask;
            async function enableAccounts() {
                await ethereum.enable()
                .then((account) => {
                    alert("Account: " + account + " " +
                       "Provider Name: " +
                       web3.currentProvider.constructor.name);
                })
            }
            enableAccounts();
        } else {

If you load this page through HTTP on a browser with MetaMask installed, MetaMask will automatically inject the web3 object. This web3 object allows you to interact with an Ethereum node. In this case, it connects to the MetaMask extension on your Chrome browser.

Using the MetaMask extension, you can obtain the address of the accounts. But before the MetaMask extension exposes the accounts, you need to enable it using the ethereum.enable() function , like this:
            async function enableAccounts() {
                await ethereum.enable()
                .then((account) => {
                    alert("Account: " + account + " " +
                       "Provider Name: " +
                       web3.currentProvider.constructor.name);
                })
            }
            enableAccounts();

When the user has approved the request to connect to the accounts, you can now get the account address and display it in the alert box.

The account object always returns the account you selected in the MetaMask extension in the browser. You can also get the name of the provider using the web3 object.

Testing the web3.js Without MetaMask

What happens if you load the TestWeb3.html page using a non-MetaMask supported browser or if you do not load it using HTTP (i.e., you load the page directly onto the browser)? In this case, the web3 object will be undefined and the else block will now be executed:
        if (typeof web3 !== 'undefined') {
            ...
        } else {
            // set the provider you want from Web3.providers
            web3 = new Web3(
                new Web3.providers.HttpProvider(
                "http://localhost:8545"));
            alert("Account: " + web3.eth.accounts[0] + " " +
                "Provider Name: " +
                web3.currentProvider.constructor.name);
        }

A good solution would be to manually connect to another Ethereum node, such as Ganache. And that’s what you will do next.

In Terminal, type the following command to launch Ganache:
$ ganache-cli

Note

Refer to Chapter 7 if you are not familiar with Ganache.

You should see the following:
Ganache CLI v6.4.2 (ganache-core: 2.5.4)
Available Accounts
==================
(0) 0xd5e7d5437cd6279444049ae1b6424737ced0aafe (~100 ETH)
(1) 0xf2bbf643e4a4a6e878eba39f61d353b6a59ad893 (~100 ETH)
(2) 0x26cd848844ca333af7cf8dde0cb1609644eb7b99 (~100 ETH)
(3) 0xdc648ffb58ce6ed2ba4675dfa984f243ac1c0756 (~100 ETH)
(4) 0xe819726440d2c986aef42f9134cd6ee157b31f54 (~100 ETH)
(5) 0x6bef68ce964fe0f7c63894a5bbce58858aba0b33 (~100 ETH)
(6) 0xac6432f160e01731f314bd6506b72446fc95bbc6 (~100 ETH)
(7) 0x55715f224052096b24e3ef2bba71c7f181d35905 (~100 ETH)
(8) 0x1f717912faab85131592439c2c00a7469990bdc9 (~100 ETH)
(9) 0x2adba1a8b9130c112994837fbe3d7595674e8814 (~100 ETH)
...
Now, load the TestWeb3.html page using either one of the following methods:
  • Load the page directly using any web browser.

  • Load the page using HTTP on any non-MetaMask supported web browser.

In any of the preceding methods, the web3 object will now connect to Ganache, as shown in Figure 8-3.
../images/471881_1_En_8_Chapter/471881_1_En_8_Fig3_HTML.jpg
Figure 8-3

The web3 object connecting to Ganache

This is because our JavaScript specifically connects to the local Ethereum node listening at port 8545:
            web3 = new Web3(
                new Web3.providers.HttpProvider(
                "http://localhost:8545"));

Tip

For security reasons, MetaMask would only inject the web3 object if the page is loaded using HTTP.

To get the current account address, you could simply specify web3.eth.accounts[0].

Deploying Contracts Using web3.js

The next thing we want to use the web3.js for is to deploy a Smart Contract. For this example, we shall use the same Smart Contract that we have developed in the previous chapter:
pragma solidity ^0.5.1;
contract ProofOfExistence {
  mapping (bytes32 => bool) private proofs;
  // store a proof of existence in the contract state
  function storeProof(bytes32 proof) private {
    proofs[proof] = true;
  }
  // calculate and store the proof for a document
  function notarize(string memory document) public {
    storeProof(proofFor(document));
  }
  // helper function to get a document's sha256
  function proofFor(string memory document) private
  pure returns (bytes32) {
    return sha256(bytes(document));
  }
  // check if a document has been notarized
  function checkDocument(string memory document) public
  view returns (bool) {
    return proofs[proofFor(document)];
  }
}
Using the Remix IDE, we can get the ABI and the bytecode of the Smart Contract. The ABI is
[ { "constant": true, "inputs": [ { "name": "document", "type": "string" } ], "name": "checkDocument", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, "inputs": [ { "name": "document", "type": "string" } ], "name": "notarize", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" } ]
And the bytecode is
608060405234801561001057600080fd5b5061033b806100206000396000f3
fe608060405260043610610046576000357c01000000000000000000000000
...
83815260200190815260200160002060006101000a81548160ff0219169083
151502179055505056fea165627a7a72305820273793d02d6109c94bde87c3
d7330575e077c3409d42a3188dcbbadeb54a18260029
We want to deploy this Smart Contract onto the Ropsten testnet, through the use of MetaMask. To do so using web3.js, create a new text file named DeployContract.html (save it in the web3projects folder) and populate it as follows:
<!DOCTYPE html>
<html lang="en">
<script src="./node_modules/web3/dist/web3.min.js"></script>
<body>
    <script>
        let account = "";
        if (typeof web3 !== 'undefined') {
            // this statement is executed if you are using
            // MetaMask;
            async function enableAccounts() {
                await ethereum.enable()
                .then((account) => {
                    account = account;
                })
            }
            enableAccounts();
        } else {
            // set the provider you want from Web3.providers
            web3 = new Web3(
                new Web3.providers.HttpProvider(
                "http://localhost:8545"));
            account = web3.eth.accounts[0];
        }
        let bytecode = '0x608060405234801561001057600080fd5b5061033e806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806353fb92331461003b5780637183616c1461010e575b600080fd5b6100f46004803603602081101561005157600080fd5b810190808035906020019064010000000081111561006e57600080fd5b82018360208201111561008057600080fd5b803590602001918460018302840111640100000000831117156100a257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506101c9565b604051808215151515815260200191505060405180910390f35b6101c76004803603602081101561012457600080fd5b810190808035906020019064010000000081111561014157600080fd5b82018360208201111561015357600080fd5b8035906020019184600183028401116401000000008311171561017557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506101fa565b005b60008060006101d78461020e565b815260200190815260200160002060009054906101000a900460ff169050919050565b61020b6102068261020e565b6102b5565b50565b60006002826040518082805190602001908083835b602083106102465780518252602082019150602081019050602083039250610223565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610288573d6000803e3d6000fd5b5050506040513d602081101561029d57600080fd5b81019080805190602001909291905050509050919050565b600160008083815260200190815260200160002060006101000a81548160ff0219169083151502179055505056fea265627a7a72305820a8142eeb58bdc8f3137d990c2e6f31f571e6fff3d8e1ef8881e6a71de963198e64736f6c637828302e352e31312d6e696768746c792e323031392e362e32352b636f6d6d69742e31636338343735330058';
        let abi = [ { "constant": true, "inputs": [ { "name": "document", "type": "string" } ], "name": "checkDocument", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, "inputs": [ { "name": "document", "type": "string" } ], "name": "notarize", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" } ];
        let contract = web3.eth.contract(abi);
        web3.eth.estimateGas({data: bytecode},
            function(error, result){
                if (!error){
                    contract.new(
                        {
                            from : account,
                            data : bytecode,
                            gas : result
                        }, function (err, contract) {
                            if (err) {
                                alert(err);
                                return;
                            } else if (contract.address){
                                alert('Contract address: '
                                    + contract.address);
                            }
                    });
                } else {
                    alert('err = ' + error);
                }
            }
        );
    </script>
</body>
</html>
As you can observe from the preceding code, we did the following:
  • Connect to the Ethereum node.

  • Get the primary account associated with the node.

  • Declare a variable containing the bytecode of the contract and another variable containing the ABI of the contract.

  • Use the web3.eth.contract() function to create a contract using the ABI of the contract.

  • Use the web3.eth.estimateGas() function to estimate the gas required to deploy the contract onto the blockchain.

  • Once the gas estimate is obtained, use the new() function to deploy the contract. You need to pass in the following – the account to use for deploying the contract, the bytecode of the contract, and the gas estimate (maximum amount of gas allowed).

  • Once the contract is deployed, you can now print out the address of the contract

Let’s test the page to see if it works. Using Chrome, load the page using this URL: http://localhost:5000/DeployContract.html. Once the page is loaded, you should see MetaMask prompting you to confirm the transaction (see Figure 8-4). Note the estimated gas needed to deploy the contract is 0.000272 ETH. Click CONFIRM.
../images/471881_1_En_8_Chapter/471881_1_En_8_Fig4_HTML.jpg
Figure 8-4

Deploying the contract through MetaMask

After a while, once the block containing the transaction is mined, you will see the alert showing you the address of the contract (see Figure 8-5).
../images/471881_1_En_8_Chapter/471881_1_En_8_Fig5_HTML.jpg
Figure 8-5

Our contract has been deployed and with its address shown

In this example, the contract address is 0x044063558d41F47cC9e1CE4B8637638a278D30aA.

Interacting with a Contract Using web3.js

In the previous section, you saw how you used web3.js to deploy a Smart Contract onto the Ethereum blockchain. Besides using it to deploy contract, web3.js is often used to build front ends so that users can interact with your Smart Contract directly. And hence in this section, you will learn how to use web3.js to interact with your newly deployed contract. For our illustration, we shall build a web front end.

Create a new text file and name it as main.css. Populate the file with the following:
body {
    background-color:#F0F0F0;
    padding: 2em;
    font-family: 'Raleway','Source Sans Pro', 'Arial';
}
.container {
    width: 95%;
    margin: 0 auto;
}
label {
    display:block;
    margin-bottom:10px;
    font-weight: bold;
}
input {
    padding:10px;
    width: 100%;
    margin-bottom: 1em;
}
button {
    margin: 2em 0;
    padding: 1em 4em;
    display:block;
    font-size: medium;
}
#result {
    padding:1em;
    background-color:#fff;
    margin: 1em 0;
}
This file will serve as the CSS for the web front end that you will build next. Create a new text file and name it as DocumentNotarizer.html (save it in the web3projects folder). Populate it with the following:
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document Notarizer</title>
    <link rel="stylesheet" type="text/css" href="main.css">
    <script src="./node_modules/web3/dist/web3.min.js">
    </script>
</head>
<body>
    <div class="container">
        <h1>Document Notarizer</h1>
        <label class="col-lg-2 control-label">
        Document to notarize</label>
        <input id="document1" type="text">
        <button id="btnNotarize">Notarize</button>
        <label class="col-lg-2 control-label">
        Check Document</label>
        <input id="document2" type="text">
        <button id="btnCheck">Check</button>
        <label class="col-lg-2 control-label">Status</label>
        <h2 id="result"></h2>
    </div>
    <script src=
        "https://code.jquery.com/jquery-3.2.1.slim.min.js">
    </script>
    <script>
        if (typeof web3 !== 'undefined') {
            // this statement is executed if you are using
            // MetaMask
            async function enableAccounts() {
                await ethereum.enable()
            }
            enableAccounts();
        } else {
            // set the provider you want from Web3.providers
            web3 = new Web3(
                new Web3.providers.HttpProvider(
                "http://localhost:8545"));
        }
        let abi = [ { "constant": true, "inputs": [ { "name": "document", "type": "string" } ], "name": "checkDocument", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, "inputs": [ { "name": "document", "type": "string" } ], "name": "notarize", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" } ];
        var contract = web3.eth.contract(abi);
        var notarizer = contract.at(
            '0x044063558d41F47cC9e1CE4B8637638a278D30aA');
        $("#btnNotarize").click(function() {
            notarizer.notarize($("#document1").val(),
            (error, result) => {
                $("#result").html(result);
            });
        });
        $("#btnCheck").click(function() {
            notarizer.checkDocument($("#document2").val(),
            (error, result) => {
                if(!error) {
                    $("#result").html(result.toString());
                } else
                    console.error(error);
            });
        });
    </script>
</body>
</html>
In Terminal, ensure that the serve command is still running (if not, type serve in the web3projects folder). Load the Chrome web browser with the following URL: http://localhost:5000/DocumentNotarizer.html. You should see the page as shown in Figure 8-6.
../images/471881_1_En_8_Chapter/471881_1_En_8_Fig6_HTML.jpg
Figure 8-6

The web front end to interact with the Smart Contract

Enter a string in the first text box and then click the Notarize button. You should see the pop-up by MetaMask (see Figure 8-7).
../images/471881_1_En_8_Chapter/471881_1_En_8_Fig7_HTML.jpg
Figure 8-7

Confirming the transaction to send the string to the Smart Contract for notarization

Click CONFIRM to confirm the transaction. When the transaction is sent, you will immediately see the transaction hash displayed at the bottom of the page (see Figure 8-8).
../images/471881_1_En_8_Chapter/471881_1_En_8_Fig8_HTML.jpg
Figure 8-8

The transaction hash is displayed at the bottom of the page

Once the block containing the transaction is mined, you will be able to type the same string in the second text box and then click the Check button to verify if the same string was previously stored on the blockchain. If the string was saved previously, you should see true in the bottom of the screen (see Figure 8-9).
../images/471881_1_En_8_Chapter/471881_1_En_8_Fig9_HTML.jpg
Figure 8-9

Verifying if a string was previous stored on the blockchain

Let’s see how the code works. First, when the Notarize button is clicked, you call the notarize() function of the contract (which is called notarizer) and pass it the value of the text box:
            notarizer.notarize($("#document1").val(),
            (error, result) => {
                $("#result").html(result);
            });

Notice that you pass in a callback function to the notarize() function so that when the transaction is confirmed by the user, you can get the transaction hash, which is then displayed in the label at the bottom of the page.

Likewise, to verify a string, you call the checkDocument() function with the string to verify, together with the callback function:
            notarizer.checkDocument($("#document2").val(),
            (error, result) => {
                if(!error) {
                    $("#result").html(result.toString());
                } else
                    console.error(error);
            });

When the result is returned back to you, you will display it in the label.

Sending Ethers to Smart Contracts

Our ProofOfExistence contract provides a free service to let people notarize their documents on the blockchain (users just need to pay for gas required to write data onto the blockchain).

In a real commercial setting, you might want to charge for this service. For example, anytime a user wants to write to the blockchain, you want to charge a service fee. In the following example, you will modify the contract so that calls to the notarize() function require a payment of 1 Ether.

For simplicity, you shall deploy the contract from the Remix IDE onto the Ropsten testnet directly (instead of using the web3.js). Here is the modified contract (in bold):
pragma solidity ^0.5.1;
contract ProofOfExistence {
  mapping (bytes32 => bool) private proofs;
  // store a proof of existence in the contract state
  function storeProof(bytes32 proof) private {
    proofs[proof] = true;
  }
  // calculate and store the proof for a document
  function notarize(string memory document) public payable {
    require(msg.value == 1 ether);
    storeProof(proofFor(document));
  }
  // helper function to get a document's sha256
  function proofFor(string memory document) private
  pure returns (bytes32) {
    return sha256(bytes(document));
  }
  // check if a document has been notarized
  function checkDocument(string memory document) public
  view returns (bool) {
    return proofs[proofFor(document)];
  }
}

The require() function in Solidity allows you to check for certain condition. In this particular example, it checks that the call to the notarize() function is accompanied with exactly 1 Ether. If not, the transaction will fail and all unused gas will be refunded back to the caller. Note that you must add the payable keyword to the end of the function declaration.

Let’s now deploy the contract using the Remix IDE (see Figure 8-10).
../images/471881_1_En_8_Chapter/471881_1_En_8_Fig10_HTML.jpg
Figure 8-10

Deploying the modified Smart Contract using the Remix IDE

When the contract is deployed, copy the address of the new contract. The address for the modified contract is now 0x3e3d5b0282c49d8e9e211b8fdc9225ec43d482c2.

Since the contract has been modified, you would also need to modify the DocumentNotarizer.html file. Add in the following statements in bold to the DocumentNotarizer.html file:
    ...
        if (typeof web3 !== 'undefined') {
            // this statement is executed if you are using
            // MetaMask
            async function enableAccounts() {
                await ethereum.enable()
            }
            enableAccounts();
        } else {
            // set the provider you want from Web3.providers
            web3 = new Web3(
                new Web3.providers.HttpProvider(
                "http://localhost:8545"));
        }
        let abi = [ { "constant": false, "inputs": [ { "name": "document", "type": "string" } ], "name": "notarize", "outputs": [], "payable": true, "stateMutability": "payable", "type": "function" }, { "constant": true, "inputs": [ { "name": "document", "type": "string" } ], "name": "checkDocument", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "view", "type": "function" } ];
        var contract = web3.eth.contract(abi);
        var notarizer = contract.at(
            '0x3e3d5b0282c49d8e9e211b8fdc9225ec43d482c2');
        $("#btnNotarize").click(function() {
            notarizer.notarize($("#document1").val(),
            {
              gas: 300000,
              from: web3.eth.accounts[0],
              value: 1000000000000000000
            },
            (error, result) => {
                $("#result").html(result);
            });
        });
        $("#btnCheck").click(function() {
            notarizer.checkDocument($("#document2").val(),
            (error, result) => {
                if(!error) {
                    $("#result").html(result.toString());
                } else
                    console.error(error);
            });
        });
   ...
There are three things that you need to modify:
  • The ABI of the new contract. The notarize() function now has a new signature, so the ABI must be updated.

  • The address of the newly deployed contract.

  • A JSON string containing the amount of Ether to be sent to the contract. Here, we specified that the maximum amount of gas required is 300000 (all unused gas will be refunded), and it is to be deducted from the account in the Ethereum node (such as MetaMask or Ganache). Finally, the amount of Ether to be sent to the contract is specified in Wei (1000000000000000000 Wei is equivalent to 1 Ether).

Once the HTML file is updated, load the Chrome browser with this URL: http://localhost:5000/DocumentNotarizer.html. As usual, enter a string to notarize and click the Notarize button. You will now see the pop-up from MetaMask (see Figure 8-11).
../images/471881_1_En_8_Chapter/471881_1_En_8_Fig11_HTML.jpg
Figure 8-11

Sending a payment of 1 Ether to the contract when you notarize a string

Observe that you will be sending 1 Ether to the contract, and the gas fee is 0.0003 Ether (based on the estimated 300,000 gas and gas price of 1 Gwei per unit). Click CONFIRM.

Tip

1 Ether = 1,000,000,000 Gwei, so 300,000 gas would cost 300,000,000,000,000 Gwei, which is equal to 0.0003 Ether. You can vary the price of gas in MetaMask by clicking the Edit button in Figure 8-11 and then clicking the Advanced tab (see Figure 8-12).

../images/471881_1_En_8_Chapter/471881_1_En_8_Fig12_HTML.jpg
Figure 8-12

Varying the price of gas in MetaMask

Once the transaction is confirmed and mined, you can check Etherscan to verify that 1 Ether has indeed been transferred to the contract (see Figure 8-13).
../images/471881_1_En_8_Chapter/471881_1_En_8_Fig13_HTML.jpg
Figure 8-13

Confirming the transaction on Etherscan

Summary

In this chapter, you learned how to use the web3.js APIs to interact with your Smart Contracts. You learned how to deploy Smart Contracts programmatically using web3.js. In addition, you also used the web3.js to build a web front end, and you saw how you can send Ethers to a Smart Contract.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.197.251