diff --git a/docs/docs/guides/advanced/_category_.yml b/docs/docs/guides/advanced/_category_.yml index 045cf1dfded..dc1665bf8a2 100644 --- a/docs/docs/guides/advanced/_category_.yml +++ b/docs/docs/guides/advanced/_category_.yml @@ -1,5 +1,5 @@ -label: 'Advanced' +label: '🧠 Advanced' collapsible: true collapsed: true link: null -position: 5 \ No newline at end of file +position: 11 \ No newline at end of file diff --git a/docs/docs/guides/advanced/support_additional_rpc_methods/index.md b/docs/docs/guides/advanced/custom_RPC.md similarity index 53% rename from docs/docs/guides/advanced/support_additional_rpc_methods/index.md rename to docs/docs/guides/advanced/custom_RPC.md index aa9fe8059e3..28ccfeeea63 100644 --- a/docs/docs/guides/advanced/support_additional_rpc_methods/index.md +++ b/docs/docs/guides/advanced/custom_RPC.md @@ -1,5 +1,5 @@ --- -sidebar_position: 0 +sidebar_position: 1 sidebar_label: Add custom RPC methods --- @@ -8,7 +8,7 @@ import TabItem from '@theme/TabItem'; # Add custom RPC methods -#### Introduction +## Introduction Web3.js is a popular library for interacting with the Ethereum blockchain. It provides a set of APIs to interact with Ethereum nodes via JSON-RPC calls. For adding new JSON-RPC function calls to the library, you can do so using the plugin feature in web3.js 4.x. This allows you to extend the functionality of Web3.js and add support for new JSON-RPC methods. @@ -18,61 +18,70 @@ In Web3.js 1.x, `web3.extend()` function could be used to add new JSON-RPC metho Following tutorial will guide you through the process of creating a custom plugin to extend the functionality of web3.js 4.x and add support for new RPC methods. -#### Creating new RPC methods Plugin in 4 Steps +## Creating new RPC methods Plugin in 4 Steps + +### Step 1: Setting Up Web3.js as a Peer Dependency and Creating a TypeScript Class 1. First add web3.js as peer dependency in project´s `package.json` and create a TypeScript class for your plugin. This class should extend the `Web3Plugin` class provided by web3.js. :::info This will give your plugin access to [requestManager](/api/web3-core/class/Web3Context#requestManager) and [accountProvider](/api/web3-core/class/Web3Context#accountProvider). -:::caution - +::: - + - + ```javascript const { Web3PluginBase } = require('web3'); +//highlight-start class CustomRpcMethodsPlugin extends Web3PluginBase { - // step 1 - // ... + // step 1 + // ... } +//highlight-end module.exports = CustomRpcMethodsPlugin; ``` - + ```typescript import { Web3PluginBase } from 'web3'; +//highlight-start export default class CustomRpcMethodsPlugin extends Web3PluginBase { - // step 1 - // ... + // step 1 + // ... } +//highlight-end ``` +### Step 2: Adding a Public `pluginNamespace` Property to the Plugin Class + 2. After that add public `pluginNamespace` property. This will be used to access your plugin, as mentioned in step number 5 code example. - + - + ```javascript const { Web3PluginBase } = require('web3'); class CustomRpcMethodsPlugin extends Web3PluginBase { - pluginNamespace = 'customRpcMethods'; // step 2 +//highlight-start + pluginNamespace = 'customRpcMethods'; // step 2 +//highlight-end } module.exports = CustomRpcMethodsPlugin; @@ -80,41 +89,48 @@ module.exports = CustomRpcMethodsPlugin; - + ```typescript import { Web3PluginBase } from 'web3'; export default class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; // step 2 + //highlight-start + public pluginNamespace = 'customRpcMethods'; // step 2 +//highlight-end } ``` + +### Step 3: Creating Custom RPC Methods in the Plugin Class + 3. Once plugin class is created using above mentioned steps, its very easy to add new RPC methods like: - + - + ```javascript const { Web3PluginBase } = require('web3'); class CustomRpcMethodsPlugin extends Web3PluginBase { - pluginNamespace = 'customRpcMethods'; - - async customRpcMethod() { - // step 3 - return this.requestManager.send({ - // plugin has access to web3.js internal features like request manager - method: 'custom_rpc_method', - params: [], - }); - } + pluginNamespace = 'customRpcMethods'; + + //highlight-start + async customRpcMethod() { + // step 3 + return this.requestManager.send({ + // plugin has access to web3.js internal features like request manager + method: 'custom_rpc_method', + params: [], + }); + } + //highlight-end } module.exports = CustomRpcMethodsPlugin; @@ -122,49 +138,53 @@ module.exports = CustomRpcMethodsPlugin; - + ```typescript import { Web3PluginBase } from 'web3'; export default class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; - - public async customRpcMethod() { - // step 3 - return this.requestManager.send({ - // plugin has access to web3.js internal features like request manager - method: 'custom_rpc_method', - params: [], - }); - } + public pluginNamespace = 'customRpcMethods'; + + //highlight-start + public async customRpcMethod() { + // step 3 + return this.requestManager.send({ + // plugin has access to web3.js internal features like request manager + method: 'custom_rpc_method', + params: [], + }); + } + //highlight-end } ``` -4. Final step is setting up module [augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation), this will allow you to access plugin on web3 object. +### Step 4: Enabling Access to the Plugin on the Web3 Object + +4. (For TypeScript) Final step is setting up module [augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation), this will allow you to access plugin on web3 object. - + - + ```javascript const { Web3PluginBase } = require('web3'); class CustomRpcMethodsPlugin extends Web3PluginBase { - pluginNamespace = 'customRpcMethods'; - - async customRpcMethod() { - return this.requestManager.send({ - // plugin has access to web3.js internal features like request manager - method: 'custom_rpc_method', - params: [], - }); - } + pluginNamespace = 'customRpcMethods'; + + async customRpcMethod() { + return this.requestManager.send({ + // plugin has access to web3.js internal features like request manager + method: 'custom_rpc_method', + params: [], + }); + } } module.exports = CustomRpcMethodsPlugin; @@ -172,32 +192,34 @@ module.exports = CustomRpcMethodsPlugin; - + ```typescript import { Web3PluginBase } from 'web3'; export default class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; - - public async customRpcMethod() { - return this.requestManager.send({ - // plugin has access to web3.js internal features like request manager - method: 'custom_rpc_method', - params: [], - }); - } + public pluginNamespace = 'customRpcMethods'; + + public async customRpcMethod() { + return this.requestManager.send({ + // plugin has access to web3.js internal features like request manager + method: 'custom_rpc_method', + params: [], + }); + } } +//highlight-start // Module Augmentation declare module 'web3' { - // step 4 + // step 4 - interface Web3Context { - customRpcMethods: CustomRpcMethodsPlugin; - } + interface Web3Context { + customRpcMethods: CustomRpcMethodsPlugin; + } } +//highlight-end ``` @@ -207,47 +229,52 @@ declare module 'web3' { After the plugin is ready, it is recommended to publish it on the NPM registry. ::: -#### Using Web3 Custom PRC Plugin (with web3 instance) +### Step 5: Using the Web3 `CustomRPCPlugin` with a Web3 Instance 5. First add plugin in your plugin consumer project's `package.json`, create web3 and plugin instances, and after that use `.registerPlugin` method with some web3.js module (in following example its registered with main web3). Once plugin is registered its custom methods will be available to use. - + - + ```javascript const { Web3 } = require('web3'); const CustomRpcMethodsPlugin = require('web3-plugin-example'); const web3 = new Web3('http://127.0.0.1:8545'); + +//highlight-start web3.registerPlugin(new CustomRpcMethodsPlugin()); // step 5 -web3.customRpcMethods.customRpcMethod(); -// ... +web3.customRpcMethods.customRpcMethod(); //usage +//highlight-end ``` - + ```typescript import { Web3 } from 'web3'; import CustomRpcMethodsPlugin from 'web3-plugin-example'; const web3 = new Web3('http://127.0.0.1:8545'); + +//highlight-start web3.registerPlugin(new CustomRpcMethodsPlugin()); // step 5 -web3.customRpcMethods.customRpcMethod(); +web3.customRpcMethods.customRpcMethod(); //usage +//highlight-end ``` -#### More Details of Plugin Feature +## More Details of Plugin Feature For more details follow : diff --git a/docs/docs/guides/advanced/web3_tree_shaking_support_guide/index.md b/docs/docs/guides/advanced/tree_shaking.md similarity index 55% rename from docs/docs/guides/advanced/web3_tree_shaking_support_guide/index.md rename to docs/docs/guides/advanced/tree_shaking.md index 6527e4a2275..46f301e738c 100644 --- a/docs/docs/guides/advanced/web3_tree_shaking_support_guide/index.md +++ b/docs/docs/guides/advanced/tree_shaking.md @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +sidebar_position: 2 sidebar_label: Tree Shaking Guide --- @@ -8,12 +8,16 @@ import TabItem from '@theme/TabItem'; # Tree shaking Support Guide +## Step 1: Enable Production Mode + 1. Use the `production` mode configuration option to enable various optimizations including minification and tree shaking. Set your webpack.config: ```js -"mode":"production" +'mode':'production' ``` +## Step 2: Configure sideEffects Property + 2. Add a `sideEffects` property to your project's `package.json` file: ```json @@ -22,34 +26,39 @@ import TabItem from '@theme/TabItem'; :::note For further information about `sideEffects` see [webpack docs](https://webpack.js.org/guides/tree-shaking/) +::: + +## Step 3: Set tsconfig Module to ES2015 -::: 3. Set your tsconfig module to `ES2015` or higher to support `imports`, because tree shaking does not work with `require`: +3. Set your tsconfig module to `ES2015` or higher to support `imports`, because tree shaking does not work with `require`: ```json "module": "ES2015" ``` +## Step 4: Use Specific Packages + 4. Use the specific packages which you need, For example, if you need `web.eth`: - + - + ```javascript -const Web3Eth = require('web3-eth'); +const { Web3Eth } = require('web3-eth'); // ... ``` - + ```typescript -import Web3Eth from 'web3-eth'; +import { Web3Eth } from 'web3-eth'; // ... ``` @@ -58,10 +67,10 @@ import Web3Eth from 'web3-eth'; If you only need a few functions from `web3-utils`: - + - + ```javascript const { numberToHex, hexToNumber } = require('web3-utils'); @@ -70,8 +79,8 @@ const { numberToHex, hexToNumber } = require('web3-utils'); - + ```typescript import { numberToHex, hexToNumber } from 'web3-utils'; @@ -81,4 +90,6 @@ import { numberToHex, hexToNumber } from 'web3-utils'; +## Example React App + You can find an example app with tree shaking [here](https://github.com/ChainSafe/web3js-example-react-app). diff --git a/docs/docs/guides/basics/eth.md b/docs/docs/guides/basics/eth.md deleted file mode 100644 index 306c3027732..00000000000 --- a/docs/docs/guides/basics/eth.md +++ /dev/null @@ -1,1032 +0,0 @@ ---- -sidebar_position: 2 -sidebar_label: 'Eth Package Usage Example' ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Getting Started with `eth` Package - -## Introduction - -The `web3-eth` package provides a set of powerful functionalities to interact with the Ethereum blockchain and smart contracts. In this tutorial, we will guide you through the basics of using the `web3-eth` package of web3.js version 4. We will be using TypeScript throughout the examples. - -## Overview - -Here is a high-level overview of the steps we will be taking in this tutorial: - -1. Setting up the Environment -2. Create a new project directory and initialize a new Node.js project. -3. Set up web3.js and connect to the Ganache network -4. Interact with the Ethereum blockchain using web3.js. -5. Importing specific package -6. Send different type of transactions -7. Package methods - -## Step 1: Setting up the Environment - -Before we start writing and deploying our contract, we need to set up our environment. For that, we need to install the following: - -1. Ganache - Ganache is a personal blockchain for Ethereum development that allows you to see how your smart contracts function in real-world scenarios. You can download it from http://truffleframework.com/ganache -2. Node.js - Node.js is a JavaScript runtime environment that allows you to run JavaScript on the server-side. You can download it from https://nodejs.org/en/download/ -3. npm - Node Package Manager is used to publish and install packages to and from the public npm registry or a private npm registry. Here is how to install it https://docs.npmjs.com/downloading-and-installing-node-js-and-npm. (Alternatively, you can use yarn instead of npm https://classic.yarnpkg.com/lang/en/docs/getting-started/) - -## Step 2: Create a new project directory and initialize a new Node.js project - -First, create a new project directory for your project and navigate into it: - -``` -mkdir web3-eth-tutorial -cd web3-eth-tutorial -``` - -Next, initialize a new Node.js project using npm: - -``` -npm init -y -``` - -This will create a new `package.json` file in your project directory. - -``` -npm i typescript @types/node -``` - -This will install typescript for our project and install the types for node. - -## Step 3: Set up web3.js and connect to the Ganache network - -In this step, we will set up the web3.js library and connect to the Ganache network. So, be sure to run Ganache if you did not already did. - -First, install the `web3` package using npm: - -``` -npm i web3 -``` - -Next, create a new file called `index.ts` in your project directory and add the following code to it: - - - - - -```javascript -const { Web3 } = require('web3'); // web3.js has native ESM builds and (`import Web3 from 'web3'`) - -// Set up a connection to the Ganache network -const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545')); - -// Log the current block number to the console -web3.eth - .getBlockNumber() - .then(result => { - console.log('Current block number: ' + result); - }) - .catch(error => { - console.error(error); - }); -``` - - - - - -```typescript -import { Web3 } from 'web3'; - -// Set up a connection to the Ganache network -const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545')); - -// Log the current block number to the console -web3.eth - .getBlockNumber() - .then(result => { - console.log('Current block number: ' + result); - }) - .catch(error => { - console.error(error); - }); -``` - - - - -This code sets up a connection to the Ganache network and logs the current block number to the console. - -Run the following command to test the connection: - -``` -npx ts-node index.ts -``` - -If everything is working correctly, you should see the current block number logged to the console. However, if you got an error with the reason `connect ECONNREFUSED 127.0.0.1:7545` then double check that you are running Ganache locally on port `7545`. - -## Step 4: Interact with the Ethereum blockchain using web3.js - -In this step, we will use web3.js to interact with the Ganache network. - -In the first example, we are going to send a simple value transaction. -Create a file named `transaction.ts` and fill it with the following code: - - - - - -```javascript -const { Web3 } = require('web3'); // web3.js has native ESM builds and (`import Web3 from 'web3'`) -const fs = require('fs'); -const path = require('path'); - -// Set up a connection to the Ethereum network -const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545')); -web3.eth.Contract.handleRevert = true; - -async function interact() { - //fetch all the available accounts - const accounts = await web3.eth.getAccounts(); - console.log(accounts); - - let balance1, balance2; - //The initial balances of the accounts should be 100 Eth (10^18 wei) - balance1 = await web3.eth.getBalance(accounts[0]); - balance2 = await web3.eth.getBalance(accounts[1]); - - console.log(balance1, balance2); - - //create a transaction sending 1 Ether from account 0 to account 1 - const transaction = { - from: accounts[0], - to: accounts[1], - // value should be passed in wei. For easier use and to avoid mistakes, - // we utilize the auxiliary `toWei` function: - value: web3.utils.toWei('1', 'ether'), - }; - - //send the actual transaction - const transactionHash = await web3.eth.sendTransaction(transaction); - console.log('transactionHash', transactionHash); - - balance1 = await web3.eth.getBalance(accounts[0]); - balance2 = await web3.eth.getBalance(accounts[1]); - - // see the updated balances - console.log(balance1, balance2); - - // irrelevant with the actual transaction, just to know the gasPrice - const gasPrice = await web3.eth.getGasPrice(); - console.log(gasPrice); -} - -(async () => { - await interact(); -})(); -``` - - - - - -```typescript -import { Web3 } from 'web3'; -import fs from 'fs'; -import path from 'path'; - -// Set up a connection to the Ethereum network -const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545')); -web3.eth.Contract.handleRevert = true; - -async function interact() { - //fetch all the available accounts - const accounts = await web3.eth.getAccounts(); - console.log(accounts); - - let balance1, balance2; - //The initial balances of the accounts should be 100 Eth (10^18 wei) - balance1 = await web3.eth.getBalance(accounts[0]); - balance2 = await web3.eth.getBalance(accounts[1]); - - console.log(balance1, balance2); - - //create a transaction sending 1 Ether from account 0 to account 1 - const transaction = { - from: accounts[0], - to: accounts[1], - // value should be passed in wei. For easier use and to avoid mistakes, - // we utilize the auxiliary `toWei` function: - value: web3.utils.toWei('1', 'ether'), - }; - - //send the actual transaction - const transactionHash = await web3.eth.sendTransaction(transaction); - console.log('transactionHash', transactionHash); - - balance1 = await web3.eth.getBalance(accounts[0]); - balance2 = await web3.eth.getBalance(accounts[1]); - - // see the updated balances - console.log(balance1, balance2); - - // irrelevant with the actual transaction, just to know the gasPrice - const gasPrice = await web3.eth.getGasPrice(); - console.log(gasPrice); -} - -(async () => { - await interact(); -})(); -``` - - - - -:::note -📝 When running a local development blockchain using Ganache, all accounts are typically unlocked by default, allowing easy access and transaction execution during development and testing. This means that the accounts are accessible without requiring a private key or passphrase. That's why we just indicate the accounts in the examples with the `from` field. -::: - -Run the following: - -``` -npx ts-node transaction.ts -``` - -If everything is working correctly, you should see something like the following: - -```typescript -[ - '0xc68863f36C48ec168AD45A86c96347D520eac1Cf', - '0x80c05939B307f9833d905A685575b45659d3EA70', - '0xA260Cf742e03B48ea1A2b76b0d20aaCfe6F85E5E', - '0xf457b8C0CBE41e2a85b6222A97b7b7bC6Df1C0c0', - '0x32dF9a0B365b6265Fb21893c551b0766084DDE21', - '0x8a6A2b8b00C1C8135F1B25DcE54f73Ee18bEF43d', - '0xAFc526Be4a2656f7E02501bdf660AbbaA8fb3d7A', - '0xc32618116370fF776Ecd18301c801e146A1746b3', - '0xDCCD49880dCf9603835B0f522c31Fcf0579b46Ff', - '0x036006084Cb62b7FAf40B979868c0c03672a59B5' -] -100000000000000000000n 100000000000000000000n - -transactionHash { - transactionHash: '0xf685b64ccf5930d3779a33335ca22195b68901dbdc439f79dfc65d87c7ae88b0', - transactionIndex: 0n, - blockHash: '0x5bc044ad949cfd32ea4cbb249f0292e7dded44c3b0f599236c6d20ddaa96cc06', - blockNumber: 1n, - from: '0xc68863f36c48ec168ad45a86c96347d520eac1cf', - to: '0x80c05939b307f9833d905a685575b45659d3ea70', - gasUsed: 21000n, - cumulativeGasUsed: 21000n, - logs: [], - status: 1n, - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' -} - -98999580000000000000n 101000000000000000000n - -20000000000n - -``` - -:::note -📝 In order to calculate the actual ether spent, we have to calculate the value sent plus the fees. Initial_balance = (Remaining_balance + value + gasUsed\*gasPrice). In our case: - -98999580000000000000 + 1000000000000000000 + (20000000000\*21000) = 100 Ether -::: - -In the next example, we are going to use `estimateGas` function to see the expected gas for contract deployment. (For more on contracts, please see the corresponding tutotial). Create a file named `estimate.ts` and fill it with the following code: - - - - - -```javascript -const { Web3, ETH_DATA_FORMAT, DEFAULT_RETURN_FORMAT } = require('web3'); - -async function estimate() { - // abi of our contract - const abi = [ - { - inputs: [{ internalType: 'uint256', name: '_myNumber', type: 'uint256' }], - stateMutability: 'nonpayable', - type: 'constructor', - }, - { - inputs: [], - name: 'myNumber', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [{ internalType: 'uint256', name: '_myNumber', type: 'uint256' }], - name: 'setMyNumber', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - ]; - - const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545')); - - //get the available accounts - const accounts = await web3.eth.getAccounts(); - let acc = await accounts[0]; - - let contract = new web3.eth.Contract(abi, undefined); - - const deployment = contract.deploy({ - data: '0x608060405234801561001057600080fd5b506040516101d93803806101d983398181016040528101906100329190610054565b806000819055505061009e565b60008151905061004e81610087565b92915050565b60006020828403121561006657600080fd5b60006100748482850161003f565b91505092915050565b6000819050919050565b6100908161007d565b811461009b57600080fd5b50565b61012c806100ad6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806323fd0e401460375780636ffd773c146051575b600080fd5b603d6069565b6040516048919060bf565b60405180910390f35b6067600480360381019060639190608c565b606f565b005b60005481565b8060008190555050565b60008135905060868160e2565b92915050565b600060208284031215609d57600080fd5b600060a9848285016079565b91505092915050565b60b98160d8565b82525050565b600060208201905060d2600083018460b2565b92915050565b6000819050919050565b60e98160d8565b811460f357600080fd5b5056fea2646970667358221220d28cf161457f7936995800eb9896635a02a559a0561bff6a09a40bfb81cd056564736f6c63430008000033', - // @ts-expect-error - arguments: [1], - }); - estimatedGas = await deployment.estimateGas( - { - from: acc, - }, - DEFAULT_RETURN_FORMAT, // the returned data will be formatted as a bigint - ); - - console.log(estimatedGas); - - let estimatedGas = await deployment.estimateGas( - { - from: acc, - }, - ETH_DATA_FORMAT, // the returned data will be formatted as a hexstring - ); - - console.log(estimatedGas); -} - -(async () => { - await estimate(); -})(); -``` - - - - - -```typescript -import { Web3, ETH_DATA_FORMAT, DEFAULT_RETURN_FORMAT } from 'web3'; - -async function estimate() { - // abi of our contract - const abi = [ - { - inputs: [{ internalType: 'uint256', name: '_myNumber', type: 'uint256' }], - stateMutability: 'nonpayable', - type: 'constructor', - }, - { - inputs: [], - name: 'myNumber', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [{ internalType: 'uint256', name: '_myNumber', type: 'uint256' }], - name: 'setMyNumber', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - ]; - - const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545')); - - //get the available accounts - const accounts = await web3.eth.getAccounts(); - let acc = await accounts[0]; - - let contract = new web3.eth.Contract(abi, undefined); - - const deployment = contract.deploy({ - data: '0x608060405234801561001057600080fd5b506040516101d93803806101d983398181016040528101906100329190610054565b806000819055505061009e565b60008151905061004e81610087565b92915050565b60006020828403121561006657600080fd5b60006100748482850161003f565b91505092915050565b6000819050919050565b6100908161007d565b811461009b57600080fd5b50565b61012c806100ad6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806323fd0e401460375780636ffd773c146051575b600080fd5b603d6069565b6040516048919060bf565b60405180910390f35b6067600480360381019060639190608c565b606f565b005b60005481565b8060008190555050565b60008135905060868160e2565b92915050565b600060208284031215609d57600080fd5b600060a9848285016079565b91505092915050565b60b98160d8565b82525050565b600060208201905060d2600083018460b2565b92915050565b6000819050919050565b60e98160d8565b811460f357600080fd5b5056fea2646970667358221220d28cf161457f7936995800eb9896635a02a559a0561bff6a09a40bfb81cd056564736f6c63430008000033', - // @ts-expect-error - arguments: [1], - }); - estimatedGas = await deployment.estimateGas( - { - from: acc, - }, - DEFAULT_RETURN_FORMAT, // the returned data will be formatted as a bigint - ); - - console.log(estimatedGas); - - let estimatedGas = await deployment.estimateGas( - { - from: acc, - }, - ETH_DATA_FORMAT, // the returned data will be formatted as a hexstring - ); - - console.log(estimatedGas); -} - -(async () => { - await estimate(); -})(); -``` - - - - -Run the following: - -``` -npx ts-node estimate.ts -``` - -If everything is working correctly, you should see something like the following: - -```typescript -0x22568; -``` - -:::note -📝 Note that numbers returned from web3.js are returned by default in the `BigInt` format. In this example we used `ETH_DATA_FORMAT` parameter, which, can be passed in most methods in web3.js in order to format the result in `hex`. -::: - -In the next example we are going to sign a transaction and use `sendSignedTransaction` to send the signed transaction. Create a file named `sendSigned.ts` and fill it with the following code: - - - - - -```javascript -const { Web3 } = require('web3'); -const web3 = new Web3('http://localhost:7545'); - -// make sure to copy the private key from ganache -const privateKey = 'YOUR PRIVATE KEY HERE'; -const value = web3.utils.toWei('1', 'ether'); - -async function sendSigned() { - const accounts = await web3.eth.getAccounts(); - const fromAddress = accounts[0]; - const toAddress = accounts[1]; - // Create a new transaction object - const tx = { - from: fromAddress, - to: toAddress, - value: value, - gas: 21000, - gasPrice: web3.utils.toWei('10', 'gwei'), - nonce: await web3.eth.getTransactionCount(fromAddress), - }; - - // Sign the transaction with the private key - const signedTx = await web3.eth.accounts.signTransaction(tx, privateKey); - - // Send the signed transaction to the network - const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction); - - console.log('Transaction receipt:', receipt); -} -(async () => { - await sendSigned(); -})(); -``` - - - - - -```typescript -import { Web3 } from 'web3'; -const web3 = new Web3('http://localhost:7545'); - -//make sure to copy the private key from ganache -const privateKey = '0x0fed6f64e01bc9fac9587b6e7245fd9d056c3c004ad546a17d3d029977f0930a'; -const value = web3.utils.toWei('1', 'ether'); - -async function sendSigned() { - const accounts = await web3.eth.getAccounts(); - const fromAddress = accounts[0]; - const toAddress = accounts[1]; - // Create a new transaction object - const tx = { - from: fromAddress, - to: toAddress, - value: value, - gas: 21000, - gasPrice: web3.utils.toWei('10', 'gwei'), - nonce: await web3.eth.getTransactionCount(fromAddress), - }; - - // Sign the transaction with the private key - const signedTx = await web3.eth.accounts.signTransaction(tx, privateKey); - - // Send the signed transaction to the network - const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction); - - console.log('Transaction receipt:', receipt); -} -(async () => { - await sendSigned(); -})(); -``` - - - - -Run the following: - -``` -npx ts-node sendSigned.ts -``` - -If everything is working correctly, you should see something like the following: - -```ts -Transaction receipt: { - transactionHash: '0x742df8f1ad4d04f6e5632889109506dbb7cdc8a6a1c80af3dfdfc71a67a04ddc', - transactionIndex: 0n, - blockNumber: 1n, - blockHash: '0xab6678d76499b0ee383f182ab8f848ba27bd787e70e227524255c86b25224ed3', - from: '0x66ce32a5200aac57b258c4eac26bc1493fefddea', - to: '0x0afcfc43ac454348d8170c77b1f912b518b4ebe8', - cumulativeGasUsed: 21000n, - gasUsed: 21000n, - logs: [], - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - status: 1n, - effectiveGasPrice: 10000000000n, - type: 2n -} -``` - -## Step 5: Importing specific package - -To harness the capabilities of the web3-eth package, you can opt to import this package directly rather than depending on the global web3 package, which will result in a reduction in the build size. - -### Import web3-eth directly - -For example [getBalance](/api/web3-eth/function/getBalance) method: - -```typescript -import Web3Eth from 'web3-eth'; - -const eth = new Web3Eth('http://localhost:7545'); - -async function test() { - const accounts = await eth.getAccounts(); - const currentBalance = await eth.getBalance(accounts[0]); - console.log('Current balance:', currentBalance); - // 115792089237316195423570985008687907853269984665640564039437613106102441895127n -} - -(async () => { - await test(); -})(); -``` - -### Set config directly to web3-eth package - -```typescript -import Web3Eth from 'web3-eth'; - -const eth = new Web3Eth('http://localhost:8545'); - -console.log('defaultTransactionType before', eth.config.defaultTransactionType); -// defaultTransactionType before 0x0 - -eth.setConfig({ defaultTransactionType: '0x1' }); - -console.log('eth.config.defaultTransactionType after', eth.config.defaultTransactionType); -// defaultTransactionType before 0x1 -``` - -## Step 6: Send different type of transactions: - -### Legacy Transaction - -In Ethereum, a "legacy transaction" typically refers to the traditional transactions, where gas fees are set explicitly by the sender and can fluctuate based on network demand. These legacy transactions were prevalent on the Ethereum network before the implementation of Ethereum Improvement Proposal (EIP) 1559. - -Key characteristics of legacy transactions include: - -1. Gas Price: In legacy transactions, the sender specifies a gas price (in Gwei) that they are willing to pay for each unit of gas consumed by the transaction. The gas price can be adjusted by the sender, and it determines the transaction's priority in getting processed by miners. Higher gas prices mean faster transaction confirmation. - -2. Gas Limit: The sender also sets a gas limit, which is the maximum amount of gas that the transaction can consume. Gas is the computational fuel used to execute transactions and smart contracts on the Ethereum network. The gas limit is primarily set to ensure that the sender doesn't run out of Ether while processing the transaction. It can also impact the success or failure of the transaction. - -3. Uncertainty in Fees: Legacy transactions are subject to fluctuating gas prices based on network congestion. During periods of high demand, gas prices can surge, causing users to pay more for their transactions to be processed promptly. Conversely, during quieter network periods, users can pay lower fees. - -4. Manual Fee Estimation: Users are responsible for manually estimating the appropriate gas price to include in their legacy transactions to ensure timely processing. This process can be challenging, as setting gas prices too low may result in slow confirmation, while setting them too high may lead to overpaying. - -5. EIP-1559, as described below, introduced changes to Ethereum's transaction fee system, making it more user-friendly and predictable. With EIP-1559, the concept of a "base fee" replaces the manual setting of gas prices, which has reduced some of the uncertainties associated with legacy transactions. - -While EIP-1559 has significantly improved the user experience, legacy transactions are still supported on the Ethereum network, and users can continue to send transactions with manually specified gas prices and gas limits if they prefer. However, the EIP-1559 mechanism is now the recommended approach for most transactions, as it simplifies the process and reduces the likelihood of overpaying for fees. - -To send Legacy transaction use code below: - -```typescript -import Web3 from 'web3'; -const web3 = new Web3('http://localhost:8545'); - -async function test() { - const privateKey = 'YOUR PRIVATE KEY HERE'; - // add private key to wallet to have auto-signing transactions feature - const account = web3.eth.accounts.privateKeyToAccount(privateKey); - web3.eth.accounts.wallet.add(account); - - // create transaction object - const tx = { - from: account.address, - to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', - value: '0x1', - gas: BigInt(21000), - gasPrice: await web3.eth.getGasPrice(), - type: BigInt(0), // <- specify type - }; - - // send transaction - const receipt = await web3.eth.sendTransaction(tx); - - console.log('Receipt:', receipt); - // Receipt: { - // blockHash: '0xc0f2fea359233b0843fb53255b8a7f42aa7b1aff53da7cbe78c45b5bac187ad4', - // blockNumber: 21n, - // cumulativeGasUsed: 21000n, - // effectiveGasPrice: 2569891347n, - // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', - // gasUsed: 21000n, - // logs: [], - // logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - // status: 1n, - // to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', - // transactionHash: '0x0ffe880776f5631e4b64caf521bd01cd816dd2cc29e533bc56f392211856cf9a', - // transactionIndex: 0n, - // type: 0n - // } -} -(async () => { - await test(); -})(); -``` - -### EIP-2930 Transaction - -Ethereum Improvement Proposal 2930 is a proposal for a change to the Ethereum network that was implemented as part of the Berlin hard fork, which was activated in April 2021. EIP-2930 introduces a feature called "Transaction Type and Access List." This improvement enhances the gas efficiency of certain smart contract interactions and provides more flexibility in specifying who can access specific resources within a smart contract. Here are the key components of EIP-2930: - -1. Transaction Type: EIP-2930 introduces a new transaction type called "Access List Transaction." This transaction type is designed to make certain interactions with smart contracts more efficient by allowing the sender to specify a list of addresses that may be accessed or modified during the transaction. - -2. Access List: The Access List is a structured data format included with the transaction. It contains a list of addresses and storage keys that are expected to be accessed or modified during the execution of the transaction. This helps in reducing the amount of gas required for these operations, as miners can check the Access List to optimize the execution. - -3. Gas Savings: EIP-2930 is intended to significantly reduce the gas costs for transactions that use the Access List feature. By specifying which storage slots and addresses are relevant to the transaction, it allows for a more efficient use of gas, especially in interactions with smart contracts that have a large state. - -4. Contract Interactions: This improvement is particularly useful when interacting with contracts that have complex state structures, as it minimizes the gas required to read from or write to specific storage slots. This can lead to cost savings for users and make certain interactions more practical. - -EIP-2930 is part of Ethereum's ongoing efforts to improve the network's efficiency and reduce transaction costs, making it more accessible and scalable for decentralized applications and users. It is especially beneficial for interactions with stateful contracts that rely on specific storage operations and access control mechanisms. - -To send EIP-2930 transaction use code below: - -```typescript -import Web3 from 'web3'; -const web3 = new Web3('http://localhost:8545'); - -async function test() { - const privateKey = 'YOUR PRIVATE KEY HERE'; - // add private key to wallet to have auto-signing transactions feature - const account = web3.eth.accounts.privateKeyToAccount(privateKey); - web3.eth.accounts.wallet.add(account); - - // create transaction object - const tx = { - from: account.address, - to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', - value: '0x1', - gasLimit: BigInt(21000), - type: BigInt(1), // <- specify type - // gasPrice - you can specify this property directly or web3js will fill this field automatically - }; - - // send transaction - const receipt = await web3.eth.sendTransaction(tx); - - console.log('Receipt:', receipt); - // Receipt: { - // blockHash: '0xd8f6a3638112d17b476fd1b7c4369d473bc1a484408b6f39dbf64410df44adf6', - // blockNumber: 24n, - // cumulativeGasUsed: 21000n, - // effectiveGasPrice: 2546893579n, - // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', - // gasUsed: 21000n, - // logs: [], - // logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - // status: 1n, - // to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', - // transactionHash: '0xd1d682b6f6467897db5b8f0a99a6be2fb788d32fbc1329b568b8f6b2c15e809a', - // transactionIndex: 0n, - // type: 1n - // } -} -(async () => { - await test(); -})(); -``` - -Here is an example of how to use an access list in a transaction. - -:::note -The code of `Greeter` contract you can find [here](https://github.com/web3/web3.js/blob/4.x/fixtures/build/Greeter.ts) -::: - -```typescript -import Web3 from 'web3'; -import { GreeterAbi, GreeterBytecode } from './fixture/Greeter'; - -const web3 = new Web3('http://localhost:8545'); - -async function test() { - const privateKey = 'YOUR PRIVATE KEY HERE'; - // add private key to wallet to have auto-signing transactions feature - const account = web3.eth.accounts.privateKeyToAccount(privateKey); - web3.eth.accounts.wallet.add(account); - - // deploy contract - const contract = new web3.eth.Contract(GreeterAbi); - const deployedContract = await contract - .deploy({ - data: GreeterBytecode, - arguments: ['My Greeting'], - }) - .send({ from: account.address }); - deployedContract.defaultAccount = account.address; - - const transaction = { - from: account.address, - to: deployedContract.options.address, - data: '0xcfae3217', // greet function call data encoded - }; - const { accessList } = await web3.eth.createAccessList(transaction, 'latest'); - - console.log('AccessList:', accessList); - // AccessList: [ - // { - // address: '0xce1f86f87bd3b8f32f0fb432f88e848f3a957ed7', - // storageKeys: [ - // '0x0000000000000000000000000000000000000000000000000000000000000001' - // ] - // } - // ] - - // create transaction object with accessList - const tx = { - from: account.address, - to: deployedContract.options.address, - gasLimit: BigInt(46000), - type: BigInt(1), // <- specify type - accessList, - data: '0xcfae3217', - // gasPrice - you can specify this property directly or web3js will fill this field automatically - }; - - // send transaction - const receipt = await web3.eth.sendTransaction(tx); - - console.log('Receipt:', receipt); - // Receipt: { - // blockHash: '0xc7b9561100c8ff6f1cde7a05916e86b7d037b2fdba86b0870e842d1814046e4b', - // blockNumber: 43n, - // cumulativeGasUsed: 26795n, - // effectiveGasPrice: 2504325716n, - // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', - // gasUsed: 26795n, - // logs: [], - // logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - // status: 1n, - // to: '0xce1f86f87bd3b8f32f0fb432f88e848f3a957ed7', - // transactionHash: '0xa49753be1e2bd22c2a8e2530726614c808838bb0ebbed72809bbcb34f178799a', - // transactionIndex: 0n, - // type: 1n - // } -} -(async () => { - await test(); -})(); -``` - -### EIP-1559 Transaction - -Ethereum Improvement Proposal 1559 is a significant upgrade to the Ethereum network's fee market and transaction pricing mechanism. It was implemented as part of the Ethereum London hard fork, which occurred in August 2021. EIP-1559 introduces several changes to how transaction fees work on the Ethereum blockchain, with the primary goals of improving user experience and network efficiency. - -Here are some of the key features and changes introduced by EIP-1559: - -1. Base Fee: EIP-1559 introduces a concept called the "base fee." The base fee is the minimum fee required for a transaction to be included in a block. It is determined algorithmically by the network and adjusts dynamically based on network congestion. When the network is busy, the base fee increases, and when it's less congested, the base fee decreases. - -2. Inclusion Fee: In addition to the base fee, users can voluntarily include a "tip" or "inclusion fee" to incentivize miners to include their transactions in the next block. This allows users to expedite their transactions by offering a tip to miners. - -3. Predictable Fees: With EIP-1559, users have a more predictable way to estimate transaction fees. They can set the maximum fee they are willing to pay, which includes the base fee and the tip. This eliminates the need for users to guess the appropriate gas price. - -4. Burn Mechanism: EIP-1559 introduces a mechanism by which the base fee is "burned" from circulation, reducing the overall supply of Ether (ETH). This deflationary mechanism can help address some of the concerns related to the increasing supply of ETH and potentially make it a better store of value. - -5. Improved Fee Auctions: Under EIP-1559, fee auctions are more efficient. Users specify the maximum fee they are willing to pay, and the protocol automatically adjusts the tip to ensure transactions get processed promptly without overpaying. - -6. Simpler Transaction Process: Users experience a simplified transaction process, as they don't have to set gas prices manually. Instead, they specify the maximum fee they are willing to pay, and the wallet software handles the rest. - -EIP-1559 has been well-received for its potential to create a more user-friendly and efficient transaction fee system, making the Ethereum network more accessible and predictable for users. It is also seen as an important step in the transition to Ethereum 2.0, which aims to address scalability and sustainability challenges on the network. - -To send EIP-1559 transaction use code below: - -```typescript -import Web3 from 'web3'; -const web3 = new Web3('http://localhost:8545'); - -async function test() { - const privateKey = 'YOUR PRIVATE KEY HERE'; - // add private key to wallet to have auto-signing transactions feature - const account = web3.eth.accounts.privateKeyToAccount(privateKey); - web3.eth.accounts.wallet.add(account); - - // create transaction object - const tx = { - from: account.address, - to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', - value: '0x1', - gasLimit: BigInt(21000), - type: BigInt(2), // <- specify type - // maxFeePerGas - you can specify this property directly or web3js will fill this field automatically - // maxPriorityFeePerGas - you can specify this property directly or web3js will fill this field automatically - }; - - // send transaction - const receipt = await web3.eth.sendTransaction(tx); - - console.log('Receipt:', receipt); - // Receipt: { - // blockHash: '0xfe472084d1471720b6887071d32a793f7c4576a489098e7d2a89aef205c977fb', - // blockNumber: 23n, - // cumulativeGasUsed: 21000n, - // effectiveGasPrice: 2546893579n, - // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', - // gasUsed: 21000n, - // logs: [], - // logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - // status: 1n, - // to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', - // transactionHash: '0x5c7a3d2965b426a5776e55f049ee379add44652322fb0b9fc2f7f57b38fafa2a', - // transactionIndex: 0n, - // type: 2n - // } -} -(async () => { - await test(); -})(); -``` - -## Step 7: Package methods - -### createAccessList - -Creating an access list in Ethereum is typically associated with Ethereum Improvement Proposal (EIP)-2930, which introduces a way to specify which accounts and storage keys a transaction expects to access. Access lists are used to optimize gas costs for transactions by providing explicit information about what the transaction needs to access. - -The [createAccessList](/api/web3-eth/function/createAccessList) method is used to create an access list. - -### estimateGas - -The [estimateGas](/api/web3-eth/function/estimateGas) function is used to estimate the amount of gas that will be consumed when executing a specific transaction or invoking a contract function. This can be very useful when you want to determine the potential cost of a transaction or function call before actually sending it to the Ethereum network. It helps users ensure that they have enough ether to cover the gas costs for the operation. - -### getBalance - -The [getBalance](/api/web3-eth/function/getBalance) function is used to retrieve the balance of an Ethereum address, which represents the amount of Ether (ETH) associated with that address. It's a fundamental and frequently used function when working with Ethereum applications. - -### getBlock - -The [getBlock](/api/web3-eth/function/getBlock) function is used to retrieve information about a specific Ethereum block. Ethereum blocks are the fundamental building blocks of the blockchain, containing a collection of transactions and other data. - -### getBlockNumber - -The [getBlockNumber](/api/web3-eth/function/getBlockNumber) function is used to retrieve the latest block number (also known as the block height) of the Ethereum blockchain. The block number is a crucial piece of information in Ethereum as it represents the current state of the blockchain, indicating the total number of blocks that have been mined up to the present. - -### getBlockTransactionCount - -The [getBlockTransactionCount](/api/web3-eth/function/getBlockTransactionCount) function is used to retrieve the number of transactions in a specific Ethereum block. It allows you to determine how many transactions were included in a particular block on the Ethereum blockchain. - -### getBlockUncleCount - -The [getBlockUncleCount](/api/web3-eth/function/getBlockUncleCount) function is used to retrieve the number of uncle blocks associated with a specific Ethereum block. In Ethereum, uncle blocks (also known as "stale blocks" or "ommer blocks") are blocks that were mined but not included in the main blockchain. They are referenced by other blocks as a way to reward miners for their efforts even if their blocks weren't part of the main chain. - -### getChainId - -The [getChainId](/api/web3-eth/function/getChainId) function is used to retrieve the chain ID of the connected Ethereum network. The chain ID is a unique identifier for a specific Ethereum network, and it's used to help prevent replay attacks when signing transactions. Different Ethereum networks, such as the mainnet, testnets, and private networks, have distinct chain IDs. - -### getCode - -The [getCode](/api/web3-eth/function/getCode) function library is used to retrieve the bytecode of a smart contract deployed on the Ethereum blockchain. Smart contracts on Ethereum are typically created by deploying bytecode to a specific address, and this function allows you to fetch the bytecode associated with a particular contract address. - -### getCoinbase - -The [getCoinbase](/api/web3-eth/function/getCoinbase) function is used to retrieve the address of the Ethereum account that is currently acting as the coinbase address for mining on the connected Ethereum node. The coinbase address is the address to which block rewards are sent when miners successfully mine a new block on the Ethereum blockchain. Miners configure their coinbase addresses to receive rewards for their mining efforts. - -### getGasPrice - -The [getGasPrice](/api/web3-eth/function/getGasPrice) function is used to retrieve the current gas price on the Ethereum network. Gas price is the amount of Ether (ETH) that users are willing to pay for each unit of gas when executing a transaction on the Ethereum network. Gas price is an important factor in determining the transaction fee (in ETH) for a transaction. - -### getPendingTransactions - -The [getPendingTransactions](/api/web3-eth/function/getPendingTransactions) function is used to retrieve information about pending transactions in the Ethereum network. Pending transactions are transactions that have been submitted to the network but have not yet been included in a mined block. This function allows you to access information about transactions that are waiting to be confirmed by miners. - -### getProof - -The [getProof](/api/web3-eth/function/getProof) function is used to obtain a Merkle proof or Patricia trie proof for a specific value or data in an Ethereum smart contract's storage. This function is typically used when you want to validate that a piece of data is stored in the contract's storage or to provide evidence for data inclusion without having to interact with the entire contract state. - -In Ethereum, storage proofs are used to demonstrate the existence of a value within a contract's storage without querying the entire storage of the contract, which can be computationally expensive. These proofs are essential for various applications, including decentralized exchanges, blockchain explorers, and certain cryptographic operations. - -### getProtocolVersion - -You can use the [getProtocolVersion](/api/web3-eth/function/getProtocolVersion) method to retrieve the current Ethereum protocol version of the connected Ethereum node. - -### getStorageAt - -The [getStorageAt](/api/web3-eth/function/getStorageAt) method is used to fetch the data stored at a specific storage slot of an Ethereum address. It is often used for inspecting the internal state of smart contracts, especially when you want to retrieve the value of a specific variable in a contract's storage. - -### getTransaction - -The [getTransaction](/api/web3-eth/function/getTransaction) method allows you to retrieve information about a transaction based on its transaction hash. You provide the transaction hash, and this method returns an object containing details about the transaction - -### getTransactionCount - -The [getTransactionCount](/api/web3-eth/function/getTransactionCount) method allows you to retrieve the transaction count (nonce) of a specific Ethereum address. - -### getTransactionReceipt - -The [getTransactionReceipt](/api/web3-eth/function/getTransactionReceipt) method allows you to retrieve the transaction receipt for a specific transaction based on its transaction hash. - -### getUncle - -The [getUncle](/api/web3-eth/function/getUncle) method allows you to retrieve information about an uncle block at a specific index within a given block. - -### isMining - -The [isMining](/api/web3-eth/function/isMining) function returns a boolean value, indicating whether the node is actively mining or not. - -### isSyncing - -The [isSyncing](/api/web3-eth/function/isSyncing) method allows you to check the current synchronization status of your Ethereum node. - -### sendTransaction - -The [sendTransaction](/api/web3-eth/function/sendTransaction) method is used to create and send a transaction to the Ethereum network. - -:::note -Please be cautious when sending transactions, especially when dealing with smart contracts, as they may execute specific functions that can have irreversible effects. Always ensure that the details in your transaction object are accurate and intended. - -[Here](/guides/basics/sign_and_send_tx/) you can find more examples how to send transaction. -::: - -### sign - -The [sign](/api/web3-eth/function/sign) method is used to sign a message or data using a private key. This is often used to prove ownership or authorship of a specific piece of data or to provide cryptographic proof in various Ethereum-related operations. - -### signTransaction - -The [signTransaction](/api/web3-eth/function/signTransaction) method is used to sign an Ethereum transaction, creating a signed transaction object that can be broadcast to the Ethereum network. - -### sendSignedTransaction - -The [sendSignedTransaction](/api/web3-eth/function/sendSignedTransaction) method is used to send a signed Ethereum transaction to the Ethereum network. Before sending a transaction, you need to sign it using a private key, and then you can use this method to broadcast the signed transaction to the network. - -:::note -[Here](/guides/basics/sign_and_send_tx/) you can find more examples how to send transaction. -::: - -## Conclusion - -In this tutorial, we learned how to use different methods provied by the `web3-eth` package. - -With this knowledge, you can start experimenting with the Ethereum blockchain. Keep in mind that this is just the beginning, and there is a lot more to learn about Ethereum and web3.js. So keep exploring and building, and have fun! - -## Additional Resources - -- [Official web3.js Documentation](https://docs.web3js.org/) -- [Solidity Documentation](https://solidity.readthedocs.io/) -- [Ganache](https://www.trufflesuite.com/ganache) -- [Truffle](https://trufflesuite.com/) -- [Remix IDE](https://remix.ethereum.org/) - -## Tips and Best Practices - -- Always test your smart contracts on a local network like Ganache before deploying them to the mainnet. -- Use the latest version of web3.js and Solidity to take advantage of the latest features and security patches. -- Keep your private keys secure and never share them with anyone. -- Use the gas limit and gas price parameters carefully to avoid spending too much on transaction fees. -- Use the `estimateGas` function in web3.js to estimate the gas required for a transaction before sending it to the network. -- Use events to notify the client application about state changes in the smart contract. -- Use a linter like Solhint to check for common Solidity coding errors. - -## Final Thoughts - -Web3.js version 4.x provides a powerful and easy-to-use interface for interacting with the Ethereum network and building decentralized applications. And it has been rewritten in TypeScript but for simplicity of this tutorial we interacted with it in JavaScript. - -The Ethereum ecosystem is constantly evolving, and there is always more to learn and discover. As you continue to develop your skills and knowledge, keep exploring and experimenting with new technologies and tools to build innovative and decentralized solutions. diff --git a/docs/docs/guides/basics/sign_and_send_tx/index.md b/docs/docs/guides/basics/sign_and_send_tx/index.md deleted file mode 100644 index 8e5501b1836..00000000000 --- a/docs/docs/guides/basics/sign_and_send_tx/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: 'Transactions' ---- - -# Sign and Send Transaction - -You can sign and send transactions in different ways. - -- [Local wallet signing](./local_wallet) -- [Using raw transaction](./raw) -- [Using wallet of Eth Node](./wallet_of_eth_node) - -For each of them you can use [Web3PromiEvent](./promi_event) to catch extra transaction's events diff --git a/docs/docs/guides/basics/sign_and_send_tx/local_wallet.md b/docs/docs/guides/basics/sign_and_send_tx/local_wallet.md deleted file mode 100644 index ec1410dd46d..00000000000 --- a/docs/docs/guides/basics/sign_and_send_tx/local_wallet.md +++ /dev/null @@ -1,227 +0,0 @@ ---- -sidebar_position: 0 -sidebar_label: 'Local wallet' ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Using Local Wallet - -The simplest way to sign and send transactions is using a local wallet: - -## Ethereum Transaction - - - - - -```javascript -// First step: initialize `web3` instance -const { Web3 } = require('web3'); -const web3 = new Web3(/* PROVIDER*/); - -// Second step: add an account to wallet -const account = web3.eth.accounts.wallet.add("privateKey").get(0); - -// Make sure the account has enough eth on balance to send the transaction - - -async function sendTransaction() { - // Third step: sign and send the transaction - // Magic happens behind sendTransaction. If a transaction is sent from an account that exists in a wallet, it will be automatically signed. - try { - const receipt = await web3.eth.sendTransaction({ - from: account?.address, - to: '0xe4beef667408b99053dc147ed19592ada0d77f59', - value: '0x1', - gas: '300000', - // other transaction's params - }); - } catch (error) { - // catch transaction error - console.error(error); - } -} - -(async () => { - await sendTransaction(); -})(); -``` - - - - - -```typescript -// First step: initialize `web3` instance -import { Web3 } from 'web3'; -const web3 = new Web3(/* PROVIDER*/); - -// Second step: add an account to wallet -const privateKeyString = 'privateKey'; -const account = web3.eth.accounts.wallet.add(privateKeyString).get(0); - -// Make sure the account has enough eth on balance to send the transaction - -async function sendTransaction() { - // Third step: sign and send the transaction - // Magic happens behind sendTransaction. If a transaction is sent from an account that exists in a wallet, it will be automatically signed. - try { - const receipt = await web3.eth.sendTransaction({ - from: account?.address, - to: '0xe4beef667408b99053dc147ed19592ada0d77f59', - value: '0x1', - gas: '300000', - // other transaction's params - }); - } catch (error) { - // catch transaction error - console.error(error); - } -} - -(async () => { - await sendTransaction(); -})(); -``` - - - - - -List of references: - -- [eth.accounts.wallet.add](/api/web3-eth-accounts/class/Wallet#add) -- [eth.sendTransaction](/api/web3-eth/class/Web3Eth#sendTransaction) - -## Contract Transaction - - - - - -```javascript -// First step: initialize `web3` instance -const { Web3 } = require('web3'); -const web3 = new Web3(/* PROVIDER*/); - -// Second step: add an account to wallet -const privateKeyString = 'privateKey'; -const account = web3.eth.accounts.wallet.add(privateKeyString).get(0); - -// Make sure the account has enough eth on balance to send the transaction - -// fill ContractAbi and ContractBytecode with your contract's abi and bytecode - -async function deploy() { - // Third step: sign and send the transaction - // In any function where you can pass from the address set address of the account that exists in a wallet, it will be automatically signed. - - try { - // deploy - const contract = new web3.eth.Contract(ContractAbi); - const contractDeployed = await contract - .deploy({ - input: ContractBytecode, - arguments: ['Constructor param1', 'Constructor param2'], - }) - .send({ - from: account?.address, - gas: '1000000', - // other transaction's params - }); - - // call method - await contractDeployed.methods - .transfer('0xe2597eb05cf9a87eb1309e86750c903ec38e527e', '0x1') - .send({ - from: account?.address, - gas: '1000000', - // other transaction's params - }); - } catch (error) { - // catch transaction error - console.error(error); - } -} - -(async () => { - await deploy(); -})(); -``` - - - - - - -```typescript - -:::warning -Using `web3.eth.personal` web3.eth.personal is not considered secure and is strongly discouraged. The personal RPC endpoints have been deprecated due to significant security issues. -::: - -// First step: initialize `web3` instance -import { Web3 } from 'web3'; -const web3 = new Web3(/* PROVIDER*/); - -// Second step: add an account to wallet -const privateKeyString = 'privateKey'; -const account = web3.eth.accounts.wallet.add(privateKeyString).get(0); - -// Make sure the account has enough eth on balance to send the transaction - -// fill ContractAbi and ContractBytecode with your contract's abi and bytecode - -async function deploy() { - // Third step: sign and send the transaction - // In any function where you can pass from the address set address of the account that exists in a wallet, it will be automatically signed. - - try { - // deploy - const contract = new web3.eth.Contract(ContractAbi); - const contractDeployed = await contract - .deploy({ - input: ContractBytecode, - arguments: ['Constructor param1', 'Constructor param2'], - }) - .send({ - from: account?.address, - gas: '1000000', - // other transaction's params - }); - - // call method - await contractDeployed.methods - .transfer('0xe2597eb05cf9a87eb1309e86750c903ec38e527e', '0x1') - .send({ - from: account?.address, - gas: '1000000', - // other transaction's params - }); - } catch (error) { - // catch transaction error - console.error(error); - } -} - -(async () => { - await deploy(); -})(); -``` - - - - - -List of references: - -- [eth.accounts.wallet.add](/api/web3-eth-accounts/class/Wallet#add) -- [eth.Contract](/api/web3-eth-contract/class/Contract) -- [contract.deploy](/api/web3-eth-contract/class/Contract#deploy) -- [contract.methods](/api/web3-eth-contract/class/Contract#methods) diff --git a/docs/docs/guides/basics/sign_and_send_tx/raw.md b/docs/docs/guides/basics/sign_and_send_tx/raw.md deleted file mode 100644 index 3402a7ebf08..00000000000 --- a/docs/docs/guides/basics/sign_and_send_tx/raw.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -sidebar_position: 2 -sidebar_label: 'Raw Transaction' ---- - -# Using Raw Transaction - -:::note -To be written! -::: diff --git a/docs/docs/guides/events_subscriptions/_category_.yml b/docs/docs/guides/events_subscriptions/_category_.yml new file mode 100644 index 00000000000..528836749db --- /dev/null +++ b/docs/docs/guides/events_subscriptions/_category_.yml @@ -0,0 +1,5 @@ +label: '🔔 Events subscription' +collapsible: true +collapsed: true +link: null +position: 6 \ No newline at end of file diff --git a/docs/docs/guides/events_subscriptions/custom_subscriptions.md b/docs/docs/guides/events_subscriptions/custom_subscriptions.md index cab85f8cc5e..6f5826fe902 100644 --- a/docs/docs/guides/events_subscriptions/custom_subscriptions.md +++ b/docs/docs/guides/events_subscriptions/custom_subscriptions.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 3 sidebar_label: 'Custom Subscriptions' --- @@ -30,16 +30,16 @@ For example: ```ts class MyCustomSubscription extends Web3Subscription< - { - // here provide the type of the `data` that will be emitted by the node - data: string; - }, - // here specify the types of the arguments that will be passed to the node when subscribing - { - customArg: string; - } + { + // here provide the type of the `data` that will be emitted by the node + data: string; + }, + // here specify the types of the arguments that will be passed to the node when subscribing + { + customArg: string; + } > { - // ... + // ... } ``` @@ -48,17 +48,17 @@ class MyCustomSubscription extends Web3Subscription< You need to specify the exact data that will be passed to the provider. You do this by overriding `_buildSubscriptionParams` in your class. It could be something as follow: ```ts - protected _buildSubscriptionParams() { - // the `someCustomSubscription` below is the name of the subscription provided by the node you are connected to. - return ['someCustomSubscription', this.args]; - } +protected _buildSubscriptionParams() { + // the `someCustomSubscription` below is the name of the subscription provided by the node you are connected to. + return ['someCustomSubscription', this.args]; +} ``` With the implementation above, the call that will be made to the provider will be as follow: ```ts { - id: "[GUID-STRING]", // something like: '3f839900-afdd-4553-bca7-b4e2b835c687' + id: '[GUID-STRING]', // something like: '3f839900-afdd-4553-bca7-b4e2b835c687' jsonrpc: '2.0', method: 'eth_subscribe', // The `someCustomSubscription` below is the name of the subscription provided by the node you are connected to. @@ -114,17 +114,17 @@ To subscribe, you need to pass the custom subscriptions to the `Web3`. And then ```ts const CustomSubscriptions = { - // the key (`custom`) is what you chose to use when you call `web3.subscriptionManager.subscribe`. - // the value (`CustomSubscription`) is your class name. - custom: MyCustomSubscription, - // you can have as many custom subscriptions as you like... - // custom2: MyCustomSubscription2, - // custom3: MyCustomSubscription3, + // the key (`custom`) is what you chose to use when you call `web3.subscriptionManager.subscribe`. + // the value (`CustomSubscription`) is your class name. + custom: MyCustomSubscription, + // you can have as many custom subscriptions as you like... + // custom2: MyCustomSubscription2, + // custom3: MyCustomSubscription3, }; const web3 = new Web3({ - provider, // the provider that support the custom event that you like to subscribe to. - registeredSubscriptions: CustomSubscriptions, + provider, // the provider that support the custom event that you like to subscribe to. + registeredSubscriptions: CustomSubscriptions, }); // subscribe at the provider: @@ -134,8 +134,8 @@ const sub = web3.subscriptionManager.subscribe('custom', args); // listen to the emitted event: // Note: the data will be optionally formatted at `formatSubscriptionResult`, before it is emitted here. -sub.on('data', result => { - // This will be called every time a new data arrived from the provider to this subscription +sub.on('data', (result) => { + // This will be called every time a new data arrived from the provider to this subscription }); ``` @@ -153,68 +153,68 @@ Here is the full example for a custom subscription implementation: ```ts // Subscription class class MyCustomSubscription extends Web3Subscription< - { - // here provide the type of the `data` that will be emitted by the node - data: string; - }, - // here specify the types of the arguments that will be passed to the node when subscribing - { - customArg: string; - } + { + // here provide the type of the `data` that will be emitted by the node + data: string; + }, + // here specify the types of the arguments that will be passed to the node when subscribing + { + customArg: string; + } > { - protected _buildSubscriptionParams() { - // the `someCustomSubscription` below is the name of the subscription provided by the node your are connected to. - return ['someCustomSubscription', this.args]; - } - - protected formatSubscriptionResult(data: string) { - return format(data); - } - - constructor( - args: { customArg: string }, - options: { - subscriptionManager: Web3SubscriptionManager; - returnFormat?: DataFormat; - }, - ) { - super(args, options); - - // Additional initialization - } + protected _buildSubscriptionParams() { + // the `someCustomSubscription` below is the name of the subscription provided by the node your are connected to. + return ['someCustomSubscription', this.args]; + } + + protected formatSubscriptionResult(data: string) { + return format(data); + } + + constructor( + args: { customArg: string }, + options: { + subscriptionManager: Web3SubscriptionManager; + returnFormat?: DataFormat; + } + ) { + super(args, options); + + // Additional initialization + } } // Usage const args = { - customArg: 'hello custom', + customArg: 'hello custom', }; const CustomSubscriptions = { - // the key (`custom`) is what you chose to use when you call `web3.subscriptionManager.subscribe`. - // the value (`MyCustomSubscription`) is your class name. - custom: MyCustomSubscription, - // you can have as many custom subscriptions as you like... - // custom2: MyCustomSubscription2, - // custom3: MyCustomSubscription3, + // the key (`custom`) is what you chose to use when you call `web3.subscriptionManager.subscribe`. + // the value (`MyCustomSubscription`) is your class name. + custom: MyCustomSubscription, + // you can have as many custom subscriptions as you like... + // custom2: MyCustomSubscription2, + // custom3: MyCustomSubscription3, }; const web3 = new Web3({ - provider, // the provider that support the custom event that you like to subscribe to. - registeredSubscriptions: CustomSubscriptions, + provider, // the provider that support the custom event that you like to subscribe to. + registeredSubscriptions: CustomSubscriptions, }); const sub = web3.subscriptionManager.subscribe('custom', args); -sub.on('data', result => { - // New data +sub.on('data', (result) => { + // New data }); -// Unsubscribe: -// If you want to subscribe later based on some code logic: -// if () { -// await sub.subscribe(); -// } +/* Unsubscribe: +If you want to subscribe later based on some code logic: + +if () { await sub.subscribe(); } +*/ ``` ## Key points diff --git a/docs/docs/guides/events_subscriptions/index.md b/docs/docs/guides/events_subscriptions/index.md index 7e1dee9d0b2..7bd2f60b958 100644 --- a/docs/docs/guides/events_subscriptions/index.md +++ b/docs/docs/guides/events_subscriptions/index.md @@ -1,6 +1,6 @@ --- -sidebar_position: 5 -sidebar_label: 'Events Subscription' +sidebar_position: 1 +sidebar_label: 'Introduction' --- # Events Subscription diff --git a/docs/docs/guides/events_subscriptions/supported_subscriptions.md b/docs/docs/guides/events_subscriptions/supported_subscriptions.md index 9e2df8c89b8..bb8b704dd62 100644 --- a/docs/docs/guides/events_subscriptions/supported_subscriptions.md +++ b/docs/docs/guides/events_subscriptions/supported_subscriptions.md @@ -1,5 +1,5 @@ --- -sidebar_position: 1 +sidebar_position: 2 sidebar_label: 'Supported Subscriptions' --- diff --git a/docs/docs/guides/getting_started.md b/docs/docs/guides/getting_started.md deleted file mode 100644 index 27222640da3..00000000000 --- a/docs/docs/guides/getting_started.md +++ /dev/null @@ -1,115 +0,0 @@ ---- -slug: / -sidebar_position: 1 -sidebar_label: Getting Started ---- - -# Getting Started - -Welcome to Web3.js Documentation. - -web3.js is a collection of libraries that allow you to interact with a local or remote Ethereum node using HTTP, IPC or WebSocket. -The following documentation will guide you through different use cases of Web3.js, upgrading from older versions, as well as providing an API reference documentation with examples. - -### Some major features of Web3.js v4 are: - -- Web3.js [Plugins Feature](/guides/web3_plugin_guide/) for extending functionality ( [List of Existing Plugins](https://web3js.org/plugins) ) -- ESM and CJS builds -- [Tree shakable with ESM](/guides/advanced/web3_tree_shaking_support_guide/) -- [Contracts dynamic types](/guides/smart_contracts/infer_contract_types_guide/) & full API in TypeScript -- Using native BigInt instead of large BigNumber libraries -- More efficient ABI Encoder & Decoder -- Custom Output formatters -- In compliance with Eth EL API - -### Installation - -If NPM is being used as package manager, use the following for installing the web3.js library. - -``` -npm i web3 -``` - -For installing using yarn package manager: - -``` -yarn add web3 -``` - -Note: Installing web3.js in this way will bring in all web3.js sub-packages, if you only need specific packages, it is recommended to install the specific required packages. - -### Importing and using Web3.js - -Web3.js v4 supports both CJS ( CommonJS ) and native ESM module imports. For importing the main Web3 class in CJS you can use: - -``` js -const { Web3 } = require('web3'); -``` - -and for ESM style imports, you can use: - -``` ts -import { Web3 } from 'web3'; - -``` - -### Providers and Transport - -Web3.js is in compliance with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) so any EIP-1193 provider can be injected in web3.js . There are HTTP, WebSocket and IPC providers also available as web3.js packages for using. - -Following are examples of creating web3 instance with HTTP provider. - -``` ts -import { Web3, HttpProvider } from 'web3'; -const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_PROJ_ID'); -web3.eth.getBlock('latest').then(console.log); -// or -const web3_2 = new Web3(new HttpProvider('https://mainnet.infura.io/v3/YOUR_PROJ_ID')); -web3_2.eth.getBlock('latest').then(console.log); -``` - -Following are examples of creating web3 instance with Websocket provider. - -``` ts -import { Web3, WebSocketProvider } from 'web3'; - -const web3 = new Web3('wss://mainnet.infura.io/ws/v3/YOUR_PROJ_ID'); -web3.eth.getBlock('latest').then(console.log); - -// or - -const web3_2 = new Web3(new WebSocketProvider('wss://mainnet.infura.io/ws/v3/YOUR_PROJ_ID')); -web3_2.eth.getBlock('latest').then(console.log); - -``` - -Following is an example of creating web3 instance with IPC provider. - -``` ts -import { Web3 } from 'web3'; -import {IpcProvider} from 'web3-providers-ipc'; - -const web3 = new Web3(new IpcProvider('/users/myuser/.ethereum/geth.ipc')); -web3.eth.getBlock('latest').then(console.log); -``` - -Further details are listed in the [Providers section](https://docs.web3js.org/guides/web3_providers_guide/). - -Once Web3 is instantiated, the following packages are available for usage: - -- Web3 Accounts : For signing transactions & data, and accounts management using Web3 Basic Wallet. -- Web3 Eth : This package allows you to interact with an Ethereum blockchain. -- Web3 Eth ABI : Functions in this package let you encode and decode parameters to ABI (Application - Binary Interface) -- Web3 Eth contract : This package allows deploying and interacting with Ethereum Contracts. -- Web3 ETH ENS : Functions in this package let you interact with ENS ( Ethereum Name Service ). -- Web3 ETH IBAN : It has functions for converting Ethereum addresses from and to IBAN and BBAN. -- Web3 ETH Personal : This package allows you to interact with the Ethereum node’s accounts. -- Web3 NET : This package allows you to interact with an Ethereum node’s network properties. - -Additional Supporting Packages -- Web3 Types : This package has common typescript types. -- Web3 Utils : This package provides utility functions for Ethereum DApps and other web3.js packages. -- Web3 Validator : This package offers functionality for validation using provided Schema. -- Web3 Core : Web3 Core has configuration, Subscriptions and Requests management functionality used by other Web3 packages. -- Web3 Errors : Web3 Errors has error codes and common error classes that are used by other Web3 packages. -- Web3 RPC Methods : This is for advanced uses for building more lightweight applications. It has functions for making RPC requests to Ethereum using a given provider. \ No newline at end of file diff --git a/docs/docs/guides/getting_started/_category_.yml b/docs/docs/guides/getting_started/_category_.yml new file mode 100644 index 00000000000..eaee578f06a --- /dev/null +++ b/docs/docs/guides/getting_started/_category_.yml @@ -0,0 +1,5 @@ +label: '🚀 Getting Started' +collapsible: true +collapsed: false +link: null +position: 1 \ No newline at end of file diff --git a/docs/docs/guides/getting_started/getting_started.md b/docs/docs/guides/getting_started/getting_started.md new file mode 100644 index 00000000000..8d08c907904 --- /dev/null +++ b/docs/docs/guides/getting_started/getting_started.md @@ -0,0 +1,249 @@ +--- +slug: / +sidebar_position: 2 +sidebar_label: Quickstart +--- + +# Quickstart + +## Installation + +If NPM is being used as package manager, use the following for installing the web3.js library. + +``` +npm i web3 +``` + +For installing using yarn package manager: + +``` +yarn add web3 +``` + +Note: Installing web3.js in this way will bring in all web3.js sub-packages, if you only need specific packages, it is recommended to install the specific required packages (e.g, if you want the contract package `npm i web3-eth-contract` instead) + +## Importing Web3.js + +Web3.js v4 supports both CJS ( CommonJS ) and native ESM module imports. For importing the main Web3 class in CJS you can use: + +``` js +const { Web3 } = require('web3'); +``` + +and for ESM style imports, you can use: + +``` ts +import { Web3 } from 'web3'; +``` + +## Initialize `Web3` with a provider + +Web3.js is in compliance with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) so any EIP-1193 provider can be injected in web3.js . There are HTTP, WebSocket and IPC providers also available as web3.js packages for using. + +:::warning +You must initialize the `Web3` object with a provider, otherwise, you won't be able to fully use web3.js functionalities. Here is an example of creating a `web3` instance with an HTTP provider: +::: + +``` ts +import { Web3 } from 'web3'; + +//private RPC endpoint +const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_ID'); + +//or public RPC endpoint +//const web3 = new Web3('https://eth.llamarpc.com'); + +web3.eth.getBlockNumber().then(console.log); +// ↳ 18849658n +``` +## Querying the blockchain + +After instantiating the `web3` instance with a `new Web3 provider`, we can access the `web3.eth` package to fetch data from the blockchain: + +```ts +// get the balance of an address +await web3.eth.getBalance('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'); +// ↳ 114438180989009447638n + +// get last block number +await web3.eth.getBlockNumber(); +// ↳ 18849658n + +// get the chain id of the current provider +await web3.eth.getChainId(); +// ↳ 1n + +// get the nonce of an address +await web3.eth.getTransactionCount('0x37826D8B5F4B175517A0f42c886f8Fca38C55Fe7'); +// ↳ 7n + +// get the current gas price +await web3.eth.getGasPrice(); +// ↳ 23879160756n +``` + +## Setting up a wallet + +If you want to write data/interact with contracts or send transactions on the blockchain, you must have an account with funds to cover the gas fees. + +The object `Wallet` is an array of accounts, it will allow you to hold several accounts from which you can send transactions `web3.eth.sendTransaction` or interact with contract objects `web3.eth.contract.methods.contractfunction().send()`, when you perform these actions, the `Wallet` object uses the account/s it holds to send the transactions. + +### Create random wallet + +```ts +//create random wallet with 1 account +web3.eth.accounts.wallet.create(1) +/* ↳ +Wallet(1) +[ + { + address: '0xcE6A5235d6033341972782a15289277E85E5b305', + privateKey: '0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + _accountProvider: { + create: [Function: createWithContext], + privateKeyToAccount: [Function: privateKeyToAccountWithContext], + decrypt: [Function: decryptWithContext] + }, + _addressMap: Map(1) { '0xce6a5235d6033341972782a15289277e85e5b305' => 0 }, + _defaultKeyName: 'web3js_wallet' +] +*/ +``` + +### Add a private key to create a wallet + +```ts +//the private key must start with the '0x' prefix +const account = web3.eth.accounts.wallet.add('0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec'); + +console.log(account[0].address); +//↳ 0xcE6A5235d6033341972782a15289277E85E5b305 + +console.log(account[0].privateKey); +//↳ 0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec +``` + +### Send transactions + +```ts title='Sending value' +//add an account to a wallet +const account = web3.eth.accounts.wallet.add('0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec'); + +//create transaction object to send 1 eth to '0xa32...c94' address from the account[0] +const tx = +{ + from: account[0].address, + to: '0xa3286628134bad128faeef82f44e99aa64085c94', + value: web3.utils.toWei('1', 'ether') +}; +//the `from` address must match the one previously added with wallet.add + +//send the transaction +const txReceipt = await web3.eth.sendTransaction(tx); + +console.log('Tx hash:', txReceipt.transactionHash) +// ↳ Tx hash: 0x03c844b069646e08af1b6f31519a36e3e08452b198ef9f6ce0f0ccafd5e3ae0e +``` + +## Interact with smart contracts + +### Instantiate a contract + +The first step to interact with a contract is to instantiate the contract, for which we will need the ABI and the address of the contract + +```ts +//Uniswap token address in mainnet +const address = '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984' + +//you can find the complete ABI in etherscan.io +const ABI = +[ + { + name: 'symbol', + outputs: [{ type: 'string' }], + type: 'function', + }, + { + name: 'totalSupply', + outputs: [{ type: 'uint256' }], + type: 'function', + }, +]; + +//instantiate the contract +const uniswapToken = new web3.eth.Contract(abi, address); +``` + +### Read-methods + +```ts +//make the call to the contract +const symbol = await uniswapToken.methods.symbol().call(); + +console.log('Uniswap symbol:',symbol); +// ↳ Uniswap symbol: UNI + +//make the call to the contract +const totalSupply = await uniswapToken.methods.totalSupply().call(); + +console.log('Uniswap Total supply:', totalSupply); +// ↳ Uniswap Total Supply: 1000000000000000000000000000n + +//use web3 utils to format the units +console.log(web3.utils.fromWei(totalSupply, 'ether')) +// ↳ 1000000000 +``` + +### Writing-methods + +```ts +//address to send the token +const to = '0xcf185f2F3Fe19D82bFdcee59E3330FD7ba5f27ce'; + +//value to transfer (1 with 18 decimals) +const value = web3.utils.toWei('1','ether'); + +//send the transaction => return the Tx receipt +const txReceipt = await uniswapToken.methods.transfer(to,value).send({from: account[0].address}); + +console.log('Tx hash:',txReceipt.transactionHash); +// ↳ Tx hash: 0x14273c2b5781cc8f1687906c68bfc93482c603026d01b4fd37a04adb6217ad43 +``` + +### Query past events + +```ts +//get past `Transfer` events from block 18850576 +const eventTransfer = await uniswapToken.getPastEvents('Transfer', { fromBlock: 18850576 }); + +console.log(eventTransfer); +// ↳ [{...},{...}, ...] array with all the events emitted +//you can only query logs from the previous 100_000 blocks +``` + +### Listening to live events + +:::warning +You MUST initialize the `Web3 provider` with a WebSocket endpoint to subscribe to live events +::: + +```ts +import { Web3 } from 'web3'; + +//WebSocket provider +const web3 = new Web3('wss://ethereum.publicnode.com'); + +//instantiate contract +const uniswapToken = new web3.eth.Contract(abi, address) + +//create the subcription to all the 'Transfer' events +const subscription = uniswapToken.events.Transfer(); + +//listen to the events +subscription.on('data',console.log); +// ↳ [{...},{...}, ...] live events will be printed in the console +``` \ No newline at end of file diff --git a/docs/docs/guides/getting_started/introduction.md b/docs/docs/guides/getting_started/introduction.md new file mode 100644 index 00000000000..30a031a5f1f --- /dev/null +++ b/docs/docs/guides/getting_started/introduction.md @@ -0,0 +1,58 @@ +--- +sidebar_position: 1 +sidebar_label: Introduction +--- + +# Introduction + +Welcome to Web3.js Documentation!👋 + +Web3.js is a robust and flexible collection of libraries for **TypeScript and JavaScript** developers. It allows you to interact with a local or remote Ethereum node (or **any EVM-compatible blockchain**) using **HTTP, IPC or WebSocket.** It serves as an essential tool for connecting and crafting applications within the Ethereum ecosystem. + +The following documentation will guide you through different use cases of Web3.js, upgrading from older versions, as well as providing an API reference documentation with examples. + +## Features of Web3.js v4 + +- Web3.js [Plugins Feature](/guides/web3_plugin_guide/) for extending functionality ( [List of Existing Plugins](https://web3js.org/plugins) ) +- ECMAScript (ESM) and CommonJS (CJS) builds +- [Tree shakable with ESM](/guides/advanced/tree_shaking) +- [Contracts dynamic types](/guides/smart_contracts/infer_contract_types/) & full API in TypeScript +- Using native BigInt instead of large BigNumber libraries +- More efficient ABI Encoder & Decoder +- Custom Output formatters +- In compliance with Eth EL API + +## Packages + +Web3.js is modular, consisting of several packages, each serving specific functionalities. If you have specific tasks in mind, you don't need to install the entire Web3 library. Instead, selectively install the package that suits your requirements for a more efficient development experience. Here is an overview of the available packages: + +- [**ABI:**](/libdocs/ABI) The `web3-eth-abi` package simplifies decoding logs and parameters, encoding function calls and signatures, and inferring types for efficient Ethereum **contract interactions.** + +- [**Accounts:**](/libdocs/Accounts) The `web3-eth-accounts` package has tools for creating Ethereum accounts/wallets and making sure transactions and data are **securely signed.** + +- [**Contract:**](/libdocs/Contract) With the `web3-eth-Contract`, you can interact with Smart contracts. This functionality allows **communication with contracts through JavaScript or TypeScript objects**, simplifying your development and interaction processes. + +- [**ENS:**](/libdocs/ENS) The `web3-eth-ens` package helps you communicate with the **Ethereum Name Service (ENS)** on the blockchain. + +- [**Iban:**](/libdocs/Iban) The `web3-eth-iban` package allows you to switch between **Ethereum addresses and special banking-like addresses** (IBAN or BBAN). It makes the conversion back and forth easier. + +- [**Net:**](/libdocs/Net) The `web3-net` class allows you to talk about and deal with an **Ethereum node's network details.** + +- [**Personal:**](/libdocs/Personal) Use `web3-eth-personal` for **direct communication with the Ethereum node about your accounts**, streamlining account management in your development workflow. + **NOTE:** *For enhanced security when interacting with public nodes, consider using `web3-eth-accounts` for local signing operations, keeping your private keys and sensitive information secure on your local machine* + +- [**Utils:**](/libdocs/Utils) With the `web3-utils` package you can perform a range of essential tasks in Ethereum development, including **converting data formats, checking addresses, encoding and decoding, hashing, handling numbers, and much more**, providing versatile utility functions for your applications. + +- [**Web3Eth:**](/libdocs/Web3Eth) The `web3-eth` is your main tool for interacting with the Ethereum blockchain. It's like the control center for managing your interactions with Ethereum. + +### Additional supporting packages + +- **Web3 Types:** This package has common typescript types. + +- **Web3 Validator:** This package offers functionality for validation using provided Schema. + +- **Web3 Core:** Web3 Core has configuration, Subscriptions and Requests management functionality used by other Web3 packages. + +- **Web3 Errors:** Web3 Errors has error codes and common error classes that are used by other Web3 packages. + +- **Web3 RPC Methods:** This is for advanced uses for building more lightweight applications. It has functions for making RPC requests to Ethereum using a given provider. \ No newline at end of file diff --git a/docs/docs/guides/getting_started/metamask.md b/docs/docs/guides/getting_started/metamask.md new file mode 100644 index 00000000000..714360b9665 --- /dev/null +++ b/docs/docs/guides/getting_started/metamask.md @@ -0,0 +1,189 @@ +--- +sidebar_position: 4 +sidebar_label: Connecting to Metamask +--- + +# Connecting to Metamask + +## React app + +After creating your react app `npx create-react-app app-name`, and installing web3 `npm i web3` you can go to `src/app.js`, you can clean up the code and import `{Web3}`. It should look like this: + +```jsx +import { useState } from 'react'; +import { Web3 } from 'web3'; + +function App() { + return <> ; +} + +export default App; +``` + +Let's divide this into 2 small steps: + +### 1. Create Button to Connect and Display Connected Address +In this step, we'll add a button to the front end for users to connect to Metamask. We'll also include an `

