Lesson 6 of 14
In Progress

Interacting with Deployed Smart Contracts using Web3.js

Smart contracts are self-executing contracts with the terms of the agreement between buyer and seller being directly written into lines of code. They are stored on the Ethereum blockchain and can be interacted with through the use of Web3.js, a JavaScript library that allows developers to interact with the Ethereum blockchain. In this chapter, we will cover the basics of interacting with deployed smart contracts using Web3.js.

Setting Up Your Project

Before we can start interacting with smart contracts, we need to set up a project and install the necessary dependencies.

First, create a new project directory and initialize npm by running the following command:

$ mkdir my-project
$ cd my-project
$ npm init -y

Next, install Web3.js by running the following command:

$ npm install web3

Now that we have Web3.js installed, we can start interacting with smart contracts.

Retrieving a Smart Contract’s ABI and Address

The ABI (Application Binary Interface) of a smart contract is a JSON object that contains information about the contract’s methods and events. The contract’s address is the location on the Ethereum blockchain where it is stored.

To retrieve a smart contract’s ABI and address, you will need to know the contract’s address or the name of the contract’s artifact file. If you do not have the contract’s address or artifact file, you will need to deploy the contract to the Ethereum blockchain first.

Once you have the contract’s address or artifact file, you can retrieve the ABI and address using the following code:

const Web3 = require('web3');
const web3 = new Web3();

const contractAddress = '0x...'; // Replace with contract address
const contractAbi = require('../build/contracts/MyContract.json').abi; // Replace with path to artifact file

const contract = new web3.eth.Contract(contractAbi, contractAddress);

Calling Smart Contract Methods

Now that we have a contract instance, we can call its methods. To call a method, you will need to know the name of the method and the parameters it requires. You can find this information in the contract’s ABI.

To call a method, use the call() method of the contract instance:

const result = await contract.methods.myMethod(param1, param2).call();
console.log(result);

Sending Transactions to Smart Contracts

In addition to calling methods, you can also send transactions to smart contracts. This is useful for modifying the state of the contract or triggering an event.

To send a transaction, you will need to sign the transaction with the private key of an Ethereum account. You can use the sendTransaction() method of the contract instance to do this:

const privateKey = '0x...'; // Replace with private key
const account = web3.eth.accounts.privateKeyToAccount(privateKey);

const result = await contract.methods.myMethod(param1, param2).send({ from: account.address });
console.log(result);

Listening for Smart Contract Events

Smart contracts can emit events when certain actions occur. To listen for events, you can use the events property of the contract instance.

To listen for events, use the on() method of the events property:

contract.events.MyEvent({}, (error, event) => {
  console.log(event);
});

You can also specify filters to only listen for specific events. For example, you can filter by the event’s parameters or by the address of the contract that emitted the event.

contract.events.MyEvent({ filter: { param1: 'value1' } }, (error, event) => {
  console.log(event);
});

Conclusion

In this chapter, we covered the basics of interacting with deployed smart contracts using Web3.js. We learned how to retrieve a contract’s ABI and address, how to call and send transactions to contract methods, and how to listen for contract events. With this knowledge, you can start building decentralized applications (DApps) that interact with smart contracts on the Ethereum blockchain.

Exercises

To review these concepts, we will go through a series of exercises designed to test your understanding and apply what you have learned.

Write a function that retrieves the balance of an Ethereum account.

async function getAccountBalance(address) {
  const balance = await web3.eth.getBalance(address);
  return balance;
}

Write a function that sends a transaction to a contract method and returns the transaction receipt.

async function sendTransaction(privateKey, contract, method, params) {
  const account = web3.eth.accounts.privateKeyToAccount(privateKey);
  const result = await contract.methods[method](...params).send({ from: account.address });
  return result;
}

Write a function that listens for a specific event emitted by a contract and returns the event data.

async function listenForEvent(contract, eventName, filters) {
  return new Promise((resolve, reject) => {
    contract.events[eventName](filters, (error, event) => {
      if (error) {
        reject(error);
      } else {
        resolve(event);
      }
    });
  });
}

Write a function that retrieves the value of a public variable in a contract.

async function getPublicVariable(contract, variableName) {
  const value = await contract.methods[variableName]().call();
  return value;
}

Write a function that deploys a contract to the Ethereum blockchain and returns the contract’s address.

async function deployContract(privateKey, contractAbi, bytecode, params) {
  const account = web3.eth.accounts.privateKeyToAccount(privateKey);
  const contract = new web3.eth.Contract(contractAbi);
  const deployedContract = await contract.deploy({ data: bytecode, arguments: params }).send({ from: account.address });
  return deployedContract.options.address;
}