diff --git a/docs/evm/tools/clients/web3-js.md b/docs/evm/tools/clients/web3-js.md index 3af823ea37..a9bd1558cf 100644 --- a/docs/evm/tools/clients/web3-js.md +++ b/docs/evm/tools/clients/web3-js.md @@ -6,20 +6,200 @@ sidebar_position: 2 # web3.js -:::info +[web3.js](https://web3js.org/) is a Javascript library for building on EVM-compatible networks. -## Coming Soon +It allows developers to interact with smart contracts, send transactions, and retrieve data from the network. -Documentation on using [web3.js](https://web3js.readthedocs.io/) to interact with smart contracts deployed on the FlowEVM network is currently under development and will be available shortly. +## Installation -web3.js is a comprehensive JavaScript library designed to facilitate interaction with EVM-compatible blockchain networks. Its integration with FlowEVM will enable developers to deploy, interact with smart contracts, and perform various blockchain operations within the Flow ecosystem seamlessly. +:::info +This guide assumes you have the latest version of [Node.js](https://nodejs.org/en) installed. +::: + +To install `web3` in your project, run the following command: + +```sh +npm install web3 +``` + +## Initializing Web3 With Flow + +To use `web3` in your project, start by importing the module and initializing your `web3` instance with the desired Flow RPC endpoint. We are specifying [Flow Previewnet](https://developers.flow.com/networks/flow-networks/accessing-previewnet) in this example. + +```js +const { Web3 } = require('web3') +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](../../build/networks.md). +::: + +## Querying The Blockchain + +`web3` provides a number of methods for querying the blockchain, such as getting the latest block number, querying account balances, and more. + +You can try using some of these methods to verify that your `web3` instance is working correctly. + +```js +// Get the latest block number +const blockNumber = await web3.eth.getBlockNumber() +console.log(blockNumber) // Latest block number + +// Get the balance of an account +const balance = await web3.eth.getBalance('0x1234') // Replace with any address +console.log(balance) // Balance in attoFlow + +// Get the chain ID +const chainId = await web3.eth.getChainId() +console.log(chainId) // 0x286 (Flow Previewnet) + +// Get the gas price +const gasPrice = await web3.eth.getGasPrice() +console.log(gasPrice) // Gas price in attoFlow +``` + +For more information about other queries you can make `web3`, please see the [official documentation](https://docs.web3js.org/). + +## 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`. Note that anyone can interact with this contract, as it is deployed on a public network, so state may not always be as expected. + +We recommend deploying your own contract, which can be done using [Hardhat](../../build/guides/deploy-contract/using-hardhat.md) or [Remix](../../build/guides/deploy-contract/using-remix.md). + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract Storage { + uint256 public storedData; + + function store(uint256 x) public { + storedData = x; + } + + function retrieve() public view returns (uint256) { + return storedData; + } +} +``` -Stay tuned for detailed guides on: +The ABI for this contract can be generated using the [`solc` compiler](https://docs.soliditylang.org/en/latest/installing-solidity.html), or another tool such as [Hardhat](../../build/guides/deploy-contract/using-hardhat.md) or [Remix](../../build/guides/deploy-contract/using-remix.md). -- Installing and setting up web3.js for your projects. -- Connecting to the FlowEVM network using web3.js. -- Reading and writing data to the blockchain. -- Deploying and interacting with smart contracts on FlowEVM. +Now that we have both the ABI and address of the contract, we can create a new `Contract` object for use in our application. -For the latest updates, please check back soon or join the [Flow Discord](https://discord.gg/flow) and visit the #evm channel. +```js +// Replace with the ABI of the deployed contract +const abi = [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "x", + "type": "uint256" + } + ], + "name": "store", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "retrieve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] + +// Replace with the address of the deployed contract +const contractAddress = "0x4c7784ae96e7cfcf0224a95059573e96f03a4e70" + +// Create a new contract object with the ABI and address +const contract = new web3.eth.Contract(abi, contractAddress) +``` + +We can now interact with the contract on the network by using the `contract` object. + +### Reading State + +State can be read from the contract by using the `call` function with one of the contract's methods. This will not change the state and will not send a transaction. + +```js +// Retrieve the current value stored in the contract +// (this is using the `retrieve` method from the contract with no arguments) +const result = await contract.methods.retrieve().call() + +console.log(result) // Current value stored in the contract +``` + +### 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: + +```sh +node -e "console.log(require('web3').eth.accounts.create())" +``` + +Note that this is not a secure way to generate an account, and you should use a more secure method in a production environment. + +For Flow Previewnet, you can fund your account using the [Flow Faucet](https://previewnet-faucet.onflow.org/fund-account). ::: + +We can use the `privateKeyToAccount` function to create an `Web3Account` object from our account's private key. + +```js +// You must replace this with the private key of the account you wish to use +const account = web3.eth.accounts.privateKeyToAccount('0x1234') +``` + +Then, we can sign a transaction using the user's account and send it to the network. + +```js +const newValue = 1337 // Replace with any value you want to store + +// Sign a transaction that stores a new value in the contract +// (this is using the `store` method from the contract with the new value as an argument) +let signed = await account.signTransaction({ + from: account.address, + to: contractAddress, + data: contract.methods.store(newValue).encodeABI(), + gas: 10000000n, // Replace with the gas limit you want to use + gasPrice: await web3.eth.getGasPrice(), // Replace with the gas price you want to use +}) + +// Send signed transaction to the network +const result = await web3.eth.sendSignedTransaction(signed.rawTransaction) + +// { status: 1, transactionHash: '0x1234', ... } +// status=1 means the transaction was successful +console.log(result) +``` + +Now that the transaction has been sent, the contract's state should have updated. We an verify this by querying the contract's state again: + +```js +const result = await contract.methods.retrieve().call() +console.log(result) // New value stored in the contract +``` + +For more information about using smart contracts in web3.js, see the [official documentation](https://docs.web3js.org/libdocs/Contract). \ No newline at end of file