` element to display the connected address once the connection is established. + +```jsx +import { useState } from 'react'; +import { Web3 } from 'web3'; + +function App() { + //highlight-start + //react state to store and show the connected account + const [connectedAccount, setConnectedAccount] = useState('null'); + //highlight-end + + return ( + <> + //highlight-start + {/* Button to trigger Metamask connection */} + + + {/* Display the connected account */} +

{connectedAccount}

+ //highlight-end + + ); +} + +export default App; +``` + +### 2. Implement the Function to Connect Metamask +In this step, we'll implement the function that triggers Metamask to prompt the user to connect their wallet. + +```jsx {} +import { useState } from 'react'; +import { Web3 } from 'web3'; + +function App() { + //state to store and show the connected account + const [connectedAccount, setConnectedAccount] = useState('null'); + + //highlight-start + async function connectMetamask() { + //check metamask is installed + if (window.ethereum) { + // instantiate Web3 with the injected provider + const web3 = new Web3(window.ethereum); + + //request user to connect accounts (Metamask will prompt) + await window.ethereum.request({ method: 'eth_requestAccounts' }); + + //get the connected accounts + const accounts = await web3.eth.getAccounts(); + + //show the first connected account in the react page + setConnectedAccount(accounts[0]); + } else { + alert('Please download metamask'); + } + } + //highlight-end + + return ( + <> + {/* Button to trigger Metamask connection */} + + + {/* Display the connected account */} +

{connectedAccount}

+ + ); +} + +export default App; +``` + +## HTML Single page + +### 1. Create an html file and import Web3 from CDN + +```html + + + + //highlight-start + Metamask Connection + + + //highlight-end + + + + +``` + +### 2. Create Button to Connect and Display Connected Address + +```html + + + + Metamask Connection + + + + + //highlight-start +

