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​
This guide assumes you have the latest version of Node.js installed.
To install web3
, run the following command:
_10npm install web3
Connecting to Flow​
To use web3
in your project, start by imporing the module and initializing your Web3 provider the desired Flow RPC endpoint.
_10const { Web3 } = require('web3')_10const web3 = new Web3('https://previewnet.evm.nodes.onflow.org')
Currently, only 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_14pragma solidity ^0.8.0;_14_14contract 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_40const 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_40const contractAddress = "0x4c7784ae96e7cfcf0224a95059573e96f03a4e70"_40_40// Create a new contract object with the ABI and address_40const 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)_10const result = await contract.methods.retrieve().call()_10_10console.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.
For Flow Previewnet, you can fund your account using the Flow Faucet. You will need to use the private key of the account to sign the transaction.
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 a private key.
_10// You must replace this with the private key of the account you wish to use_10const account = web3.eth.accounts.privateKeyToAccount('0x1234')
Then, we can sign a transaction using the user's account and send it to the network.
_15const 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)_15let 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_15const result = await web3.eth.sendSignedTransaction(signed.rawTransaction)_15_15console.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.
_10const result = await contract.methods.retrieve().call()_10_10console.log(result) // "1337"
For more information about using smart contracts in web3.js, see the official documentation.