Skip to main content

web3.js

web3.js is a Javascript library for building on EVM-compatible networks.

It allows developers to interact with smart contracts, send transactions, and retrieve data from the network.

Installation​

info

This guide assumes you have the latest version of Node.js installed.

To install web3, run the following command:


_10
npm install web3

Initialization​

To use web3 in your project, start by importing the module and initializing your Web3 provider the desired Flow RPC endpoint.


_10
const { Web3 } = require('web3')
_10
const web3 = new Web3('https://previewnet.evm.nodes.onflow.org')

info

Currently, only Flow Previewnet is available. More networks are coming soon - see here for more info.

Interacting With Smart Contracts​

The web3 library allows developers to interact with smart contracts via the web3.eth.Contract API.

For this example we will use the following "Storage" contract, deployed on the Flow Previewnet to the address 0x4c7784ae96e7cfcf0224a95059573e96f03a4e70. However, if you wish to deploy your own contract, see the how to do so using Hardhat or Remix.


_14
// SPDX-License-Identifier: MIT
_14
pragma solidity ^0.8.0;
_14
_14
contract Storage {
_14
uint256 public storedData;
_14
_14
function store(uint256 x) public {
_14
storedData = x;
_14
}
_14
_14
function retrieve() public view returns (uint256) {
_14
return storedData;
_14
}
_14
}

The ABI for this contract can be generated using the solc compiler, or another tool such as Hardhat or Remix.

Now that we have both the ABI and address of the contract, we can create a new Contract object for use in our application.


_40
// Replace with the ABI of the deployed contract
_40
const abi = [
_40
{
_40
"inputs": [],
_40
"stateMutability": "nonpayable",
_40
"type": "constructor"
_40
},
_40
{
_40
"inputs": [
_40
{
_40
"internalType": "uint256",
_40
"name": "x",
_40
"type": "uint256"
_40
}
_40
],
_40
"name": "store",
_40
"outputs": [],
_40
"stateMutability": "nonpayable",
_40
"type": "function"
_40
},
_40
{
_40
"inputs": [],
_40
"name": "retrieve",
_40
"outputs": [
_40
{
_40
"internalType": "uint256",
_40
"name": "",
_40
"type": "uint256"
_40
}
_40
],
_40
"stateMutability": "view",
_40
"type": "function"
_40
}
_40
]
_40
_40
// Replace with the address of the deployed contract
_40
const contractAddress = "0x4c7784ae96e7cfcf0224a95059573e96f03a4e70"
_40
_40
// Create a new contract object with the ABI and address
_40
const contract = new web3.eth.Contract(abi, contractAddress)

Using this newly created object, we can now interact with the contract on the network.

Reading State​

Querying data from the contract is done using the call function with one of the contract's methods. This will not change the state and will not send a transaction.


_10
// Retrieve the current value stored in the contract
_10
// (this is using the `retrieve` method from the contract with no arguments)
_10
const result = await contract.methods.retrieve().call()
_10
_10
console.log(result) // "0" (if the contract has not been interacted with yet)

Changing State​

We can mutate the state of the contract by sending a transaction to the network.

In order to send a transaction to the network, you will need an account with sufficient funds to pay for the transaction.

info

If you do not have an account yet, you can create one using the following command from your project's root directory:


_10
node -e "console.log(require('web3').eth.accounts.create())"

For Flow Previewnet, you can fund your account using the Flow Faucet.

First, we will need to be able to sign a transaction using an account. To do this, we can use the privateKeyToAccount function to create an Web3Account object from the account's private key.


_10
// You must replace this with the private key of the account you wish to use
_10
const account = web3.eth.accounts.privateKeyToAccount('0x1234')

Then, we can sign a transaction using the user's account and send it to the network.


_15
const newValue = 1337 // Replace with any value you want to store
_15
_15
// Sign a transaction that stores a new value in the contract
_15
// (this is using the `store` method from the contract with the new value as an argument)
_15
let signed = await account.signTransaction({
_15
from: account.address,
_15
to: contractAddress,
_15
data: contract.methods.store(newValue).encodeABI(),
_15
gasPrice: 0,
_15
})
_15
_15
// Send signed transaction to the network
_15
const result = await web3.eth.sendSignedTransaction(signed.rawTransaction)
_15
_15
console.log(result) // { status: 1, transactionHash: '0x1234', ... }

Now that the transaction has been sent, the contract's state has been updated. We an verify this by querying the contract's state again.


_10
const result = await contract.methods.retrieve().call()
_10
console.log(result) // "1337"

For more information about using smart contracts in web3.js, see the official documentation.