Metamask Connection

+ + + + + +

null

+ //highlight-end + + +``` + +### 3. Implement Script to Connect Metamask + +```html + + + + Metamask Connection + + + + +

Metamask Connection

+ + + + + +

null

+ + //highlight-start + + //highlight-end + + + +``` + + \ No newline at end of file diff --git a/docs/docs/guides/glossary/index.md b/docs/docs/guides/glossary/index.md new file mode 100644 index 00000000000..7cecf076a4f --- /dev/null +++ b/docs/docs/guides/glossary/index.md @@ -0,0 +1,110 @@ +--- +sidebar_position: 13 +sidebar_label: '📖 Glossary' +title: Glossary +--- + + +## Provider + +In web3.js, a `provider` is an object responsible for enabling connectivity with the Ethereum network in various ways. Providers facilitate the connection of your web application to an Ethereum node, different provider types are available in web3.js(HTTP, WebSocket and IPC), each with its own features and use cases. **It's important to note that a provider itself only provides read-only access to the blockchain.** It does not use any private keys or accounts for interaction. This read-only functionality is particularly useful for querying data and making calls to the blockchain without the need for private key authorization. + +## Accounts + +In web3.js, an `account` allows you to perform operations on the blockchain, such as sending transactions, signing data, and interacting with contracts. It serves as the key component for **using a private key** directly to execute various blockchain operations. In other libraries, this concept is often referred to as a `signer`. This versatility in terminology doesn't change its fundamental purpose, providing a secure and straightforward means to manage Ethereum-related operations. + + +## Wallet + +A `wallet` in web3.js can store multiple `accounts`. This feature allows you to manage various private keys for different operations. When using methods such as `web3.eth.sendTransaction()` or `web3.eth.contract.methods.doSomething().send({})`, the web3.js library handles these transactions using the wallet accounts under the hood. Essentially, the wallet makes it easier to coordinate multiple accounts for smoother Ethereum operations. + + +## Contract + +The `Contract` class is an important class in the `web3-eth-contract` package, also available in the `web3` package. It serves as an abstraction representing a connection to a specific contract on the Ethereum Network, enabling applications to interact with it as a typical JavaScript object. Through the `Contract` class, you can execute functions and listen to events associated with the smart contract (e.g, `contract.methods.doSomething().call()`) + +## JSON Interface (ABI) + +The JSON interface is a `JSON` object describing the [Application Binary Interface (ABI)](https://docs.soliditylang.org/en/develop/abi-spec.html) for an Ethereum smart contract. + +Using this JSON interface, web3.js is able to create a JavaScript object representing the smart contract , its methods and events using the `web3.eth.Contract` object. + +### Functions + +- `type`: `"function"`, `"constructor"` (can be omitted, defaulting to `"function"`; `"fallback"` also possible but not relevant in web3.js); +- `name`: the name of the function (only present for function types); +- `constant`: `true` if function is specified to not modify the blockchain state; +- `payable`: `true` if function accepts ether, defaults to false; +- `stateMutability`: a `string` with one of the following values: `"pure"` (specified to not read blockchain state), `"view"` (same as constant above), `"non-payable"` and `"payable"` (same as payable above); +- `inputs`: an `Array of objects`, each of which contains: + -- `name`: the name of the parameter; + -- `type`: the canonical type of the parameter. +- `outputs`: an `Array of objects`, same as inputs, can be omitted if no outputs exist. + +### Events + +- `type`: always `"event"` +- `name`: the name of the event; +- `inputs`: an `Array of objects`, each of which contains: + + - `name`: the name of the parameter; + + - `type`: the canonical type of the parameter. + + - `indexed`: `true` if the field is part of the log’s topics, false if it is one of the log’s data segment. + + - `anonymous`: `true` if the event was declared as anonymous. + +#### Example + +```solidity title='Solidity Contract' +pragma solidity ^0.8.4; + +contract Test { + uint256 a; + address d = 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF; + + constructor(uint256 testInt) { + a = testInt; + } + + event Event(uint256 indexed b, bytes32 c); + + event Event2(uint256 indexed b, bytes32 c); + + function foo(uint256 b, bytes32 c) public returns (address) { + emit Event(b, c); + return d; + } +} + +``` + +```json title='Resulting JSON ABI' +[ + { + "type": "constructor" + "stateMutability": "nonpayable", + "inputs": [{"internalType":"uint256","name":"testInt","type":"uint256"}], + }, + { + "type": "event" + "name": "Event", + "inputs": [{"indexed":true,"internalType":"uint256","name":"b","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"c","type":"bytes32"}], + "anonymous": false, + }, + { + "type": "event" + "name": "Event2", + "inputs": [{"indexed":true,"internalType":"uint256","name":"b","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"c","type":"bytes32"}], + "anonymous": false, + }, + { + "type": "function" + "name": "foo", + "stateMutability": "nonpayable", + "inputs": [{"internalType":"uint256","name":"b","type":"uint256"},{"internalType":"bytes32","name":"c","type":"bytes32"}], + "outputs": [{"internalType":"address","name":"","type":"address"}], + } +] +``` diff --git a/docs/docs/guides/migration_from_other_libs/_category_.yml b/docs/docs/guides/migration_from_other_libs/_category_.yml index ee8c672520c..61d3868cee1 100644 --- a/docs/docs/guides/migration_from_other_libs/_category_.yml +++ b/docs/docs/guides/migration_from_other_libs/_category_.yml @@ -1,4 +1,5 @@ -label: 'Migration from Other Libraries' +label: '🔄 Migration Guides' collapsible: true -collapsed: false -link: null \ No newline at end of file +collapsed: true +link: null +position: 10 \ No newline at end of file diff --git a/docs/docs/guides/migration_from_other_libs/ethers.md b/docs/docs/guides/migration_from_other_libs/ethers.md index 96dfa9e5943..3d924499972 100644 --- a/docs/docs/guides/migration_from_other_libs/ethers.md +++ b/docs/docs/guides/migration_from_other_libs/ethers.md @@ -50,8 +50,9 @@ blockNumber.then(console.log); ``` :::tip -📝 web3.js uses `bigint` as the default type for all big numbers returned. For, this you see above the blocknumber has the `n` at its end (`18561956n`). However, you can change the returned type by passing an optional parameter like: -```ts +📝 web3.js uses `bigint` as the default type for all big numbers returned. For, this you see above the blocknumber has the `n` at its end (`18561956n`). However, you can change the returned type by passing an optional parameter like: +::: +```ts title='BigInt Tip' import { Web3, DEFAULT_RETURN_FORMAT, FMT_NUMBER } from 'web3'; const blockNumber = web3.eth.getBlockNumber({ @@ -69,7 +70,6 @@ const blockNumber = web3.eth.getBlockNumber({ // the value would like: '18561956' blockNumber.then(console.log); ``` -::: ### Use browser-injected provider @@ -292,7 +292,7 @@ To deploy a contract in ethers.js you might have something like: ```typescript const signer = provider.getSigner(); const factory = new ethers.ContractFactory(abi, bytecode, signer); -const contract = await factory.deploy("constructor param"); +const contract = await factory.deploy('constructor param'); console.log('contract address', contract.address); // wait for contract creation transaction to be mined @@ -305,9 +305,9 @@ In web3.js: const contractObject = new web3.eth.Contract(abi); const deployedContract = await contractObject.deploy({ data: bytecode, - arguments: ["constructor param"] + arguments: ['constructor param'] }).send({ - from: "0x12598d2Fd88B420ED571beFDA8dD112624B5E730", + from: '0x12598d2Fd88B420ED571beFDA8dD112624B5E730', gas: '1000000', // other transaction's params }); @@ -316,7 +316,7 @@ console.log('contract address', deployedContract.options.address) ``` :::tip -📝 To get the smart contract ABI, you are advised to check: [Compile the Solidity code using the Solidity Compiler and get its ABI and Bytecode](/guides/smart_contracts/deploying_and_interacting_with_smart_contracts#step-4-compile-the-solidity-code-using-the-solidity-compiler-and-get-its-abi-and-bytecode) and [Infer Contract Types from JSON Artifact](/guides/smart_contracts/infer_contract_types_guide/) +📝 To get the smart contract ABI, you are advised to check: [#Step 4: Compile the Solidity code using the Solidity Compiler and get its ABI and Bytecode](/guides/smart_contracts/smart_contracts_guide#step-4-compile-the-solidity-code-using-the-solidity-compiler-and-get-its-abi-and-bytecode) and [Infer Contract Types from JSON Artifact](/guides/smart_contracts/infer_contract_types/) ::: @@ -348,8 +348,8 @@ In ethers.js: ```typescript // ethers const abi = [ - "function getMessage(string) public view returns (string)", - "function getMessage() public view returns (string)" + 'function getMessage(string) public view returns (string)', + 'function getMessage() public view returns (string)' ] const contract = new ethers.Contract(address, abi, signer); @@ -460,12 +460,12 @@ console.log(fromEtherToWie); With web3.js: ```typescript -// the second parameter is "the unit to convert to" +// the second parameter is 'the unit to convert to' const fromWieToEther = Web3.utils.fromWei('1000000000000000000', 'ether'); // outputs: 1 console.log(fromWieToEther); -// the second parameter is "the unit of the number passed" +// the second parameter is 'the unit of the number passed' const fromEtherToWie = Web3.utils.toWei('1.0', 'ether'); // outputs: 1000000000000000000 console.log(fromEtherToWie); diff --git a/docs/docs/guides/smart_contracts/_category_.yml b/docs/docs/guides/smart_contracts/_category_.yml index d234faa131b..6bf6e7694db 100644 --- a/docs/docs/guides/smart_contracts/_category_.yml +++ b/docs/docs/guides/smart_contracts/_category_.yml @@ -1,4 +1,4 @@ -label: 'Smart Contracts' +label: '📜 Smart Contracts' collapsible: true collapsed: true link: null diff --git a/docs/docs/guides/smart_contracts/index.md b/docs/docs/guides/smart_contracts/index.md index 52abc382011..6e73975a550 100644 --- a/docs/docs/guides/smart_contracts/index.md +++ b/docs/docs/guides/smart_contracts/index.md @@ -1,15 +1,12 @@ --- -sidebar_position: 2 +sidebar_position: 1 sidebar_label: 'Mastering Smart Contracts' --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - # Mastering Smart Contracts :::info -This guide expects you to have some basic knowledge. If you are just starting, it is recommended to first check out this [Tutorial: Deploying and Interacting with Smart Contracts](./deploying_and_interacting_with_smart_contracts). +This guide expects you to have some basic knowledge. If you are just starting, it is recommended to first check out this [Tutorial: Deploying and Interacting with Smart Contracts](./smart_contracts_guide.md). ::: ## Contract class @@ -22,37 +19,9 @@ To use the `Contract` class, you'll need to import it from one of two packages: Here's an example of importing from each: - - - -```javascript -// Importing from web3-eth-contract package -const { Contract } = require("web3-eth-contract"); -const contract = new Contract(...); - -// Importing from the main web3 package -const { Contract } = require("web3"); -const contract = new Contract(...); - -// Importing from the main web3 package from inside `web3.eth` namespace -const { Web3 } = require("web3"); -const web3 = new Web3("http://127.0.0.1:8545"); -const contract = new web3.eth.Contract(...); - -// to set the provider for the contract instance: -contract.setProvider('http://127.0.0.1:7545'); -``` - - - - - - ```ts // Importing from web3-eth-contract package -import { Contract } from "web3-eth-contract"; +import { Contract } from 'web3-eth-contract'; const contract = new Contract(...); // Importing from the main web3 package @@ -61,16 +30,13 @@ const contract = new Contract(...); // Importing from the main web3 package from inside `web3.eth` namespace import { Web3 } from 'web3'; -const web3 = new Web3("http://127.0.0.1:8545"); +const web3 = new Web3('http://127.0.0.1:8545'); const contract = new web3.eth.Contract(...); // to set the provider for the contract instance: contract.setProvider('http://127.0.0.1:7545'); ``` - - - ### `Contract` vs `web3.eth.Contract` @@ -86,43 +52,14 @@ Actually, the `web3.eth.Contract` is typically how you access the class through Examples: - - - -```javascript -const { Contract } = require("web3-eth-contract"); - -// instantiating Contract directly with provider URL from Contract package -// alternatively, you can instantiate the Contract without a provider and set it later using contract.setProvider() -const abi = [{...}]; -const address = '0x...'; -const contract = new Contract(abi, address { provider: "http://127.0.0.1:8545" }); - -// the provider can be set like this if not provided at the constructor: -contract.setProvider('http://127.0.0.1:7545'); - -// using Contract from a web3 instance -const web3 = new Web3('http://localhost:8545'); -const contract = new web3.eth.Contract(abi, address); -// no need to pass the provider to this contract instance. -// because it will have the same provider of the web3 instance. -``` - - - - - - ```ts -import { Contract } from "web3-eth-contract"; +import { Contract } from 'web3-eth-contract'; // instantiating Contract directly with provider URL from Contract package // alternatively, you can instantiate the Contract without a provider and set it later using contract.setProvider() const abi = [{...}]; const address = '0x...'; -const contract = new Contract(abi, address { provider: "http://127.0.0.1:8545" }); +const contract = new Contract(abi, address { provider: 'http://127.0.0.1:8545' }); // the provider can be set like this if not provided at the constructor: contract.setProvider('http://127.0.0.1:7545'); @@ -134,10 +71,6 @@ const contract = new web3.eth.Contract(abi, address); // because it will have the same provider of the web3 instance. ``` - - - - ### Constructor Parameters When you instantiate a `Contract`, you primarily provide one or two parameters, and sometimes 3 parameters: @@ -145,7 +78,7 @@ When you instantiate a `Contract`, you primarily provide one or two parameters, 1. **ABI (Application Binary Interface):** The ABI tells the `Contract` how to format calls and transactions so that the contract can understand them. :::tip -If you do not know how to get the contract ABI, we recommend you to check the Step 4 at the [Deploying and Interacting with Smart Contracts](./deploying_and_interacting_with_smart_contracts#step-4-compile-the-solidity-code-using-the-solidity-compiler-and-get-its-abi-and-bytecode) tutorial. And to look into the guide: [Infer Contract Types from JSON Artifact](./infer_contract_types_guide/). +If you do not know how to get the contract ABI, we recommend you to check the Step 4 at the [# Step 4: Deploying and Interacting with Smart Contracts](./smart_contracts_guide/#step-4-compile-the-solidity-code-using-the-solidity-compiler-and-get-its-abi-and-bytecode) tutorial. And to look into the guide: [Infer Contract Types from JSON Artifact](./infer_contract_types). ::: 2. (optional) **Contract Address:** The Ethereum address at which your contract is deployed. If the contract is not deployed yet, do not pass a second parameter or pass `undefined` to it. @@ -172,33 +105,7 @@ The `Contract` class comes equipped with a range of properties and methods for c - **config**: The set of configurations for the contract instance that is defaults to the same values as the `web3` object instance. But, it allows for using a different configurations for a specific contract instance. So, in most cases, you would use `web3.eth.Contract` and keep the configurations of the parent context (from the `web3` instance). Except if there is something you need to handle differently for only a specific contract instance. - Here is an example on how to set a value of a specific config variable on a contract instance: - - - - - -```javascript -const {Web3} = require('web3'); - -// Set up a connection to a testnet or Ethereum network -const web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:8545')); //or new Web3('http://127.0.0.1:8545') - -// Create a new contract object using the ABI and bytecode -const abi = [{...}] -const myContract = new web3.eth.Contract(abi); -console.log(myContract.config.handleRevert); //false - -// This will set `handleRevert` to `true` only on `myContract` instance: -myContract.handleRevert = true; // same as: myContract.config.handleRevert -console.log(myContract.config.handleRevert); //true - -``` - - - +Here is an example on how to set a value of a specific config variable on a contract instance: ```ts import {Web3} from 'web3'; @@ -216,10 +123,6 @@ myContract.handleRevert = true; // same as: myContract.config.handleRevert console.log(myContract.config.handleRevert); //true ``` - - - - More on the `config` properties in the [API documentation](/api/web3/namespace/core/#Web3ConfigOptions) @@ -265,7 +168,7 @@ myContract.options.jsonInterface = [{...}]; // ABI // to call a method by sending a transaction contract.methods.METHOD_NAME(METHOD_PARAMETERS).send(); // you need to specify the account (from) that will be used to sign and send the transaction -contract.methods.METHOD_NAME(METHOD_PARAMETERS).send({from: "0x..."}); +contract.methods.METHOD_NAME(METHOD_PARAMETERS).send({from: '0x...'}); // to call a view or pure method that does not send a transaction contract.methods.METHOD_NAME(METHOD_PARAMETERS).call(); @@ -346,7 +249,7 @@ console.log('Contract deployed at address: ' + tx.options.address); ``` :::tip -If you do not know how to get the contract bytecode, we recommend you to check the Step 4 at the [Deploying and Interacting with Smart Contracts](./deploying_and_interacting_with_smart_contracts#step-4-compile-the-solidity-code-using-the-solidity-compiler-and-get-its-abi-and-bytecode) tutorial. +If you do not know how to get the contract bytecode, we recommend you to check the Step 4 at the [Deploying and Interacting with Smart Contracts](./smart_contracts_guide#step-4-compile-the-solidity-code-using-the-solidity-compiler-and-get-its-abi-and-bytecode) tutorial. ::: - **getPastEvents**: Gets past events for this contract. It differs from `events` properties that it returns the past events as an array, rather than allowing to subscribe to them like when using `events` properties. More on the [API documentation](/api/web3-eth-contract/class/Contract#getPastEvents) @@ -354,24 +257,6 @@ If you do not know how to get the contract bytecode, we recommend you to check t - **setProvider**: This allows you to set a specific provider for a contract instance. As highlighted early in this guide, this is especially handy if you are importing the `Contract` object from `web3-eth-contract` and then you will need to set the provider while there is no `web3` context to read the provider from. - - - - -```javascript -// Importing from web3-eth-contract package -const { Contract } = require('web3-eth-contract'); -const contract = new Contract(...); - -// to set the provider for the contract instance -contract.setProvider('yourProvider'); -``` - - - - ```ts // Importing from web3-eth-contract package import { Contract } from 'web3-eth-contract'; @@ -381,9 +266,6 @@ const contract = new Contract(...); contract.setProvider('yourProvider'); ``` - - - ## ABI and Bytecode @@ -392,7 +274,7 @@ The ABI is the Application Binary Interface ( ABI ) of a smart contract. Which d For example, for the following solidity code: -```js +```ts // SPDX-License-Identifier: MIT pragma solidity 0.8.0; @@ -408,7 +290,9 @@ contract MyContract { } } ``` + Its ABI would be: + ```ts const abi = [ { @@ -442,13 +326,14 @@ const bytecode = '0x60806040523480156100115760006000fd5b506040516102243803806102 :::info And as mentioned in the tips inside previous sections: -If you do not know how to get the contract ABI and bytecode, we recommend you to check the Step 4 at the [Deploying and Interacting with Smart Contracts](./deploying_and_interacting_with_smart_contracts#step-4-compile-the-solidity-code-using-the-solidity-compiler-and-get-its-abi-and-bytecode) tutorial. +If you do not know how to get the contract ABI and bytecode, we recommend you to check the Step 4 at the [Deploying and Interacting with Smart Contracts](./smart_contracts_guide#step-4-compile-the-solidity-code-using-the-solidity-compiler-and-get-its-abi-and-bytecode) tutorial. ::: ### Do I always need the contract ByteCode? The short answer is yes, only if you need to deploy the smart contract yourself. And below is more elaboration on this. Basically, with every Contract instance, there are 2 cases. First case is when you want to deploy a smart contract. And in this case, you will need to provide the bytecode of this smart contract. + ```ts import {Contract} from 'web3-eth-contract'; diff --git a/docs/docs/guides/smart_contracts/infer_contract_types_guide/index.md b/docs/docs/guides/smart_contracts/infer_contract_types.md similarity index 70% rename from docs/docs/guides/smart_contracts/infer_contract_types_guide/index.md rename to docs/docs/guides/smart_contracts/infer_contract_types.md index d216a40809e..8dcd006e2e4 100644 --- a/docs/docs/guides/smart_contracts/infer_contract_types_guide/index.md +++ b/docs/docs/guides/smart_contracts/infer_contract_types.md @@ -1,5 +1,6 @@ --- -sidebar_label: 'Infer Contract Types from JSON Artifact' +sidebar_position: 3 +sidebar_label: 'Infer Contract Types from JSON Artifact (TypeScript)' --- # Infer Contract Types from JSON Artifact @@ -13,45 +14,44 @@ Web3.js is a popular library used for interacting with EVM blockchains. One of i Before we dive into the problem, let's take a quick look at the problem. Web3.js provides a simple and convenient way to interact with Solidity contracts. To use Web3.js to interact with a Solidity contract, you need to know the contract's address and the ABI (Application Binary Interface) of the contract. The ABI is JSON data that contains the definition of the functions in the contract, including their, name, input parameters and return values. -Web3.js uses ABI type to dynamically load available methods and events but Typescript currently [doesn't support loading JSON as const](https://github.com/microsoft/TypeScript/issues/32063). If you go to the [Playground Link](https://www.typescriptlang.org/play?#code/MYewdgzgLgBAhgIwJYwLwwNoCga5gbxz1wCIkwAHAVyghIC5MjjdCWWywoBTAJzDgAbACoBPCtwYwS0XuQDmJADTN20gQFtJjEpu4B9ZavYko47dNkKSxvAF8VagreKce-IWIlSZUOWEVHJ3U4LR8IUQ0EEEFDIKdTc3C-axcYO1sAXXi8XzgeAFkaRCRBJDMfMHAKOFFEQUkc0jNvHVBIPypgKBBeG2IHVTYOOCqwSJAqOkYAMyEIbibpcmpaKWwnYYTyABNuAA9uHalOxbTScncBESSdOB2d3m4IOiXXPR8QAHcwPiNg6QtCwke6PZ50NKDTbnZZgPaHY6MU5vXKXPjXLzA0FPF7-YK6ULAiASOF-FHNW7SbHg-pqKFqLZqTjwo5SOaCBbk2FXTyUkhUS4AJgArAA2PEJD46ABuQiojRhiVa0gFXBF4shWSWBLCOgAghQKLwQLLBBLckCfNxpdwuLTcPTWLYQWMJlM2fMziYVjRpkxoQDmQdWUjePKuW50bzlSCHjjXoqpdIZsaNOaTJa7nGaZCUYzvaSEScw178WiPDcY9TcRGk6YQOmOJmqdncbm0vmOLtg4iYOzOYryxi+aqoOrG+9CT5TfKJxaR0KxfaWBl2NlnXXhLxRhAZmTnc2SNbbVBl47nAXVn6NgzB1wo5Wsa2E4G699fn0I4fqxCnOfiJ2rhDtGT5gjWiZTjoxK2nsn6Kt+z7LgMWobpBVKCII3yjMAComJMUBXusHZ3jyj4+KO461mhJBzhSMYUUumprtq0D5NwRRQCUZQVDKSDcF8jZKsCMxUGA3RIOAZ45J2nCEYwN7sIBqL3hWmI+D+tEhLqlgkrBmlCepiHtgGZYqcO9GLuKVHaSCGiTHaX4LmqjF-ihJh1nAhrGjagn4XJ-q3oGwFkTo0QxPpdb6YeYVmkxLDriYrGFMUyDcaIlTVLU9S4U2fIiWJUASWAUlDM6PprPJxFBWZIGGWBL74h5wCgKJp6OVWRmucxqE2QgQjYdwADyMy+TQ-kKSwSkXDVIUqpZEXUVFTlji5dJuRwSXsSlpTlOlvH8YJh75eJkmqOeMnldeCUcHWezAEgGjzKNBG+kRJnbDNak6KOAAcC02UtFlcH9cXENdribRxXG7dOfECdqR2iSdxVndJZWUK9lXvUywVfS29X-USun7oGCEE8ZgWmaReP8vN1lElQCB+HA3RHAAanKOUJIeDEal18Xard3DAE8cALHqGFYWJXO5H5mMBYpJEPjTMWEz4gPAqroN4ODuSQ9taUZZQWUIA0h15UjhWnQMaOXvLE0AUrql8hp9PhMTcGky7nV0nmTvmcCvNq1mew7Bzgizu1gfzdruC66QdbkCL3Bi9wEuYV8A3PeNVVU8rfKq27Ogaz4Wv82DLGcclnGpTDOhjDUdSmzLdHCZbRUlY7dsVZg8dacCHzanLPcO3gU3cvnMZWAEwfSCXUEpDPscwH3eTV9DPHSNKcPmzGx1WyjNuld3V2C9RERROFQ9jfbucfdTfLT4EEEA1HyT+Ioy+r-rNc7ZvJDbwOgjC2BUO6o2Pl2DGI9V51h6JxQQABlKghpBDpWvi9Eed8cafWWpRF+wJ55zWcnzNa3VEpVy2r-Q2+14YHhAcjTuY90Y52xgWB+HUCZF0BA2N+Id4xIXsH7aq7Do7ENnrZeybV4K4NWuwVcAserAmZpAPcnsODD2vFgthk9NYgCvvg9WvDpBl1IQo8hbEoa13-g3E2ZtgF73btbQRECgJQM0awyBIi6r8K4SQFMIA0xGNjOTP8Qi87Ow4T4gxOgeiEOCfwimithE6PInTaJVI7KtTiUHL+Z8bLKN3HwAAYqmbOt8PGuK8aFPRZpfFxJMXI9aEMKGWL-ntdQmUm52LoQ40BTiHREEyPACAMB2jQAANxAA) and choose ".d.ts" you can check type difference with and without `as const`. +Web3.js uses ABI type to dynamically load available methods and events but Typescript currently [doesn't support loading JSON as const](https://github.com/microsoft/TypeScript/issues/32063). If you go to the [Playground Link](https://www.typescriptlang.org/play?#code/MYewdgzgLgBAhgIwJYwLwwNoCga5gbxz1wCIkwAHAVyghIC5MjjdCWWywoBTAJzDgAbACoBPCtwYwS0XuQDmJADTN20gQFtJjEpu4B9ZavYko47dNkKSxvAF8VagreKce-IWIlSZUOWEVHJ3U4LR8IUQ0EEEFDIKdTc3C-axcYO1sAXXi8XzgeAFkaRCRBJDMfMHAKOFFEQUkc0jNvHVBIPypgKBBeG2IHVTYOOCqwSJAqOkYAMyEIbibpcmpaKWwnYYTyABNuAA9uHalOxbTScncBESSdOB2d3m4IOiXXPR8QAHcwPiNg6QtCwke6PZ50NKDTbnZZgPaHY6MU5vXKXPjXLzA0FPF7-YK6ULAiASOF-FHNW7SbHg-pqKFqLZqTjwo5SOaCBbk2FXTyUkhUS4AJgArAA2PEJD46ABuQiojRhiVa0gFXBF4shWSWBLCOgAghQKLwQLLBBLckCfNxpdwuLTcPTWLYQWMJlM2fMziYVjRpkxoQDmQdWUjePKuW50bzlSCHjjXoqpdIZsaNOaTJa7nGaZCUYzvaSEScw178WiPDcY9TcRGk6YQOmOJmqdncbm0vmOLtg4iYOzOYryxi+aqoOrG+9CT5TfKJxaR0KxfaWBl2NlnXXhLxRhAZmTnc2SNbbVBl47nAXVn6NgzB1wo5Wsa2E4G699fn0I4fqxCnOfiJ2rhDtGT5gjWiZTjoxK2nsn6Kt+z7LgMWobpBVKCII3yjMAComJMUBXusHZ3jyj4+KO461mhJBzhSMYUUumprtq0D5NwRRQCUZQVDKSDcF8jZKsCMxUGA3RIOAZ45J2nCEYwN7sIBqL3hWmI+D+tEhLqlgkrBmlCepiHtgGZYqcO9GLuKVHaSCGiTHaX4LmqjF-ihJh1nAhrGjagn4XJ-q3oGwFkTo0QxPpdb6YeYVmkxLDriYrGFMUyDcaIlTVLU9S4U2fIiWJUASWAUlDM6PprPJxFBWZIGGWBL74h5wCgKJp6OVWRmucxqE2QgQjYdwADyMy+TQ-kKSwSkXDVIUqpZEXUVFTlji5dJuRwSXsSlpTlOlvH8YJh75eJkmqOeMnldeCUcHWezAEgGjzKNBG+kRJnbDNak6KOAAcC02UtFlcH9cXENdribRxXG7dOfECdqR2iSdxVndJZWUK9lXvUywVfS29X-USun7oGCEE8ZgWmaReP8vN1lElQCB+HA3RHAAanKOUJIeDEal18Xard3DAE8cALHqGFYWJXO5H5mMBYpJEPjTMWEz4gPAqroN4ODuSQ9taUZZQWUIA0h15UjhWnQMaOXvLE0AUrql8hp9PhMTcGky7nV0nmTvmcCvNq1mew7Bzgizu1gfzdruC66QdbkCL3Bi9wEuYV8A3PeNVVU8rfKq27Ogaz4Wv82DLGcclnGpTDOhjDUdSmzLdHCZbRUlY7dsVZg8dacCHzanLPcO3gU3cvnMZWAEwfSCXUEpDPscwH3eTV9DPHSNKcPmzGx1WyjNuld3V2C9RERROFQ9jfbucfdTfLT4EEEA1HyT+Ioy+r-rNc7ZvJDbwOgjC2BUO6o2Pl2DGI9V51h6JxQQABlKghpBDpWvi9Eed8cafWWpRF+wJ55zWcnzNa3VEpVy2r-Q2+14YHhAcjTuY90Y52xgWB+HUCZF0BA2N+Id4xIXsH7aq7Do7ENnrZeybV4K4NWuwVcAserAmZpAPcnsODD2vFgthk9NYgCvvg9WvDpBl1IQo8hbEoa13-g3E2ZtgF73btbQRECgJQM0awyBIi6r8K4SQFMIA0xGNjOTP8Qi87Ow4T4gxOgeiEOCfwimithE6PInTaJVI7KtTiUHL+Z8bLKN3HwAAYqmbOt8PGuK8aFPRZpfFxJMXI9aEMKGWL-ntdQmUm52LoQ40BTiHREEyPACAMB2jQAANxAA) and choose '.d.ts' you can check type difference with and without `as const`. ```typescript import { Contract, Web3 } from 'web3'; import ERC20 from './node_modules/@openzeppelin/contracts/build/contracts/ERC20.json'; (async function () { - const web3 = new Web3('rpc url'); + const web3 = new Web3('rpc url'); - const contract = new Contract(ERC20.abi, '0x7af963cF6D228E564e2A0aA0DdBF06210B38615D', web3); + const contract = new Contract(ERC20.abi, '0x7af963cF6D228E564e2A0aA0DdBF06210B38615D', web3); - const holder = '0xa8F6eB216e26C1F7d924A801E46eaE0CE8ed1A0A'; + const holder = '0xa8F6eB216e26C1F7d924A801E46eaE0CE8ed1A0A'; - //Error because Contract doesn't know what methods exists - const balance = await contract.methods.balanceOf(holder).call(); + //Error because Contract doesn't know what methods exists + const balance = await contract.methods.balanceOf(holder).call(); })(); ``` To work around it you need to copy abi into a Typescript file like this: ```typescript -import {Contract, Web3} from "web3"; - +import {Contract, Web3} from 'web3'; const ERC20 = [ ... - // "as const" is important part, without it typescript would create generic type and remove available methods from type + // 'as const' is important part, without it typescript would create generic type and remove available methods from type ] as const; -(async function() { - const web3 = new Web3("rpc url") +(async function () { + const web3 = new Web3('rpc url'); - const contract = new Contract(ERC20, "0x7af963cF6D228E564e2A0aA0DdBF06210B38615D", web3) + const contract = new Contract(ERC20, '0x7af963cF6D228E564e2A0aA0DdBF06210B38615D', web3); - const holder = "0xa8F6eB216e26C1F7d924A801E46eaE0CE8ed1A0A" + const holder = '0xa8F6eB216e26C1F7d924A801E46eaE0CE8ed1A0A'; - //Works now - const balance = await contract.methods.balanceOf(holder).call() -})() + //Works now + const balance = await contract.methods.balanceOf(holder).call(); +})(); ``` Now it's working but it also means that abi is no longer updated when you bump your npm dependencies. @@ -59,7 +59,7 @@ To solve this problem, you can use a custom script that copies the JSON artifact Script: -```typescript title="gen.ts" +```typescript title='gen.ts' import fs from 'fs'; import path from 'path'; @@ -72,57 +72,53 @@ const artifactContent = fs.readFileSync('./artifacts.json', 'utf-8'); const artifacts: string[] = JSON.parse(artifactContent); (async function () { - for (const artifact of artifacts) { - let content; - try { - //try to import from node_modules - content = JSON.stringify(await import(artifact)); - } catch (e) { - //try to read as path on disc - content = fs.readFileSync(artifact, 'utf-8'); - } - const filename = path.basename(artifact, '.json'); - //create and write typescript file - fs.writeFileSync( - path.join(destination, filename + '.ts'), - `const artifact = ${content.trimEnd()} as const; export default artifact;`, - ); - } + for (const artifact of artifacts) { + let content; + try { + //try to import from node_modules + content = JSON.stringify(await import(artifact)); + } catch (e) { + //try to read as path on disc + content = fs.readFileSync(artifact, 'utf-8'); + } + const filename = path.basename(artifact, '.json'); + //create and write typescript file + fs.writeFileSync(path.join(destination, filename + '.ts'), `const artifact = ${content.trimEnd()} as const; export default artifact;`); + } })(); ``` To use this script, just create an `artifacts.json` file at the root of your project with all the artifacts you are using. -```json title="artifacts.json" +```json title='artifacts.json' [ - "@openzeppelin/contracts/build/contracts/ERC20.json", - "@openzeppelin/contracts/build/contracts/ERC1155.json", - "./build/contracts/MyContract.json" + '@openzeppelin/contracts/build/contracts/ERC20.json', + '@openzeppelin/contracts/build/contracts/ERC1155.json', + './build/contracts/MyContract.json' ] ``` -and run the script with `node -r ts-node/register - - - - - - - - +//interact with the contract +//wallet[0].address == '0x57CaabD59a5436F0F1b2B191b1d070e58E6449AE' +//highlight-next-line +const txReceipt = await myContract.methods.doSomething().send({ from: wallet[0].address }); +console.log('Transaction receipt:', txReceipt); +/* ↳ + Transaction receipt: {...} +*/ ``` -## Sending a transaction using a local wallet with contract methods +### Reading functions (view) -``` ts -// First step: initialize `web3` instance +To interact with smart contracts `view public/external returns`, we don't need to instantiate a `Wallet`, we can do it just by instantiating the smart contract and the provider. + +```ts title='Interacting with reading-functions of a smart contract' import { Web3 } from 'web3'; -const web3 = new Web3(/* PROVIDER*/); - -// Second step: add an account to wallet -const privateKeyString = 'Private key'; -const account = web3.eth.accounts.wallet.add(privateKeyString).get(0); - -// Make sure the account has enough eth on balance to send the transaction - -// fill ContractAbi and ContractBytecode with your contract's abi and bytecode - -async function contractMethod() { - try { - - // add the contract details of which method you want to call, using the contract abi and contract address - const contract = new web3.eth.Contract(ContractAbi, "contract address"); - - // call contract method and send - await contractDeployed.methods - .method('0xe2597eb05cf9a87eb1309e86750c903ec38e527e') - .send({ - from: account?.address, - gas: '1000000', - // other transaction's params - }); - } catch (error) { - // catch transaction error - console.error(error); - } -} -(async () => { - await contractMethod(); -})(); +//instantiate the provider +const web3 = new Web3('https://ethereum-sepolia.publicnode.com'); + +//instantiate the contract +const myContract = new web3.eth.Contract(ABI, CONTRACT_ADDRESS); + +//call the `view function` in the contract +//highlight-next-line +const result = await myContract.methods.doSomething().call(); + +console.log('Result:', result) +/* ↳ + Result: ... +*/ +``` -``` \ No newline at end of file +## Wallet methods + +The following is a list of `Wallet` [methods](/libdocs/Wallet) in the `web3.eth.accounts.wallet` package with description and example usage: + +- [add](/libdocs/Wallet#add) +- [clear](/libdocs/Wallet#clear) +- [create](/libdocs/Wallet#create) +- [decrypt](/libdocs/Wallet#decrypt) +- [encrypt](/libdocs/Wallet#encrypt) +- [get](/libdocs/Wallet#get) +- [load](/libdocs/Wallet#load) +- [remove](/libdocs/Wallet#remove) +- [save](/libdocs/Wallet#save) +- [getStorage](/libdocs/Wallet#getStorage) + +## Account methods + +The following is a list of `Accounts` [methods](/libdocs/Wallet) in the `web3.eth.accounts` package with description and example usage: + +- [create](/libdocs/Accounts#create) +- [decrypt](/libdocs/Accounts#decrypt) +- [encrypt](/libdocs/Accounts#encrypt) +- [hashMessage](/libdocs/Accounts#hashMessage) +- [parseAndValidatePrivateKey](/libdocs/Accounts#libdocs/Accounts#parseandvalidateprivatekey) +- [privateKeyToAccount](/libdocs/Accounts#privatekeytoaccount) +- [privateKeyToAddress](/libdocs/Accounts#privatekeytoaddress) +- [privateKeyToPublicKey](/libdocs/Accounts#privatekeytopublickey) +- [recover](/libdocs/Accounts#recover) +- [recoverTransaction](/libdocs/Accounts#recovertransaction) +- [sign](/libdocs/Accounts#sign) +- [signTransaction](/libdocs/Accounts#signtransaction) \ No newline at end of file diff --git a/docs/docs/guides/wallet/local_wallet.md b/docs/docs/guides/wallet/local_wallet.md new file mode 100644 index 00000000000..26f86dd5fd8 --- /dev/null +++ b/docs/docs/guides/wallet/local_wallet.md @@ -0,0 +1,124 @@ +--- +sidebar_position: 3 +sidebar_label: 'Tutorial: Local Wallets' +--- + +# Local Wallets + +Local wallets are an in-memory [wallet](/api/web3-eth-accounts/class/Wallet/) that can hold multiple accounts. +Wallets are a convenient way to sign and send transactions in web3.js + +:::warning +If used within the browser, wallets are not saved anywhere and disappear when the page is refreshed. +If used within your application, wallets will disappear after the program is completed. +::: + +## Create an account and add it to an empty `Wallet` + +```ts title='Creating an Account and Adding it to an Empty Wallet' +import { Web3 } from 'web3'; + +const web3 = new Web3(/* PROVIDER */); + +// 1st - creating a new empty wallet (0 accounts inside) +const wallet = web3.eth.accounts.wallet.create(); + +console.log(wallet); +/* ↳ +Wallet(0) [ + _accountProvider: { + create: [Function: createWithContext], + privateKeyToAccount: [Function: privateKeyToAccountWithContext], + decrypt: [Function: decryptWithContext] + }, + _addressMap: Map(0) {}, + _defaultKeyName: 'web3js_wallet' +] +*/ + +// 2nd - create an account +const account = web3.eth.accounts.create(); + +console.log(account) +/* ↳ +{ + address: '0x0770B4713B62E0c08C43743bCFcfBAA39Fa703EF', + privateKey: '0x97b0c07e275a0d8d9983331ca1a7ecb1a4a6f7dcdd7657529fe07446fa4dfe23', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] +} +*/ + +// 3rd - add the account to the wallet +web3.eth.accounts.wallet.add(account); + +console.log(wallet); +/* ↳ +Wallet(1) [ + { + address: '0x0770B4713B62E0c08C43743bCFcfBAA39Fa703EF', + privateKey: '0x97b0c07e275a0d8d9983331ca1a7ecb1a4a6f7dcdd7657529fe07446fa4dfe23', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + _accountProvider: { + create: [Function: createWithContext], + privateKeyToAccount: [Function: privateKeyToAccountWithContext], + decrypt: [Function: decryptWithContext] + }, + _addressMap: Map(1) { '0x0770b4713b62e0c08c43743bcfcfbaa39fa703ef' => 0 }, + _defaultKeyName: 'web3js_wallet' +] +*/ +``` + +## Import a privateKey and add it to an empty `Wallet` + +```ts title='Creating a wallet and adding an account with a private key' +import { Web3 } from 'web3'; + +const web3 = new Web3(/* PROVIDER */); + +// 1st - creating a new empty wallet +const wallet = web3.eth.accounts.wallet.create() + +console.log(wallet); +/* ↳ +> Wallet(0) [ + _accountProvider: { + create: [Function: createWithContext], + privateKeyToAccount: [Function: privateKeyToAccountWithContext], + decrypt: [Function: decryptWithContext] + }, + _addressMap: Map(0) {}, + _defaultKeyName: 'web3js_wallet' +] +*/ + +// 2nd - add an account to the wallet using a private key +const privateKey = '0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba' +web3.eth.accounts.wallet.add(privateKey); + +console.log(wallet); +/* ↳ +Wallet(1) [ + { + address: '0x9E82491d1978217d631a3b467BF912933F54788f', + privateKey: '0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + _accountProvider: { + create: [Function: createWithContext], + privateKeyToAccount: [Function: privateKeyToAccountWithContext], + decrypt: [Function: decryptWithContext] + }, + _addressMap: Map(1) { '0x9e82491d1978217d631a3b467bf912933f54788f' => 0 }, + _defaultKeyName: 'web3js_wallet' +] +*/ +``` + diff --git a/docs/docs/guides/basics/sign_and_send_tx/wallet_of_eth_node.md b/docs/docs/guides/wallet/node_wallet.md similarity index 50% rename from docs/docs/guides/basics/sign_and_send_tx/wallet_of_eth_node.md rename to docs/docs/guides/wallet/node_wallet.md index fa2e89a3c8e..a4adbbab987 100644 --- a/docs/docs/guides/basics/sign_and_send_tx/wallet_of_eth_node.md +++ b/docs/docs/guides/wallet/node_wallet.md @@ -1,61 +1,17 @@ --- -sidebar_position: 1 -sidebar_label: 'Node Wallet' +sidebar_position: 6 +sidebar_label: 'Tutorial: Node Wallet' --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - # Using Node Wallet If Ethereum node has unlocked account in its wallet you can send transaction without need of signing locally in web3.js -## Transaction - - - - - -```javascript -// First step: initialize web3 instance -const { Web3 } = require('web3'); -const web3 = new Web3(/* PROVIDER*/); - -// Second step: add an account to the Ethereum node and unlock it -const account = { - privateKey: 'privateKey', - address: '0xe4beef667408b99053dc147ed19592ada0d77f59', -}; - -// if you use ganache backend, use a private key with 0x -await web3.eth.personal.importRawKey(account.privateKey); -// if you use geth backend, use a private key without 0x -await web3.eth.personal.importRawKey(account.privateKey.slice(2)); - -// unlock account -await web3Personal.unlockAccount(account.address, 'anyPassword', 100000000); -// Make sure the account has enough eth on balance to send the transaction - -// Third step: sign and send the transaction -try { - const receipt = await web3.eth.sendTransaction({ - from: account.address, - to: '0xe4beef667408b99053dc147ed19592ada0d77f59', - value: '0x1', - gas: '300000', - // other transaction's params - }); -} catch (error) { - // catch transaction error - console.error(error); -} -``` +:::danger +Using `web3.eth.personal` is not considered secure and is strongly discouraged. The personal RPC endpoints have been deprecated due to significant security issues. More info: [geth.ethereum.org](https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-personal) +::: - - - +## Transaction ```typescript // First step: initialize web3 instance @@ -92,76 +48,13 @@ try { } ``` - - - List of references: - [eth.sendTransaction](/api/web3-eth/class/Web3Eth#sendTransaction) - [eth.personal.importRawKey](/api/web3-eth-personal/class/Personal#importRawKey) - [eth.personal.unlockAccount](/api/web3-eth-personal/class/Personal#unlockAccount) -## Contract Transaction - - - - - - -```javascript -// First step: initialize web3 instance -const { Web3 } = require('web3'); -const web3 = new Web3(/* PROVIDER*/); - -// Second step: add an account to the Ethereum node and unlock it -const account = { - privateKey: 'privateKey', - address: '0xe4beef667408b99053dc147ed19592ada0d77f59', -}; - -// if you use ganache backend, use a private key with 0x -await web3.eth.personal.importRawKey(account.privateKey); -// if you use geth backend, use a private key without 0x -await web3.eth.personal.importRawKey(account.privateKey.slice(2)); - -// unlock account -await web3.eth.personal.unlockAccount(account.address, 'anyPassword', 100000000); -// Make sure the account has enough eth on balance to send the transaction - -// Third step: sign and send the transaction -try { - // deploy - const contract = new web3.eth.Contract(ContractAbi); - const contractDeployed = await contract - .deploy({ - input: ContractBytecode, - arguments: ['Constructor param1', 'Constructor param2'], - }) - .send({ - from: account.address, - gas: '1000000', - // other transaction's params - }); - - // call method - await contractDeployed.methods - .transfer('0xe2597eb05cf9a87eb1309e86750c903ec38e527e', '0x1') - .send({ - from: account.address, - gas: '1000000', - // other transaction's params - }); -} catch (error) { - // catch transaction error - console.error(error); -} -``` - - - - +## Contract Deployment ```typescript // First step: initialize web3 instance @@ -212,10 +105,6 @@ try { } ``` - - - - List of references: - [eth.Contract](/api/web3-eth-contract/class/Contract) diff --git a/docs/docs/guides/basics/sign_and_send_tx/promi_event.md b/docs/docs/guides/wallet/promi_event.md similarity index 93% rename from docs/docs/guides/basics/sign_and_send_tx/promi_event.md rename to docs/docs/guides/wallet/promi_event.md index b1372bb315f..6f310c41557 100644 --- a/docs/docs/guides/basics/sign_and_send_tx/promi_event.md +++ b/docs/docs/guides/wallet/promi_event.md @@ -1,13 +1,13 @@ --- -sidebar_position: 3 -sidebar_label: 'Web3PromiEvent' +sidebar_position: 2 +sidebar_label: 'Transactions Events Listening' --- -# PromiEvent +# Promise Event -You can use Web3PromiEvent when you send transaction via `web3.eth.sendTransaction`, `web3.eth.sendSignedTransaction`, `contractDeployed.methods['methodName'](...methodParams).send` functions +You can use `Web3PromiEvent` when you send transaction via `web3.eth.sendTransaction`, `web3.eth.sendSignedTransaction`, `contractDeployed.methods['methodName'](...methodParams).send` functions -```ts +```ts title='Transaction Promise Events' web3.eth.sendTransaction({...}) .on('sending', (sending) => { // Sending example @@ -83,8 +83,6 @@ web3.eth.sendTransaction({...}) // ] // } }); - - ``` List of references: diff --git a/docs/docs/guides/wallet/signing.md b/docs/docs/guides/wallet/signing.md new file mode 100644 index 00000000000..88184c2a7fa --- /dev/null +++ b/docs/docs/guides/wallet/signing.md @@ -0,0 +1,131 @@ +--- +sidebar_position: 4 +sidebar_label: 'Tutorial: Signing operations' +--- + +# Signing operations + +In this guide, we'll cover how to sign `data` and `transactions` using web3.js. Whether it's signing data with an account, signing transactions, or using wallets and private keys, we'll walk you through the basic steps. Let's get started! + + +## Sign Data With an `Account` + +In this example we are creating a random account `web3.eth.account.create()`, but you can also import a specific account by using `web3.eth.accounts.privateKeyToAccount('0x...')` + +``` ts +import { create } from 'web3-eth-accounts'; + +// the create method returns a `Web3Account` object +// the account contains an `address` and `privateKey` and allows you to be able to encrypt, signData and signTransaction. +const account = create(); //this is the same as web3.eth.accounts.create(); + +/* ↳ +{ +address: '0xbD504f977021b5E5DdccD8741A368b147B3B38bB', +privateKey: 'privateKey', +signTransaction: [Function: signTransaction], +sign: [Function: sign], +encrypt: [AsyncFunction: encrypt] +} +*/ + +account.sign('hello world'); +/* ↳ +{ + message: 'hello world', + messageHash: '0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68', + v: '0x1b', + r: '0xe4fce466ef18f6cd8b4f4175a9a04cd2872a1a6a8cfc2ff67fb0cfd6d78ec758', + s: '0x37ca3a789976f1854d16e50a04caf2e06ee14b0ac4a5878b43929767f2008288', + signature: '0xe4fce466ef18f6cd8b4f4175a9a04cd2872a1a6a8cfc2ff67fb0cfd6d78ec75837ca3a789976f1854d16e50a04caf2e06ee14b0ac4a5878b43929767f20082881b' +} +*/ +``` + +## Sign a Transaction With an `Account` + +In this example we are importing a specific account by using `web3.eth.accounts.privateKeyToAccount('0x...')` but you can also create a random account by using `web3.eth.account.create()`. + +``` ts +import { Web3 } from 'web3'; + +const web3 = new Web3(/* PROVIDER */); + +const privateKey = '0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba' +const account = web3.eth.accounts.privateKeyToAccount(privateKey); + +// Magic happens inside signTransaction. If a transaction is sent from an account that exists in a wallet, it will be automatically signed using that account. +signedTransaction = await account.signTransaction({ + from: account.address, + to: '0xe4beef667408b99053dc147ed19592ada0d77f59', + value: '0x1', + gas: '300000', + gasPrice: await web3.eth.getGasPrice(), +}); + +console.log(signedTransaction); +/* ↳ +{ +messageHash: '0xfad22c3ab5ecbb6eec934a21243ee1866fbbd3786f4e8e8ec631b917ef65174d', +v: '0xf4f6', +r: '0xc0035636d9417f63fdd418bc545190e59b58a4ff921bbf4efebf352dac211f11', +s: '0x4944d746ff12c7bca41f77c8f7d75301cea8b205e021dfde34d09d5bdccc713d', +rawTransaction: + '0xf866808477359400830493e094e4beef667408b99053dc147ed19592ada0d77f59018082f4f6a0c0035636d9417f63fdd418bc545190e59b58a4ff921bbf4efebf352dac211f11a04944d746ff12c7bca41f77c8f7d75301cea8b205e021dfde34d09d5bdccc713d', +transactionHash: '0xa3fed275c97abc4a160cd9bef3ec90206686f32821a8fd4e01a04130bff35c1a', +}; +*/ +``` + +## Signing data/messages using a wallet + +``` ts title='Signing with a wallet' +import { Web3 } from 'web3'; + +const web3 = new Web3(/* PROVIDER */); + +// create a `Wallet` with 1 account inside +const wallet = web3.eth.accounts.wallet.create(1); + +const message = web3.utils.utf8ToHex('Hello world'); // sign only takes hexstrings, so turn message to hexstring + +const signedMessage = web3.eth.sign(message, wallet[0].address); + +console.log(signedMessage); +/* ↳ +{ + message: '0x48656c6c6f20776f726c64', + messageHash: '0x8144a6fa26be252b86456491fbcd43c1de7e022241845ffea1c3df066f7cfede', + v: '0x1c', + r: '0x3a420906f331896cb5db1366cdaeef1f0b14f9f71d72c178e87b76f8b31f3f36', + s: '0x32ffccc78638c1d7e46dbf16041ddaef90ab50a85eeeaa46f8c496a39237831a', + signature: '0x3a420906f331896cb5db1366cdaeef1f0b14f9f71d72c178e87b76f8b31f3f3632ffccc78638c1d7e46dbf16041ddaef90ab50a85eeeaa46f8c496a39237831a1c' +} +*/ +``` + +## Signing data/messages using a privateKey + +```ts title= 'Signing with a private key' +import { Web3 } from 'web3'; + +const web3 = new Web3(/* PROVIDER */); + +const privateKey = '0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba'; + +const message = 'Hello world'; +const signedMessage = web3.eth.accounts.sign(message, privateKey); + +console.log(signedMessage); +/* ↳ +{ + message: 'Hello world', + messageHash: '0x8144a6fa26be252b86456491fbcd43c1de7e022241845ffea1c3df066f7cfede', + v: '0x1c', + r: '0xb669ef385082d7c4393522ab2fc37f8684fe948b313fb64b7cb8bee851b765f1', + s: '0x26eec81e9900d25500c13024b273e238cfb2a4d4554b79f74b372e1132b6cb2f', + signature: '0xb669ef385082d7c4393522ab2fc37f8684fe948b313fb64b7cb8bee851b765f126eec81e9900d25500c13024b273e238cfb2a4d4554b79f74b372e1132b6cb2f1c' +} +*/ +``` + diff --git a/docs/docs/guides/wallet/transactions.md b/docs/docs/guides/wallet/transactions.md new file mode 100644 index 00000000000..4219185bb57 --- /dev/null +++ b/docs/docs/guides/wallet/transactions.md @@ -0,0 +1,345 @@ +--- +sidebar_position: 5 +sidebar_label: 'Tutorial: Sending Transactions' +--- + +# Transactions + +This guide provides insights into sending transactions using web3.js, covering various scenarios from utilizing a local wallet to sending raw transactions. + +## Sending transactions with a local wallet + +The simplest way to sign and send transactions is using a local wallet: + +```typescript +// 1st step: initialize `web3` instance +import { Web3 } from 'web3'; + +const web3 = new Web3(/* PROVIDER*/); + +// 2nd step: add an account to wallet +const privateKey = '0x7b907534ec13b19c67c2a738fdaa69014298c71f2221d7e5dec280232e996610'; +const account = web3.eth.accounts.wallet.add(privateKey).get(0); +// Make sure the account has enough eth on balance to send the transaction + +// 3rd step: sign and send the transaction +//highlight-start +// Magic happens inside sendTransaction. If a transaction is sent from an account that exists in a wallet, it will be automatically signed using that account. +const receipt = await web3.eth.sendTransaction({ + from: account?.address, + to: '0xe4beef667408b99053dc147ed19592ada0d77f59', + value: '0x1', + gas: '300000', + // other transaction's params +}); +//highlight-end +``` + +## Sending a raw transaction + +```ts +import { Web3 } from 'web3'; + +// 1st - initialize the provider +const web3 = new Web3('https://ethereum-sepolia.publicnode.com'); + +// 2nd - create an account +const account = web3.eth.accounts.privateKeyToAccount('0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba'); + +// 3rd - create a raw transaction object +const rawTransaction = { + from: account.address, + to: '0x5875da5854c2adadbc1a7a448b5b2a09b26baff8', //random wallet + value: 1, //1 wei + gasPrice: await web3.eth.getGasPrice(), + gasLimit: 300000, + nonce: await web3.eth.getTransactionCount(account.address), //get the current nonce of the account +}; + +// 4th - sign the raw transaction with the private key +const signedTransaction = await web3.eth.accounts.signTransaction(rawTransaction, account.privateKey); + +// 5th - send the signed transaction +const txReceipt = await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction); + +console.log('Transaction Receipt:', txReceipt); +/* ↳ +Transaction Receipt: { + blockHash: '0xd73a824348ebb8c1895fbe7b2c506c287cfaadc8104628a140e7b39d7e41d50f', + blockNumber: 4972805n, + cumulativeGasUsed: 15266381n, + effectiveGasPrice: 118637814298n, + from: '0xa3286628134bad128faeef82f44e99aa64085c94', + gasUsed: 21000n, + logs: [], + logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + status: 1n, + to: '0x5875da5854c2adadbc1a7a448b5b2a09b26baff8', + transactionHash: '0x247e4540f9b399655da90e8a0c3d9ec165f62a304f6364f45518a4d6a531cd36', + transactionIndex: 156n, + type: 0n +} +*/ +``` + +## Sending a transaction with Browser Injection (Metamask) + +This is an example html file that will send a transaction when the button element is clicked. + +To run this example you'll need Metamask, the `index.html` file below in your folder and you'll need a local server: + +```bash +npm i http-server +``` + +```bash +npx http-server +``` + +Afterwards your file will be served on a local port, which will usually be on `http://127.0.0.1:8080` + +``` html + + + + + + Send Transaction Example + + + + + + + + +``` + + +## Contract Deployment + +```typescript title='Deploy a contract' +// 1st step: initialize `web3` instance +import { Web3 } from 'web3'; + +const web3 = new Web3(/* PROVIDER*/); + +// 2nd step: add an account to wallet +const privateKey = '0x7b907534ec13b19c67c2a738fdaa69014298c71f2221d7e5dec280232e996610'; +const account = web3.eth.accounts.wallet.add(privateKey).get(0); +// Make sure the account has enough eth on balance to send the transaction + +// fill ContractAbi and ContractBytecode with your contract's abi and bytecode + +async function deploy() { + // 3rd step: sign and send the transaction + // In any function where you can pass from the address set address of the account that exists in a wallet, it will be automatically signed. + + try { + // deploy + const contract = new web3.eth.Contract(ContractAbi); + const contractDeployed = await contract + .deploy({ + input: ContractBytecode, + arguments: ['Constructor param1', 'Constructor param2'], + }) + .send({ + from: account?.address, + gas: '1000000', + // other transaction's params + }); + + // call method + await contractDeployed.methods.transfer('0xe2597eb05cf9a87eb1309e86750c903ec38e527e', '0x1').send({ + from: account?.address, + gas: '1000000', + // other transaction's params + }); + } catch (error) { + // catch transaction error + console.error(error); + } +} + +(async () => { + await deploy(); +})(); +``` + + +## Interacting with contract methods + +``` ts title='Interact with contracts using a wallet under the hood' +// 1st step: initialize `web3` instance +import { Web3 } from 'web3'; + +const web3 = new Web3(/* PROVIDER*/); + +// 2nd step: add an account to wallet +const privateKeyString = '0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba'; + +const wallet = web3.eth.accounts.wallet.add(privateKeyString); +// Make sure the account has enough eth on balance to send the transaction + +async function contractMethod() { + try { + // 3rd step: instantiate the contract with the ABI and contract address + const myContract = new web3.eth.Contract(ABI, CONTRACT_ADDRESS); + + // 4th step: call contract method and send the tx + await myContract.methods.doSomething().send({ + from: wallet[0].address, + gas: '1000000', + // other transaction's params + }); + } catch (error) { + // catch transaction error + console.error(error); + } +} + +(async () => { + await contractMethod(); +})(); +``` + +## Sending a transaction and listening to the events + +```ts title='Transactions with Web3PromiEvent' +import { Web3 } from 'web3'; + +// 1st - initialize the provider +const web3 = new Web3(/* PROVIDER*/); + +// 2nd - add an account to wallet +const privateKey = '0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba'; +const account = web3.eth.accounts.wallet.add(privateKey).get(0); +// Make sure the account has enough eth on balance to send the transaction + +// 3rd - sign and send the transaction +// Magic happens behind sendTransaction. If a transaction is sent from an account that exists in a wallet, it will be automatically signed. +const transaction = web3.eth.sendTransaction({ + from: account?.address, + to: '0xe4beef667408b99053dc147ed19592ada0d77f59', + value: '0x1', + gas: '300000', + // other transaction's params +}); + +// highlight-start +// 4th - listen to the transaction events +transaction + .on('sending', (sending) => { + // Sending example + console.log('Sending:', sending); + }) + .on('sent', (sent) => { + // Sent example + console.log('Sent:', sent); + }) + .on('transactionHash', (transactionHash) => { + // Transaction hash example + console.log('Transaction Hash:', transactionHash); + }) + .on('confirmation', (confirmation) => { + // Confirmation example + console.log('Confirmation:', confirmation); + }) + .on('error', (error) => { + // Error example + console.error('Error:', error); + }); +// highlight-end +/* ↳ +Sending: { + from: '0xA3286628134baD128faeef82F44e99AA64085C94', + to: '0xe4beef667408b99053dc147ed19592ada0d77f59', + value: '0x1', + gas: '0x493e0', + gasPrice: undefined, + maxPriorityFeePerGas: '0x9502f900', + maxFeePerGas: '0x2b53cf7960' +} +Sent: { + from: '0xA3286628134baD128faeef82F44e99AA64085C94', + to: '0xe4beef667408b99053dc147ed19592ada0d77f59', + value: '0x1', + gas: '0x493e0', + gasPrice: undefined, + maxPriorityFeePerGas: '0x9502f900', + maxFeePerGas: '0x2b53cf7960' +} +Transaction Hash: 0xa7493bc3eb6e7f41b54291cfd19d90111e68ea2cd9718da937ca4dcc1f831dde +Receipt: { + blockHash: '0xe049c2cd2a473dad2af5ccf40c2df788cd42a237616cc84cc3861937f1aa2195', + blockNumber: 4972912n, + cumulativeGasUsed: 1018070n, + effectiveGasPrice: 100635626363n, + from: '0xa3286628134bad128faeef82f44e99aa64085c94', + gasUsed: 21000n, + logs: [], + logsBloom: '0x...00', + status: 1n, + to: '0xe4beef667408b99053dc147ed19592ada0d77f59', + transactionHash: '0xa7493bc3eb6e7f41b54291cfd19d90111e68ea2cd9718da937ca4dcc1f831dde', + transactionIndex: 15n, + type: 2n +} +Confirmation: { + confirmations: 1n, + receipt: { + blockHash: '0xe049c2cd2a473dad2af5ccf40c2df788cd42a237616cc84cc3861937f1aa2195', + blockNumber: 4972912n, + cumulativeGasUsed: 1018070n, + effectiveGasPrice: 100635626363n, + from: '0xa3286628134bad128faeef82f44e99aa64085c94', + gasUsed: 21000n, + logs: [], + logsBloom: '0x...000', + status: 1n, + to: '0xe4beef667408b99053dc147ed19592ada0d77f59', + transactionHash: '0xa7493bc3eb6e7f41b54291cfd19d90111e68ea2cd9718da937ca4dcc1f831dde', + transactionIndex: 15n, + type: 2n + }, + latestBlockHash: '0xe049c2cd2a473dad2af5ccf40c2df788cd42a237616cc84cc3861937f1aa2195' +} +Confirmation: { + confirmations: 2n, + receipt: {...}, + latestBlockHash: '0xf20261fc59d059c9dfd048e44c7fe1499d45822d9fe804bca70ac56559b54b1b' +} +Confirmation: { + confirmations: 3n, + receipt: {...}, + latestBlockHash: '0xb52380054ad2382620615ba7b7b40638021d85c5904a402cd11d00fd4db9fba9' +} +*/ +``` \ No newline at end of file diff --git a/docs/docs/guides/web3_config/_category_.yml b/docs/docs/guides/web3_config/_category_.yml new file mode 100644 index 00000000000..55873523dd1 --- /dev/null +++ b/docs/docs/guides/web3_config/_category_.yml @@ -0,0 +1,5 @@ +label: '⚙️ Web3 config' +collapsible: true +collapsed: true +link: null +position: 8 \ No newline at end of file diff --git a/docs/docs/guides/web3_config/index.md b/docs/docs/guides/web3_config/index.md index 71815713827..ea061762968 100644 --- a/docs/docs/guides/web3_config/index.md +++ b/docs/docs/guides/web3_config/index.md @@ -1,13 +1,13 @@ --- sidebar_position: 6 -sidebar_label: 'Web3 Config' +sidebar_label: 'Web3 Config Guide' --- -# web3.js Config Guide +# Web3.js Config Guide -## Introduction +## Configuration parameters -There is list of configuration params that can be set for modifying behavior of different functions in web3.js packages. Following is list of configuration options with details. +There is list of configuration params that can be set for modifying behavior of different functions in web3.js packages. Following is list of configuration options with details: - [handleRevert]( /api/web3-core/class/Web3Config#handleRevert) - [defaultAccount](/api/web3-core/class/Web3Config#defaultAccount) @@ -33,25 +33,25 @@ There is list of configuration params that can be set for modifying behavior of There is option of modifying any of above-mentioned configuration parameter at global level when instantiating Web3, and it will be available to all packages. ``` ts - import { Web3 } from 'web3'; - - const web3 = new Web3({ - provider: "https://mainnet.infura.io/v3/YOURID", - config: { - defaultTransactionType: "0x0" - }} - ); - - //now default transaction type will be 0x0 so using following function in eth will send type 0x0 transaction +import { Web3 } from 'web3'; - web3.eth.sendTransaction({ - from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', - to: '0xB2f70d8965e754cc07D343a9b5332876D3070155', - value: 100, - gasLimit: 21000 - }).then(res => console.log(res));; +const web3 = new Web3({ + provider: 'https://mainnet.infura.io/v3/YOURID', + config: { + defaultTransactionType: '0x0', + }, +}); +//now default transaction type will be 0x0 so using following function in eth will send type 0x0 transaction +web3.eth + .sendTransaction({ + from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', + to: '0xB2f70d8965e754cc07D343a9b5332876D3070155', + value: 100, + gasLimit: 21000, + }) + .then((res) => console.log(res)); ``` For Advance Users: Global level config can also be set using `Web3Context` object. @@ -59,8 +59,8 @@ For Advance Users: Global level config can also be set using `Web3Context` objec ``` ts import { Web3, Web3Context } from 'web3'; -const context = new Web3Context("http://127.0.0.1:7545"); -context.setConfig({ defaultTransactionType: "0x0" }); +const context = new Web3Context('http://127.0.0.1:7545'); +context.setConfig({ defaultTransactionType: '0x0' }); const web3 = new Web3(context); @@ -71,7 +71,6 @@ web3.eth.sendTransaction({ value: 100, gasLimit: 21000 }).then(res => console.log(res)); - ``` ## Package level config @@ -80,21 +79,20 @@ web3.eth.sendTransaction({ Some configuration options that effects selected packages can be modified using `setConfig(...)` function. ``` ts - import { Web3 } from 'web3'; - - const web3 = new Web3( "https://mainnet.infura.io/v3/YOURID"); +import { Web3 } from 'web3'; - web3.eth.setConfig({ - defaultTransactionType: "0x0" - }); +const web3 = new Web3('https://mainnet.infura.io/v3/YOURID'); - web3.eth.sendTransaction({ - from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', - to: '0xB2f70d8965e754cc07D343a9b5332876D3070155', - value: 100, - gasLimit: 21000 - }).then(res => console.log(res));; +web3.eth.setConfig({ defaultTransactionType: '0x0'}); +web3.eth + .sendTransaction({ + from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', + to: '0xB2f70d8965e754cc07D343a9b5332876D3070155', + value: 100, + gasLimit: 21000, + }) + .then((res) => console.log(res)); ``` ### Setting config in Individually imported Packages @@ -103,65 +101,62 @@ If an individual package is being imported instead of whole web3.js, there is op For example if only web3Eth package is installed using: -``` ts +```sh npm i web3-eth ``` Configuration options can be set by passing in constructor: -``` ts +```ts title='setConfig in the constructor' import { Web3Eth } from 'web3-eth'; -const web3EthObj = new Web3Eth( - { - provider: "http://127.0.0.1:7545", - config: { - defaultTransactionType: 0x0 - } - }); - - web3EthObj.sendTransaction({ - from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', - to: '0x018e221145dE7cefAD09BD53F41c11A918Bf1Cb7', - value: 100, - gasLimit: 21000 - }).then(res => console.log(res)); +const web3EthObj = new Web3Eth({ + provider: 'http://127.0.0.1:7545', + config: { + defaultTransactionType: 0x0, + }, +}); +web3EthObj + .sendTransaction({ + from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', + to: '0x018e221145dE7cefAD09BD53F41c11A918Bf1Cb7', + value: 100, + gasLimit: 21000, + }) + .then((res) => console.log(res)); ``` Another way of setting config for individually imported package is by using `setConfig(...)` function. -``` ts +```ts title='setConfig function' import { Web3Eth } from 'web3-eth'; -const web3EthObj = new Web3Eth("http://127.0.0.1:7545"); - - web3EthObj.setConfig({ - defaultTransactionType: 0x0 - }); +const web3EthObj = new Web3Eth('http://127.0.0.1:7545'); - web3EthObj.sendTransaction({ - from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', - to: '0x018e221145dE7cefAD09BD53F41c11A918Bf1Cb7', - value: 100, - gasLimit: 21000 - }).then(res => console.log(res)); +web3EthObj.setConfig({ defaultTransactionType: 0x0 }); +web3EthObj + .sendTransaction({ + from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', + to: '0x018e221145dE7cefAD09BD53F41c11A918Bf1Cb7', + value: 100, + gasLimit: 21000, + }) + .then((res) => console.log(res)); ``` ## Getting Current Config For getting list of current config params `getContextObject().config` can be used as : -``` ts +``` ts title='getContextObject() in Web3 object' import { Web3 } from 'web3'; -const web3 = new Web3("http://127.0.0.1:7545"); -console.log(web3.getContextObject().config) - -/* -This will give current config object: +const web3 = new Web3('http://127.0.0.1:7545'); +console.log(web3.getContextObject().config) +/* ↳ handleRevert: false, defaultAccount: undefined, defaultBlock: 'latest', @@ -182,18 +177,25 @@ This will give current config object: defaultTransactionType: '0x2', defaultMaxPriorityFeePerGas: '0x9502f900', ... - */ - ``` For individually imported packages same approach can be used to get current config params. -``` ts - +```ts title='getContextObject() in an imported package' import { Web3Eth } from 'web3'; -const web3 = new Web3Eth("http://127.0.0.1:7545"); -console.log(web3.getContextObject().config) +const web3 = new Web3Eth('http://127.0.0.1:7545'); +console.log(web3.getContextObject().config) +/* ↳ + handleRevert: false, + defaultAccount: undefined, + defaultBlock: 'latest', + transactionBlockTimeout: 50, + transactionConfirmationBlocks: 24, + transactionPollingInterval: 1000, + transactionPollingTimeout: 750000, + ... +*/ ``` \ No newline at end of file diff --git a/docs/docs/guides/web3_eth/_category_.yml b/docs/docs/guides/web3_eth/_category_.yml new file mode 100644 index 00000000000..f7e09e00d19 --- /dev/null +++ b/docs/docs/guides/web3_eth/_category_.yml @@ -0,0 +1,5 @@ +label: '📦 Web3Eth module' +collapsible: true +collapsed: true +link: null +position: 7 \ No newline at end of file diff --git a/docs/docs/guides/web3_eth/eth.md b/docs/docs/guides/web3_eth/eth.md new file mode 100644 index 00000000000..78f031ca665 --- /dev/null +++ b/docs/docs/guides/web3_eth/eth.md @@ -0,0 +1,700 @@ +--- +sidebar_position: 1 +sidebar_label: 'Mastering the Web3Eth package' +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Getting Started with `eth` Package + +## Introduction + +The `web3-eth` package provides a set of powerful functionalities to interact with the Ethereum blockchain and smart contracts. In this tutorial, we will guide you through the basics of using the `web3-eth` package of web3.js version 4. We will be using TypeScript throughout the examples. + +## Overview + +Here is a high-level overview of the steps we will be taking in this tutorial: + +1. [Setting up the Environment](#step-1-setting-up-the-environment) +2. [Create a new project directory and initialize a new Node.js project](#step-2-create-a-new-project-directory-and-initialize-a-new-nodejs-project) +3. [Set up web3.js and connect to the Ganache network](#step-3-set-up-web3js-and-connect-to-the-ganache-network) +4. [Interact with the Ethereum blockchain using web3.js](#step-4-interact-with-the-ethereum-blockchain-using-web3js) +5. [Importing specific package](#step-5-importing-specific-package) +6. [Send different type of transactions](#step-6-send-different-type-of-transactions) + +## Step 1: Setting up the Environment + +Before we start writing and deploying our contract, we need to set up our environment. For that, we need to install the following: + +:::tip +You can also interact with a mainnet/testnet by using a node provider instead of ganache, you can use [Alchemy](https://www.alchemy.com/), [Infura](https://www.infura.io/), [QuickNode](https://www.quicknode.com/) or get a public endpoint from [Chainlist](https://chainlist.org/) +::: + +1. `Ganache` - Ganache is a personal blockchain for Ethereum development that allows you to see how your smart contracts function in real-world scenarios. You can download it from http://truffleframework.com/ganache +2. `Node.js` - Node.js is a JavaScript runtime environment that allows you to run JavaScript on the server-side. You can download it from https://nodejs.org/en/download/ +3. `npm` - Node Package Manager is used to publish and install packages to and from the public npm registry or a private npm registry. Here is how to install it https://docs.npmjs.com/downloading-and-installing-node-js-and-npm. (Alternatively, you can use yarn instead of npm https://classic.yarnpkg.com/lang/en/docs/getting-started/) + +## Step 2: Create a new project directory and initialize a new Node.js project + +First, create a new project directory for your project and navigate into it: + +```bash +mkdir web3-eth-tutorial +cd web3-eth-tutorial +``` + +Next, initialize a new Node.js project using npm: + +```bash +npm init -y +``` + +This will create a new `package.json` file in your project directory. + +```bash +npm i typescript @types/node +``` + +This will install typescript for our project and install the types for node. + +## Step 3: Set up web3.js and connect to the Ganache network + +In this step, we will set up the web3.js library and connect to the Ganache network. So, be sure to run Ganache if you did not already did. + +First, install the `web3` package using npm: + +```bash +npm i web3 +``` + +Next, create a new file called `index.ts` in your project directory and add the following code to it: + +```ts +import { Web3 } from 'web3'; + +// Set up a connection to the Ganache network +const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545')); +/* NOTE: +instead of using ganache, you can also interact with a testnet/mainnet using another provider +https://app.infura.io/ +https://dashboard.alchemy.com/ +or use a public provider https://chainlist.org/ +*/ + +// Log the current block number to the console +const block = await web3.eth.getBlockNumber(); + +console.log('Last block:', block); +// ↳ Last block: 4975299n +``` + +This code sets up a connection to the Ganache network and logs the current block number to the console. + +Run the following command to test the connection: + +``` +npx ts-node index.ts +``` + +If everything is working correctly, you should see the current block number logged to the console. However, if you got an error with the reason `connect ECONNREFUSED 127.0.0.1:7545` then double check that you are running Ganache locally on port `7545`. + +## Step 4: Interact with the Ethereum blockchain using web3.js + +In this step, we will use web3.js to interact with the Ganache network. + +In the first example, we are going to send a simple value transaction. +Create a file named `transaction.ts` and fill it with the following code: + +```typescript +import { Web3 } from 'web3'; +import fs from 'fs'; +import path from 'path'; + +// Set up a connection to the Ethereum network +const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545')); +web3.eth.Contract.handleRevert = true; + +async function interact() { + //fetch all the available accounts + const accounts = await web3.eth.getAccounts(); + console.log(accounts); + + let balance1, balance2; + //The initial balances of the accounts should be 100 Eth (10^18 wei) + balance1 = await web3.eth.getBalance(accounts[0]); + balance2 = await web3.eth.getBalance(accounts[1]); + + console.log(balance1, balance2); + + //create a transaction sending 1 Ether from account 0 to account 1 + const transaction = { + from: accounts[0], + to: accounts[1], + // value should be passed in wei. For easier use and to avoid mistakes, + // we utilize the auxiliary `toWei` function: + value: web3.utils.toWei('1', 'ether'), + }; + + //send the actual transaction + const transactionHash = await web3.eth.sendTransaction(transaction); + console.log('transactionHash', transactionHash); + + balance1 = await web3.eth.getBalance(accounts[0]); + balance2 = await web3.eth.getBalance(accounts[1]); + + // see the updated balances + console.log(balance1, balance2); + + // irrelevant with the actual transaction, just to know the gasPrice + const gasPrice = await web3.eth.getGasPrice(); + console.log(gasPrice); +} + +(async () => { + await interact(); +})(); +``` + +:::important +📝 When running a local development blockchain using Ganache, all accounts are typically unlocked by default, allowing easy access and transaction execution during development and testing. This means that the accounts are accessible without requiring a private key or passphrase. That's why we just indicate the accounts in the examples with the `from` field. +::: + +Run the following: + +```bash +npx ts-node transaction.ts +``` + +If everything is working correctly, you should see something like the following: + +```ts +[ + '0xc68863f36C48ec168AD45A86c96347D520eac1Cf', + '0x80c05939B307f9833d905A685575b45659d3EA70', + '0xA260Cf742e03B48ea1A2b76b0d20aaCfe6F85E5E', + '0xf457b8C0CBE41e2a85b6222A97b7b7bC6Df1C0c0', + '0x32dF9a0B365b6265Fb21893c551b0766084DDE21', + '0x8a6A2b8b00C1C8135F1B25DcE54f73Ee18bEF43d', + '0xAFc526Be4a2656f7E02501bdf660AbbaA8fb3d7A', + '0xc32618116370fF776Ecd18301c801e146A1746b3', + '0xDCCD49880dCf9603835B0f522c31Fcf0579b46Ff', + '0x036006084Cb62b7FAf40B979868c0c03672a59B5' +] +100000000000000000000n 100000000000000000000n + +transactionHash { + transactionHash: '0xf685b64ccf5930d3779a33335ca22195b68901dbdc439f79dfc65d87c7ae88b0', + transactionIndex: 0n, + blockHash: '0x5bc044ad949cfd32ea4cbb249f0292e7dded44c3b0f599236c6d20ddaa96cc06', + blockNumber: 1n, + from: '0xc68863f36c48ec168ad45a86c96347d520eac1cf', + to: '0x80c05939b307f9833d905a685575b45659d3ea70', + gasUsed: 21000n, + cumulativeGasUsed: 21000n, + logs: [], + status: 1n, + logsBloom: '0x......000' +} + +98999580000000000000n 101000000000000000000n + +20000000000n + +``` + +:::note +📝 In order to calculate the actual ether spent, we have to calculate the value sent plus the fees. Initial_balance = (Remaining_balance + value + gasUsed\*gasPrice). In our case: + +98999580000000000000 + 1000000000000000000 + (20000000000\*21000) = 100 Ether +::: + +In the next example, we are going to use `estimateGas` function to see the expected gas for contract deployment. (For more on contracts, please see the corresponding tutotial). Create a file named `estimate.ts` and fill it with the following code: + +```typescript +import { Web3, ETH_DATA_FORMAT, DEFAULT_RETURN_FORMAT } from 'web3'; + +async function estimate() { + // abi of our contract + const abi = [ + { + inputs: [{ internalType: 'uint256', name: '_myNumber', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + inputs: [], + name: 'myNumber', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: '_myNumber', type: 'uint256' }], + name: 'setMyNumber', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + ]; + + const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545')); + + //get the available accounts + const accounts = await web3.eth.getAccounts(); + let acc = await accounts[0]; + + let contract = new web3.eth.Contract(abi); + + const deployment = contract.deploy({ + data: '0x608060405234801561001057600080fd5b506040516101d93803806101d983398181016040528101906100329190610054565b806000819055505061009e565b60008151905061004e81610087565b92915050565b60006020828403121561006657600080fd5b60006100748482850161003f565b91505092915050565b6000819050919050565b6100908161007d565b811461009b57600080fd5b50565b61012c806100ad6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806323fd0e401460375780636ffd773c146051575b600080fd5b603d6069565b6040516048919060bf565b60405180910390f35b6067600480360381019060639190608c565b606f565b005b60005481565b8060008190555050565b60008135905060868160e2565b92915050565b600060208284031215609d57600080fd5b600060a9848285016079565b91505092915050565b60b98160d8565b82525050565b600060208201905060d2600083018460b2565b92915050565b6000819050919050565b60e98160d8565b811460f357600080fd5b5056fea2646970667358221220d28cf161457f7936995800eb9896635a02a559a0561bff6a09a40bfb81cd056564736f6c63430008000033', + // @ts-expect-error + arguments: [1], + }); + + let estimatedGas = await deployment.estimateGas({ from: acc }, DEFAULT_RETURN_FORMAT); + // the returned data will be formatted as a bigint + + console.log('Default format:', estimatedGas); + + estimatedGas = await deployment.estimateGas({ from: acc }, ETH_DATA_FORMAT); + // the returned data will be formatted as a hexstring + + console.log('Eth format:', estimatedGas); +} + +(async () => { + await estimate(); +})(); +``` + +Run the following: + +```bash +npx ts-node estimate.ts +``` + +If everything is working correctly, you should see something like the following: + +```bash +Default format: 140648n +Eth format: 0x22568 +``` + +:::note +📝 Note that numbers returned from web3.js are returned by default in the `BigInt` format. In this example we used `ETH_DATA_FORMAT` parameter, which, can be passed in most methods in web3.js in order to format the result in `hex`. +::: + +In the next example we are going to sign a transaction and use `sendSignedTransaction` to send the signed transaction. Create a file named `sendSigned.ts` and fill it with the following code: + +```typescript +import { Web3 } from 'web3'; +const web3 = new Web3('http://localhost:7545'); + +//make sure to copy the private key from ganache +const privateKey = '0x0fed6f64e01bc9fac9587b6e7245fd9d056c3c004ad546a17d3d029977f0930a'; +const value = web3.utils.toWei('1', 'ether'); + +async function sendSigned() { + const accounts = await web3.eth.getAccounts(); + const fromAddress = accounts[0]; + const toAddress = accounts[1]; + // Create a new transaction object + const tx = { + from: fromAddress, + to: toAddress, + value: value, + gas: 21000, + gasPrice: web3.utils.toWei('10', 'gwei'), + nonce: await web3.eth.getTransactionCount(fromAddress), + }; + + // Sign the transaction with the private key + const signedTx = await web3.eth.accounts.signTransaction(tx, privateKey); + + // Send the signed transaction to the network + const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction); + + console.log('Transaction receipt:', receipt); +} +(async () => { + await sendSigned(); +})(); +``` + +Run the following: + +```bash +npx ts-node sendSigned.ts +``` + +If everything is working correctly, you should see something like the following: + +```ts +Transaction receipt: { + transactionHash: '0x742df8f1ad4d04f6e5632889109506dbb7cdc8a6a1c80af3dfdfc71a67a04ddc', + transactionIndex: 0n, + blockNumber: 1n, + blockHash: '0xab6678d76499b0ee383f182ab8f848ba27bd787e70e227524255c86b25224ed3', + from: '0x66ce32a5200aac57b258c4eac26bc1493fefddea', + to: '0x0afcfc43ac454348d8170c77b1f912b518b4ebe8', + cumulativeGasUsed: 21000n, + gasUsed: 21000n, + logs: [], + logsBloom: '0x...0000', + status: 1n, + effectiveGasPrice: 10000000000n, + type: 2n +} +``` + +## Step 5: Importing specific package + +To harness the capabilities of the web3-eth package, you can opt to import this package directly rather than depending on the global web3 package, which will result in a reduction in the build size. + +### Import web3-eth directly + +For example [getBalance](/api/web3-eth/function/getBalance) method: + +```typescript +import { Web3Eth } from 'web3-eth'; + +const eth = new Web3Eth('http://localhost:7545'); + +async function test() { + const accounts = await eth.getAccounts(); + const currentBalance = await eth.getBalance(accounts[0]); + console.log('Current balance:', currentBalance); + // 115792089237316195423570985008687907853269984665640564039437613106102441895127n +} + +(async () => { + await test(); +})(); +``` + +### Set config directly to web3-eth package + +```typescript +import { Web3Eth } from 'web3-eth'; + +const eth = new Web3Eth('http://localhost:8545'); + +console.log('defaultTransactionType before', eth.config.defaultTransactionType); +// defaultTransactionType before 0x0 + +eth.setConfig({ defaultTransactionType: '0x1' }); + +console.log('eth.config.defaultTransactionType after', eth.config.defaultTransactionType); +// defaultTransactionType before 0x1 +``` + +## Step 6: Send different type of transactions: + +### Legacy Transaction + +In Ethereum, a 'legacy transaction' typically refers to the traditional transactions, where gas fees are set explicitly by the sender and can fluctuate based on network demand. These legacy transactions were prevalent on the Ethereum network before the implementation of Ethereum Improvement Proposal (EIP) 1559. + +Key characteristics of legacy transactions include: + +1. Gas Price: In legacy transactions, the sender specifies a gas price (in Gwei) that they are willing to pay for each unit of gas consumed by the transaction. The gas price can be adjusted by the sender, and it determines the transaction's priority in getting processed by miners. Higher gas prices mean faster transaction confirmation. + +2. Gas Limit: The sender also sets a gas limit, which is the maximum amount of gas that the transaction can consume. Gas is the computational fuel used to execute transactions and smart contracts on the Ethereum network. The gas limit is primarily set to ensure that the sender doesn't run out of Ether while processing the transaction. It can also impact the success or failure of the transaction. + +3. Uncertainty in Fees: Legacy transactions are subject to fluctuating gas prices based on network congestion. During periods of high demand, gas prices can surge, causing users to pay more for their transactions to be processed promptly. Conversely, during quieter network periods, users can pay lower fees. + +4. Manual Fee Estimation: Users are responsible for manually estimating the appropriate gas price to include in their legacy transactions to ensure timely processing. This process can be challenging, as setting gas prices too low may result in slow confirmation, while setting them too high may lead to overpaying. + +5. EIP-1559, as described below, introduced changes to Ethereum's transaction fee system, making it more user-friendly and predictable. With EIP-1559, the concept of a 'base fee' replaces the manual setting of gas prices, which has reduced some of the uncertainties associated with legacy transactions. + +While EIP-1559 has significantly improved the user experience, legacy transactions are still supported on the Ethereum network, and users can continue to send transactions with manually specified gas prices and gas limits if they prefer. However, the EIP-1559 mechanism is now the recommended approach for most transactions, as it simplifies the process and reduces the likelihood of overpaying for fees. + +To send Legacy transaction use code below: + +```typescript +import { Web3 } from 'web3'; + +const web3 = new Web3('http://localhost:8545'); + +async function test() { + const privateKey = 'YOUR PRIVATE KEY HERE'; + // add private key to wallet to have auto-signing transactions feature + const account = web3.eth.accounts.privateKeyToAccount(privateKey); + web3.eth.accounts.wallet.add(account); + + // create transaction object + const tx = { + from: account.address, + to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', + value: '0x1', + gas: BigInt(21000), + gasPrice: await web3.eth.getGasPrice(), + type: BigInt(0), // <- specify type + }; + + // send transaction + const receipt = await web3.eth.sendTransaction(tx); + + console.log('Receipt:', receipt); + // Receipt: { + // blockHash: '0xc0f2fea359233b0843fb53255b8a7f42aa7b1aff53da7cbe78c45b5bac187ad4', + // blockNumber: 21n, + // cumulativeGasUsed: 21000n, + // effectiveGasPrice: 2569891347n, + // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', + // gasUsed: 21000n, + // logs: [], + // logsBloom: '0x0...00000', + // status: 1n, + // to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', + // transactionHash: '0x0ffe880776f5631e4b64caf521bd01cd816dd2cc29e533bc56f392211856cf9a', + // transactionIndex: 0n, + // type: 0n + // } +} +(async () => { + await test(); +})(); +``` + +### EIP-2930 Transaction + +Ethereum Improvement Proposal 2930 is a proposal for a change to the Ethereum network that was implemented as part of the Berlin hard fork, which was activated in April 2021. EIP-2930 introduces a feature called 'Transaction Type and Access List.' This improvement enhances the gas efficiency of certain smart contract interactions and provides more flexibility in specifying who can access specific resources within a smart contract. Here are the key components of EIP-2930: + +1. Transaction Type: EIP-2930 introduces a new transaction type called 'Access List Transaction.' This transaction type is designed to make certain interactions with smart contracts more efficient by allowing the sender to specify a list of addresses that may be accessed or modified during the transaction. + +2. Access List: The Access List is a structured data format included with the transaction. It contains a list of addresses and storage keys that are expected to be accessed or modified during the execution of the transaction. This helps in reducing the amount of gas required for these operations, as miners can check the Access List to optimize the execution. + +3. Gas Savings: EIP-2930 is intended to significantly reduce the gas costs for transactions that use the Access List feature. By specifying which storage slots and addresses are relevant to the transaction, it allows for a more efficient use of gas, especially in interactions with smart contracts that have a large state. + +4. Contract Interactions: This improvement is particularly useful when interacting with contracts that have complex state structures, as it minimizes the gas required to read from or write to specific storage slots. This can lead to cost savings for users and make certain interactions more practical. + +EIP-2930 is part of Ethereum's ongoing efforts to improve the network's efficiency and reduce transaction costs, making it more accessible and scalable for decentralized applications and users. It is especially beneficial for interactions with stateful contracts that rely on specific storage operations and access control mechanisms. + +To send EIP-2930 transaction use code below: + +```typescript +import {Web3} from 'web3'; + +const web3 = new Web3('http://localhost:8545'); + +async function test() { + const privateKey = 'YOUR PRIVATE KEY HERE'; + // add private key to wallet to have auto-signing transactions feature + const account = web3.eth.accounts.privateKeyToAccount(privateKey); + web3.eth.accounts.wallet.add(account); + + // create transaction object + const tx = { + from: account.address, + to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', + value: '0x1', + gasLimit: BigInt(21000), + type: BigInt(1), // <- specify type + // gasPrice - you can specify this property directly or web3js will fill this field automatically + }; + + // send transaction + const receipt = await web3.eth.sendTransaction(tx); + + console.log('Receipt:', receipt); + // Receipt: { + // blockHash: '0xd8f6a3638112d17b476fd1b7c4369d473bc1a484408b6f39dbf64410df44adf6', + // blockNumber: 24n, + // cumulativeGasUsed: 21000n, + // effectiveGasPrice: 2546893579n, + // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', + // gasUsed: 21000n, + // logs: [], + // logsBloom: '0x...0000', + // status: 1n, + // to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', + // transactionHash: '0xd1d682b6f6467897db5b8f0a99a6be2fb788d32fbc1329b568b8f6b2c15e809a', + // transactionIndex: 0n, + // type: 1n + // } +} +(async () => { + await test(); +})(); +``` + +Here is an example of how to use an access list in a transaction. + +:::note +The code of `Greeter` contract you can find [here](https://github.com/web3/web3.js/blob/4.x/fixtures/build/Greeter.ts) +::: + +```typescript +import {Web3} from 'web3'; + +import { GreeterAbi, GreeterBytecode } from './fixture/Greeter'; + +const web3 = new Web3('http://localhost:8545'); + +async function test() { + const privateKey = 'YOUR PRIVATE KEY HERE'; + // add private key to wallet to have auto-signing transactions feature + const account = web3.eth.accounts.privateKeyToAccount(privateKey); + web3.eth.accounts.wallet.add(account); + + // deploy contract + const contract = new web3.eth.Contract(GreeterAbi); + const deployedContract = await contract + .deploy({ + data: GreeterBytecode, + arguments: ['My Greeting'], + }) + .send({ from: account.address }); + deployedContract.defaultAccount = account.address; + + const transaction = { + from: account.address, + to: deployedContract.options.address, + data: '0xcfae3217', // greet function call data encoded + }; + const { accessList } = await web3.eth.createAccessList(transaction, 'latest'); + + console.log('AccessList:', accessList); + // AccessList: [ + // { + // address: '0xce1f86f87bd3b8f32f0fb432f88e848f3a957ed7', + // storageKeys: [ + // '0x0000000000000000000000000000000000000000000000000000000000000001' + // ] + // } + // ] + + // create transaction object with accessList + const tx = { + from: account.address, + to: deployedContract.options.address, + gasLimit: BigInt(46000), + type: BigInt(1), // <- specify type + accessList, + data: '0xcfae3217', + // gasPrice - you can specify this property directly or web3js will fill this field automatically + }; + + // send transaction + const receipt = await web3.eth.sendTransaction(tx); + + console.log('Receipt:', receipt); + // Receipt: { + // blockHash: '0xc7b9561100c8ff6f1cde7a05916e86b7d037b2fdba86b0870e842d1814046e4b', + // blockNumber: 43n, + // cumulativeGasUsed: 26795n, + // effectiveGasPrice: 2504325716n, + // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', + // gasUsed: 26795n, + // logs: [], + // logsBloom: '0x...00000000000', + // status: 1n, + // to: '0xce1f86f87bd3b8f32f0fb432f88e848f3a957ed7', + // transactionHash: '0xa49753be1e2bd22c2a8e2530726614c808838bb0ebbed72809bbcb34f178799a', + // transactionIndex: 0n, + // type: 1n + // } +} +(async () => { + await test(); +})(); +``` + +### EIP-1559 Transaction + +Ethereum Improvement Proposal 1559 is a significant upgrade to the Ethereum network's fee market and transaction pricing mechanism. It was implemented as part of the Ethereum London hard fork, which occurred in August 2021. EIP-1559 introduces several changes to how transaction fees work on the Ethereum blockchain, with the primary goals of improving user experience and network efficiency. + +Here are some of the key features and changes introduced by EIP-1559: + +1. Base Fee: EIP-1559 introduces a concept called the 'base fee.' The base fee is the minimum fee required for a transaction to be included in a block. It is determined algorithmically by the network and adjusts dynamically based on network congestion. When the network is busy, the base fee increases, and when it's less congested, the base fee decreases. + +2. Inclusion Fee: In addition to the base fee, users can voluntarily include a 'tip' or 'inclusion fee' to incentivize miners to include their transactions in the next block. This allows users to expedite their transactions by offering a tip to miners. + +3. Predictable Fees: With EIP-1559, users have a more predictable way to estimate transaction fees. They can set the maximum fee they are willing to pay, which includes the base fee and the tip. This eliminates the need for users to guess the appropriate gas price. + +4. Burn Mechanism: EIP-1559 introduces a mechanism by which the base fee is 'burned' from circulation, reducing the overall supply of Ether (ETH). This deflationary mechanism can help address some of the concerns related to the increasing supply of ETH and potentially make it a better store of value. + +5. Improved Fee Auctions: Under EIP-1559, fee auctions are more efficient. Users specify the maximum fee they are willing to pay, and the protocol automatically adjusts the tip to ensure transactions get processed promptly without overpaying. + +6. Simpler Transaction Process: Users experience a simplified transaction process, as they don't have to set gas prices manually. Instead, they specify the maximum fee they are willing to pay, and the wallet software handles the rest. + +EIP-1559 has been well-received for its potential to create a more user-friendly and efficient transaction fee system, making the Ethereum network more accessible and predictable for users. It is also seen as an important step in the transition to Ethereum 2.0, which aims to address scalability and sustainability challenges on the network. + +To send EIP-1559 transaction use code below: + +```typescript +import { Web3 } from 'web3'; + +const web3 = new Web3('http://localhost:8545'); + +async function test() { + const privateKey = 'YOUR PRIVATE KEY HERE'; + // add private key to wallet to have auto-signing transactions feature + const account = web3.eth.accounts.privateKeyToAccount(privateKey); + web3.eth.accounts.wallet.add(account); + + // create transaction object + const tx = { + from: account.address, + to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', + value: '0x1', + gasLimit: BigInt(21000), + type: BigInt(2), // <- specify type + // maxFeePerGas - you can specify this property directly or web3js will fill this field automatically + // maxPriorityFeePerGas - you can specify this property directly or web3js will fill this field automatically + }; + + // send transaction + const receipt = await web3.eth.sendTransaction(tx); + + console.log('Receipt:', receipt); + // Receipt: { + // blockHash: '0xfe472084d1471720b6887071d32a793f7c4576a489098e7d2a89aef205c977fb', + // blockNumber: 23n, + // cumulativeGasUsed: 21000n, + // effectiveGasPrice: 2546893579n, + // from: '0xe2597eb05cf9a87eb1309e86750c903ec38e527e', + // gasUsed: 21000n, + // logs: [], + // logsBloom: '0x0000...00000000000', + // status: 1n, + // to: '0x27aa427c1d668ddefd7bc93f8857e7599ffd16ab', + // transactionHash: '0x5c7a3d2965b426a5776e55f049ee379add44652322fb0b9fc2f7f57b38fafa2a', + // transactionIndex: 0n, + // type: 2n + // } +} +(async () => { + await test(); +})(); +``` + +## Conclusion + +In this tutorial, we learned how to use different methods provied by the `web3-eth` package. + +With this knowledge, you can start experimenting with the Ethereum blockchain. Keep in mind that this is just the beginning, and there is a lot more to learn about Ethereum and web3.js. So keep exploring and building, and have fun! + +Web3.js version 4.x provides a powerful and easy-to-use interface for interacting with the Ethereum network and building decentralized applications. And it has been rewritten in TypeScript but for simplicity of this tutorial we interacted with it in JavaScript. + +The Ethereum ecosystem is constantly evolving, and there is always more to learn and discover. As you continue to develop your skills and knowledge, keep exploring and experimenting with new technologies and tools to build innovative and decentralized solutions. + +## Additional Resources + +- [Official web3.js Documentation](https://docs.web3js.org/) +- [Solidity Documentation](https://solidity.readthedocs.io/) +- [Ganache](https://www.trufflesuite.com/ganache) +- [Truffle](https://trufflesuite.com/) +- [Remix IDE](https://remix.ethereum.org/) + +## Tips and Best Practices + +- Always test your smart contracts on a local network like Ganache or Hardhat before deploying them to the mainnet. +- Use the latest version of web3.js and Solidity to take advantage of the latest features and security patches. +- Keep your private keys secure and never share them with anyone. +- Use the gas limit and gas price parameters carefully to avoid spending too much on transaction fees. +- Use the `estimateGas` function in web3.js to estimate the gas required for a transaction before sending it to the network. +- Use events to notify the client application about state changes in the smart contract. +- Use a linter like Solhint to check for common Solidity coding errors. + diff --git a/docs/docs/guides/web3_eth/methods.md b/docs/docs/guides/web3_eth/methods.md new file mode 100644 index 00000000000..36125f0f253 --- /dev/null +++ b/docs/docs/guides/web3_eth/methods.md @@ -0,0 +1,120 @@ +--- +sidebar_position: 2 +sidebar_label: 'Web3Eth methods' +--- + +# Web3Eth methods + +## createAccessList + + +The [createAccessList](/api/web3-eth/function/createAccessList) method is used to create an access list. +Creating an access list in Ethereum is typically associated with Ethereum Improvement Proposal (EIP)-2930, which introduces a way to specify which accounts and storage keys a transaction expects to access. Access lists are used to optimize gas costs for transactions by providing explicit information about what the transaction needs to access. + +## estimateGas + +The [estimateGas](/api/web3-eth/function/estimateGas) function is used to estimate the amount of gas that will be consumed when executing a specific transaction or invoking a contract function. This can be very useful when you want to determine the potential cost of a transaction or function call before actually sending it to the Ethereum network. It helps users ensure that they have enough ether to cover the gas costs for the operation. + +## getBalance + +The [getBalance](/api/web3-eth/function/getBalance) function is used to retrieve the balance of an Ethereum address, which represents the amount of Ether (ETH) associated with that address. It's a fundamental and frequently used function when working with Ethereum applications. + +## getBlock + +The [getBlock](/api/web3-eth/function/getBlock) function is used to retrieve information about a specific Ethereum block. Ethereum blocks are the fundamental building blocks of the blockchain, containing a collection of transactions and other data. + +## getBlockNumber + +The [getBlockNumber](/api/web3-eth/function/getBlockNumber) function is used to retrieve the latest block number (also known as the block height) of the Ethereum blockchain. The block number is a crucial piece of information in Ethereum as it represents the current state of the blockchain, indicating the total number of blocks that have been mined up to the present. + +## getBlockTransactionCount + +The [getBlockTransactionCount](/api/web3-eth/function/getBlockTransactionCount) function is used to retrieve the number of transactions in a specific Ethereum block. It allows you to determine how many transactions were included in a particular block on the Ethereum blockchain. + +## getBlockUncleCount + +The [getBlockUncleCount](/api/web3-eth/function/getBlockUncleCount) function is used to retrieve the number of uncle blocks associated with a specific Ethereum block. In Ethereum, uncle blocks (also known as "stale blocks" or "ommer blocks") are blocks that were mined but not included in the main blockchain. They are referenced by other blocks as a way to reward miners for their efforts even if their blocks weren't part of the main chain. + +## getChainId + +The [getChainId](/api/web3-eth/function/getChainId) function is used to retrieve the chain ID of the connected Ethereum network. The chain ID is a unique identifier for a specific Ethereum network, and it's used to help prevent replay attacks when signing transactions. Different Ethereum networks, such as the mainnet, testnets, and private networks, have distinct chain IDs. + +## getCode + +The [getCode](/api/web3-eth/function/getCode) function library is used to retrieve the bytecode of a smart contract deployed on the Ethereum blockchain. Smart contracts on Ethereum are typically created by deploying bytecode to a specific address, and this function allows you to fetch the bytecode associated with a particular contract address. + +## getCoinbase + +The [getCoinbase](/api/web3-eth/function/getCoinbase) function is used to retrieve the address of the Ethereum account that is currently acting as the coinbase address for mining on the connected Ethereum node. The coinbase address is the address to which block rewards are sent when miners successfully mine a new block on the Ethereum blockchain. Miners configure their coinbase addresses to receive rewards for their mining efforts. + +## getGasPrice + +The [getGasPrice](/api/web3-eth/function/getGasPrice) function is used to retrieve the current gas price on the Ethereum network. Gas price is the amount of Ether (ETH) that users are willing to pay for each unit of gas when executing a transaction on the Ethereum network. Gas price is an important factor in determining the transaction fee (in ETH) for a transaction. + +## getPendingTransactions + +The [getPendingTransactions](/api/web3-eth/function/getPendingTransactions) function is used to retrieve information about pending transactions in the Ethereum network. Pending transactions are transactions that have been submitted to the network but have not yet been included in a mined block. This function allows you to access information about transactions that are waiting to be confirmed by miners. + +## getProof + +The [getProof](/api/web3-eth/function/getProof) function is used to obtain a Merkle proof or Patricia trie proof for a specific value or data in an Ethereum smart contract's storage. This function is typically used when you want to validate that a piece of data is stored in the contract's storage or to provide evidence for data inclusion without having to interact with the entire contract state. + +In Ethereum, storage proofs are used to demonstrate the existence of a value within a contract's storage without querying the entire storage of the contract, which can be computationally expensive. These proofs are essential for various applications, including decentralized exchanges, blockchain explorers, and certain cryptographic operations. + +## getProtocolVersion + +You can use the [getProtocolVersion](/api/web3-eth/function/getProtocolVersion) method to retrieve the current Ethereum protocol version of the connected Ethereum node. + +## getStorageAt + +The [getStorageAt](/api/web3-eth/function/getStorageAt) method is used to fetch the data stored at a specific storage slot of an Ethereum address. It is often used for inspecting the internal state of smart contracts, especially when you want to retrieve the value of a specific variable in a contract's storage. + +## getTransaction + +The [getTransaction](/api/web3-eth/function/getTransaction) method allows you to retrieve information about a transaction based on its transaction hash. You provide the transaction hash, and this method returns an object containing details about the transaction + +## getTransactionCount + +The [getTransactionCount](/api/web3-eth/function/getTransactionCount) method allows you to retrieve the transaction count (nonce) of a specific Ethereum address. + +## getTransactionReceipt + +The [getTransactionReceipt](/api/web3-eth/function/getTransactionReceipt) method allows you to retrieve the transaction receipt for a specific transaction based on its transaction hash. + +## getUncle + +The [getUncle](/api/web3-eth/function/getUncle) method allows you to retrieve information about an uncle block at a specific index within a given block. + +## isMining + +The [isMining](/api/web3-eth/function/isMining) function returns a boolean value, indicating whether the node is actively mining or not. + +## isSyncing + +The [isSyncing](/api/web3-eth/function/isSyncing) method allows you to check the current synchronization status of your Ethereum node. + +## sendTransaction + +The [sendTransaction](/api/web3-eth/function/sendTransaction) method is used to create and send a transaction to the Ethereum network. + +:::important +Please be cautious when sending transactions, especially when dealing with smart contracts, as they may execute specific functions that can have irreversible effects. Always ensure that the details in your transaction object are accurate and intended. + +[Here](guides/wallet/transactions) you can find more examples how to send transaction. +::: + +## sign + +The [sign](/api/web3-eth/function/sign) method is used to sign a message or data using a private key. This is often used to prove ownership or authorship of a specific piece of data or to provide cryptographic proof in various Ethereum-related operations. + +## signTransaction + +The [signTransaction](/api/web3-eth/function/signTransaction) method is used to sign an Ethereum transaction, creating a signed transaction object that can be broadcast to the Ethereum network. + +## sendSignedTransaction + +The [sendSignedTransaction](/api/web3-eth/function/sendSignedTransaction) method is used to send a signed Ethereum transaction to the Ethereum network. Before sending a transaction, you need to sign it using a private key, and then you can use this method to broadcast the signed transaction to the network. + +:::note +[Here](/guides/wallet/transactions) you can find more examples how to send transaction. +::: \ No newline at end of file diff --git a/docs/docs/guides/web3_plugin_guide/_category_.yml b/docs/docs/guides/web3_plugin_guide/_category_.yml new file mode 100644 index 00000000000..409a53c7a84 --- /dev/null +++ b/docs/docs/guides/web3_plugin_guide/_category_.yml @@ -0,0 +1,5 @@ +label: '🧩🛠️ Web3 Plugin' +collapsible: true +collapsed: true +link: null +position: 12 \ No newline at end of file diff --git a/docs/docs/guides/web3_plugin_guide/index.md b/docs/docs/guides/web3_plugin_guide/index.md index 1a554851e9c..365ca7b82f1 100644 --- a/docs/docs/guides/web3_plugin_guide/index.md +++ b/docs/docs/guides/web3_plugin_guide/index.md @@ -1,11 +1,50 @@ --- -sidebar_position: 6 -sidebar_label: 'Plugins' +sidebar_position: 1 +sidebar_label: 'Introduction' --- -# web3.js Plugins Guide +# Introduction -In addition to the web3.js standard libraries, plugins add specific functionality to the end user. This extra functionality could be wrappers around specific contracts, additional RPC method wrappers, or could even extend the logic of web3.js methods. +Welcome to the web3.js Plugins Guide, an exciting new feature introduced in web3.js v4! In addition to the core web3.js libraries, plugins bring specialized functionalities tailored for end-users (functionalities that you, as a developer, can create). These enhancements may involve creating wrappers for specific contracts, adding extra features to RPC methods, or extending the capabilities of web3.js methods. Dive in and explore this innovative addition to web3.js v4! -- [web3.js Plugin Developer Guide](/guides/web3_plugin_guide/plugin_authors) -- [Plugin User Guide](/guides/web3_plugin_guide/plugin_users) \ No newline at end of file +- [Plugin Developer Guide (For Creators)](/guides/web3_plugin_guide/plugin_authors) +- [Plugin User Guide (Usage)](/guides/web3_plugin_guide/plugin_users) +- [Plugin List](https://web3js.org/plugins) + + +## Plugin Showcase + +### Chainlink Plugin +- [`npm i @chainsafe/web3-plugin-chainlink`](https://www.npmjs.com/package/@chainsafe/web3-plugin-chainlink) +- **Description**: A Web3.js 4.x Plugin for Interacting With Chainlink Smart Contracts +- **Author**: ChainSafe Systems + +### Tokens Plugin +- [`npm i @chainsafe/web3-plugin-tokens`](https://www.npmjs.com/package/@chainsafe/web3-plugin-tokens) +- **Description**: Plugin to extend web3.js with additional methods to interact with common token interfaces (ERC20, ERC721, ERC1155...) +- **Author**: Peter Grassberger & ChainSafe + +### Craftsman Plugin +- [`npm i web3-plugin-craftsman`](https://www.npmjs.com/package/web3-plugin-craftsman) +- **Description**: web3.js plugin allowing instantiation of contract objects directly from Solidity source code +- **Author**: Muhammad-Altabba + +### Optimism Plugin +- [`npm i @eth-optimism/web3.js-plugin`](https://www.npmjs.com/package/@eth-optimism/web3.js-plugin) +- **Description**: Web3.js plugin for OP-Chain gas estimation +- **Author**: Unknown + +### Near Protocol Plugin +- [`npm i @conx3/web3-plugin-near`](https://npmjs.com/package/@conx3/web3-plugin-near) +- **Description**: web3.js plugin for Near Protocol +- **Author**: Muhammad Altabba + +### Aurora Engine Plugin +- [`npm i @conx3/web3-plugin-aurora`](https://www.npmjs.com/package/@conx3/web3-plugin-aurora) +- **Description**: web3.js plugin for Aurora Engine, an EVM running atop NEAR protocol +- **Author**: Muhammad Altabba + +### Superfluid Plugin +- [`npm i web3-plugin-superfluid`](https://www.npmjs.com/package/web3-plugin-superfluid) +- **Description**: Superfluid Web3.js Plugin +- **Author**: Salman Dabbakuti diff --git a/docs/docs/guides/web3_plugin_guide/plugin_authors.md b/docs/docs/guides/web3_plugin_guide/plugin_authors.md index 31f26d6ce3f..9de3fedb079 100644 --- a/docs/docs/guides/web3_plugin_guide/plugin_authors.md +++ b/docs/docs/guides/web3_plugin_guide/plugin_authors.md @@ -1,13 +1,13 @@ --- -sidebar_position: 1 +sidebar_position: 2 sidebar_label: 'For Plugin Developers' --- -# web3.js Plugin Developer Guide +# Plugin Developer Guide This guide intends to provide the necessary context for developing plugins for web3.js. -Feel free to explore some of [the already built plugins](https://github.com/chainSafe?q=web3.js-plugin) and/or +Feel free to explore some of [the already built plugins](https://web3js.org/plugins) and/or use this [template](https://github.com/ChainSafe/web3.js-plugin-template) to start with development of your Web3.js plugin. :::caution @@ -44,18 +44,18 @@ Furthermore, you have the flexibility to expand your range of transaction types, import { BaseTransaction } from 'web3-eth-accounts'; const TRANSACTION_TYPE = 15; class SomeNewTxTypeTransaction extends BaseTransaction { - // ... + // ... } // create new plugin and add `SomeNewTxTypeTransaction` to the library import { Web3EthPluginBase } from 'web3'; class SomeNewTxTypeTransactionPlugin extends Web3PluginBase { - public pluginNamespace = 'someNewTxTypeTransaction'; - public constructor() { - super(); - TransactionFactory.registerTransactionType(TRANSACTION_TYPE, SomeNewTxTypeTransaction); - } + public pluginNamespace = 'someNewTxTypeTransaction'; + public constructor() { + super(); + TransactionFactory.registerTransactionType(TRANSACTION_TYPE, SomeNewTxTypeTransaction); + } } ``` @@ -90,11 +90,11 @@ The following represents your plugin code: import { Web3PluginBase } from 'web3'; export class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; + public pluginNamespace = 'customRpcMethods'; - public someMethod() { - return 'someValue'; - } + public someMethod() { + return 'someValue'; + } } ``` @@ -120,14 +120,14 @@ Below is an example of `CustomRpcMethodsPlugin` making use of `this.requestManag import { Web3PluginBase } from 'web3'; export class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; - - public async customRpcMethod() { - return this.requestManager.send({ - method: 'custom_rpc_method', - params: [], - }); - } + public pluginNamespace = 'customRpcMethods'; + + public async customRpcMethod() { + return this.requestManager.send({ + method: 'custom_rpc_method', + params: [], + }); + } } ``` @@ -161,18 +161,18 @@ If needed, you can provide an API type (that follows the [Web3ApiSpec](/api/web3 import { Web3PluginBase } from 'web3'; type CustomRpcApi = { - custom_rpc_method_with_parameters: (parameter1: string, parameter2: number) => string; + custom_rpc_method_with_parameters: (parameter1: string, parameter2: number) => string; }; export class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; - - public async customRpcMethodWithParameters(parameter1: string, parameter2: number) { - return this.requestManager.send({ - method: 'custom_rpc_method_with_parameters', - params: [parameter1, parameter2], - }); - } + public pluginNamespace = 'customRpcMethods'; + + public async customRpcMethodWithParameters(parameter1: string, parameter2: number) { + return this.requestManager.send({ + method: 'custom_rpc_method_with_parameters', + params: [parameter1, parameter2], + }); + } } ``` @@ -190,39 +190,32 @@ import { Contract, ContractAbi, Web3Context, Web3PluginBase, types, utils } from import { ERC20TokenAbi } from './ERC20Token'; export class ContractMethodWrappersPlugin extends Web3PluginBase { - public pluginNamespace = 'contractMethodWrappersPlugin'; - - private readonly _contract: Contract; - - public constructor(abi: ContractAbi, address: types.Address) { - super(); - this._contract = new Contract(abi, address); - } - - /** - * This method overrides the inherited `link` method from - * `Web3PluginBase` to add a configured `RequestManager` - * to the Contract instance when `Web3.registerPlugin` - * is called. - * - * @param parentContext - The context to be added to the instance of `ChainlinkPlugin`, - * and by extension, the instance of `Contract`. - */ - public link(parentContext: Web3Context) { - super.link(parentContext); - this._contract.link(parentContext); - } - - public async getFormattedBalance( - address: types.Address, - returnFormat?: ReturnFormat, - ) { - return utils.format( - { eth: 'unit' }, - await this._contract.methods.balanceOf(address).call(), - returnFormat ?? types.DEFAULT_RETURN_FORMAT, - ); - } + public pluginNamespace = 'contractMethodWrappersPlugin'; + + private readonly _contract: Contract; + + public constructor(abi: ContractAbi, address: types.Address) { + super(); + this._contract = new Contract(abi, address); + } + + /** + * This method overrides the inherited `link` method from + * `Web3PluginBase` to add a configured `RequestManager` + * to the Contract instance when `Web3.registerPlugin` + * is called. + * + * @param parentContext - The context to be added to the instance of `ChainlinkPlugin`, + * and by extension, the instance of `Contract`. + */ + public link(parentContext: Web3Context) { + super.link(parentContext); + this._contract.link(parentContext); + } + + public async getFormattedBalance(address: types.Address, returnFormat?: ReturnFormat) { + return utils.format({ eth: 'unit' }, await this._contract.methods.balanceOf(address).call(), returnFormat ?? types.DEFAULT_RETURN_FORMAT); + } } ``` @@ -255,20 +248,20 @@ When registering a plugin, you're adding additional methods and/or classes to th import { Web3PluginBase } from 'web3'; export class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; + public pluginNamespace = 'customRpcMethods'; - public someMethod() { - return 'someValue'; - } + public someMethod() { + return 'someValue'; + } } // Module Augmentation declare module 'web3' { - // Here is where you're adding your plugin's - // class inside Web3Context class - interface Web3Context { - customRpcMethods: CustomRpcMethodsPlugin; - } + // Here is where you're adding your plugin's + // class inside Web3Context class + interface Web3Context { + customRpcMethods: CustomRpcMethodsPlugin; + } } ``` @@ -296,40 +289,40 @@ But, the user who does not call `.registerPlugin`, before accessing your plugin, Module Augmentation: - ```typescript - // code written by the plugin **developer** +```typescript +// code written by the plugin **developer** - declare module 'web3' { - // Here is where you're adding your plugin inside Web3Context - interface Web3Context { - customRpcMethods: CustomRpcMethodsPlugin; - } - } - ``` +declare module 'web3' { + // Here is where you're adding your plugin inside Web3Context + interface Web3Context { + customRpcMethods: CustomRpcMethodsPlugin; + } +} +``` - Your the plugin class: +Your the plugin class: - ```typescript - // code written by the plugin **developer** +```typescript +// code written by the plugin **developer** - export class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; +export class CustomRpcMethodsPlugin extends Web3PluginBase { + public pluginNamespace = 'customRpcMethods'; - ... - } - ``` + //... +} +``` - This is because `.registerPlugin` will use the `pluginNamespace` property provided by the plugin as the property name when it registers the plugin with the class instance that the **plugin user** will call `.registerPlugin` on: +This is because `.registerPlugin` will use the `pluginNamespace` property provided by the plugin as the property name when it registers the plugin with the class instance that the **plugin user** will call `.registerPlugin` on: - ```typescript - // code written by the plugin **user** +```typescript +// code written by the plugin **user** - const web3 = new Web3('http://127.0.0.1:8545'); - web3.registerPlugin(new CustomRpcMethodsPlugin()); - // Now customRpcMethods (i.e. the pluginNamespace) is available - // on the instance of Web3 - web3.customRpcMethods; - ``` +const web3 = new Web3('http://127.0.0.1:8545'); +web3.registerPlugin(new CustomRpcMethodsPlugin()); +// Now customRpcMethods (i.e. the pluginNamespace) is available +// on the instance of Web3 +web3.customRpcMethods; +``` ## Complete Example diff --git a/docs/docs/guides/web3_plugin_guide/plugin_users.md b/docs/docs/guides/web3_plugin_guide/plugin_users.md index d18a8eced5b..3c900d9e2a3 100644 --- a/docs/docs/guides/web3_plugin_guide/plugin_users.md +++ b/docs/docs/guides/web3_plugin_guide/plugin_users.md @@ -1,5 +1,5 @@ --- -sidebar_position: 0 +sidebar_position: 3 sidebar_label: 'For Plugin Users' --- @@ -32,10 +32,10 @@ To add a plugin to an instance of a class sourced from web3.js' modules (such as For illustration purposes, let's assume a plugin developer has the following code for their plugin. Please note that this code should not be touched by the plugin user: - + - + ```typescript // code written by the plugin **developer** @@ -43,25 +43,25 @@ For illustration purposes, let's assume a plugin developer has the following cod const { Web3PluginBase } = require('web3'); export class PluginExample extends Web3PluginBase { - public pluginNamespace = 'pluginExample'; + public pluginNamespace = 'pluginExample'; - public sampleMethod() { - return 'simpleValue'; - } + public sampleMethod() { + return 'simpleValue'; + } } // Module Augmentation declare module 'web3' { - interface Web3Context { - pluginExample: PluginExample; - } + interface Web3Context { + pluginExample: PluginExample; + } } ``` - + ```typescript @@ -70,18 +70,18 @@ declare module 'web3' { import { Web3PluginBase } from 'web3'; export class PluginExample extends Web3PluginBase { - public pluginNamespace = 'pluginExample'; + public pluginNamespace = 'pluginExample'; - public sampleMethod() { - return 'simpleValue'; - } + public sampleMethod() { + return 'simpleValue'; + } } // Module Augmentation declare module 'web3' { - interface Web3Context { - pluginExample: PluginExample; - } + interface Web3Context { + pluginExample: PluginExample; + } } ``` @@ -90,10 +90,10 @@ declare module 'web3' { Here is an example of how to register the `PluginExample` onto an instance of `Web3`: - + - + ```javascript // code written by the plugin **user** @@ -109,8 +109,8 @@ web3.pluginExample.sampleMethod(); - + ```typescript diff --git a/docs/docs/guides/web3_providers_guide/_category_.yml b/docs/docs/guides/web3_providers_guide/_category_.yml new file mode 100644 index 00000000000..3b85fe4849e --- /dev/null +++ b/docs/docs/guides/web3_providers_guide/_category_.yml @@ -0,0 +1,5 @@ +label: '🔌 Providers' +collapsible: true +collapsed: true +link: null +position: 2 \ No newline at end of file diff --git a/docs/docs/guides/web3_providers_guide/events_listening.md b/docs/docs/guides/web3_providers_guide/events_listening.md index 3ebd686db64..4208e4d2777 100644 --- a/docs/docs/guides/web3_providers_guide/events_listening.md +++ b/docs/docs/guides/web3_providers_guide/events_listening.md @@ -1,11 +1,8 @@ --- -sidebar_position: 1 -sidebar_label: 'Event Listening' +sidebar_position: 2 +sidebar_label: 'Providers Events Listening' --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - # Providers Events Listening Some providers are, by design, always connected. Therefor, they can communicate changes with the user through events. Actually, among the 3 providers, `HttpProvider` is the only one that does not support event. And the other 2: @@ -23,107 +20,49 @@ Actually, the events can be categorized as follows ([according to EIP 1193](http Below a sample code for listening and remove listening to EIP 1193 events: - - - - -```javascript -const { Web3 } = require('web3'); +```ts title='Listening to EIP1193 events'import { Web3 } from 'web3'; +import { Web3 } from 'web3'; const web3 = new Web3(/* PROVIDER*/); -web3.provider.on('message',()=>{ +web3.provider.on('message', () => { // ... -}) +}); -web3.provider.on('connect',()=>{ +web3.provider.on('connect', () => { // ... -}) +}); -web3.provider.on('disconnect',()=>{ +web3.provider.on('disconnect', () => { // ... -}) +}); -web3.provider.on('accountsChanged',()=>{ +web3.provider.on('accountsChanged', () => { // ... -}) +}); -web3.provider.on('chainChanged',()=>{ +web3.provider.on('chainChanged', () => { // ... -}) - -// it is possible to catch errors that could happen in the underlying connection Socket with the `error` event -// and it is also used to catch the error when max reconnection attempts exceeded -// as in section: /docs/guides/web3_providers_guide/#error-message -web3.provider.on('error',()=>{ - // ... -}) - -// ... - -// for every event above `once` can be used to register to the event only once -web3.provider.once('SUPPORTED_EVENT_NAME',()=>{ - // ... -}) - -// And to unregister a listener `removeListener` could be called -web3.provider.removeListener('SUPPORTED_EVENT_NAME',()=>{ - // ... -}) -``` - - - - - -```typescript -import { Web3 } from 'web3' - -const web3 = new Web3(/* PROVIDER*/); - -web3.provider.on('message',()=>{ - // ... -}) - -web3.provider.on('connect',()=>{ - // ... -}) - -web3.provider.on('disconnect',()=>{ - // ... -}) - -web3.provider.on('accountsChanged',()=>{ - // ... -}) - -web3.provider.on('chainChanged',()=>{ - // ... -}) +}); // it is possible to catch errors that could happen in the underlying connection Socket with the `error` event // and it is also used to catch the error when max reconnection attempts is exceeded // as in section: /docs/guides/web3_providers_guide/#error-message -web3.provider.on('error',()=>{ +web3.provider.on('error', () => { // ... -}) +}); // ... // for every event above `once` can be used to register to the event only once -web3.provider.once('SUPPORTED_EVENT_NAME',()=>{ +web3.provider.once('SUPPORTED_EVENT_NAME', () => { // ... -}) +}); // And to unregister a listener `removeListener` could be called -web3.provider.removeListener('SUPPORTED_EVENT_NAME',()=>{ +web3.provider.removeListener('SUPPORTED_EVENT_NAME', () => { // ... -}) +}); ``` - - - However, the underlying `SocketConnection` of both `WebSocketProvider` and `IpcProvider` could be accessed. This enables the user to access any special properties of the used Socket. As well as, registering to the custom server events directly. Actually the Socket used at `WebSocketProvider` is [isomorphic-ws](https://github.com/heineiuo/isomorphic-ws). And the Socket used at `IpcProvider` is [net.Server](https://nodejs.org/api/net.html#class-netserver) diff --git a/docs/docs/guides/web3_providers_guide/examples.md b/docs/docs/guides/web3_providers_guide/examples.md deleted file mode 100644 index 942c51a272d..00000000000 --- a/docs/docs/guides/web3_providers_guide/examples.md +++ /dev/null @@ -1,790 +0,0 @@ ---- -sidebar_label: Examples ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Example usage - -## Prerequisites - -Before we get started, make sure you have a basic understanding of JavaScript and Ethereum. Additionally, we need to set up our environment by installing the following: - -1. **Ganache** - - Ganache is a personal blockchain for Ethereum development that allows you to test how your smart contracts function in real-world scenarios. You can download it from [http://truffleframework.com/ganache](http://truffleframework.com/ganache). - -2. **Node.js** - - Node.js is a JavaScript runtime environment that enables you to run JavaScript on the server-side. You can download it from [https://nodejs.org/en/download/](https://nodejs.org/en/download/). - -3. **npm** - - npm (Node Package Manager) is used to publish and install packages to and from the public npm registry or a private npm registry. You can install it by following the instructions here: [https://docs.npmjs.com/downloading-and-installing-node-js-and-npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). - - Alternatively, you can use **yarn** instead of **npm** by following the instructions here: [https://classic.yarnpkg.com/lang/en/docs/getting-started/](https://classic.yarnpkg.com/lang/en/docs/getting-started/). - -4. **Geth** (Optional, used only at the IPC provider example) - - Geth (go-ethereum) is an Ethereum execution client meaning it handles transactions, deployment and execution of smart contracts and contains an embedded computer known as the Ethereum Virtual Machine. You can install it by following the instructions here: [https://geth.ethereum.org/docs/getting-started/installing-geth](https://geth.ethereum.org/docs/getting-started/installing-geth) - -## Types of Providers - -web3.js supports several types of providers, each with its own unique features or specific use cases. Here are the main types: - -1. [HTTP Provider](#http-provider) -2. [WebSocket Provider](#websocket-provider) -3. [IPC Provider (for Node.js)](#websocket-provider) -4. [Third-party Providers (Compliant with EIP 1193)](#third-party-providers-compliant-with-eip-1193) - -### HTTP Provider - -The HTTP Provider allows you to connect to a publicly available Ethereum node, making it easy and straightforward to communicate with the Ethereum network from your web application. - -To connect to the Ethereum network using the HTTP provider, follow these steps: - -1. Open a command prompt or terminal window and navigate to the directory where you want to create the folder for this example. -2. Create a new folder and navigate to it: - - ```bash - mkdir web3-providers-tutorial - cd web3-providers-tutorial - ``` - -3. Install web3.js using npm: - - ```bash - npm i web3 - ``` - -4. Create a new JavaScript file called `web3-http-provider.js` in your code editor. - -5. Copy and paste the following code into your `web3-http-provider.js` file and save it: - - - - - -```javascript -const { Web3 } = require('web3'); - -// Connect to the Ethereum network using the HTTP provider -const ganacheUrl = 'http://localhost:7545'; -const httpProvider = new Web3.providers.HttpProvider(ganacheUrl); -const web3 = new Web3(httpProvider); - -async function main() { - try { - // Get the current block number from the network - const currentBlockNumber = await web3.eth.getBlockNumber(); - console.log('Current block number:', currentBlockNumber); - - // Get the list of accounts in the connected node (e.g., Ganache) - const accounts = await web3.eth.getAccounts(); - - // Send a transaction to the network and wait for the transaction to be mined. - // Note that sending a transaction with Ganache will cause it, in its default configuration, to min a new block. - const transactionReceipt = await web3.eth.sendTransaction({ - from: accounts[0], - to: accounts[1], - value: web3.utils.toWei('0.001', 'ether'), - }); - console.log('Transaction Receipt:', transactionReceipt); - - // Get the updated block number - const updatedBlockNumber = await web3.eth.getBlockNumber(); - console.log('Updated block number:', updatedBlockNumber); - } catch (error) { - console.error('An error occurred:', error); - } -} - -main(); -``` - - - - - -```typescript -import { Web3 } from 'web3'; - -// Connect to the Ethereum network using the HTTP provider -const ganacheUrl = 'http://localhost:7545'; -const httpProvider = new Web3.providers.HttpProvider(ganacheUrl); -const web3 = new Web3(httpProvider); - -async function main() { - try { - // Get the current block number from the network - const currentBlockNumber = await web3.eth.getBlockNumber(); - console.log('Current block number:', currentBlockNumber); - - // Get the list of accounts in the connected node (e.g., Ganache) - const accounts = await web3.eth.getAccounts(); - - // Send a transaction to the network and wait for the transaction to be mined. - // Note that sending a transaction with Ganache will cause it, in its default configuration, to min a new block. - const transactionReceipt = await web3.eth.sendTransaction({ - from: accounts[0], - to: accounts[1], - value: web3.utils.toWei('0.001', 'ether'), - }); - console.log('Transaction Receipt:', transactionReceipt); - - // Get the updated block number - const updatedBlockNumber = await web3.eth.getBlockNumber(); - console.log('Updated block number:', updatedBlockNumber); - } catch (error) { - console.error('An error occurred:', error); - } -} - -main(); -``` - - - - -6. Ensure that Ganache is running as mentioned in the [Prerequisites](#prerequisites) section. - -7. In the command prompt or terminal window, type `node web3-http-provider.js` and press Enter. This will run your JavaScript file and connect to the Ethereum network using the HTTP provider and Ganache. - -If everything is set up properly, you should see the current block number, the transaction receipt, and the updated block number printed in the console: - -```bash -Current block number: 0n -Transaction Receipt: { - transactionHash: '0x0578672e97d072b4b91773c8bfc710e4f777616398b82b276323408e59d11362', - transactionIndex: 0n, - blockNumber: 1n, - blockHash: '0x348a6706e7cce6547fae2c06b3e8eff1f58e4669aff88f0af7ca250ffdcdeef5', - from: '0x6e599da0bff7a6598ac1224e4985430bf16458a4', - to: '0x6f1df96865d09d21e8f3f9a7fba3b17a11c7c53c', - cumulativeGasUsed: 21000n, - gasUsed: 21000n, - logs: [], - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - status: 1n, - effectiveGasPrice: 2000000000n, - type: 0n -} -Updated block number: 1n -``` - -### WebSocket Provider - -WebSocket Provider allows us to communicate with the Ethereum node via WebSocket protocol, which is useful when we want continuous updates on our subscribed items. This provider is ideal for real-time applications that require constant updates from the Ethereum network. - -Follow these steps to connect to the Ethereum network using WebSocket provider: - -:::tip -The first 3 steps are the same as in the pervious section. So, you may skip them if you already executed the previous section. -::: - -1. Open a command prompt or terminal window and navigate to where you would like to create the folder for this example. -2. Create a new folder and navigate to it: - - ```bash - mkdir web3-providers-tutorial - cd web3-providers-tutorial - ``` - -3. Install web3.js using npm: - - ```bash - - npm i web3 - - ``` - -4. Create a new JavaScript file called `web3-websocket-provider.js` in your code editor. - -5. Copy and paste the following code into your `web3-websocket-provider.js` file and save it: - - - - - -```javascript -const { Web3 } = require('web3'); - -// Connect to the Ethereum network using WebSocket provider -const ganacheUrl = 'ws://localhost:8545'; -const wsProvider = new Web3.providers.WebsocketProvider(ganacheUrl); -const web3 = new Web3(wsProvider); - -async function main() { - try { - console.log( - 'Does the provider support subscriptions?:', - wsProvider.supportsSubscriptions(), - ); - - // Subscribe to new block headers - const subscription = await web3.eth.subscribe('newBlockHeaders'); - - subscription.on('data', async blockhead => { - console.log('New block header: ', blockhead); - - // You do not need the next line if you like to keep being notified for every new block - await subscription.unsubscribe(); - console.log('Unsubscribed from new block headers.'); - }); - subscription.on('error', error => - console.log('Error when subscribing to New block header: ', error), - ); - - // Get the list of accounts in the connected node which is in this case: Ganache. - const accounts = await web3.eth.getAccounts(); - // Send a transaction to the network - const transactionReceipt = await web3.eth.sendTransaction({ - from: accounts[0], - to: accounts[1], - value: web3.utils.toWei('0.001', 'ether'), - }); - console.log('Transaction Receipt:', transactionReceipt); - } catch (error) { - console.error(error); - } -} - -main(); -``` - - - - - -```typescript -import { Web3 } from 'web3'; - -// Connect to the Ethereum network using WebSocket provider -const ganacheUrl = 'ws://localhost:8545'; -const wsProvider = new Web3.providers.WebsocketProvider(ganacheUrl); -const web3 = new Web3(wsProvider); - -async function main() { - try { - console.log( - 'Does the provider support subscriptions?:', - wsProvider.supportsSubscriptions(), - ); - - // Subscribe to new block headers - const subscription = await web3.eth.subscribe('newBlockHeaders'); - - subscription.on('data', async blockhead => { - console.log('New block header: ', blockhead); - - // You do not need the next line if you like to keep being notified for every new block - await subscription.unsubscribe(); - console.log('Unsubscribed from new block headers.'); - }); - subscription.on('error', error => - console.log('Error when subscribing to New block header: ', error), - ); - - // Get the list of accounts in the connected node which is in this case: Ganache. - const accounts = await web3.eth.getAccounts(); - // Send a transaction to the network - const transactionReceipt = await web3.eth.sendTransaction({ - from: accounts[0], - to: accounts[1], - value: web3.utils.toWei('0.001', 'ether'), - }); - console.log('Transaction Receipt:', transactionReceipt); - } catch (error) { - console.error(error); - } -} - -main(); -``` - - - - -6. Ensure that Ganache is running as mentioned in the [Prerequisites](#prerequisites) section. - -7. Type `node web3-websocket-provider.js` in the command prompt or terminal window and press Enter. This will run your JavaScript file. - -If everything is set up properly, you should see the new block headers, transaction hash, and pending transaction printed in the console. The unique feature of WebSocket provider highlighted in this example is that it can subscribe to new block headers and pending transactions to get them in real-time. And by running the sample, you will get something similar to this in your console: - -```bash -Do the provider supports subscription?: true -New block header: { - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - miner: '0x0000000000000000000000000000000000000000', - difficulty: '0', - totalDifficulty: '0', - extraData: '0x', - gasLimit: 6721975, - gasUsed: 21000, - hash: '0xd315cecf3336640bcd1301930805370b7fe7528c894b931dcf8a3b1c833b68c8', - mixHash: '0x1304070fde1c7bee383f3a59da8bb94d515cbd033b2638046520fb6fb596d827', - nonce: '0x0000000000000000', - number: 40, - parentHash: '0xeb7ce3260911db2596ac843df11dbcbef302e813e1922db413f6f0b2a54d584d', - receiptsRoot: '0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa', - stateRoot: '0x95e416eec0932e725ec253779a4e28b3d014d05e41e63c3369f5da42d26d1240', - timestamp: 1684165088, - transactionsRoot: '0x8f87380cc7acfb6d10633e10f72567136492cb8301f52a41742eaca9449bb378', - sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', - baseFeePerGas: 4959456, - size: undefined -} -Transaction Receipt: { - transactionHash: '0x0578672e97d072b4b91773c8bfc710e4f777616398b82b276323408e59d11362', - transactionIndex: 0n, - blockNumber: 1n, - blockHash: '0x5c05248fe0fb8f45a8c9b9600904a36c0e5c74dce01495cfc72278c185fe7838', - from: '0x6e599da0bff7a6598ac1224e4985430bf16458a4', - to: '0x6f1df96865d09d21e8f3f9a7fba3b17a11c7c53c', - cumulativeGasUsed: 21000n, - gasUsed: 21000n, - logs: [], - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - status: 1n, - effectiveGasPrice: 2000000000n, - type: 0n -} -Unsubscribed from new block headers. -``` - -### IPC Provider (for Node.js) - -The IPC Provider allows you to connect to an Ethereum node using Inter-Process Communication (IPC) in a Node.js environment. This provider is useful when you have a local Ethereum node running on your machine and want to interact with it using Node.js. - -In the following steps you will run `geth` in development mode and you will run a piece of code that reads the Ethereum accounts and sends a transaction: - -To connect to the Ethereum network using the IPC provider, follow these steps: - -1. Start a `geth` node in development mode by opening a terminal window and navigating to the `geth` executable file. Then, run the following command to create a development chain: - -```bash -geth --dev --ipcpath -``` - -Make sure to replace `` with the desired IPC path. For example: - -```bash -geth --dev --ipcpath /Users/username/Library/Ethereum/geth.ipc -``` - -This will start a `geth` node in development mode with IPC enabled and an IPC path specified. If the command is successful, the `geth` node will be running, and you should see output similar to the following: - -```bash -INFO [12-10|15:10:37.121] IPC endpoint opened url= -INFO [12-10|15:10:37.122] HTTP endpoint opened url=http://localhost:8545 -INFO [12-10|15:10:37.122] WebSocket endpoint opened url=ws://localhost:8546 -INFO [12-10|15:10:37.127] Mapped network port proto=udp extport=0 intport=30303 interface=UPnP(UDP) -``` - -2. Open a command prompt or terminal window and navigate to where you would like to create the folder for this example. -3. Create a new folder and navigate to it: - - ```bash - mkdir web3-providers-tutorial - cd web3-providers-tutorial - ``` - -4. Install web3.js using npm: - - ```bash - - npm i web3 - - ``` - -5. Create a new JavaScript file called `web3-ipc-provider.js` in your code editor. - -6. Copy and paste the following code into your `web3-ipc-provider.js` file and save it: - - - - - -```javascript -const { Web3 } = require('web3'); -const { IpcProvider } = require('web3-providers-ipc'); - -// Connect to the Ethereum network using IPC provider -const ipcPath = ''; // Replace with your actual IPC path -const ipcProvider = new IpcProvider(ipcPath); - -const web3 = new Web3(ipcProvider); - -async function main() { - try { - console.log('Does the provider support subscriptions?:', ipcProvider.supportsSubscriptions()); - - // Get the list of accounts in the connected node which is in this case: geth in dev mode. - const accounts = await web3.eth.getAccounts(); - console.log('Accounts:', accounts); - - // Send a transaction to the network - const transactionReceipt = await web3.eth.sendTransaction({ - from: accounts[0], - to: accounts[0], // sending a self-transaction - value: web3.utils.toWei('0.001', 'ether'), - }); - console.log('Transaction Receipt:', transactionReceipt); - } catch (error) { - console.error('An error occurred:', error); - } -} - -main(); -``` - - - - - -```typescript -import { Web3 } from 'web3'; -import { IpcProvider } from 'web3-providers-ipc'; - -// Connect to the Ethereum network using IPC provider -const ipcPath = ''; // Replace with your actual IPC path -const ipcProvider = new IpcProvider(ipcPath); - -const web3 = new Web3(ipcProvider); - -async function main() { - try { - console.log('Does the provider support subscriptions?:', ipcProvider.supportsSubscriptions()); - - // Get the list of accounts in the connected node which is in this case: geth in dev mode. - const accounts = await web3.eth.getAccounts(); - console.log('Accounts:', accounts); - - // Send a transaction to the network - const transactionReceipt = await web3.eth.sendTransaction({ - from: accounts[0], - to: accounts[0], // sending a self-transaction - value: web3.utils.toWei('0.001', 'ether'), - }); - console.log('Transaction Receipt:', transactionReceipt); - } catch (error) { - console.error('An error occurred:', error); - } -} - -main(); -``` - - - - -7. replace `` with the `ipcPath` that you had specified, when starting the `geth` node, in the first step. - -8. Type `node web3-ipc-provider.js` in the command prompt or terminal window and press Enter. This will run your JavaScript file. - -If everything is set up properly, you should see the list of accounts and transaction receipt printed in the console, similar to the following: - -```bash -Do the provider supports subscription?: true -Accounts: [ '0x82333ED0FAA7a883297C4d8e0FDE1E1CFABAeB7D' ] -Transaction Receipt: { - blockHash: '0xd1220a9b6f86083e420da025179593f5aad3732165a687019a89528a4ab2bcd8', - blockNumber: 1n, - cumulativeGasUsed: 21000n, - effectiveGasPrice: 1000000001n, - from: '0x82333ed0faa7a883297c4d8e0fde1e1cfabaeb7d', - gasUsed: 21000n, - logs: [], - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - status: 1n, - to: '0x82333ed0faa7a883297c4d8e0fde1e1cfabaeb7d', - transactionHash: '0x76c05df78dc5dbfade0d11322b3cadc894c17efe36851856aca29488b47c3fbd', - transactionIndex: 0n, - type: 0n -} -``` - -Keep in mind that using IPC Provider with `geth` in development mode in a production environment is not recommended as it can pose a security risk. - -### Third-party Providers (Compliant with EIP 1193) - -web3.js accepts any provider that is in compliance with [EIP-1193](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md). It has tests written to ensure compatibility with @truffle/hdwallet-provider, Ganache provider, Hardhat provider, and Incubed (IN3) as a provider. The following section, [Browser Injected Ethereum Provider](#browser-injected-ethereum-provider), in this tutorial explains how to use a special case of these third-party providers. - -Here is a step-by-step example and a code snippet to connect your web application to the Ethereum network using `@truffle/hdwallet-provider` as an example of an external provider compliant with EIP 1193. - -1. Open a command prompt or terminal window in a new folder. -2. Type `npm init -y` and press Enter. This will create a `package.json` file in the current directory. -3. Install web3.js and HTTP provider using npm: - - ```bash - - npm i web3 @truffle/hdwallet-provider bip39 - - ``` - -4. Create a new JavaScript file, called `index.js`, in your code editor. -5. Copy and paste the following code into your JavaScript file, and then save the file: - - - - - -```javascript -const { Web3 } = require('web3'); -const HDWalletProvider = require('@truffle/hdwallet-provider'); -const bip39 = require('bip39'); - -const mnemonic = bip39.generateMnemonic(); // generates seed phrase -console.log('seed phrase:', mnemonic); - -// Connect to the Ethereum network using an HTTP provider and WalletProvider -const provider = new HDWalletProvider( - mnemonic, - 'https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID', -); -const web3 = new Web3(provider); - -// Get the current block number from the network -web3.eth - .getBlockNumber() - .then(function (blockNumber) { - console.log('Current block number:', blockNumber); - }) - .catch(function (error) { - console.log('Error:', error); - }); -``` - - - - - -```typescript -import { Web3 } from 'web3'; -import HDWalletProvider from '@truffle/hdwallet-provider'; -import bip39 from 'bip39'; - -const mnemonic: string = bip39.generateMnemonic(); // generates seed phrase -console.log('seed phrase:', mnemonic); - -// Connect to the Ethereum network using an HTTP provider and WalletProvider -const provider: HDWalletProvider = new HDWalletProvider( - mnemonic, - 'https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID', -); -const web3: Web3 = new Web3(provider); - -// Get the current block number from the network -web3.eth - .getBlockNumber() - .then(function (blockNumber: number) { - console.log('Current block number:', blockNumber); - }) - .catch(function (error: any) { - console.log('Error:', error); - }); -``` - - - - -6. Replace `'YOUR_INFURA_PROJECT_ID'` with your own Infura project ID. You can obtain an Infura project ID by signing up for a free account at https://infura.io/register. Alternatively, you can use any other URL that is compatible with HDWalletProvider, such as a local Ganache accessible at `'http://localhost:7545'`. - -7. In the command prompt, run `node index.js` and press Enter. This will execute your JavaScript file and connect to the Ethereum network using HDWalletProvider with Infura. - -If everything is set up properly, you should see the current block number printed in the console similar to the following. - -```bash -seed phrase: remain climb clock valid budget cable tunnel force split level measure repair -Current block number: 17317844n -``` - -:::danger -Your seed phrase gives complete access to your Ethereum account and it should **never** be shared with anyone you don't want to give full access to your account. The seed phrase is `console.log`ed in the code example to show you what it looks like, but you should **never** do this with a seed phrase to an account you plan on using to send real money. -::: - -The sample above connected you to the Ethereum network using truffle HD Wallet-enabled Web3 provider. You can modify it to interact with the network, perform transactions, and read/write data from the Ethereum network. - -## Practical ways of connecting to a provider - -1. Browser Injected Ethereum Provider -2. Setting Web3 Provider using a string URL - -### Browser Injected Ethereum Provider - -It is easy to connect to the Ethereum network using an Ethereum browser extension such as MetaMask, or an Ethereum-enabled browser like the browser inside TrustWallet. Because they inject their provider object into the browser's JavaScript context, enabling direct interaction with the Ethereum network from your web application. Moreover, the wallet management is conveniently handled by these extensions or browsers, making it the standard approach for DApp developers to facilitate user interactions with the Ethereum network. - -Technically, you use `window.ethereum` when it is injected by the Ethereum browser extension or the Ethereum-enabled browser. However, before using this provider, you need to check if it is available and then call `enable()` to request access to the user's MetaMask account. - -Before start coding you will need to setup and configure Ganache and MetaMask, if you have not already: - -- Ensure that Ganache is running as mentioned in the [Prerequisites](#prerequisites) section. -- Install the MetaMask extension for your browser. You can download MetaMask from their website: https://metamask.io/. - -Follow these steps to connect to the Ethereum network with MetaMask and web3.js, including the steps to create a local web server using Node.js: - -1. Open a command prompt or terminal window and navigate to where you would like to create the folder for this example. -2. Create a new folder and navigate to it: - - ```bash - mkdir web3-browser-injected-providers - cd web3-browser-injected-providers - ``` - -3. Use npm to initialize the folder. This will simply create a `package.json` file: - - ```bash - npm init -y - ``` - -4. Install the Express module and add it to your project's dependencies: - - ```bash - npm i express - ``` - -5. Create a new HTML file named `index.html` in your code editor (inside `web3-browser-injected-providers`). - -6. Copy and paste the following code into `index.html`, and save it after: - -```html - - - - - Connecting to the Ethereum network with Web3.js and MetaMask - - -

Connecting to the Ethereum network with Web3.js and MetaMask

-
-  You need to approve connecting this website to MetaMask.
-  Click on the MetaMask icon in the browser extension, if it did not show a popup already.
-  
- - - - - -``` - -7. Create a new file called `server.js` (inside `web3-browser-injected-providers`). -8. Copy and paste the following code into `server.js`, and save it after: - - ```js - const express = require('express'); - const app = express(); - const path = require('path'); - - app.use(express.static(path.join(__dirname, '.'))); - - app.listen(8097, () => { - console.log('Server started on port 8097'); - }); - ``` - -9. Start the Node.js server by executing the following command. This will execute the content of `server.js` which will run the server on port 8097: - - ```bash - node server.js - ``` - -10. Open your web browser and navigate to `http://localhost:8097/`. MetaMask should ask for your approval to connect to your website. Follow the steps and give your consent. -11. If everything is set up properly, you should be able to connect to the Ethereum network with MetaMask and see the logged account address. - -Note that in the above steps you had created a local web server using Node.js and Express, serving your HTML file from the root directory of your project. You needs this local server because many browser does not allow extensions to inject objects for static files located on your machine. However, you can customize the port number and the root directory if needed. - -Now you can start building your Ethereum application with web3.js and MetaMask! - -### Setting Web3 Provider using a String URL - -web3.js allows you to set the Ethereum network provider, easily, by passing a string URL containing either the `http`, `https`, `ws`, or `wss` protocol. This provider can be used to connect to a remote server or node. - -And when a string is passed, an instance of the compatible class above will be created accordingly. ex. WebSocketProvider instance will be created for string containing `ws` or `wss`. And you access this instance by calling `web3.provider` to read the provider and possibly register an event listener. - -To set the Web3 provider from a URL, you can use the following code snippet: - -```js -const web3 = new Web3('https://ropsten.infura.io/v3/YOUR_INFURA_PROJECT_ID'); -``` - -Replace `` with your own Infura project ID. This code snippet creates a new Web3 instance with Infura's Ropsten network endpoint as the provider. - -However, if you do not want to use Infura and want to run your own Ethereum node, you can set the provider to a local node with, for example, the `http` protocol, like this: - -```js -const web3 = new Web3('http://localhost:8545'); -``` - -This code snippet sets the provider to a local node running on port 8545. - -You can also use the `WebSocket` protocol to connect to a remote Ethereum node that supports it, like this: - -```js -const web3 = new Web3('wss://eth-mainnet.alchemyapi.io/v2/'); -``` - -With this code snippet, Web3 will create a WebSocket provider object connection to Alchemy's mainnet endpoint. However, you need to replace `` with your own API Key. - -A few points to consider: - -- Make sure the URL you are using is correct, including the protocol and port if necessary. -- If you are using a remote node, make sure your firewall allows access to the specified port. -- It is recommended to use encrypted protocols `https` and `wss` when connecting to Ethereum network using a string URL. - -## Conclusion - -In this tutorial, we explored different types of providers available in web3.js and learned how to set them up and use them in our code. Depending on your application's needs, you can choose the provider that best suits your requirements. The HTTP Provider is the simplest and most widely used provider, while the Websocket Provider and IPC Provider offer real-time communication and faster performance, respectively. With these providers, you can connect your web application to the Ethereum network and start building decentralized applications. diff --git a/docs/docs/guides/web3_providers_guide/http.md b/docs/docs/guides/web3_providers_guide/http.md new file mode 100644 index 00000000000..c30db83873d --- /dev/null +++ b/docs/docs/guides/web3_providers_guide/http.md @@ -0,0 +1,113 @@ +--- +sidebar_position: 3 +sidebar_label: 'Tutorial: HTTP Provider' +--- + +# Tutorial: HTTP Provider + +The HTTP Provider is the simplest and most widely used provider, while the Websocket Provider and IPC Provider offer real-time communication and faster performance, respectively. With these providers, you can connect your web application to the Ethereum network and start building decentralized applications. + +## Prerequisites + +Before we get started, make sure you have a basic understanding of JavaScript and Ethereum. Additionally, we need to set up our environment by installing the following: + +1. **Ganache** + + Ganache is a personal blockchain for Ethereum development that allows you to test how your smart contracts function in real-world scenarios. You can download it from [http://truffleframework.com/ganache](http://truffleframework.com/ganache). + +2. **Node.js** + + Node.js is a JavaScript runtime environment that enables you to run JavaScript on the server-side. You can download it from [https://nodejs.org/en/download/](https://nodejs.org/en/download/). + +3. **npm** + + npm (Node Package Manager) is used to publish and install packages to and from the public npm registry or a private npm registry. You can install it by following the instructions here: [https://docs.npmjs.com/downloading-and-installing-node-js-and-npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). + + Alternatively, you can use **yarn** instead of **npm** by following the instructions here: [https://classic.yarnpkg.com/lang/en/docs/getting-started/](https://classic.yarnpkg.com/lang/en/docs/getting-started/). + +## HTTP Provider + +The HTTP Provider allows you to connect to a publicly available Ethereum node, making it easy and straightforward to communicate with the Ethereum network from your web application. + +To connect to the Ethereum network using the HTTP provider, follow these steps: + +1. Open a command prompt or terminal window and navigate to the directory where you want to create the folder for this example. +2. Create a new folder and navigate to it: + +```bash +mkdir web3-providers-tutorial +cd web3-providers-tutorial +``` + +3. Install web3.js using npm: + +```bash +npm i web3 +``` + +4. Create a new JavaScript file called `web3-http-provider.js` in your code editor. + +5. Copy and paste the following code into your `web3-http-provider.js` file and save it: + +```typescript title='HTTP Provider' +import { Web3 } from 'web3'; + +// Connect to the Ethereum network using the HTTP provider +const ganacheUrl = 'http://localhost:7545'; +const httpProvider = new Web3.providers.HttpProvider(ganacheUrl); +const web3 = new Web3(httpProvider); + +async function main() { + try { + // Get the current block number from the network + const currentBlockNumber = await web3.eth.getBlockNumber(); + console.log('Current block number:', currentBlockNumber); + + // Get the list of accounts in the connected node (e.g., Ganache) + const accounts = await web3.eth.getAccounts(); + + // Send a transaction to the network and wait for the transaction to be mined. + // Note that sending a transaction with Ganache will cause it, in its default configuration, to min a new block. + const transactionReceipt = await web3.eth.sendTransaction({ + from: accounts[0], + to: accounts[1], + value: web3.utils.toWei('0.001', 'ether'), + }); + console.log('Transaction Receipt:', transactionReceipt); + + // Get the updated block number + const updatedBlockNumber = await web3.eth.getBlockNumber(); + console.log('Updated block number:', updatedBlockNumber); + } catch (error) { + console.error('An error occurred:', error); + } +} + +main(); +``` + +6. Ensure that Ganache is running as mentioned in the [Prerequisites](#prerequisites) section. + +7. In the command prompt or terminal window, type `node web3-http-provider.js` and press Enter. This will run your JavaScript file and connect to the Ethereum network using the HTTP provider and Ganache. + +If everything is set up properly, you should see the current block number, the transaction receipt, and the updated block number printed in the console: + +```bash +Current block number: 0n +Transaction Receipt: { + transactionHash: '0x0578672e97d072b4b91773c8bfc710e4f777616398b82b276323408e59d11362', + transactionIndex: 0n, + blockNumber: 1n, + blockHash: '0x348a6706e7cce6547fae2c06b3e8eff1f58e4669aff88f0af7ca250ffdcdeef5', + from: '0x6e599da0bff7a6598ac1224e4985430bf16458a4', + to: '0x6f1df96865d09d21e8f3f9a7fba3b17a11c7c53c', + cumulativeGasUsed: 21000n, + gasUsed: 21000n, + logs: [], + logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + status: 1n, + effectiveGasPrice: 2000000000n, + type: 0n +} +Updated block number: 1n +``` diff --git a/docs/docs/guides/web3_providers_guide/index.md b/docs/docs/guides/web3_providers_guide/index.md index 96f593360d1..9595fe9d07c 100644 --- a/docs/docs/guides/web3_providers_guide/index.md +++ b/docs/docs/guides/web3_providers_guide/index.md @@ -1,12 +1,9 @@ --- -sidebar_position: 2 -sidebar_label: 'Providers' +sidebar_position: 1 +sidebar_label: 'Mastering Providers' --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# web3.js Providers Guide +# Web3js providers overview ## Introduction @@ -14,65 +11,89 @@ web3.js providers are objects responsible for enabling connectivity with the Eth Connecting to a chain happens through a provider. You can pass the provider to the constructor as in the following example: +:::tip +If you want to subscribe to live events in the blockchain, you should use [`WebSocket provider`](#websocket-provider) or [`IPC provider`](#ipc-provider) +::: - - - - -```javascript -const { Web3 } = require('web3'); - -const web3 = new Web3(/* PROVIDER*/); - -// calling any method that interact with the network would involve using the early passed provider. -await web3.eth.sendTransaction({ - from, - to, - value, -}); -``` - - - - - -```typescript +```typescript title='Initialize a provider' import { Web3 } from 'web3'; const web3 = new Web3(/* PROVIDER*/); -// calling any method that interact with the network would involve using the early passed provider. -await web3.eth.sendTransaction({ - from, - to, - value, -}); +//calling any method that interact with the network would use the previous passed provider. +await web3.eth.getBlockNumber(); ``` - - - - -The created Web3 instance will use the passed provider to interact with the blockchain network. This interaction happens when sending a request and receiving the response, and possibly when listening to provider events (if the provider support this). +The created `Web3` instance will use the passed provider to interact with the blockchain network. This interaction happens when sending a request and receiving the response, and possibly when listening to provider events (if the provider support this). ## Providers Types -Actually, the provider could be any of the following: +web3.js supports several types of providers, each with its own unique features or specific use cases. Here are the main types: -- An instance of [HttpProvider](/api/web3-providers-http/class/HttpProvider) -- An instance of [WebSocketProvider](/api/web3-providers-ws/class/WebSocketProvider) -- An instance of [IpcProvider](/api/web3-providers-ipc/class/IpcProvider) -- A string containing string url for `http`/`https` or `ws`/`wss` protocol. And when a string is passed, an instance of the compatible class above will be created accordingly. ex. WebSocketProvider instance will be created for string containing `ws` or `wss`. And you access this instance by calling `web3.provider` to read the provider and possibly register an event listener. -- Any provider object that adhere to [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193). And it has been tested with Ganache provider, Hardhat provider, and Incubed (IN3) as a provider. +1. [HTTP Provider](/api/web3-providers-http/class/HttpProvider) +2. [WebSocket Provider](/api/web3-providers-ws/class/WebSocketProvider) +3. [IPC Provider (for Node.js)](/api/web3-providers-ipc/class/IpcProvider) +4. [Third-party Providers (Compliant with EIP 1193)](https://eips.ethereum.org/EIPS/eip-1193) -For both [WebSocketProvider](/api/web3-providers-ws/class/WebSocketProvider) and [IpcProvider](/api/web3-providers-ipc/class/IpcProvider) the user can listen to emitted events. More on this is at [Providers Events Listening](events_listening). +A string containing string url for `http`/`https` or `ws`/`wss` protocol. And when a string is passed, an instance of the compatible class above will be created accordingly. ex. WebSocketProvider instance will be created for string containing `ws` or `wss`. And you access this instance by calling `web3.provider` to read the provider and possibly register an event listener. :::tip The passed provider can be either type `string` or one of the [`SupportedProviders`](/api/web3-core#SupportedProviders). And if it is passed as a string, then internally the compatible provider object will be created and used. ::: +### HTTP Provider + +``` ts title='Initialize HTTP Provider' +import { Web3, HttpProvider } from 'web3'; + +//highlight-next-line +const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_ID'); + +await web3.eth.getBlockNumber() +// ↳ 18849658n + +// or + +//highlight-next-line +const web3_2 = new Web3(new HttpProvider('https://mainnet.infura.io/v3/YOUR_INFURA_ID')); + +await web3.eth.getBlockNumber() +// ↳ 18849658n +``` + +### WebSocket provider + +``` ts title='Initialize WS Provider' +import { Web3, WebSocketProvider } from 'web3'; + +//highlight-next-line +const web3 = new Web3('wss://mainnet.infura.io/ws/v3/YOUR_INFURA_ID'); + +await web3.eth.getBlockNumber(); +// ↳ 18849658n + +// or +//highlight-next-line +const web3_2 = new Web3(new WebSocketProvider('wss://mainnet.infura.io/ws/v3/YOUR_INFURA_ID')); + +await web3.eth.getBlockNumber(); +// ↳ 18849658n +``` + +### IPC Provider + +``` ts title='Initialize IPC Provider' +import { Web3 } from 'web3'; +//highlight-next-line +import { IpcProvider } from 'web3-providers-ipc'; + +//highlight-next-line +const web3 = new Web3(new IpcProvider('/users/myuser/.ethereum/geth.ipc')); + +await web3.eth.getBlockNumber(); +// ↳ 18849658n +``` + ## Providers Priorities There are multiple ways to set the provider. @@ -91,164 +112,110 @@ The key rule for setting provider is as follows: --- -## Examples +## Usage Scenarios ### Local Geth Node - - - - -```javascript -const { Web3 } = require('web3'); -const web3 = new Web3('http://localhost:8545'); -// or -const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); - -// change provider -web3.setProvider('ws://localhost:8546'); -// or -web3.setProvider(new Web3.providers.WebsocketProvider('ws://localhost:8546')); - - -// Using the IPC provider in node.js -const { Web3 } = require('web3'); -const { IpcProvider } = require('web3-providers-ipc'); - -const web3 = new Web3( - new IpcProvider('/Users/myuser/Library/Ethereum/geth.ipc'), -); // mac os path -// on windows the path is: "\\\\.\\pipe\\geth.ipc" -// on linux the path is: "/users/myuser/.ethereum/geth.ipc" -``` - - +```typescript title='IPC, HTTP and WS provider' +import { Web3 } from 'web3'; +import { IpcProvider } from 'web3-providers-ipc'; - +//highlight-next-line +//IPC provider +const web3 = new Web3(new IpcProvider('/Users/myuser/Library/Ethereum/geth.ipc'));//mac os path +// on windows the path is: '\\\\.\\pipe\\geth.ipc' +// on linux the path is: '/users/myuser/.ethereum/geth.ipc' -```typescript -import { Web3 } from 'web3'; -const web3 = new Web3('http://localhost:8545'); +//highlight-next-line +//HTTP provider +web3.setProvider('http://localhost:8545'); // or -const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); +web3.setProvider(new Web3.providers.HttpProvider('http://localhost:8545')); -// change provider +//highlight-next-line +//WebSocket provider web3.setProvider('ws://localhost:8546'); // or web3.setProvider(new Web3.providers.WebsocketProvider('ws://localhost:8546')); - - -// Using the IPC provider in node.js -import { Web3 } from 'web3'; -import { IpcProvider } from 'web3-providers-ipc'; - -const web3 = new Web3( - new IpcProvider('/Users/myuser/Library/Ethereum/geth.ipc'), -); // mac os path -// on windows the path is: "\\\\.\\pipe\\geth.ipc" -// on linux the path is: "/users/myuser/.ethereum/geth.ipc" ``` - - - ### Remote Node Provider - - - - -```javascript -// Using a remote node provider, like Alchemy (https://www.alchemyapi.io/supernode), is simple. -const { Web3 } = require('web3'); -const web3 = new Web3('https://eth-mainnet.alchemyapi.io/v2/your-api-key'); -``` - - - - - -```typescript -// Using a remote node provider, like Alchemy (https://www.alchemyapi.io/supernode), is simple. +```ts title='Alchemy, Infura, etc' +// like Alchemy (https://www.alchemyapi.io/supernode) +// or infura (https://mainnet.infura.io/v3/your_infura_key) import { Web3 } from 'web3'; const web3 = new Web3('https://eth-mainnet.alchemyapi.io/v2/your-api-key'); ``` - - - - -### Injected providers +### Injected Provider As stated above, the injected provider should be in compliance with [EIP-1193](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md). And it is tested with Ganache provider, Hardhat provider, and Incubed (IN3) as a provider. The web3.js 4.x Provider specifications are defined in [web3 base provider](https://github.com/ChainSafe/web3.js/blob/4.x/packages/web3-types/src/web3_base_provider.ts) for Injected Providers. -```html - +```html title='E.g, Metamask' + ``` Note that the above code should be hosted in a web server (that could be a simple local web server), because many browser does not support this feature for static files located on your machine. -### Provider Options +## Provider Options There are differences in the objects that could be passed in the Provider constructors. -#### HttpProvider +### HttpProvider The options is of type `HttpProviderOptions`, which is an object with a single key named `providerOptions` and its value is an object of type `RequestInit`. Regarding `RequestInit` see [microsoft's github](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules_typedoc_node_modules_typescript_lib_lib_dom_d_.requestinit.html). -For example: - -```ts +```ts title='HTTP Provider example' const httpOptions = { - providerOptions: { - body: undefined, - cache: 'force-cache', - credentials: 'same-origin', - headers: { - 'Content-Type': 'application/json', - }, - integrity: 'foo', - keepalive: true, - method: 'GET', - mode: 'same-origin', - redirect: 'error', - referrer: 'foo', - referrerPolicy: 'same-origin', - signal: undefined, - window: undefined, - } as RequestInit, + providerOptions: { + body: undefined, + cache: 'force-cache', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + }, + integrity: 'foo', + keepalive: true, + method: 'GET', + mode: 'same-origin', + redirect: 'error', + referrer: 'foo', + referrerPolicy: 'same-origin', + signal: undefined, + window: undefined, + } as RequestInit, }; ``` -#### WebSocketProvider +### WebSocketProvider Use WebSocketProvider to connect to a Node using a WebSocket connection, i.e. over the `ws` or `wss` protocol. @@ -256,65 +223,62 @@ The options object is of type `ClientRequestArgs` or of `ClientOptions`. See [he The second option parameter can be given regarding reconnecting. And here is its type: -```ts +```ts title='WebSocket Provider example' // this is the same options interface used for both WebSocketProvider and IpcProvider type ReconnectOptions = { - autoReconnect: boolean; // default: `true` - delay: number; // default: `5000` - maxAttempts: number; // default: `5` + autoReconnect: boolean, // default: `true` + delay: number, // default: `5000` + maxAttempts: number, // default: `5` }; -``` -And here is a sample instantiation for the `WebSocketProvider`: +``` -```ts +```ts title='Instantiation of WebSocket Provider' const provider = new WebSocketProvider( - `ws://localhost:8545`, - { - headers: { - // to provide the API key if the Node requires the key to be inside the `headers` for example: - 'x-api-key': '', - }, - }, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - }, + `ws://localhost:8545`, + { + headers: { + // to provide the API key if the Node requires the key to be inside the `headers` for example: + 'x-api-key': '', + }, + }, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + } ); ``` The second and the third parameters are both optional. And, for example, the second parameter could be an empty object or undefined, like in the following example: -```ts +```ts title='Instantiation of WebSocket Provider' const provider = new WebSocketProvider( - `ws://localhost:8545`, - {}, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - }, + `ws://localhost:8545`, + {}, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + } ); ``` -##### Options example - Below is an example for the passed options: -```ts +```ts title='WS Provider options example' let clientOptions: ClientOptions = { - // Useful for credentialed urls, e.g: ws://username:password@localhost:8546 - headers: { - authorization: 'Basic username:password', - }, - maxPayload: 100000000, + // Useful for credentialed urls, e.g: ws://username:password@localhost:8546 + headers: { + authorization: 'Basic username:password', + }, + maxPayload: 100000000, }; const reconnectOptions: ReconnectOptions = { - autoReconnect: true, - delay: 5000, - maxAttempts: 5, + autoReconnect: true, + delay: 5000, + maxAttempts: 5, }; ``` @@ -324,13 +288,13 @@ The IPC Provider could be used in node.js dapps when running a local node. And i It accepts a second parameter called `socketOptions`. And, its type is `SocketConstructorOpts`. See [here](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_net_d_._net_.socketconstructoropts.html) for full details. And here is its interface: -```ts -// for more check: https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_net_d_._net_.socketconstructoropts.html +```ts title='IPC Provider options' +// for more check https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_net_d_._net_.socketconstructoropts.html interface SocketConstructorOpts { - fd?: number | undefined; - allowHalfOpen?: boolean | undefined; - readable?: boolean | undefined; - writable?: boolean | undefined; + fd?: number | undefined; + allowHalfOpen?: boolean | undefined; + readable?: boolean | undefined; + writable?: boolean | undefined; } ``` @@ -339,17 +303,15 @@ And, the third parameter is called `reconnectOptions` that is of the type `Recon ```ts // this is the same options interface used for both WebSocketProvider and IpcProvider type ReconnectOptions = { - autoReconnect: boolean; // default: `true` - delay: number; // default: `5000` - maxAttempts: number; // default: `5` + autoReconnect: boolean, // default: `true` + delay: number, // default: `5000` + maxAttempts: number, // default: `5` }; ``` -##### Options examples - Below is an example for the passed options for each version: -```ts +```ts title='Options Example' let clientOptions: SocketConstructorOpts = { allowHalfOpen: false; readable: true; @@ -365,36 +327,34 @@ const reconnectOptions: ReconnectOptions = { And here is a sample instantiation for the `IpcProvider`: -```ts +```ts title='IPC Provider example' const provider = new IpcProvider( - `path.ipc`, - { - writable: false, - }, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - }, + `path.ipc`, + { + writable: false, + }, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + } ); ``` The second and the third parameters are both optional. And, for example, the second parameter could be an empty object or undefined. -```ts +```ts title='IPC Provider example' const provider = new IpcProvider( - `path.ipc`, - {}, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - }, + `path.ipc`, + {}, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + } ); ``` -#### Error message for reconnect attempts - :::info This section applies for both `IpcProvider` and `WebSocketProvider`. ::: @@ -405,11 +365,11 @@ The error message, for the max reconnect attempts, will contain the value of the And here is how to catch the error, if max attempts reached when there is auto reconnecting: -```ts -provider.on('error', error => { - if (error.message.startsWith('Maximum number of reconnect attempts reached!')) { - // the `error.message` will be `Maximum number of reconnect attempts reached! (${maxAttempts})` - // the `maxAttempts` is equal to the provided value by the user, or the default value `5`. - } +```ts title='Error message for reconnect attempts' +provider.on('error', (error) => { + if (error.message.startsWith('Maximum number of reconnect attempts reached!')) { + // the `error.message` will be `Maximum number of reconnect attempts reached! (${maxAttempts})` + // the `maxAttempts` is equal to the provided value by the user, or the default value `5`. + } }); -``` +``` \ No newline at end of file diff --git a/docs/docs/guides/web3_providers_guide/injected_provider.md b/docs/docs/guides/web3_providers_guide/injected_provider.md new file mode 100644 index 00000000000..1088e576507 --- /dev/null +++ b/docs/docs/guides/web3_providers_guide/injected_provider.md @@ -0,0 +1,126 @@ +--- +sidebar_position: 6 +sidebar_label: 'Tutorial: Injected provider' +--- + +# Browser Injected Ethereum Provider + +It is easy to connect to the Ethereum network using an Ethereum browser extension such as MetaMask, or an Ethereum-enabled browser like the browser inside TrustWallet. Because they inject their provider object into the browser's JavaScript context, enabling direct interaction with the Ethereum network from your web application. Moreover, the wallet management is conveniently handled by these extensions or browsers, making it the standard approach for DApp developers to facilitate user interactions with the Ethereum network. + +Technically, you use `window.ethereum` when it is injected by the Ethereum browser extension or the Ethereum-enabled browser. However, before using this provider, you need to check if it is available and then call `enable()` to request access to the user's MetaMask account. + +Before start coding you will need to setup and configure Ganache and MetaMask, if you have not already: + +- Ensure that Ganache is running as mentioned in the [Prerequisites](#prerequisites) section. +- Install the MetaMask extension for your browser. You can download MetaMask from their website: https://metamask.io/. + +Follow these steps to connect to the Ethereum network with MetaMask and web3.js, including the steps to create a local web server using Node.js: + +1. Open a command prompt or terminal window and navigate to where you would like to create the folder for this example. +2. Create a new folder and navigate to it: + +```bash +mkdir web3-browser-injected-providers +cd web3-browser-injected-providers +``` + +3. Use npm to initialize the folder. This will simply create a `package.json` file: + +```bash +npm init -y +``` + +4. Install the Express module and add it to your project's dependencies: + +```bash +npm i express +``` + +5. Create a new HTML file named `index.html` in your code editor (inside `web3-browser-injected-providers`). + +6. Copy and paste the following code into `index.html`, and save it after: + +```html + + + + + Connecting to the Ethereum network with Web3.js and MetaMask + + +

Connecting to the Ethereum network with Web3.js and MetaMask

+
+  You need to approve connecting this website to MetaMask.
+  Click on the MetaMask icon in the browser extension, if it did not show a popup already.
+  
+ + + + + +``` + +7. Create a new file called `server.js` (inside `web3-browser-injected-providers`). +8. Copy and paste the following code into `server.js`, and save it after: + +```js +const express = require('express'); +const app = express(); +const path = require('path'); + +app.use(express.static(path.join(__dirname, '.'))); + +app.listen(8097, () => { + console.log('Server started on port 8097'); +}); +``` + +9. Start the Node.js server by executing the following command. This will execute the content of `server.js` which will run the server on port 8097: + +```bash +node server.js +``` + +10. Open your web browser and navigate to `http://localhost:8097/`. MetaMask should ask for your approval to connect to your website. Follow the steps and give your consent. +11. If everything is set up properly, you should be able to connect to the Ethereum network with MetaMask and see the logged account address. + +Note that in the above steps you had created a local web server using Node.js and Express, serving your HTML file from the root directory of your project. You needs this local server because many browser does not allow extensions to inject objects for static files located on your machine. However, you can customize the port number and the root directory if needed. + +Now you can start building your Ethereum application with web3.js and MetaMask! diff --git a/docs/docs/guides/web3_providers_guide/ipc.md b/docs/docs/guides/web3_providers_guide/ipc.md new file mode 100644 index 00000000000..fd7ad921cc1 --- /dev/null +++ b/docs/docs/guides/web3_providers_guide/ipc.md @@ -0,0 +1,134 @@ +--- +sidebar_position: 5 +sidebar_label: 'Tutorial: IPC Provider' +--- + +# Tutorial: IPC Provider + +The IPC Provider offers high-performance local communication, providing a swift alternative to the straightforward HTTP Provider. Tailored for efficiency, it excels in local environments, enhancing the speed of your web application's connection to the Ethereum network for decentralized applications. + +## Prerequisites + +Before we get started, make sure you have a basic understanding of JavaScript and Ethereum. Additionally, we need to set up our environment by installing the following: + +1. **Node.js** + + Node.js is a JavaScript runtime environment that enables you to run JavaScript on the server-side. You can download it from [https://nodejs.org/en/download/](https://nodejs.org/en/download/). + +2. **npm** + + npm (Node Package Manager) is used to publish and install packages to and from the public npm registry or a private npm registry. You can install it by following the instructions here: [https://docs.npmjs.com/downloading-and-installing-node-js-and-npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). + + Alternatively, you can use **yarn** instead of **npm** by following the instructions here: [https://classic.yarnpkg.com/lang/en/docs/getting-started/](https://classic.yarnpkg.com/lang/en/docs/getting-started/). + +3. **Geth** (Optional, used only at the IPC provider example) + + Geth (go-ethereum) is an Ethereum execution client meaning it handles transactions, deployment and execution of smart contracts and contains an embedded computer known as the Ethereum Virtual Machine. You can install it by following the instructions here: [https://geth.ethereum.org/docs/getting-started/installing-geth](https://geth.ethereum.org/docs/getting-started/installing-geth) + +## IPC Provider (for Node.js) + +The IPC Provider allows you to connect to an Ethereum node using Inter-Process Communication (IPC) in a Node.js environment. This provider is useful when you have a local Ethereum node running on your machine and want to interact with it using Node.js. + +In the following steps you will run `geth` in development mode and you will run a piece of code that reads the Ethereum accounts and sends a transaction: + +To connect to the Ethereum network using the IPC provider, follow these steps: + +1. Start a `geth` node in development mode by opening a terminal window and navigating to the `geth` executable file. Then, run the following command to create a development chain: + +```bash +geth --dev --ipcpath +``` + +Make sure to replace `` with the desired IPC path. For example: + +```bash +geth --dev --ipcpath /Users/username/Library/Ethereum/geth.ipc +``` + +This will start a `geth` node in development mode with IPC enabled and an IPC path specified. If the command is successful, the `geth` node will be running, and you should see output similar to the following: + +```bash +INFO [12-10|15:10:37.121] IPC endpoint opened url= +INFO [12-10|15:10:37.122] HTTP endpoint opened url=http://localhost:8545 +INFO [12-10|15:10:37.122] WebSocket endpoint opened url=ws://localhost:8546 +INFO [12-10|15:10:37.127] Mapped network port proto=udp extport=0 intport=30303 interface=UPnP(UDP) +``` + +2. Open a command prompt or terminal window and navigate to where you would like to create the folder for this example. +3. Create a new folder and navigate to it: + +```bash +mkdir web3-providers-tutorial +cd web3-providers-tutorial +``` + +4. Install web3.js using npm: + +```bash +npm i web3 +``` + +5. Create a new JavaScript file called `web3-ipc-provider.js` in your code editor. + +6. Copy and paste the following code into your `web3-ipc-provider.js` file and save it: + +```typescript title='IPC Provider' +import { Web3 } from 'web3'; +import { IpcProvider } from 'web3-providers-ipc'; + +// Connect to the Ethereum network using IPC provider +const ipcPath = ''; // Replace with your actual IPC path +const ipcProvider = new IpcProvider(ipcPath); + +const web3 = new Web3(ipcProvider); + +async function main() { + try { + console.log('Does the provider support subscriptions?:', ipcProvider.supportsSubscriptions()); + + // Get the list of accounts in the connected node which is in this case: geth in dev mode. + const accounts = await web3.eth.getAccounts(); + console.log('Accounts:', accounts); + + // Send a transaction to the network + const transactionReceipt = await web3.eth.sendTransaction({ + from: accounts[0], + to: accounts[0], // sending a self-transaction + value: web3.utils.toWei('0.001', 'ether'), + }); + console.log('Transaction Receipt:', transactionReceipt); + } catch (error) { + console.error('An error occurred:', error); + } +} + +main(); +``` + +7. replace `` with the `ipcPath` that you had specified, when starting the `geth` node, in the first step. + +8. Type `node web3-ipc-provider.js` in the command prompt or terminal window and press Enter. This will run your JavaScript file. + +If everything is set up properly, you should see the list of accounts and transaction receipt printed in the console, similar to the following: + +```bash +Do the provider supports subscription?: true +Accounts: [ '0x82333ED0FAA7a883297C4d8e0FDE1E1CFABAeB7D' ] +Transaction Receipt: { + blockHash: '0xd1220a9b6f86083e420da025179593f5aad3732165a687019a89528a4ab2bcd8', + blockNumber: 1n, + cumulativeGasUsed: 21000n, + effectiveGasPrice: 1000000001n, + from: '0x82333ed0faa7a883297c4d8e0fde1e1cfabaeb7d', + gasUsed: 21000n, + logs: [], + logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + status: 1n, + to: '0x82333ed0faa7a883297c4d8e0fde1e1cfabaeb7d', + transactionHash: '0x76c05df78dc5dbfade0d11322b3cadc894c17efe36851856aca29488b47c3fbd', + transactionIndex: 0n, + type: 0n +} +``` + +Keep in mind that using IPC Provider with `geth` in development mode in a production environment is not recommended as it can pose a security risk. diff --git a/docs/docs/guides/web3_providers_guide/truffle.md b/docs/docs/guides/web3_providers_guide/truffle.md new file mode 100644 index 00000000000..0c52cb76902 --- /dev/null +++ b/docs/docs/guides/web3_providers_guide/truffle.md @@ -0,0 +1,84 @@ +--- +sidebar_position: 7 +sidebar_label: 'Tutorial: Third Party Provider' +--- + +# Truffle + +The Truffle HDWallet Provider will be used as an example of a third party provider that is EIP 1193 compatible. + +## Prerequisites + +Before we get started, make sure you have a basic understanding of JavaScript and Ethereum. Additionally, we need to set up our environment by installing the following: + +1. **Ganache** + + Ganache is a personal blockchain for Ethereum development that allows you to test how your smart contracts function in real-world scenarios. You can download it from [http://truffleframework.com/ganache](http://truffleframework.com/ganache). + +2. **Node.js** + + Node.js is a JavaScript runtime environment that enables you to run JavaScript on the server-side. You can download it from [https://nodejs.org/en/download/](https://nodejs.org/en/download/). + +3. **npm** + + npm (Node Package Manager) is used to publish and install packages to and from the public npm registry or a private npm registry. You can install it by following the instructions here: [https://docs.npmjs.com/downloading-and-installing-node-js-and-npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). + + Alternatively, you can use **yarn** instead of **npm** by following the instructions here: [https://classic.yarnpkg.com/lang/en/docs/getting-started/](https://classic.yarnpkg.com/lang/en/docs/getting-started/). + +## Third-party Providers (Compliant with EIP 1193) + +web3.js accepts any provider that is in compliance with [EIP-1193](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md). It has tests written to ensure compatibility with @truffle/hdwallet-provider, Ganache provider, Hardhat provider, and Incubed (IN3) as a provider. The following section, [Browser Injected Ethereum Provider](#browser-injected-ethereum-provider), in this tutorial explains how to use a special case of these third-party providers. + +Here is a step-by-step example and a code snippet to connect your web application to the Ethereum network using `@truffle/hdwallet-provider` as an example of an external provider compliant with EIP 1193. + +1. Open a command prompt or terminal window in a new folder. +2. Type `npm init -y` and press Enter. This will create a `package.json` file in the current directory. +3. Install web3.js and HTTP provider using npm: + +```bash +npm i web3 @truffle/hdwallet-provider bip39 +``` + +4. Create a new JavaScript file, called `index.js`, in your code editor. +5. Copy and paste the following code into your JavaScript file, and then save the file: + +```typescript title='EIP1193 Provider (Truffle)' +import { Web3 } from 'web3'; +import HDWalletProvider from '@truffle/hdwallet-provider'; +import bip39 from 'bip39'; + +const mnemonic: string = bip39.generateMnemonic(); // generates seed phrase +console.log('seed phrase:', mnemonic); + +// Connect to the Ethereum network using an HTTP provider and WalletProvider +const provider: HDWalletProvider = new HDWalletProvider(mnemonic, 'https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID'); +const web3: Web3 = new Web3(provider); + +// Get the current block number from the network +web3.eth + .getBlockNumber() + .then(function (blockNumber: number) { + console.log('Current block number:', blockNumber); + }) + .catch(function (error: any) { + console.log('Error:', error); + }); +``` + +6. Replace `'YOUR_INFURA_PROJECT_ID'` with your own Infura project ID. You can obtain an Infura project ID by signing up for a free account at https://infura.io/register. Alternatively, you can use any other URL that is compatible with HDWalletProvider, such as a local Ganache accessible at `'http://localhost:7545'`. + +7. In the command prompt, run `node index.js` and press Enter. This will execute your JavaScript file and connect to the Ethereum network using HDWalletProvider with Infura. + +If everything is set up properly, you should see the current block number printed in the console similar to the following. + +```bash +seed phrase: remain climb clock valid budget cable tunnel force split level measure repair +Current block number: 17317844n +``` + +:::danger +Your seed phrase gives complete access to your Ethereum account and it should **never** be shared with anyone you don't want to give full access to your account. The seed phrase is `console.log`ed in the code example to show you what it looks like, but you should **never** do this with a seed phrase to an account you plan on using to send real money. +::: + +The sample above connected you to the Ethereum network using truffle HD Wallet-enabled Web3 provider. You can modify it to interact with the network, perform transactions, and read/write data from the Ethereum network. + diff --git a/docs/docs/guides/web3_providers_guide/websocket.md b/docs/docs/guides/web3_providers_guide/websocket.md new file mode 100644 index 00000000000..0f732b29be1 --- /dev/null +++ b/docs/docs/guides/web3_providers_guide/websocket.md @@ -0,0 +1,142 @@ +--- +sidebar_position: 4 +sidebar_label: 'Tutorial: WebSocket Provider' +--- + +# Tutorial: WebSocket Provider + +The WebSocket Provider provides real-time communication and enhanced performance, offering a dynamic alternative to the simplicity of the HTTP Provider. In comparison to the widely used HTTP Provider, the WebSocket Provider enables your web application to establish a continuous, bidirectional connection, allowing for live updates and faster interactions with the Ethereum network. Incorporate the WebSocket Provider to empower your decentralized applications with real-time capabilities. + +## Prerequisites + +Before we get started, make sure you have a basic understanding of JavaScript and Ethereum. Additionally, we need to set up our environment by installing the following: + +1. **Ganache** + + Ganache is a personal blockchain for Ethereum development that allows you to test how your smart contracts function in real-world scenarios. You can download it from [http://truffleframework.com/ganache](http://truffleframework.com/ganache). + +2. **Node.js** + + Node.js is a JavaScript runtime environment that enables you to run JavaScript on the server-side. You can download it from [https://nodejs.org/en/download/](https://nodejs.org/en/download/). + +3. **npm** + + npm (Node Package Manager) is used to publish and install packages to and from the public npm registry or a private npm registry. You can install it by following the instructions here: [https://docs.npmjs.com/downloading-and-installing-node-js-and-npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). + + Alternatively, you can use **yarn** instead of **npm** by following the instructions here: [https://classic.yarnpkg.com/lang/en/docs/getting-started/](https://classic.yarnpkg.com/lang/en/docs/getting-started/). + +## WebSocket Provider + +WebSocket Provider allows us to communicate with the Ethereum node via WebSocket protocol, which is useful when we want continuous updates on our subscribed items. This provider is ideal for real-time applications that require constant updates from the Ethereum network. + +Follow these steps to connect to the Ethereum network using WebSocket provider: + +:::tip +The first 3 steps are the same as in the pervious section. So, you may skip them if you already executed the previous section. +::: + +1. Open a command prompt or terminal window and navigate to where you would like to create the folder for this example. +2. Create a new folder and navigate to it: + +```bash +mkdir web3-providers-tutorial +cd web3-providers-tutorial +``` + +3. Install web3.js using npm: + +```bash +npm i web3 +``` + +4. Create a new JavaScript file called `web3-websocket-provider.js` in your code editor. + +5. Copy and paste the following code into your `web3-websocket-provider.js` file and save it: + +```typescript title='WebSocket Provider' +import { Web3 } from 'web3'; + +// Connect to the Ethereum network using WebSocket provider +const ganacheUrl = 'ws://localhost:8545'; +const wsProvider = new Web3.providers.WebsocketProvider(ganacheUrl); +const web3 = new Web3(wsProvider); + +async function main() { + try { + console.log('Does the provider support subscriptions?:', wsProvider.supportsSubscriptions()); + + // Subscribe to new block headers + const subscription = await web3.eth.subscribe('newBlockHeaders'); + + subscription.on('data', async (blockhead) => { + console.log('New block header: ', blockhead); + + // You do not need the next line if you like to keep being notified for every new block + await subscription.unsubscribe(); + console.log('Unsubscribed from new block headers.'); + }); + subscription.on('error', (error) => console.log('Error when subscribing to New block header: ', error)); + + // Get the list of accounts in the connected node which is in this case: Ganache. + const accounts = await web3.eth.getAccounts(); + // Send a transaction to the network + const transactionReceipt = await web3.eth.sendTransaction({ + from: accounts[0], + to: accounts[1], + value: web3.utils.toWei('0.001', 'ether'), + }); + console.log('Transaction Receipt:', transactionReceipt); + } catch (error) { + console.error(error); + } +} + +main(); +``` + +6. Ensure that Ganache is running as mentioned in the [Prerequisites](#prerequisites) section. + +7. Type `node web3-websocket-provider.js` in the command prompt or terminal window and press Enter. This will run your JavaScript file. + +If everything is set up properly, you should see the new block headers, transaction hash, and pending transaction printed in the console. The unique feature of WebSocket provider highlighted in this example is that it can subscribe to new block headers and pending transactions to get them in real-time. And by running the sample, you will get something similar to this in your console: + +```bash +Do the provider supports subscription?: true +New block header: { + logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + miner: '0x0000000000000000000000000000000000000000', + difficulty: '0', + totalDifficulty: '0', + extraData: '0x', + gasLimit: 6721975, + gasUsed: 21000, + hash: '0xd315cecf3336640bcd1301930805370b7fe7528c894b931dcf8a3b1c833b68c8', + mixHash: '0x1304070fde1c7bee383f3a59da8bb94d515cbd033b2638046520fb6fb596d827', + nonce: '0x0000000000000000', + number: 40, + parentHash: '0xeb7ce3260911db2596ac843df11dbcbef302e813e1922db413f6f0b2a54d584d', + receiptsRoot: '0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa', + stateRoot: '0x95e416eec0932e725ec253779a4e28b3d014d05e41e63c3369f5da42d26d1240', + timestamp: 1684165088, + transactionsRoot: '0x8f87380cc7acfb6d10633e10f72567136492cb8301f52a41742eaca9449bb378', + sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', + baseFeePerGas: 4959456, + size: undefined +} +Transaction Receipt: { + transactionHash: '0x0578672e97d072b4b91773c8bfc710e4f777616398b82b276323408e59d11362', + transactionIndex: 0n, + blockNumber: 1n, + blockHash: '0x5c05248fe0fb8f45a8c9b9600904a36c0e5c74dce01495cfc72278c185fe7838', + from: '0x6e599da0bff7a6598ac1224e4985430bf16458a4', + to: '0x6f1df96865d09d21e8f3f9a7fba3b17a11c7c53c', + cumulativeGasUsed: 21000n, + gasUsed: 21000n, + logs: [], + logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + status: 1n, + effectiveGasPrice: 2000000000n, + type: 0n +} +Unsubscribed from new block headers. +``` diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/_category_.yml b/docs/docs/guides/web3_upgrade_guide/1.x/_category_.yml new file mode 100644 index 00000000000..7723475cb40 --- /dev/null +++ b/docs/docs/guides/web3_upgrade_guide/1.x/_category_.yml @@ -0,0 +1,5 @@ +label: 'Upgrade from 1.x' +collapsible: true +collapsed: true +link: null +position: 1 \ No newline at end of file diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/index.md b/docs/docs/guides/web3_upgrade_guide/1.x/index.md index c7dc961d20b..52530284ed2 100644 --- a/docs/docs/guides/web3_upgrade_guide/1.x/index.md +++ b/docs/docs/guides/web3_upgrade_guide/1.x/index.md @@ -1,6 +1,6 @@ --- sidebar_position: 1 -sidebar_label: 'Upgrade from 1.x' +sidebar_label: 'Introduction' --- diff --git a/docs/docs/guides/web3_upgrade_guide/_category_.yml b/docs/docs/guides/web3_upgrade_guide/_category_.yml index 7c77bf16406..3d1a89dfb90 100644 --- a/docs/docs/guides/web3_upgrade_guide/_category_.yml +++ b/docs/docs/guides/web3_upgrade_guide/_category_.yml @@ -1,4 +1,5 @@ -label: 'Upgrading' +label: '⬆️ Upgrading' collapsible: true -collapsed: false -link: null \ No newline at end of file +collapsed: true +link: null +position: 9 \ No newline at end of file