diff --git a/README.md b/README.md index adf5ec07574..3284ef04f23 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ yarn add web3 ## Migration Guide -- [Migration Guide from Web3.js 1.x to 4.x](https://docs.web3js.org/guides/web3_upgrade_guide/x/) +- [Migration Guide from Web3.js 1.x to 4.x](https://docs.web3js.org/guides/web3_upgrade_guide/index) Breaking changes are listed in migration guide and its first step for migrating from Web3.js 1.x to 4.x. If there is any question or discussion feel free to ask in [Discord](https://discord.gg/yjyvFRP), and in case of any bug or new feature request [open issue](https://github.com/web3/web3.js/issues/new) or create a pull request for [contributions](https://github.com/web3/web3.js/blob/4.x/.github/CONTRIBUTING.md). ## Useful links @@ -76,18 +76,18 @@ yarn add web3 ## Package.json Scripts -| Script | Description | -| ---------------- |--------------------------------------------------------------------| -| clean | Uses `rimraf` to remove `dist/` | -| build | Uses `tsc` to build all packages | -| lint | Uses `eslint` to lint all packages | -| lint:fix | Uses `eslint` to check and fix any warnings | -| format | Uses `prettier` to format the code | -| test | Uses `jest` to run unit tests in each package | -| test:integration | Uses `jest` to run tests under `/test/integration` in each package | -| test:unit | Uses `jest` to run tests under `/test/unit` in each package | -| test:manual:long-connection-ws | Runs manual tests for keeping a long WebSocket connection | -| test:manual | Runs manual tests under `test/manual` in the web3 package | +| Script | Description | +| ------------------------------ | ------------------------------------------------------------------ | +| clean | Uses `rimraf` to remove `dist/` | +| build | Uses `tsc` to build all packages | +| lint | Uses `eslint` to lint all packages | +| lint:fix | Uses `eslint` to check and fix any warnings | +| format | Uses `prettier` to format the code | +| test | Uses `jest` to run unit tests in each package | +| test:integration | Uses `jest` to run tests under `/test/integration` in each package | +| test:unit | Uses `jest` to run tests under `/test/unit` in each package | +| test:manual:long-connection-ws | Runs manual tests for keeping a long WebSocket connection | +| test:manual | Runs manual tests under `test/manual` in the web3 package | [npm-url]: https://npmjs.org/package/web3 [downloads-image]: https://img.shields.io/npm/dm/web3?label=npm%20downloads diff --git a/docs/docs/glossary/index.md b/docs/docs/glossary/index.md index 1af9691a85e..7af367af75b 100644 --- a/docs/docs/glossary/index.md +++ b/docs/docs/glossary/index.md @@ -4,7 +4,6 @@ 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. @@ -13,12 +12,10 @@ In web3.js, a `provider` is an object responsible for enabling connectivity with 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()`) @@ -82,30 +79,39 @@ contract Test { ```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"}], - } + { + "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" }] + } ] ``` @@ -123,6 +129,7 @@ const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); ``` ## WebSocketProvider + [WebSocketProvider](https://docs.web3js.org/guides/web3_providers_guide/#websocket-provider) in Web3.js connects your application to an Ethereum node via WebSocket, enabling real-time and asynchronous communication. This provider is ideal for applications needing real-time updates, such as new blocks or smart contract events. It offers better performance for high-throughput applications compared to `HttpProvider`. Ensure secure connections with `wss://` for exposed endpoints. Handle reconnections gracefully for reliable operation. ```javascript title='WebSocketProvider example' @@ -138,13 +145,14 @@ The `Events` class in Web3.js is a crucial part of the library that enables deve ```solidity title='Event in solidity' contract MyContract { - event Transfer(address indexed from, address indexed to, uint value); + event Transfer(address indexed from, address indexed to, uint256 value); - function transfer(address recipient, uint amount) public { - // ... transfer logic ... - emit Transfer(msg.sender, recipient, amount); - } + function transfer(address recipient, uint256 amount) public { + // ... transfer logic ... + emit Transfer(msg.sender, recipient, amount); + } } + ``` ```javascript title='Event in web3.js' @@ -158,9 +166,9 @@ const myContract = new web3.eth.Contract(MyContract.abi, contractAddress); const transferEvent = myContract.events.Transfer(); // Access the Transfer event -transferEvent.on('data', (event) => { - console.log('Transfer Event:', event); - // Process the event data (from, to, value) +transferEvent.on('data', event => { + console.log('Transfer Event:', event); + // Process the event data (from, to, value) }); ``` @@ -190,4 +198,5 @@ web3.eth.getPastLogs(options) .catch((error) => { console.error('Error retrieving logs:', error); }); -` \ No newline at end of file +` +``` diff --git a/docs/docs/guides/getting_started/_category_.yml b/docs/docs/guides/01_getting_started/_category_.yml similarity index 100% rename from docs/docs/guides/getting_started/_category_.yml rename to docs/docs/guides/01_getting_started/_category_.yml diff --git a/docs/docs/guides/01_getting_started/introduction.md b/docs/docs/guides/01_getting_started/introduction.md new file mode 100644 index 00000000000..b1fc2a8469a --- /dev/null +++ b/docs/docs/guides/01_getting_started/introduction.md @@ -0,0 +1,92 @@ +--- +slug: / +sidebar_position: 1 +sidebar_label: Introduction +--- + +# Introduction + +Web3.js is a robust and flexible collection of **TypeScript and JavaScript** libraries that allows developers to interact with local or remote [Ethereum](https://ethereum.org/en/) nodes (or **any EVM-compatible blockchain**) over **HTTP, IPC or WebSocket** connections. It is a powerful and efficient toolkit for crafting applications within the Ethereum ecosystem and beyond. + +This documentation is the entrypoint to Web3.js for developers. It covers [basic](/guides/getting_started/quickstart) and [advanced](/guides/smart_contracts/mastering_smart_contracts) usage with examples, and includes comprehensive [API documentation](/api) as well as guides for common tasks, like [upgrading](/guides/web3_upgrade_guide) from older versions. + +## Features of Web3.js v4 + +- Flexible + - ECMAScript (ESM) and CommonJS (CJS) builds + - [Plugins](/guides/web3_plugin_guide/) for extending functionality +- Efficient + - Modular, [package](/#packages)-based design reduces unneeded dependencies + - [Tree shakable with ESM](/guides/advanced/tree_shaking) + - Use of native [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (instead of large [BigNumber](https://mikemcl.github.io/bignumber.js/) libraries) + - Efficient ABI [encoding](/api/web3-eth-abi/function/encodeFunctionCall) & [decoding](/api/web3-eth-abi/function/decodeParameter) +- Developer-Friendly + - [Dynamic contract types](/guides/smart_contracts/infer_contract_types/) & full API in TypeScript + - Custom output [formatters](https://docs.web3js.org/api/web3-utils/function/format) + - In compliance with the [Ethereum JSON-RPC Specification](https://ethereum.github.io/execution-apis/api-documentation/) + +## Using These Docs + +There is a lot to learn about Web3.js! Here are some tips for developers of different skill levels. Remember, you can always [reach out directly](/guides/feedback/#urgent-questions-or-concerns) with Discord or Twitter if you're feeling stuck. + +### For Beginner Web3.js Developers + +New Web3.js developers should proceed to the [Quickstart](/guides/getting_started/quickstart) section to learn how to get started with Web3.js. Once you understand the basics, you may want to consider learning more about [providers](/guides/web3_providers_guide/), [wallets and accounts](/guides/wallet), [smart contracts](/guides/smart_contracts/smart_contracts_guide), and how to [use Web3.js with the Hardhat development environment](/guides/hardhat_tutorial). + +### For Intermediate & Advanced Web3.js Developers + +If you're already familiar with Ethereum and Web3.js development, you may want to review the Web3.js [package structure](#packages--plugins) and proceed directly to the [package-level documentation](/libdocs/ABI) and [API documentation](/api). Application developers may wish to review the [Web3.js configuration guide](/guides/web3_config) or learn how to use Web3.js with tools like the [MetaMask](/guides/dapps/metamask-react) wallet or the [WalletConnect](/guides/dapps/web3_modal_guide) wallet selection modal. Don't forget to review the [list of available plugins](https://web3js.org/plugins) or even [learn how to build your own Web3.js plugin](/guides/web3_plugin_guide/plugin_authors)! + +## Packages & Plugins + +Web3.js is a modular collection of packages, each of which serves a specific needs. This means developers don't need to install the entire Web3 library for most use cases. Instead, necessary packages are selectively installed for a more efficient development experience. Here is an overview of a selection of available packages: + +- [**Web3Eth:**](/libdocs/Web3Eth) The `web3-eth` package is the entrypoint to Web3.js - it's the control center for managing interactions with Ethereum and other EVM-compatible networks. + +- [**Net:**](/libdocs/Net) The `web3-net` package provides discovery and interactions for an **Ethereum node's network properties.** + +- [**Accounts:**](/libdocs/Accounts) The `web3-eth-accounts` package has tools for creating Ethereum accounts and the **secure signing** of transactions and data. + +- [**Personal:**](/libdocs/Personal) Use `web3-eth-personal` for **direct communication about your accounts with the Ethereum node**, which streamlines account management during development. + + **NOTE:** _For enhanced security in production and when interacting with public nodes, consider using `web3-eth-accounts` for local signing operations, which keeps your private keys and sensitive information secure on your local machine_ + +- [**Utils:**](/libdocs/Utils) The `web3-utils` package provides helpers to perform a range of essential Ethereum development tasks, including **converting data formats, checking addresses, encoding and decoding data, hashing, handling numbers, and much more.**. + +- [**Contract:**](/libdocs/Contract) The `web3-eth-contract` package makes it easy to **interact with smart contracts through JavaScript or TypeScript,** which streamlines the development process and makes it less error-prone. + +- [**ABI:**](/libdocs/ABI) The `web3-eth-abi` package simplifies decoding logs and parameters, encoding function calls and signatures, and inferring types for efficient Ethereum **smart contract interactions.** + +- [**ENS:**](/libdocs/ENS) The `web3-eth-ens` package makes it easy for developers to communicate with the **Ethereum Name Service (ENS).** + +- [**Iban:**](/libdocs/Iban) The `web3-eth-iban` package allows you to switch between **Ethereum addresses and special banking-like addresses** (IBAN or BBAN) and simplifies conversion between the types. + +### Additional Supporting Packages + +- [**Web3 Core:**](/api/web3-core) subscriptions, request management, and configuration used by other Web3 packages + +- [**Web3 Types:**](/api/web3-types) data structures, objects, interfaces and types used by Web3 + +- [**Web3 Validator:**](/api/web3-validator) runtime type validation against predefined types or custom schemas + +- [**Web3 Errors:**](/api/web3-errors) error codes and common error classes that are used by other Web3 packages + +- [**Web3 RPC Methods:**](/api/web3/namespace/rpcMethods) functions for making RPC requests to Ethereum using a given provider + +### Plugins + +Web3.js supports [plugins](/guides/web3_plugin_guide/), which are another way to encapsulate capabilities that support a specific need. There are plugins that exist to support native features, like those described by [EIPs](https://eips.ethereum.org/) as well as plugins that are designed to support specific smart contracts, middleware, or even other Ethereum-compatible networks. Visit the [Web3.js plugins homepage](https://web3js.org/plugins) to view a list of the most important Web3.js plugins, which includes: + +- [EIP-4337 (Account Abstraction) Plugin](https://www.npmjs.com/package/@chainsafe/web3-plugin-eip4337) + +- [EIP-4844 (Blob Transactions) Plugin](https://www.npmjs.com/package/web3-plugin-blob-tx) + +- [zkSync Plugin](https://www.npmjs.com/package/web3-plugin-zksync) + +## Advantages Over Other Libraries + +- **Extensive Documentation and Community**: Web3.js is one of the most established Ethereum libraries, which means it benefits from extensive documentation and a large, active community. Web3.js is widely adopted and has been thoroughly tested in various production environments, and is compatible with a broad range of other tools and services in the Ethereum ecosystem. + +- **Modular Design**: Web3.js is designed to be modular, which allows developers to use specific packages according to their needs. This leads to smaller bundle sizes and faster load times for web applications. + +- **Active Development and Support**: Web3.js sees regular updates and active development. This support is crucial for developers needing assurance that the library they're using will keep pace with the evolving Ethereum landscape. diff --git a/docs/docs/guides/getting_started/quickstart.md b/docs/docs/guides/01_getting_started/quickstart.md similarity index 87% rename from docs/docs/guides/getting_started/quickstart.md rename to docs/docs/guides/01_getting_started/quickstart.md index 80551ad735b..fb0a70c851f 100644 --- a/docs/docs/guides/getting_started/quickstart.md +++ b/docs/docs/guides/01_getting_started/quickstart.md @@ -9,11 +9,11 @@ Use the live code editor to try Web3.js in your browser now! Keep reading to lea ## Live Code Editor - + ## Installation -If NPM is being used as package manager, install Web3.js with the following command: +If NPM is being used as package manager, install Web3.js with the following command: ``` npm i web3 @@ -25,19 +25,19 @@ For projects using Yarn as a package manager, use: yarn add web3 ``` -Note: Installing Web3.js in this way will bring in all Web3.js sub-[packages](/#packages). If you only need specific packages, it is recommended to install them individually (e.g, if you want the [Contract](/libdocs/Contract) package, use `npm i web3-eth-contract` instead) +Note: Installing Web3.js in this way will bring in all Web3.js sub-[packages](/#packages). If you only need specific packages, it is recommended to install them individually (e.g, if you want the [Contract](/libdocs/Contract) package, use `npm i web3-eth-contract` instead) ## Importing Web3.js Web3.js v4 supports both CommonJS (CJS) and native ECMAScript module (ESM) imports. For importing the main Web3 class in CJS, use: -``` js +```js const { Web3 } = require('web3'); ``` For ESM-style imports, use: -``` ts +```ts import { Web3 } from 'web3'; ``` @@ -47,18 +47,19 @@ import { Web3 } from 'web3'; Web3.js is in compliance with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193), the Ethereum Provider JavaScript API, so any EIP-1193 provider can be used to initialize the `Web3` object. -``` ts +```ts import { Web3 } from 'web3'; -// private RPC endpoint -const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_ID'); +// 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'); +// 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 provider, the [`web3-eth`](/libdocs/Web3Eth) package can be used to fetch data from the Ethereum network: @@ -97,7 +98,7 @@ Using the `Wallet` to create a random account is a good way to accelerate the de ```ts // create random wallet with 1 account -web3.eth.accounts.wallet.create(1) +web3.eth.accounts.wallet.create(1); /* ↳ Wallet(1) [ @@ -129,7 +130,9 @@ Private keys are sensitive data and should be treated as such. Make sure that pr ```ts // the private key must start with the "0x" prefix -const account = web3.eth.accounts.wallet.add('0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec'); +const account = web3.eth.accounts.wallet.add( + '0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec', +); console.log(account[0].address); //↳ 0xcE6A5235d6033341972782a15289277E85E5b305 @@ -144,21 +147,22 @@ This is an example of using a private key to add an account to a wallet, and the ```ts // add an account to a wallet -const account = web3.eth.accounts.wallet.add('0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec'); +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') +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) +console.log('Tx hash:', txReceipt.transactionHash); // ↳ Tx hash: 0x03c844b069646e08af1b6f31519a36e3e08452b198ef9f6ce0f0ccafd5e3ae0e ``` @@ -172,22 +176,21 @@ The first step to interacting with a smart contract is to instantiate it, which ```ts // Uniswap token smart contract address (Mainnet) -const address = '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984' +const address = '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984'; // you can find the complete ABI on etherscan.io // https://etherscan.io/address/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984#code -const ABI = -[ - { - name: 'symbol', - outputs: [{ type: 'string' }], - type: 'function', - }, - { - name: 'totalSupply', - outputs: [{ type: 'uint256' }], - type: 'function', - }, +const ABI = [ + { + name: 'symbol', + outputs: [{ type: 'string' }], + type: 'function', + }, + { + name: 'totalSupply', + outputs: [{ type: 'uint256' }], + type: 'function', + }, ]; // instantiate the smart contract @@ -202,7 +205,7 @@ Since reading data from a smart contract does not consume any gas, it's not nece // make the call to the contract const symbol = await uniswapToken.methods.symbol().call(); -console.log('Uniswap symbol:',symbol); +console.log('Uniswap symbol:', symbol); // ↳ Uniswap symbol: UNI // make the call to the contract @@ -221,12 +224,12 @@ Writing data to a smart contract consumes gas and requires the use of an account const to = '0xcf185f2F3Fe19D82bFdcee59E3330FD7ba5f27ce'; // value to transfer (1 with 18 decimals) -const value = web3.utils.toWei('1','ether'); +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}); +const txReceipt = await uniswapToken.methods.transfer(to, value).send({ from: account[0].address }); -console.log('Tx hash:',txReceipt.transactionHash); +console.log('Tx hash:', txReceipt.transactionHash); // ↳ Tx hash: 0x14273c2b5781cc8f1687906c68bfc93482c603026d01b4fd37a04adb6217ad43 ``` @@ -261,12 +264,12 @@ import { Web3 } from 'web3'; const web3 = new Web3('wss://ethereum.publicnode.com'); // instantiate contract -const uniswapToken = new web3.eth.Contract(abi, address) +const uniswapToken = new web3.eth.Contract(abi, address); // create the subscription to all the 'Transfer' events const subscription = uniswapToken.events.Transfer(); // listen to the events -subscription.on('data',console.log); +subscription.on('data', console.log); // ↳ [{...},{...}, ...] live events will be printed in the console ``` diff --git a/docs/docs/guides/01_getting_started/return-formats.md b/docs/docs/guides/01_getting_started/return-formats.md new file mode 100644 index 00000000000..3afabcb6871 --- /dev/null +++ b/docs/docs/guides/01_getting_started/return-formats.md @@ -0,0 +1,121 @@ +--- +sidebar_position: 3 +sidebar_label: Return Formats +--- + +# Return Formats + +By default, Web3.js formats byte values as hexadecimal strings (e.g. `"0x221`") and number values as [`BigInt`s](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt). The default formats can be configured at the global level by updating the [`defaultReturnFormat` configuration option](/guides/web3_config/#defaultreturnformat). Many Web3.js functions (e.g. [`getBlock`](/api/web3-eth/function/getBlock), [`sendTransaction`](/api/web3-eth/function/sendTransaction)) accept an optional parameter named `returnFormat` of the [type `DataFormat`](/api/web3-types#DataFormat) that can be used to configure the format for data returned by that single function invocation. + +The following example demonstrates working with return formats: + +```ts +import { Block, FMT_BYTES, FMT_NUMBER, Numbers, Web3 } from 'web3'; + +const web3 = new Web3('https://eth.llamarpc.com'); + +// use the default return format +web3.eth.getBlock().then((block: Block) => { + console.log(`Block #${block.number} Hash: ${block.hash}`); +}); +// ↳ Block #20735255 Hash: 0xbaea6dbd46fa810a27be4c9eac782602f8efe7512fb30a8455c127b101a23e22 + +// specify the return format for a single function invocation +web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.HEX, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); +// ↳ Block #0x13c6517 + +// configure default return format for the web3-eth package +web3.eth.defaultReturnFormat = { + bytes: FMT_BYTES.UINT8ARRAY, + number: FMT_NUMBER.HEX, +}; + +web3.eth.getBlock().then((block: Block) => { + console.log(`Block #${block.number} Hash: [${block.hash}]`); +}); +// ↳ Block #0x13c6517 Hash: [186,234,109,...,162,62,34] +``` + +The supported return formats are: + +- Bytes + - [`FMT_BYTES.HEX`](/api/web3-types/enum/FMT_BYTES#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + ```ts + web3.eth + .getBlock(undefined, undefined, { + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.BIGINT, + }) + .then((block: Block) => { + console.log(`Block hash: ${block.hash}`); + }); + // ↳ Block hash: 0xbaea6dbd46fa810a27be4c9eac782602f8efe7512fb30a8455c127b101a23e22 + ``` + - [`FMT_BYTES.UINT8ARRAY`](/api/web3-types/enum/FMT_BYTES#UINT8ARRAY): [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) (e.g. `[ 2, 33 ]`) + ```ts + web3.eth + .getBlock(undefined, undefined, { + bytes: FMT_BYTES.UINT8ARRAY, + number: FMT_NUMBER.BIGINT, + }) + .then((block: Block) => { + console.log(`Block hash: [${block.hash}]`); + }); + // ↳ Block hash: [186,234,109,...,162,62,34] + ``` +- Numbers + - [`FMT_NUMBER.BIGINT`](/api/web3-types/enum/FMT_NUMBER#BIGINT): [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (e.g. `221n`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.BIGINT, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #20735255 + ``` + - [`FMT_NUMBER.HEX`](/api/web3-types/enum/FMT_NUMBER#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.HEX, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #0x13c6517 + ``` + - [`FMT_NUMBER.NUMBER`](/api/web3-types/enum/FMT_NUMBER#NUMBER): [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) (e.g. `221`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.NUMBER, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #20735255 + ``` + - [`FMT_NUMBER.STR`](/api/web3-types/enum/FMT_NUMBER#STR): [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"221"`) + ```ts + web3.eth + .getBlockNumber({ + bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.STR, + }) + .then((blockNumber: Numbers) => { + console.log(`Block #${blockNumber}`); + }); + // ↳ Block #20735255 + ``` diff --git a/docs/docs/guides/web3_providers_guide/_category_.yml b/docs/docs/guides/02_web3_providers_guide/_category_.yml similarity index 100% rename from docs/docs/guides/web3_providers_guide/_category_.yml rename to docs/docs/guides/02_web3_providers_guide/_category_.yml diff --git a/docs/docs/guides/web3_providers_guide/eip6963.md b/docs/docs/guides/02_web3_providers_guide/eip6963.md similarity index 66% rename from docs/docs/guides/web3_providers_guide/eip6963.md rename to docs/docs/guides/02_web3_providers_guide/eip6963.md index 0965e440c9b..37577aa54d4 100644 --- a/docs/docs/guides/web3_providers_guide/eip6963.md +++ b/docs/docs/guides/02_web3_providers_guide/eip6963.md @@ -9,7 +9,7 @@ sidebar_label: 'EIP-6963: Multi Injected Provider Discovery' EIP-6963 proposes the "Multi Injected Provider Discovery" standard, which aims to enhance the discoverability and interaction with multiple injected Ethereum providers in a browser environment. Injected providers refer to browser extensions or other injected scripts that provide access to an Ethereum provider within the context of a web application. -Web3.js library has utility functions for discovery of injected providers using `requestEIP6963Providers()` and `onNewProviderDiscovered(eventDetails)`. +Web3.js library has utility functions for discovery of injected providers using `requestEIP6963Providers()` and `onNewProviderDiscovered(eventDetails)`. `onNewProviderDiscovered(eventDetails)` can be used to subscribe to events of provider discovery & providers map update and `requestEIP6963Providers()` returns Promise object that resolves to `Map` object containing list of providers. For updated providers `eip6963:providersMapUpdated` event is emitted and it has updated Map object. This event can be subscribed as mentioned earlier using `onNewProviderDiscovered(eventDetails)` @@ -17,8 +17,8 @@ Web3.js library has utility functions for discovery of injected providers using ```ts export interface EIP6963ProviderDetail { - info: EIP6963ProviderInfo; - provider: EIP1193Provider; + info: EIP6963ProviderInfo; + provider: EIP1193Provider; } ``` @@ -26,42 +26,45 @@ where `info` has details of provider containing UUID, name, Icon and RDNS as def ```ts export interface EIP6963ProviderInfo { - uuid: string; - name: string; - icon: string; - rdns: string; + uuid: string; + name: string; + icon: string; + rdns: string; } ``` `provider` in `EIP6963ProviderDetail` is `EIP1193Provider` and it contains actual provider that can be injected in web3 instance. -Following code snippet demonstrates usage of `requestEIP6963Providers()` function for providers discovery. +Following code snippet demonstrates usage of `requestEIP6963Providers()` function for providers discovery. ```ts -//Assuming multiple providers are installed in browser. +//Assuming multiple providers are installed in browser. import { Web3 } from 'web3'; // Following will subscribe to event that will be triggered when providers map is updated. -Web3.onNewProviderDiscovered((provider) => { - console.log(provider.detail); // This will log the populated providers map object, provider.detail has Map of all providers yet discovered - // add logic here for updating UI of your DApp +Web3.onNewProviderDiscovered(provider => { + console.log(provider.detail); // This will log the populated providers map object, provider.detail has Map of all providers yet discovered + // add logic here for updating UI of your DApp }); // Call the function and wait for the promise to resolve let providers = await Web3.requestEIP6963Providers(); for (const [key, value] of providers) { - console.log(value); + console.log(value); -/* Based on your DApp's logic show use list of providers and get selected provider's UUID from user for injecting its EIP6963ProviderDetail.provider EIP1193 object into web3 object */ + /* Based on your DApp's logic show use list of providers and get selected provider's UUID from user for injecting its EIP6963ProviderDetail.provider EIP1193 object into web3 object */ - if (value.info.name === 'MetaMask') { - const web3 = new Web3(value.provider); + if (value.info.name === 'MetaMask') { + const web3 = new Web3(value.provider); - // now you can use web3 object with injected provider - console.log(await web3.eth.getTransaction('0x82512812c11f56aa2474a16d5cc8916b73cd6ed96bf9b8defb3499ec2d9070cb')); - } + // now you can use web3 object with injected provider + console.log( + await web3.eth.getTransaction( + '0x82512812c11f56aa2474a16d5cc8916b73cd6ed96bf9b8defb3499ec2d9070cb', + ), + ); + } } - -``` \ No newline at end of file +``` diff --git a/docs/docs/guides/web3_providers_guide/events_listening.md b/docs/docs/guides/02_web3_providers_guide/events_listening.md similarity index 97% rename from docs/docs/guides/web3_providers_guide/events_listening.md rename to docs/docs/guides/02_web3_providers_guide/events_listening.md index a8e36a3cd22..ae0b809d4a5 100644 --- a/docs/docs/guides/web3_providers_guide/events_listening.md +++ b/docs/docs/guides/02_web3_providers_guide/events_listening.md @@ -26,42 +26,42 @@ 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', () => { - // ... + // ... }); // ... // 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', () => { - // ... + // ... }); ``` diff --git a/docs/docs/guides/web3_providers_guide/index.md b/docs/docs/guides/02_web3_providers_guide/index.md similarity index 74% rename from docs/docs/guides/web3_providers_guide/index.md rename to docs/docs/guides/02_web3_providers_guide/index.md index 726ccd8c229..65e49eb9c00 100644 --- a/docs/docs/guides/web3_providers_guide/index.md +++ b/docs/docs/guides/02_web3_providers_guide/index.md @@ -37,14 +37,14 @@ Keep reading to learn more about the different types of providers and how to use HTTP is a request-response protocol and does not support persistent connection, which means that HTTP providers are not suitable for use cases that require real-time [event subscriptions](/guides/events_subscriptions/). -``` ts title='Initialize an HTTP Provider' +```ts title='Initialize an HTTP Provider' import { Web3, HttpProvider } from 'web3'; // supply an HTTP provider as a URL string // highlight-next-line const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_ID'); -await web3.eth.getBlockNumber() +await web3.eth.getBlockNumber(); // ↳ 18849658n // OR @@ -53,7 +53,7 @@ await web3.eth.getBlockNumber() // highlight-next-line const web3_2 = new Web3(new HttpProvider('https://mainnet.infura.io/v3/YOUR_INFURA_ID')); -await web3.eth.getBlockNumber() +await web3.eth.getBlockNumber(); // ↳ 18849658n ``` @@ -65,23 +65,23 @@ HTTP providers can be configured by including an [`HttpProviderOptions`](/api/we import { Web3, HttpProvider } from 'web3'; const httpOptions = { - providerOptions: { - body: undefined, - cache: 'force-cache', - credentials: 'same-origin', - headers: { - 'Content-Type': 'application/json', - }, - integrity: undefined, - keepalive: true, - method: 'GET', - mode: 'same-origin', - redirect: 'error', - referrer: undefined, - referrerPolicy: 'same-origin', - signal: undefined, - window: undefined, - } as RequestInit, + providerOptions: { + body: undefined, + cache: 'force-cache', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + }, + integrity: undefined, + keepalive: true, + method: 'GET', + mode: 'same-origin', + redirect: 'error', + referrer: undefined, + referrerPolicy: 'same-origin', + signal: undefined, + window: undefined, + } as RequestInit, }; const web3 = new Web3(new HttpProvider('https://eth.llamarpc.com', httpOptions)); @@ -91,14 +91,14 @@ const web3 = new Web3(new HttpProvider('https://eth.llamarpc.com', httpOptions)) WebSockets support a persistent connection between a client and a server, which means they are suitable for use cases that require real-time [event subscriptions](/guides/events_subscriptions/). -``` ts title='Initialize WS Provider' +```ts title='Initialize WS Provider' import { Web3, WebSocketProvider } from 'web3'; // supply a WebSocket provider as a URL string // highlight-next-line const web3 = new Web3('wss://mainnet.infura.io/ws/v3/YOUR_INFURA_ID'); -await web3.eth.getBlockNumber(); +await web3.eth.getBlockNumber(); // ↳ 18849658n // OR @@ -118,29 +118,29 @@ The [`WebSocketProvider` constructor](/api/web3-providers-ws/class/WebSocketProv ```ts title='Configuring a WebSocket Provider' // include both optional parameters const provider = new WebSocketProvider( - `ws://localhost:8545`, - { - headers: { - // for node services that require an API key in a header - 'x-api-key': '', - }, - }, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } + `ws://localhost:8545`, + { + headers: { + // for node services that require an API key in a header + 'x-api-key': '', + }, + }, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + }, ); // OR include only ReconnectOptions const provider = new WebSocketProvider( - `ws://localhost:8545`, - {}, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } + `ws://localhost:8545`, + {}, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + }, ); ``` @@ -148,7 +148,7 @@ const provider = new WebSocketProvider( IPC (inter-process communication) providers offer high-performance local communication and provide a faster alternative to HTTP providers. IPC providers are tailored for efficiency and excel in local environments, and also support real-time [event subscriptions](/guides/events_subscriptions/). -``` ts title='Initialize IPC Provider' +```ts title='Initialize IPC Provider' import { Web3 } from 'web3'; // highlight-next-line import { IpcProvider } from 'web3-providers-ipc'; @@ -164,37 +164,35 @@ await web3.eth.getBlockNumber(); The [`IpcProvider` constructor](/api/web3-providers-ipc/class/IpcProvider#constructor) accepts two optional parameters that can be used to configure the behavior of the `IpcProvider`: the first parameter must be of type [`SocketConstructorOpts`](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_net_d_._net_.socketconstructoropts.html) and the second parameter must be of type [`ReconnectOptions`](/api/web3/namespace/utils#ReconnectOptions). - - ```ts title='Configuring an IPC Provider' // include both optional parameters const provider = new IpcProvider( - '/Users/myuser/Library/Ethereum/geth.ipc', - { - writable: false, - }, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } + '/Users/myuser/Library/Ethereum/geth.ipc', + { + writable: false, + }, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + }, ); // OR include only ReconnectOptions const provider = new IpcProvider( - '/Users/myuser/Library/Ethereum/geth.ipc', - {}, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } + '/Users/myuser/Library/Ethereum/geth.ipc', + {}, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + }, ); ``` ### Injected Provider -Injected providers are supplied by an external third-party, most often a wallet or a web browser that is designed to be used with the Ethereum network. In addition to providing network connectivity, injected providers often supply one or more [accounts](/guides/wallet/). Web3.js supports any injected provider that is compliant with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193). Injected providers support real-time [event subscriptions](/guides/events_subscriptions/). Continue reading for an [example](#injected-provider-1) of using an injected provider. +Injected providers are supplied by an external third-party, most often a wallet or a web browser that is designed to be used with the Ethereum network. In addition to providing network connectivity, injected providers often supply one or more [accounts](/guides/wallet/index). Web3.js supports any injected provider that is compliant with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193). Injected providers support real-time [event subscriptions](/guides/events_subscriptions/). Continue reading for an [example](#injected-provider-1) of using an injected provider. ## Provider Origins @@ -239,36 +237,37 @@ const web3 = new Web3('https://eth-mainnet.alchemyapi.io/v2/your-api-key'); ### Injected Provider -Injected providers are supplied by an external third-party, most often a wallet or a web browser that is designed to be used with the Ethereum network. In addition to providing network connectivity, injected providers often supply one or more [accounts](/guides/wallet/). Web3.js supports any injected provider that is compliant with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) and has been tested with multiple EIP-1193 providers, including [MetaMask](https://docs.metamask.io/wallet/reference/provider-api/), [Hardhat](https://hardhat.org/hardhat-runner/docs/advanced/hardhat-runtime-environment), and [Incubed (IN3)](https://in3.readthedocs.io/en/develop/index.html). +Injected providers are supplied by an external third-party, most often a wallet or a web browser that is designed to be used with the Ethereum network. In addition to providing network connectivity, injected providers often supply one or more [accounts](/guides/wallet). Web3.js supports any injected provider that is compliant with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) and has been tested with multiple EIP-1193 providers, including [MetaMask](https://docs.metamask.io/wallet/reference/provider-api/), [Hardhat](https://hardhat.org/hardhat-runner/docs/advanced/hardhat-runtime-environment), and [Incubed (IN3)](https://in3.readthedocs.io/en/develop/index.html). :::note The following example should be run in a browser with the MetaMask extension installed. ::: ```html title='E.g, Metamask' - + ``` diff --git a/docs/docs/guides/wallet/index.md b/docs/docs/guides/03_wallet/index.md similarity index 78% rename from docs/docs/guides/wallet/index.md rename to docs/docs/guides/03_wallet/index.md index ef75a663ec8..d93ba737a50 100644 --- a/docs/docs/guides/wallet/index.md +++ b/docs/docs/guides/03_wallet/index.md @@ -1,11 +1,11 @@ --- -sidebar_position: 1 -sidebar_label: 'Introduction to Accounts & Wallets' +sidebar_position: 3 +sidebar_label: '🔑 Accounts & Wallets' --- # Introduction to Accounts & Wallets -The concept of an [account](https://ethereum.org/en/developers/docs/accounts/) is central to Ethereum and it can be used to refer to two types of entities that are native to Ethereum: externally-owned accounts and contract accounts. This document relates _exclusively_ to **externally-owned accounts**. An externally-owned account is associated with a "[key pair](https://ethereum.org/en/developers/docs/accounts/#externally-owned-accounts-and-key-pairs)", which is a general concept that is related to [public-key cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography). The key pair consists of a private key, which must always be kept secret, and a public key, which is used to derive a public identifier (address) for an account. Ethereum accounts have an [ETH](https://ethereum.org/en/developers/docs/intro-to-ethereum/#eth) balance, which can be [transferred](/guides/wallet/transactions) to other accounts or used to pay for interactions with [smart contracts](/guides/smart_contracts/smart_contracts_guide). Anyone with access to an account's private key has the ability to control that account's ETH balance, so it's important that an account's private key is always kept secret. In addition to the general guidelines for [protecting private keys](https://ethereum.org/en/security/#protect-private-keys/), private keys should never be included in client-side code that can be seen by end users and should never be committed to code repositories. +The concept of an [account](https://ethereum.org/en/developers/docs/accounts/) is central to Ethereum and it can be used to refer to two types of entities that are native to Ethereum: externally-owned accounts and contract accounts. This document relates _exclusively_ to **externally-owned accounts**. An externally-owned account is associated with a "[key pair](https://ethereum.org/en/developers/docs/accounts/#externally-owned-accounts-and-key-pairs)", which is a general concept that is related to [public-key cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography). The key pair consists of a private key, which must always be kept secret, and a public key, which is used to derive a public identifier (address) for an account. Ethereum accounts have an [ETH](https://ethereum.org/en/developers/docs/intro-to-ethereum/#eth) balance, which can be [transferred](/guides/transactions/transactions) to other accounts or used to pay for interactions with [smart contracts](/guides/smart_contracts/smart_contracts_guide). Anyone with access to an account's private key has the ability to control that account's ETH balance, so it's important that an account's private key is always kept secret. In addition to the general guidelines for [protecting private keys](https://ethereum.org/en/security/#protect-private-keys/), private keys should never be included in client-side code that can be seen by end users and should never be committed to code repositories. In the context of this document, the term "wallet" refers to a collection of accounts and should not be confused with [wallet "applications"](https://ethereum.org/en/wallets/). @@ -29,7 +29,7 @@ console.log(account); */ // use the account to sign a message -const signature = account.sign("Hello, Web3.js!"); +const signature = account.sign('Hello, Web3.js!'); /* ↳ { message: 'Hello, Web3.js!', @@ -48,7 +48,7 @@ In addition to generating new random accounts, the Account package can also be u ```js // load an existing account from its private key -const account = web3.eth.accounts.privateKeyToAccount(""); +const account = web3.eth.accounts.privateKeyToAccount(''); console.log(account); /* ↳ @@ -62,7 +62,7 @@ console.log(account); */ // use the account to sign a message -const signature = account.sign("Hello, Web3.js!"); +const signature = account.sign('Hello, Web3.js!'); /* ↳ { message: 'Hello, Web3.js!', @@ -77,30 +77,30 @@ const signature = account.sign("Hello, Web3.js!"); ### Account Methods -The following is a list of [`Accounts`](/libdocs/Accounts) methods in the `web3.eth.accounts` package with descriptions 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) +The following is a list of [`Accounts`](/libdocs/Accounts) methods in the `web3.eth.accounts` package with descriptions 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) ## Wallets -A Web3.js wallet is a collection of accounts and is represented with the [`Wallet`](/api/web3-eth-accounts/class/Wallet) class. When a wallet is used to track an account, that account is added to an internal context (i.e. [`Web3Context`](/api/web3-core/class/Web3Context/)), which makes it easier to use that account in the future - this is described in more detail in the [transactions tutorial](/guides/wallet/transactions). The following snippet demonstrates creating a wallet with 2 new random accounts and using the second account to sign a message: +A Web3.js wallet is a collection of accounts and is represented with the [`Wallet`](/api/web3-eth-accounts/class/Wallet) class. When a wallet is used to track an account, that account is added to an internal context (i.e. [`Web3Context`](/api/web3-core/class/Web3Context/)), which makes it easier to use that account in the future - this is described in more detail in the [transactions tutorial](/guides/transactions/transactions). The following snippet demonstrates creating a wallet with 2 new random accounts and using the second account to sign a message: ```js // create a wallet with 2 new random accounts const wallet = web3.eth.accounts.wallet.create(2); -console.log(wallet) +console.log(wallet); /* ↳ Wallet(2) [ { @@ -131,7 +131,7 @@ Wallet(2) [ */ // use the second account in the wallet to sign a message -const signature = wallet[1].sign("Hello, Web3.js!"); +const signature = wallet[1].sign('Hello, Web3.js!'); // wallet accounts can also be accessed with the "at" and "get" methods // wallet.at(1).sign("Hello, Web3.js!") // wallet.get(1).sign("Hello, Web3.js!") @@ -154,7 +154,7 @@ In addition to generating new random accounts, a wallet can also be used to load ```js // create a wallet with a single existing account -const wallet = web3.eth.accounts.wallet.add(""); +const wallet = web3.eth.accounts.wallet.add(''); console.log(wallet); /* ↳ @@ -281,23 +281,23 @@ Wallet(3) [ ### Wallet Methods -The following is a list of [`Wallet`](/libdocs/Wallet) methods in the `web3.eth.accounts.wallet` package with description and example usage: +The following is a list of [`Wallet`](/libdocs/Wallet) methods 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) +- [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) ## Next Steps This document is just an introduction to Web3.js accounts and wallets. Here are some suggestions for what to review next: -- Learn how to [transfer ETH](/guides/wallet/transactions) from one account to another. -- Build a front-end application that uses [injected accounts](/guides/wallet/metamask-vanilla) from the MetaMask wallet. -- Use an account to [deploy and interact with a smart contract](/guides/smart_contracts/smart_contracts_guide). +- Learn how to [transfer ETH](/guides/transactions/transactions) from one account to another. +- Build a front-end application that uses [injected accounts](/guides/dapps/metamask-vanilla) from the MetaMask wallet. +- Use an account to [deploy and interact with a smart contract](/guides/smart_contracts/smart_contracts_guide). diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/_category_.yml b/docs/docs/guides/04_transactions/_category_.yml similarity index 53% rename from docs/docs/guides/web3_upgrade_guide/1.x/_category_.yml rename to docs/docs/guides/04_transactions/_category_.yml index 7723475cb40..99d68c8c3bc 100644 --- a/docs/docs/guides/web3_upgrade_guide/1.x/_category_.yml +++ b/docs/docs/guides/04_transactions/_category_.yml @@ -1,5 +1,5 @@ -label: 'Upgrade from 1.x' +label: '🔄 Transactions' collapsible: true collapsed: true link: null -position: 1 \ No newline at end of file +position: 4 diff --git a/docs/docs/guides/wallet/transactions.md b/docs/docs/guides/04_transactions/transactions.md similarity index 81% rename from docs/docs/guides/wallet/transactions.md rename to docs/docs/guides/04_transactions/transactions.md index dfc92765844..8b830554593 100644 --- a/docs/docs/guides/wallet/transactions.md +++ b/docs/docs/guides/04_transactions/transactions.md @@ -1,11 +1,11 @@ --- -sidebar_position: 2 +sidebar_position: 1 sidebar_label: 'Tutorial: Sending Transactions' --- # Sending Transactions -This tutorial will walk through the process of using accounts to send transactions on a [development network](https://ethereum.org/en/developers/docs/development-networks/), including how to subscribe to the events associated with a transaction. The topics covered in this tutorial include basic concepts of [Ethereum](https://ethereum.org/), such as [accounts](/guides/wallet/), [denominations of ether](https://ethereum.org/en/developers/docs/intro-to-ether/#denominations), [transactions](https://ethereum.org/en/developers/docs/transactions/), and [gas fees](https://ethereum.org/en/developers/docs/gas/), as well as the basics of the [Hardhat](https://hardhat.org/) development environment. +This tutorial will walk through the process of using accounts to send transactions on a [development network](https://ethereum.org/en/developers/docs/development-networks/), including how to subscribe to the events associated with a transaction. The topics covered in this tutorial include basic concepts of [Ethereum](https://ethereum.org/), such as [accounts](/guides/wallet), [denominations of ether](https://ethereum.org/en/developers/docs/intro-to-ether/#denominations), [transactions](https://ethereum.org/en/developers/docs/transactions/), and [gas fees](https://ethereum.org/en/developers/docs/gas/), as well as the basics of the [Hardhat](https://hardhat.org/) development environment. ## Overview @@ -19,7 +19,7 @@ Here is a high-level overview of the steps we will be taking in this tutorial: 6. Send a raw transaction :::tip -If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. +If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. ::: ## Step 1: Prerequisites @@ -105,19 +105,19 @@ The Hardhat development network needs to remain running in the terminal that was Next, create a new file called `index.js` in your project directory and add the following code to it: ```js -const { Web3 } = require("web3"); +const { Web3 } = require('web3'); -const web3 = new Web3("http://127.0.0.1:8545/"); +const web3 = new Web3('http://127.0.0.1:8545/'); // Log the chain ID to the console web3.eth - .getChainId() - .then((result) => { - console.log("Chain ID: " + result); - }) - .catch((error) => { - console.error(error); - }); + .getChainId() + .then(result => { + console.log('Chain ID: ' + result); + }) + .catch(error => { + console.error(error); + }); ``` This code sets up a Web3.js connection to the Hardhat development network and logs the chain ID to the console. @@ -147,51 +147,45 @@ Replace the value of the `privateKey` variable with one of the private keys of t ::: ```js -const { Web3 } = require("web3"); +const { Web3 } = require('web3'); async function main() { - const web3 = new Web3("http://127.0.0.1:8545/"); - - // create a new Web3.js account object with the private key of a Hardhat test account - const privateKey = ""; - // the account is created with a wallet, which makes it easier to use - const sender = web3.eth.accounts.wallet.add(privateKey)[0]; - - // generate a new random Web3.js account object to receive the transaction - const receiver = web3.eth.accounts.create(); - - // log initial balances - console.log( - "Initial sender balance:", - // account balance in wei - await web3.eth.getBalance(sender.address) - ); - console.log( - "Initial receiver balance:", - // account balance in wei - await web3.eth.getBalance(receiver.address) - ); - - // sign and send the transaction - const receipt = await web3.eth.sendTransaction({ - from: sender.address, - to: receiver.address, - // amount in wei - value: 100, - }); - - // log transaction receipt - console.log(receipt); - - // log final balances - console.log( - "Final sender balance:", - await web3.eth.getBalance(sender.address) - ); - console.log( - "Final receiver balance:", - await web3.eth.getBalance(receiver.address) - ); + const web3 = new Web3('http://127.0.0.1:8545/'); + + // create a new Web3.js account object with the private key of a Hardhat test account + const privateKey = ''; + // the account is created with a wallet, which makes it easier to use + const sender = web3.eth.accounts.wallet.add(privateKey)[0]; + + // generate a new random Web3.js account object to receive the transaction + const receiver = web3.eth.accounts.create(); + + // log initial balances + console.log( + 'Initial sender balance:', + // account balance in wei + await web3.eth.getBalance(sender.address), + ); + console.log( + 'Initial receiver balance:', + // account balance in wei + await web3.eth.getBalance(receiver.address), + ); + + // sign and send the transaction + const receipt = await web3.eth.sendTransaction({ + from: sender.address, + to: receiver.address, + // amount in wei + value: 100, + }); + + // log transaction receipt + console.log(receipt); + + // log final balances + console.log('Final sender balance:', await web3.eth.getBalance(sender.address)); + console.log('Final receiver balance:', await web3.eth.getBalance(receiver.address)); } main(); @@ -241,51 +235,51 @@ Note that the sender's balance has decreased by more than the amount that was tr In the previous example, the `transaction-receipt.js` script demonstrates sending a transaction to the network and reviewing the results after it has been successfully received. However, there are more stages to the [transaction lifecycle](https://ethereum.org/en/developers/docs/transactions/#transaction-lifecycle) and Web3.js makes it easy to subscribe to these lifecycle stages and create custom handlers for each one. Web3.js supports subscriptions for the following transaction lifecycle events: -- Sending - Web3.js is preparing to send the transaction to the network -- Sent - the transaction has been sent to the network -- Transaction hash - a hash of the transaction has been generated -- Receipt - the transaction has been included in a block -- Confirmation - the block in which the transaction was included has been [finalized](https://ethereum.org/en/glossary/#finality) -- Error - a problem with the transaction was encountered +- Sending - Web3.js is preparing to send the transaction to the network +- Sent - the transaction has been sent to the network +- Transaction hash - a hash of the transaction has been generated +- Receipt - the transaction has been included in a block +- Confirmation - the block in which the transaction was included has been [finalized](https://ethereum.org/en/glossary/#finality) +- Error - a problem with the transaction was encountered Create a new file called `transaction-events.js` in your project directory and add the following code to it: ```js -const { Web3 } = require("web3"); +const { Web3 } = require('web3'); -const web3 = new Web3("http://127.0.0.1:8545/"); +const web3 = new Web3('http://127.0.0.1:8545/'); -const privateKey = ""; +const privateKey = ''; const sender = web3.eth.accounts.wallet.add(privateKey)[0]; const receiver = web3.eth.accounts.create(); web3.eth - .sendTransaction({ - from: sender.address, - to: receiver.address, - value: 100, - }) - .on("sending", (sending) => { - console.log("Sending:", sending); - }) - .on("sent", (sent) => { - console.log("Sent:", sent); - }) - .on("transactionHash", (transactionHash) => { - console.log("Transaction Hash:", transactionHash); - }) - .on("receipt", (receipt) => { - console.log("Receipt:", receipt); - }) - .on("confirmation", (confirmation) => { - console.log("Confirmation:", confirmation); - process.exit(0); - }) - .on("error", (error) => { - console.log("Error:", error); - process.exit(1); - }); + .sendTransaction({ + from: sender.address, + to: receiver.address, + value: 100, + }) + .on('sending', sending => { + console.log('Sending:', sending); + }) + .on('sent', sent => { + console.log('Sent:', sent); + }) + .on('transactionHash', transactionHash => { + console.log('Transaction Hash:', transactionHash); + }) + .on('receipt', receipt => { + console.log('Receipt:', receipt); + }) + .on('confirmation', confirmation => { + console.log('Confirmation:', confirmation); + process.exit(0); + }) + .on('error', error => { + console.log('Error:', error); + process.exit(1); + }); ``` Execute the following command to run the code from `transaction-events.js`: @@ -406,37 +400,35 @@ The previous examples have relied on the helpful Web3.js context to automaticall Create a new file called `raw-transaction.js` in your project directory and add the following code to it: ```js -const { Web3 } = require("web3"); +const { Web3 } = require('web3'); async function main() { - const web3 = new Web3("http://127.0.0.1:8545/"); - - const privateKey = ""; - // import the Hardhat test account without the use of a wallet - const sender = web3.eth.accounts.privateKeyToAccount(privateKey); - - const receiver = web3.eth.accounts.create(); - - // used to calculate the transaction's maxFeePerGas - const block = await web3.eth.getBlock(); - - const transaction = { - from: sender.address, - to: receiver.address, - value: 100, - // the following two properties must be included in raw transactions - maxFeePerGas: block.baseFeePerGas * 2n, - maxPriorityFeePerGas: 100000, - }; - - const signedTransaction = await web3.eth.accounts.signTransaction( - transaction, - sender.privateKey - ); - const receipt = await web3.eth.sendSignedTransaction( - signedTransaction.rawTransaction - ); - console.log(receipt); + const web3 = new Web3('http://127.0.0.1:8545/'); + + const privateKey = ''; + // import the Hardhat test account without the use of a wallet + const sender = web3.eth.accounts.privateKeyToAccount(privateKey); + + const receiver = web3.eth.accounts.create(); + + // used to calculate the transaction's maxFeePerGas + const block = await web3.eth.getBlock(); + + const transaction = { + from: sender.address, + to: receiver.address, + value: 100, + // the following two properties must be included in raw transactions + maxFeePerGas: block.baseFeePerGas * 2n, + maxPriorityFeePerGas: 100000, + }; + + const signedTransaction = await web3.eth.accounts.signTransaction( + transaction, + sender.privateKey, + ); + const receipt = await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction); + console.log(receipt); } main(); diff --git a/docs/docs/guides/04_transactions/tx-types.md b/docs/docs/guides/04_transactions/tx-types.md new file mode 100644 index 00000000000..33152103aec --- /dev/null +++ b/docs/docs/guides/04_transactions/tx-types.md @@ -0,0 +1,279 @@ +--- +sidebar_position: 2 +sidebar_label: 'Transaction Types' +--- + +# Transactions + +In this tutorial, we will explore how to send different types of [transactions](https://ethereum.org/en/developers/docs/transactions/) using web3.js, focusing on Ethereum's evolving transaction formats. We'll start with [legacy transactions (Transaction Type 0)](#transaction-type-0-legacy). Next, we'll delve into Transaction [Type 1 (EIP-2930)](#transaction-type-1-eip-2930), which introduces access lists to optimize gas usage. Finally, we'll cover [Transaction Type 2 (EIP-1559)](#transaction-type-2-eip-1559), the current default, which allows users to specify maximum fees and priority tips for more efficient and cost-effective transactions. Each section will include practical code examples to demonstrate sending raw transactions and interacting with ERC20 tokens on the Sepolia test network + +:::note +Web3.js uses transaction type 2 by default +::: + +## Transaction Type 0 (Legacy) + +### Raw Transaction + +A Legacy Transaction refers to a transaction that was created using an older version of Ethereum's transaction format, also known as "transaction type 0". This transaction format was used before the EIP-1559 upgrade, which was implemented in August 2021. + +```ts +import { Web3 } from 'web3'; + +const web3 = new Web3('https://rpc2.sepolia.org'); // RPC node url + +async function txLegacy() { + const wallet = web3.eth.wallet.add('YOUR_PRIVATE_KEY'); // make sure you have funds + + const sender = wallet[0].address; + const recipient = '0x807BFe4940016B5a7FdA19482042917B02e68359'; + const value = 1; // wei + const nonce = await web3.eth.getTransactionCount(sender); + const gas = 21000; + const gasPrice = await web3.eth.getGasPrice(); + + const tx = { + from: sender, + to: recipient, + value, + nonce, + gas, + gasPrice, + // highlight-next-line + type: 0, + }; + + const txReceipt = await web3.eth.sendTransaction(tx); + console.log('Tx hash', txReceipt.transactionHash); +} + +txLegacy(); +``` + +### ERC20 Interaction + +```ts +import { Web3 } from 'web3'; + +const web3 = new Web3('https://rpc2.sepolia.org'); + +//WETH token in Sepolia https://sepolia.etherscan.io/address/0xfff9976782d46cc05630d1f6ebab18b2324d6b14#code +const ADDRESS_WETH_SEPOLIA = '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14'; +const ABI = [ + { + constant: false, + inputs: [ + { + name: 'dst', + type: 'address', + }, + { + name: 'wad', + type: 'uint256', + }, + ], + name: 'transfer', + outputs: [ + { + name: '', + type: 'bool', + }, + ], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, +]; + +async function transfer() { + //initialize wallet + const wallet = web3.eth.accounts.wallet.add('YOUR_PRIVATE_KEY'); //make sure you have WETH tokens in the Sepolia network + //you can swap Sepolia tokens for WETH here https://app.uniswap.org/swap?chain=sepolia + + //initialize WETH contract in sepolia + const myERC20 = new web3.eth.Contract(ABI, ADDRESS_WETH_SEPOLIA); + + const TO = '0xEA9eEca67682Cd9c6Ce3DdD1681049D7A897289F'; //address to send the tokens to + const VALUE = 1; //wei value, dont forget to multiply by decimals + + //send transfer and specify the type + const txReceipt = await myERC20.methods.transfer(TO, VALUE).send({ + from: wallet[0].address, + // highlight-next-line + type: 0, + }); + + console.log(txReceipt.transactionHash); + //=> 0x5f2087c22166f3a1909c40ce537dd564dc3d4c70c5be02f35c6406a628123b16 +} + +transfer(); +``` + +## Transaction Type 1 (EIP-2930) + +This EIP was introduced in April 2021, it introduces a feature called 'Access List.' This improvement allows saving gas on cross-contract calls by declaring in advance which contract and storage slots will be accessed. + +### Raw Transaction + +```ts +import { Web3 } from 'web3'; + +const web3 = new Web3('https://rpc2.sepolia.org'); + +async function txEIP2930() { + const wallet = web3.eth.wallet.add('YOUR_PRIVATE_KEY'); + + const sender = wallet[0].address; + const contractAddress1 = '0x...'; + const gas = 500000; //could be higher + const gasPrice = await web3.eth.getGasPrice(); + const data = '0x9a67c8b100000000000000000000000000000000000000000000000000000000000004d0'; + + // highlight-start + //create access list using web3.eth + const accessListData = await web3.eth.createAccessList({ + from: sender, + to: contractAddress1, + data, + }); + // highlight-end + + console.log(accessListData); + /* + => + { + // highlight-start + "accessList": [ + { + "address": "0x15859bdf5aff2080a9968f6a410361e9598df62f", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + // highlight-end + "gasUsed": "0x7671" + } + */ + + const tx = { + from: sender, + to: contractAddress1, //the contract we are calling + data, + gas, + gasPrice, + // highlight-next-line + type: 1, + // highlight-next-line + accessList: accessListData.accessList, //access the object `accessList` + }; + + const txReceipt = await web3.eth.sendTransaction(tx); + + console.log('Tx hash', txReceipt.transactionHash); +} + +txEIP2930(); +``` + +## Transaction Type 2 (EIP-1559) + +When a user creates an EIP-1559 transaction, they specify the maximum fee they are willing to pay `maxFeePerGas` as well as a tip `maxPriorityFeePerGas` to incentivize the miner. The actual fee paid by the user is then determined by the network based on the current demand for block space and the priority of the transaction. + +### Raw Transaction + +```ts +import { Web3 } from 'web3'; + +const web3 = new Web3('https://rpc2.sepolia.org'); + +async function txEIP1559() { + const wallet = web3.eth.wallet.add('YOUR_PRIVATE_KEY'); //make sure you have funds + + const sender = wallet[0].address; + const recipient = '0x807BFe4940016B5a7FdA19482042917B02e68359'; + const value = 1; //wei + const nonce = await web3.eth.getTransactionCount(sender); + const gasLimit = 21000; + const maxFeePerGas = Number((await web3.eth.calculateFeeData()).maxFeePerGas); + const maxPriorityFeePerGas = Number((await web3.eth.calculateFeeData()).maxPriorityFeePerGas); + + const tx = { + from: sender, + to: recipient, + value, + nonce, + gasLimit, + maxFeePerGas, + maxPriorityFeePerGas, + // highlight-next-line + type: 2, + }; + + const txReceipt = await web3.eth.sendTransaction(tx); + console.log('Tx hash', txReceipt.transactionHash); +} + +txEIP1559(); +``` + +### ERC20 Interaction + +```ts +import { Web3 } from 'web3'; + +const web3 = new Web3('https://rpc2.sepolia.org'); + +//WETH token in Sepolia https://sepolia.etherscan.io/address/0xfff9976782d46cc05630d1f6ebab18b2324d6b14#code +const ADDRESS_WETH_SEPOLIA = '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14'; +const ABI = [ + { + constant: false, + inputs: [ + { + name: 'dst', + type: 'address', + }, + { + name: 'wad', + type: 'uint256', + }, + ], + name: 'transfer', + outputs: [ + { + name: '', + type: 'bool', + }, + ], + payable: false, + stateMutability: 'nonpayable', + type: 'function', + }, +]; + +async function transfer() { + //initialize wallet + const wallet = web3.eth.accounts.wallet.add('YOUR_PRIVATE_KEY'); //make sure you have WETH tokens in the Sepolia network + //you can swap Sepolia tokens for WETH here https://app.uniswap.org/swap?chain=sepolia + + //initialize WETH contract in sepolia + const myERC20 = new web3.eth.Contract(ABI, ADDRESS_WETH_SEPOLIA); + + const TO = '0xEA9eEca67682Cd9c6Ce3DdD1681049D7A897289F'; //address to send the tokens to + const VALUE = 1; //wei value, dont forget to multiply by decimals + + //send transfer and specify the type + const txReceipt = await myERC20.methods.transfer(TO, VALUE).send({ + from: wallet[0].address, + // highlight-next-line + type: 2, + }); + + console.log(txReceipt.transactionHash); + //=> 0x174bc88023be4af431fad1693a59f7a41135238510cdcd00f15f6409b5471d77 +} + +transfer(); +``` diff --git a/docs/docs/guides/smart_contracts/_category_.yml b/docs/docs/guides/05_smart_contracts/_category_.yml similarity index 86% rename from docs/docs/guides/smart_contracts/_category_.yml rename to docs/docs/guides/05_smart_contracts/_category_.yml index 8a1d21c75b4..96b97cea9d2 100644 --- a/docs/docs/guides/smart_contracts/_category_.yml +++ b/docs/docs/guides/05_smart_contracts/_category_.yml @@ -2,4 +2,4 @@ label: '📜 Smart Contracts' collapsible: true collapsed: true link: null -position: 4 +position: 5 diff --git a/docs/docs/guides/smart_contracts/infer_contract_types.md b/docs/docs/guides/05_smart_contracts/infer_contract_types.md similarity index 82% rename from docs/docs/guides/smart_contracts/infer_contract_types.md rename to docs/docs/guides/05_smart_contracts/infer_contract_types.md index 3e7d4bfc7f1..b5288412522 100644 --- a/docs/docs/guides/smart_contracts/infer_contract_types.md +++ b/docs/docs/guides/05_smart_contracts/infer_contract_types.md @@ -7,7 +7,7 @@ sidebar_label: 'Infer Contract Types from JSON Artifact (TypeScript)' :::tip 📝 This article is for **TypeScript** developers. So, if you are using JavaScript, you do not need to read this. -However, web3.js version 4.x has been rewritten in TypeScript. And we encorage you to use its strongly-typed features with TypeScript. +However, web3.js version 4.x has been rewritten in TypeScript. And we encorage you to use its strongly-typed features with TypeScript. ::: Web3.js is a popular library used for interacting with EVM blockchains. One of its key features is the ability to invoke EVM smart contracts deployed on the blockchain. In this blog post, we will show how to interact with the smart contract in **TypeScript**, with a special focus on how to infer types from JSON artifact files. @@ -21,14 +21,14 @@ 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(); })(); ``` @@ -72,19 +72,22 @@ 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;`, + ); + } })(); ``` @@ -98,10 +101,12 @@ To use this script, just create an `artifacts.json` file at the root of your pro ] ``` -and run the script with -```bash +and run the script with + +```bash node -r ts-node/register + + + +
+
+
+
+ + + +``` + +Review the comments in `index.html`. This document imports Web3.js, creates several placeholders that will be used to display network information, and defines a script that checks for an [injected provider](/guides/web3_providers_guide/#injected-provider). If an injected provider is found, it's used to construct a new `Web3` instance and connect to the Ethereum network. A check is performed to ensure that the injected provider is coming from MetaMask and the result of this check is displayed to the user. Once connected through the injected provider, the script updates the placeholders with the chain ID and latest block number, and creates an event subscription to update the block number as new blocks are created. If no injected provider is found, the user is instructed to install MetaMask. + +To start a local HTTP server to serve `index.html`, execute the following command in the project directory: + +```bash +npx watch-http-server . +``` + +The output should look like: + +``` +Websocket Server Listening on Port: 8086 +Starting up http-server, serving . on: http://0.0.0.0:8080 +Hit CTRL-C to stop the server +Scanned working directory. ready for changes.. +``` + +The HTTP server needs to remain running in the terminal that was used to start it. Any changes that are made in the project directory will cause the webpage to automatically refresh. + +Use a MetaMask-enabled web browser to navigate to the URL from the output (http://0.0.0.0:8080 in the example above). If everything is set up correctly, the webpage should state that it is connected to the Ethereum network with MetaMask and list the chain ID (for the default Ethereum Mainnet network this value should be `1`) and latest block number. The latest block number should change when new blocks are created. + +## Step 4: Request Access to the MetaMask Accounts + +Replace the contents of `index.html` with the following (take note of the highlighted sections, which are new): + +```html + + + + + + Web3.js MetaMask Tutorial + + + + + +
+
+
+ +
+
+ + +
+ +
+ + + + +``` + +The file has been updated to include a placeholder for the MetaMask account, as well as a button that is used to request the accounts from MetaMask. + +Once connected to MetaMask, the script now registers a click event for the new button. The accounts are requested by invoking `window.ethereum.request({ method: ["eth_requestAccounts"] })` and once the request has been approved, the account addresses are available by calling [`web3.eth.getAccounts()`](https://docs.web3js.org/api/web3-eth/class/Web3Eth#getAccounts). MetaMask can be used to manage multiple accounts, but this tutorial only makes use of a single account. More information about the [`window.ethereum.request`](https://docs.metamask.io/wallet/reference/provider-api/#request) function and [`eth_requestAccounts`](https://docs.metamask.io/wallet/reference/eth_requestaccounts/) RPC call can be found in the MetaMask documentation. + +If no Ethereum provider is found, the button to request the MetaMask accounts is disabled. + +Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. Click the button that says "Request MetaMask Accounts", which should activate MetaMask. After accepting the MetaMask notifications, the address of the MetaMask account should be displayed on the webpage. MetaMask will remember that the webpage has been given permission to access its accounts and it will not be necessary to accept any confirmations when requesting accounts in the future. + +## Step #5: Sign a Message with a MetaMask Account + +Replace the contents of `index.html` with the following (take note of the highlighted sections, which are new): + +```html + + + + + + Web3.js MetaMask Tutorial + + + + + +
+
+
+
+
+ +
+ +
+ + +
+ + +
+
+ + + + +``` + +`index.html` has been updated to include inputs for signing a message with the MetaMask account. Initially, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the signing operation. + +Inside the click event for the "Request MetaMask Accounts" button, the signing inputs are initialized. First, the inputs are enabled. Then, a click event is registered for the "Sign" button. This click event calls the [`web3.eth.personal.sign`](/api/web3-eth-personal/class/Personal#sign) method. The first parameter to this method is the message to be signed, which is taken from the input field. The second parameter is the address of the account to use for signing. The third parameter is the passphrase to decrypt the account, which is not used in this example since MetaMask is managing the account. Once the message has been signed, the placeholder is updated with the signed message. + +Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be disabled input fields below the "Request MetaMask Accounts" button. Click the button to request the accounts (remember, it will not be necessary to accept any MetaMask notifications this time). If everything is working properly, the address of the MetaMask account should be displayed on the webpage and the input fields should become enabled. Type a message (e.g. "Hello, Web3.js!") in the input field and click the "Sign Message" button. If everything is working properly, a MetaMask notification will appear. After the notification has been accepted, the signed message should appear beneath the input fields. + +## Step #6: Verify the Account Used to Sign a Message + +Replace the contents of `index.html` with the following (take note of the highlighted sections, which are new): + +```html + + + + + + Web3.js MetaMask Tutorial + + + + + +
+
+
+
+
+ +
+ +
+ +
+ + +
+
+ + +
+ + + +
+
+ + + + +``` + +As in the previous step, `index.html` has been updated to include inputs for recovering the account that was used to sign a message. As before, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the recovery operation. + +Inside the click event for the "Request MetaMask Accounts" button, the recovery inputs are initialized. First, the inputs are enabled. Then, a click event is registered for the "Recover" button. This click event calls the [`web3.eth.personal.ecRecover`](/api/web3-eth-personal/class/Personal#ecRecover) method. The first parameter to this method is the original unsigned message, which is taken from the first input field. The second parameter is the signed message, which is taken from the second input field. Once the account has been recovered, the placeholder is updated with the address of the account. + +Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be additional disabled input fields below those from the previous step. Follow the same steps as before to request the accounts from MetaMask and sign a message, then copy and paste the original message and message signature (starting with the leading `0x` characters) into the new input fields. Click the "Recover Account" button. If everything is working properly, the address of the account that was used to sign the message should appear below the new input fields. This address should match the one that is displayed above the input fields that were used to sign the message. + +## Conclusion + +This tutorial demonstrated using Web3.js with MetaMask, including using the MetaMask injected provider and using a MetaMask account to sign a message. To use the MetaMask injected provider with Web3.js, simply construct a new instance of the `Web3` class with the `window.ethereum` property. To request access to the MetaMask accounts, use `window.ethereum.request({ method: "eth_requestAccounts" })` - once the user has confirmed this request, the MetaMask accounts will be available with `web3.eth.getAccounts()`. When the MetaMask injected provider handles a request that requires the use of a MetaMask account, MetaMask will prompt the user to confirm the request. diff --git a/docs/docs/guides/wallet/web3_modal_guide/_category_.yml b/docs/docs/guides/07_dapps/web3_modal_guide/_category_.yml similarity index 87% rename from docs/docs/guides/wallet/web3_modal_guide/_category_.yml rename to docs/docs/guides/07_dapps/web3_modal_guide/_category_.yml index 0ce376f6e80..c89deac9d4b 100644 --- a/docs/docs/guides/wallet/web3_modal_guide/_category_.yml +++ b/docs/docs/guides/07_dapps/web3_modal_guide/_category_.yml @@ -2,4 +2,4 @@ label: '📱 WalletConnect Tutorial' collapsible: true collapsed: true link: null -position: 6 +position: 4 diff --git a/docs/docs/guides/wallet/web3_modal_guide/index.mdx b/docs/docs/guides/07_dapps/web3_modal_guide/index.mdx similarity index 98% rename from docs/docs/guides/wallet/web3_modal_guide/index.mdx rename to docs/docs/guides/07_dapps/web3_modal_guide/index.mdx index 7e6f077b1a9..643ccb2cc79 100644 --- a/docs/docs/guides/wallet/web3_modal_guide/index.mdx +++ b/docs/docs/guides/07_dapps/web3_modal_guide/index.mdx @@ -126,5 +126,5 @@ function Components() { ``` :::info -- To learn how to set up Web3modal with React, click [here](/guides/wallet/web3_modal_guide/react). +- To learn how to set up Web3modal with React, click [here](/guides/dapps/web3_modal_guide/react). ::: diff --git a/docs/docs/guides/07_dapps/web3_modal_guide/react.md b/docs/docs/guides/07_dapps/web3_modal_guide/react.md new file mode 100644 index 00000000000..23f4bbcc052 --- /dev/null +++ b/docs/docs/guides/07_dapps/web3_modal_guide/react.md @@ -0,0 +1,122 @@ +--- +sidebar_position: 1 +sidebar_label: 'Web3Modal with React' +--- + +# Web3Modal with React and web3js + +## Live code editor + + + +## Installation + +For this guide we will be creating a new project will need to install dependancies. We will be using vite to locally host the app, React and web3modal-web3js + +```bash +npm install web3modal-web3js react react-dom +npm install --save-dev vite @vitejs/plugin-react +``` + +## Implementation + +Within the root of the project create `index.html` + +```html + + + + + + React Web3 example + + +
+ + + +``` + +Now we will add the Web3modal code within `src/Web3modal.tsx` + +```typescript +import { createWeb3Modal, defaultConfig } from 'web3modal-web3/react'; + +// 1. Get projectId, Your Project ID can be obtained from walletconnect.com +const projectId = 'YOUR_PROJECT_ID'; + +// 2. Set chains +const mainnet = { + chainId: 1, + name: 'Ethereum', + currency: 'ETH', + explorerUrl: 'https://etherscan.io', + rpcUrl: 'https://cloudflare-eth.com', +}; + +// 3. Create a metadata object +const metadata = { + name: 'My Website', + description: 'My Website description', + url: 'https://mywebsite.com', // origin must match your domain & subdomain + icons: ['https://avatars.mywebsite.com/'], +}; + +// 4. Create web3 config +const web3Config = defaultConfig({ + /*Required*/ + metadata, + + /*Optional*/ + enableEIP6963: true, // true by default + enableInjected: true, // true by default + enableCoinbase: true, // true by default + rpcUrl: '...', // used for the Coinbase SDK + defaultChainId: 1, // used for the Coinbase SDK +}); + +// 5. Create a Web3Modal instance +createWeb3Modal({ + web3Config, + chains: [mainnet], + projectId, + enableAnalytics: true, // Optional - defaults to your Cloud configuration +}); + +export default function App() { + return ; +} +``` + +Set up vite configs within root `vite.config.js` + +```javascript +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [react()], +}); +``` + +And finally add react to the app `src/main.tsx` + +```typescript +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App.js'; + +ReactDOM.createRoot(document.getElementById('app')!).render( + + + , +); +``` + +You are finished and have successfully created Web3modal with React! + +:::info + +- For additional information take a look into the interactive code editor above. +- Learn more about Web3modal [here](https://docs.walletconnect.com/web3modal/about) + ::: diff --git a/docs/docs/guides/hardhat_tutorial/asset/artifacts.png b/docs/docs/guides/08_hardhat_tutorial/asset/artifacts.png similarity index 100% rename from docs/docs/guides/hardhat_tutorial/asset/artifacts.png rename to docs/docs/guides/08_hardhat_tutorial/asset/artifacts.png diff --git a/docs/docs/guides/hardhat_tutorial/asset/image_2.png b/docs/docs/guides/08_hardhat_tutorial/asset/image_2.png similarity index 100% rename from docs/docs/guides/hardhat_tutorial/asset/image_2.png rename to docs/docs/guides/08_hardhat_tutorial/asset/image_2.png diff --git a/docs/docs/guides/hardhat_tutorial/asset/image_3.png b/docs/docs/guides/08_hardhat_tutorial/asset/image_3.png similarity index 100% rename from docs/docs/guides/hardhat_tutorial/asset/image_3.png rename to docs/docs/guides/08_hardhat_tutorial/asset/image_3.png diff --git a/docs/docs/guides/hardhat_tutorial/index.md b/docs/docs/guides/08_hardhat_tutorial/index.md similarity index 59% rename from docs/docs/guides/hardhat_tutorial/index.md rename to docs/docs/guides/08_hardhat_tutorial/index.md index ea97d80e9b4..32850b50211 100644 --- a/docs/docs/guides/hardhat_tutorial/index.md +++ b/docs/docs/guides/08_hardhat_tutorial/index.md @@ -1,11 +1,12 @@ --- -sidebar_position: 1 -sidebar_label: Web3.js v4 with Hardhat +sidebar_position: 8 +sidebar_label: ⛑️ Web3.js v4 with Hardhat --- # Using Web3 With Hardhat ## Introduction + Following the recent compatibility update of Hardhat plugin [hardhat-web3-v4](https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-web3-v4), `Web3.Js` is now available to use as plugin in Hardhat. This tutorial will guide you through using Web3js as a plugin to interact with the Blockchain. @@ -15,20 +16,23 @@ This tutorial explains how to create a Web3.js + Hardhat project from scratch. T ::: ## Pre-requisite + This tutorial assumes you have previous knowledge of writing Smart contracts, and are convenient working with JavaScript/TypeScript. You should have [NodeJS](https://nodejs.org/en) version greater than v16 installed. :::note -To install dependencies, we will use `NPM`. +To install dependencies, we will use `NPM`. ::: ## Steps -- [Initiate a Hardhat project](#initiate-a-hardhat-project) -- [Install required dependencies (including `hardhat-web3-v4`)](#install-required-dependencies-including-hardhat-web3-v4) -- [Write the Smart Contract](#write-the-smart-contract) -- [Compile and deploying the contract](#compile-test-and-deploy-the-contract) -- [Testing and interacting with the contract](#testing-and-interacting-with-the-contract) + +- [Initiate a Hardhat project](#initiate-a-hardhat-project) +- [Install required dependencies (including `hardhat-web3-v4`)](#install-required-dependencies-including-hardhat-web3-v4) +- [Write the Smart Contract](#write-the-smart-contract) +- [Compile and deploying the contract](#compile-test-and-deploy-the-contract) +- [Testing and interacting with the contract](#testing-and-interacting-with-the-contract) ### Initiate a Hardhat project + Create a new project folder and navigate into it. ```bash @@ -55,7 +59,7 @@ npx hardhat init Select `TypeScript` and `Yes` for the rest of the options. You will be prompted to install the required dependencies. Reply `yes` to complete the installation. -To include the `Hardhat-web3-v4` plugin, we will install it via `npm`. +To include the `Hardhat-web3-v4` plugin, we will install it via `npm`. ```bash npm install --save-dev @nomicfoundation/hardhat-web3-v4 'web3@4' @@ -64,21 +68,21 @@ npm install --save-dev @nomicfoundation/hardhat-web3-v4 'web3@4' This will add Web3.Js to your project by including it in the 'node_modules' folder. To extend the Hardhat functionality with this plugin, we have to import the `web3-v4 plugin` in the Hardhat configuration file `hardhat.config.ts`. Import this at the top of the config file. ```ts -import { HardhatUserConfig } from "hardhat/config"; -import "@nomicfoundation/hardhat-toolbox"; -import "@nomicfoundation/hardhat-web3-v4"; // <================ +import { HardhatUserConfig } from 'hardhat/config'; +import '@nomicfoundation/hardhat-toolbox'; +import '@nomicfoundation/hardhat-web3-v4'; // <================ const config: HardhatUserConfig = { - solidity: "0.8.19", + solidity: '0.8.19', }; export default config; - ``` By default, `hardhat-toolbox` is added to the file. You will need to explicitly invoke the plugin. This will modify the Hardhat Run-time Environment - HRE and to include both the Web3 class and an instantiated web3 object. With the latter, you get a modified ready-to-use web3 object can comes with an initialized local/Hardhat provider. The object will be available to use anywhere in the project such as testing and deployment files. ### Write the Smart Contract + When you start a new project, Hardhat provides a sample `Lock` contracts. Please refer to the contract in `myproject/contracts/Lock.sol` file. ```ts @@ -122,11 +126,13 @@ When you start a new project, Hardhat provides a sample `Lock` contracts. Please `Lock.sol` is a simple timeLock contract capable of accepting any amount of `Ether` at deployment while expecting one parameter that will be assigned to a state variable when deployed. The `withdraw` function allows only the address marked as `owner` to withdraw the total contract balance only if the 'unlockTime' is not in the future. ### Compile, test and deploy the contract -- Compile and deploying the contract + +- Compile and deploying the contract ```bash npx hardhat compile ``` + Running the above command will generate a folder called `artifacts` containing the build information and the compiled contracts. From this directory, we will require the jasonInterface otherwise called the Application Binary Interface - ABI during testing and deployment. ![images](./asset/artifacts.png) @@ -136,60 +142,58 @@ To deploy the contract, we will modify the `script/deploy.ts` file as shown belo First, we import the initialized web3 object from hardhat. Next we get the artifacts. ```ts -import { web3 } from "hardhat"; -import artifacts from "../artifacts/contracts/Lock.sol/Lock.json"; +import { web3 } from 'hardhat'; +import artifacts from '../artifacts/contracts/Lock.sol/Lock.json'; -async function main() { - -} +async function main() {} // We recommend this pattern to be able to use async/await everywhere // and properly handle errors. -main().catch((error) => { - console.error(error); - process.exitCode = 1; +main().catch(error => { + console.error(error); + process.exitCode = 1; }); - ``` Inside the main function, we prepare the deployment using a few of the web3.Js functionalities such as the `.utils` and `.eth` modules. ```ts async function main() { - const currentTimestampInSeconds = Math.round(Date.now() / 1000); - const unlockTime = currentTimestampInSeconds + 60; - - const lockedAmount = web3.utils.toWei("0.001", 'ether'); - - const [deployer] = await web3.eth.getAccounts(); - const lockContract = new web3.eth.Contract(artifacts.abi); - const rawContract = lockContract.deploy({ - data: artifacts.bytecode, - arguments: [unlockTime], - }); - - const lock = await rawContract.send({ - from: deployer, - gasPrice: "10000000000", - value: lockedAmount.toString() - }); - - console.log( - `Lock with ${web3.utils.toWei( - lockedAmount, - 'ether' - )}ETH and unlock timestamp ${unlockTime} deployed to ${lock.options.address}` - ); + const currentTimestampInSeconds = Math.round(Date.now() / 1000); + const unlockTime = currentTimestampInSeconds + 60; + + const lockedAmount = web3.utils.toWei('0.001', 'ether'); + + const [deployer] = await web3.eth.getAccounts(); + const lockContract = new web3.eth.Contract(artifacts.abi); + const rawContract = lockContract.deploy({ + data: artifacts.bytecode, + arguments: [unlockTime], + }); + + const lock = await rawContract.send({ + from: deployer, + gasPrice: '10000000000', + value: lockedAmount.toString(), + }); + + console.log( + `Lock with ${web3.utils.toWei( + lockedAmount, + 'ether', + )}ETH and unlock timestamp ${unlockTime} deployed to ${lock.options.address}`, + ); } // We recommend this pattern to be able to use async/await everywhere // and properly handle errors. -main().catch((error) => { - console.error(error); - process.exitCode = 1; +main().catch(error => { + console.error(error); + process.exitCode = 1; }); ``` -Running the following command will deploy the `Lock` contract to a local Blockchain built into Hardhat. We use Web3.Js to talk to the Blockchain to broadcast our smart contract data to the network. + +Running the following command will deploy the `Lock` contract to a local Blockchain built into Hardhat. We use Web3.Js to talk to the Blockchain to broadcast our smart contract data to the network. ```bash npx hardhat run scripts/deploy.ts @@ -197,86 +201,78 @@ npx hardhat run scripts/deploy.ts ### Testing and interacting with the contract -In the previous steps, we compiled and deployed the contract to the local Blockchain network. It's time to test our contract ensuring it performs as expected. Since we used Web3.Js to talk to the Blockchain to broadcast and save our data, we will use same protocol to view and modify the data. +In the previous steps, we compiled and deployed the contract to the local Blockchain network. It's time to test our contract ensuring it performs as expected. Since we used Web3.Js to talk to the Blockchain to broadcast and save our data, we will use same protocol to view and modify the data. In the `myproject/test/Lock.ts` file, replace the content with the code below. ```ts - import { - time, - loadFixture, - } from "@nomicfoundation/hardhat-toolbox/network-helpers"; - import { expect } from "chai"; - import { web3 } from "hardhat"; - import artifacts from "../artifacts/contracts/Lock.sol/Lock.json"; - - describe("Lock", function () { - async function deployOneYearLockFixture() { - const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60; - const ONE_GWEI = 1_000_000_000; - - const lockedAmount = ONE_GWEI; - const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS; - - const lockContract = new web3.eth.Contract(artifacts.abi); - lockContract.handleRevert = true; - - const [deployer, otherAccount] = await web3.eth.getAccounts(); - const rawContract = lockContract.deploy({ - data: artifacts.bytecode, - arguments: [unlockTime], - }); - - // To know how much gas will be consumed, we can estimate it first. - const estimateGas = await rawContract.estimateGas({ - from: deployer, - value: lockedAmount.toString() - }); - - const lock = await rawContract.send({ - from: deployer, - gas: estimateGas.toString(), - gasPrice: "10000000000", - value: lockedAmount.toString() - }); - - console.log("Lock contract deployed to: ", lock.options.address); - return { lock, unlockTime, lockedAmount, deployer, otherAccount, rawContract }; - } - - describe("Deployment", function () { - it("Should set the right unlockTime", async function () { - const { lock, unlockTime } = await loadFixture(deployOneYearLockFixture); - const setTime = await lock.methods.unlockTime().call(); - console.log("SetTime", setTime); - expect(setTime).to.equal(unlockTime); - }); - - it("Should set the right deployer", async function () { - const { lock, deployer } = await loadFixture(deployOneYearLockFixture); - - expect(await lock.methods.owner().call()).to.equal(deployer); - }); - - it("Should receive and store the funds to lock", async function () { - const { lock, lockedAmount } = await loadFixture( - deployOneYearLockFixture - ); - const balance = await web3.eth.getBalance(String(lock.options.address)); - expect(balance).to.equal(lockedAmount); - }); - - it("Shouldn't fail if the unlockTime has arrived and the deployer calls it", async function () { - const { lock, unlockTime, deployer } = await loadFixture( - deployOneYearLockFixture - ); - - await time.increaseTo(unlockTime); - await expect(lock.methods.withdraw().send({from: deployer})).not.to.be.reverted; - }); - }); - }); - +import { time, loadFixture } from '@nomicfoundation/hardhat-toolbox/network-helpers'; +import { expect } from 'chai'; +import { web3 } from 'hardhat'; +import artifacts from '../artifacts/contracts/Lock.sol/Lock.json'; + +describe('Lock', function () { + async function deployOneYearLockFixture() { + const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60; + const ONE_GWEI = 1_000_000_000; + + const lockedAmount = ONE_GWEI; + const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS; + + const lockContract = new web3.eth.Contract(artifacts.abi); + lockContract.handleRevert = true; + + const [deployer, otherAccount] = await web3.eth.getAccounts(); + const rawContract = lockContract.deploy({ + data: artifacts.bytecode, + arguments: [unlockTime], + }); + + // To know how much gas will be consumed, we can estimate it first. + const estimateGas = await rawContract.estimateGas({ + from: deployer, + value: lockedAmount.toString(), + }); + + const lock = await rawContract.send({ + from: deployer, + gas: estimateGas.toString(), + gasPrice: '10000000000', + value: lockedAmount.toString(), + }); + + console.log('Lock contract deployed to: ', lock.options.address); + return { lock, unlockTime, lockedAmount, deployer, otherAccount, rawContract }; + } + + describe('Deployment', function () { + it('Should set the right unlockTime', async function () { + const { lock, unlockTime } = await loadFixture(deployOneYearLockFixture); + const setTime = await lock.methods.unlockTime().call(); + console.log('SetTime', setTime); + expect(setTime).to.equal(unlockTime); + }); + + it('Should set the right deployer', async function () { + const { lock, deployer } = await loadFixture(deployOneYearLockFixture); + + expect(await lock.methods.owner().call()).to.equal(deployer); + }); + + it('Should receive and store the funds to lock', async function () { + const { lock, lockedAmount } = await loadFixture(deployOneYearLockFixture); + const balance = await web3.eth.getBalance(String(lock.options.address)); + expect(balance).to.equal(lockedAmount); + }); + + it("Shouldn't fail if the unlockTime has arrived and the deployer calls it", async function () { + const { lock, unlockTime, deployer } = await loadFixture(deployOneYearLockFixture); + + await time.increaseTo(unlockTime); + await expect(lock.methods.withdraw().send({ from: deployer })).not.to.be.reverted; + }); + }); +}); ``` in this file, we performed similar steps as in the deployment script to prepare and deploy the contract using the `ABI` and `bytecode` in `deployOneYearLockFixture()`. To read the `owner` data from the Blockchain, we used an instance of the deployed contract i.e `lock.methods.owner().call().`Invoking `.call()` does not change the state of the blockchain hence no wallet signature is required. @@ -287,13 +283,14 @@ To change the status of the data we previously saved, we have to access the `met When using `.send()`, you must explicitly provide the `sender` of the transaction in the `from` field (in the above example is the address of the `deployer` account). ::: - To run the test you can use the command + ```bash npx hardhat test test/Lock.ts ``` And you'll get a similar result to this: + ```js /* Lock diff --git a/docs/docs/guides/web3_config/index.md b/docs/docs/guides/09_web3_config/index.md similarity index 70% rename from docs/docs/guides/web3_config/index.md rename to docs/docs/guides/09_web3_config/index.md index 32f645a465a..de8a8b9db7c 100644 --- a/docs/docs/guides/web3_config/index.md +++ b/docs/docs/guides/09_web3_config/index.md @@ -1,65 +1,64 @@ --- -sidebar_position: 6 -sidebar_label: 'Web3 Config Guide' +sidebar_position: 9 +sidebar_label: '⚙️ Web3 config' +title: 'Web3.js Config Guide' --- -# Web3.js Config Guide - ## 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: -- [handleRevert](/guides/web3_config/#handlerevert) -- [defaultAccount](/guides/web3_config/#defaultaccount) -- [defaultBlock](/guides/web3_config/#defaultblock) -- [transactionBlockTimeout](/guides/web3_config/#transactionblocktimeout) -- [transactionConfirmationBlocks](/guides/web3_config/#transactionconfirmationblocks) -- [transactionPollingInterval](/guides/web3_config/#transactionpollinginterval) -- [transactionPollingTimeout](/guides/web3_config/#transactionpollingtimeout) -- [transactionReceiptPollingInterval](/guides/web3_config/#transactionreceiptpollinginterval) -- [transactionSendTimeout](/guides/web3_config/#transactionsendtimeout) -- [[Deprecated] transactionConfirmationPollingInterval](/guides/web3_config/#transactionconfirmationpollinginterval) -- [blockHeaderTimeout](/guides/web3_config/#blockheadertimeout) -- [maxListenersWarningThreshold](/guides/web3_config/#maxlistenerswarningthreshold) -- [contractDataInputFill](/guides/web3_config/#contractdatainputfill) -- [defaultNetworkId](/guides/web3_config/#defaultnetworkid) -- [defaultChain](/guides/web3_config/#defaultchain) -- [defaultHardfork](/guides/web3_config/#defaulthardfork) -- [defaultCommon](/guides/web3_config/#defaultcommon) -- [defaultTransactionType](/guides/web3_config/#defaulttransactiontype) -- [defaultMaxPriorityFeePerGas](/guides/web3_config/#defaultmaxpriorityfeepergas) -- [customTransactionSchema](/guides/web3_config/#customTransactionSchema) -- [defaultReturnFormat](/guides/web3_config/#defaultreturnformat) +- [handleRevert](/guides/web3_config/#handlerevert) +- [defaultAccount](/guides/web3_config/#defaultaccount) +- [defaultBlock](/guides/web3_config/#defaultblock) +- [transactionBlockTimeout](/guides/web3_config/#transactionblocktimeout) +- [transactionConfirmationBlocks](/guides/web3_config/#transactionconfirmationblocks) +- [transactionPollingInterval](/guides/web3_config/#transactionpollinginterval) +- [transactionPollingTimeout](/guides/web3_config/#transactionpollingtimeout) +- [transactionReceiptPollingInterval](/guides/web3_config/#transactionreceiptpollinginterval) +- [transactionSendTimeout](/guides/web3_config/#transactionsendtimeout) +- [[Deprecated] transactionConfirmationPollingInterval](/guides/web3_config/#transactionconfirmationpollinginterval) +- [blockHeaderTimeout](/guides/web3_config/#blockheadertimeout) +- [maxListenersWarningThreshold](/guides/web3_config/#maxlistenerswarningthreshold) +- [contractDataInputFill](/guides/web3_config/#contractdatainputfill) +- [defaultNetworkId](/guides/web3_config/#defaultnetworkid) +- [defaultChain](/guides/web3_config/#defaultchain) +- [defaultHardfork](/guides/web3_config/#defaulthardfork) +- [defaultCommon](/guides/web3_config/#defaultcommon) +- [defaultTransactionType](/guides/web3_config/#defaulttransactiontype) +- [defaultMaxPriorityFeePerGas](/guides/web3_config/#defaultmaxpriorityfeepergas) +- [customTransactionSchema](/guides/web3_config/#customTransactionSchema) +- [defaultReturnFormat](/guides/web3_config/#defaultreturnformat) ## Global level Config -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. +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 +```ts import { Web3 } from 'web3'; const web3 = new Web3({ - provider: 'https://mainnet.infura.io/v3/YOURID', - config: { - defaultTransactionType: '0x0', - }, + 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)); + .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. -``` ts +```ts import { Web3, Web3Context } from 'web3'; const context = new Web3Context('http://127.0.0.1:7545'); @@ -68,34 +67,37 @@ context.setConfig({ defaultTransactionType: '0x0' }); const web3 = new Web3(context); //it will not default to 0x0 type transactions -web3.eth.sendTransaction({ - from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', - to: '0x018e221145dE7cefAD09BD53F41c11A918Bf1Cb7', - value: 100, - gasLimit: 21000 -}).then(res => console.log(res)); +web3.eth + .sendTransaction({ + from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', + to: '0x018e221145dE7cefAD09BD53F41c11A918Bf1Cb7', + value: 100, + gasLimit: 21000, + }) + .then(res => console.log(res)); ``` ## Package level config ### Setting config in Individual Package under Web3 instance + Some configuration options that effects selected packages can be modified using `setConfig(...)` function. -``` ts +```ts import { Web3 } from 'web3'; const web3 = new Web3('https://mainnet.infura.io/v3/YOURID'); -web3.eth.setConfig({ defaultTransactionType: '0x0'}); +web3.eth.setConfig({ defaultTransactionType: '0x0' }); web3.eth - .sendTransaction({ - from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', - to: '0xB2f70d8965e754cc07D343a9b5332876D3070155', - value: 100, - gasLimit: 21000, - }) - .then((res) => console.log(res)); + .sendTransaction({ + from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', + to: '0xB2f70d8965e754cc07D343a9b5332876D3070155', + value: 100, + gasLimit: 21000, + }) + .then(res => console.log(res)); ``` ### Setting config in Individually imported Packages @@ -114,20 +116,20 @@ Configuration options can be set by passing in constructor: import { Web3Eth } from 'web3-eth'; const web3EthObj = new Web3Eth({ - provider: 'http://127.0.0.1:7545', - config: { - defaultTransactionType: 0x0, - }, + 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)); + .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. @@ -140,25 +142,25 @@ const web3EthObj = new Web3Eth('http://127.0.0.1:7545'); web3EthObj.setConfig({ defaultTransactionType: 0x0 }); web3EthObj - .sendTransaction({ - from: '0x18532dF2Ab835d4E9D07a8b9B759bf5F8f890f49', - to: '0x018e221145dE7cefAD09BD53F41c11A918Bf1Cb7', - value: 100, - gasLimit: 21000, - }) - .then((res) => console.log(res)); + .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 title='getContextObject() in Web3 object' +```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) +console.log(web3.getContextObject().config); /* ↳ handleRevert: false, defaultAccount: undefined, @@ -190,7 +192,7 @@ import { Web3Eth } from 'web3'; const web3 = new Web3Eth('http://127.0.0.1:7545'); -console.log(web3.getContextObject().config) +console.log(web3.getContextObject().config); /* ↳ handleRevert: false, defaultAccount: undefined, @@ -206,65 +208,76 @@ console.log(web3.getContextObject().config) ## Explanation of Configuration Parameters ### [handleRevert](/api/web3-core/class/Web3Config#handleRevert) + The following methods will retrieve specific error types and error messages when `handleRevert` is set to `true`: -- [`web3.eth.sendTransaction()`](/api/web3-eth/function/sendTransaction); -- [`myContract.methods.myMethod().send()`](/libdocs/Contract#send); + +- [`web3.eth.sendTransaction()`](/api/web3-eth/function/sendTransaction); +- [`myContract.methods.myMethod().send()`](/libdocs/Contract#send); The error type will be one of the following: -- [InvalidResponseError](/api/web3-errors/class/InvalidResponseError) -- [ContractExecutionError](/api/web3-errors/class/ContractExecutionError) -- [TransactionRevertWithCustomError](/api/web3-errors/class/TransactionRevertWithCustomError) -- [TransactionRevertedWithoutReasonError](/api/web3-errors/class/TransactionRevertedWithoutReasonError) -- [TransactionRevertInstructionError](/api/web3-errors/class/TransactionRevertInstructionError) -- [TransactionPollingTimeoutError](/api/web3-errors/class/TransactionPollingTimeoutError) + +- [InvalidResponseError](/api/web3-errors/class/InvalidResponseError) +- [ContractExecutionError](/api/web3-errors/class/ContractExecutionError) +- [TransactionRevertWithCustomError](/api/web3-errors/class/TransactionRevertWithCustomError) +- [TransactionRevertedWithoutReasonError](/api/web3-errors/class/TransactionRevertedWithoutReasonError) +- [TransactionRevertInstructionError](/api/web3-errors/class/TransactionRevertInstructionError) +- [TransactionPollingTimeoutError](/api/web3-errors/class/TransactionPollingTimeoutError) For example, the error message could be `TransactionRevertInstructionError('Returned error: invalid argument 0: json: cannot unmarshal invalid hex string into Go struct field TransactionArgs.data of type hexutil.Bytes')`. The `handleRevert` option is only supported for [`sendTransaction`](/api/web3-eth/function/sendTransaction) and not for [`sendSignedTransaction`](/api/web3-eth/function/sendSignedTransaction) for now. The default value of `handleRevert` is `false`. ### [defaultAccount](/api/web3-core/class/Web3Config#defaultAccount) + The `defaultAccount` option is used as the default `from` property, if no `from` property is specified for the following methods: -- [`web3.eth.sendTransaction()`](/api/web3-eth/function/sendTransaction); -- [`web3.eth.call()`](/api/web3-eth/function/call); -- [`myContract.methods.myMethod().call()`](/libdocs/Contract#call); -- [`myContract.methods.myMethod().send()`](/libdocs/Contract#send); + +- [`web3.eth.sendTransaction()`](/api/web3-eth/function/sendTransaction); +- [`web3.eth.call()`](/api/web3-eth/function/call); +- [`myContract.methods.myMethod().call()`](/libdocs/Contract#call); +- [`myContract.methods.myMethod().send()`](/libdocs/Contract#send); The default value of `defaultAccount` is `undefined`. ### [defaultBlock](/api/web3-core/class/Web3Config#defaultBlock) -The following methods accept an optional `blockNumber` parameter, the `defaultBlock` option is used for these methods if no `blockNumber` parameter is provided. -- [`web3.eth.getBalance()`](/api/web3-eth/function/getBalance); -- [`web3.eth.getCode()`](/api/web3-eth/function/getCode); -- [`web3.eth.getTransactionCount()`](/api/web3-eth/function/getTransactionCount); -- [`web3.eth.getStorageAt()`](/api/web3-eth/function/getStorageAt); -- [`web3.eth.call()`](/api/web3-eth/function/call); -- [`myContract.methods.myMethod().call()`](/libdocs/Contract#call); + +The following methods accept an optional `blockNumber` parameter, the `defaultBlock` option is used for these methods if no `blockNumber` parameter is provided. + +- [`web3.eth.getBalance()`](/api/web3-eth/function/getBalance); +- [`web3.eth.getCode()`](/api/web3-eth/function/getCode); +- [`web3.eth.getTransactionCount()`](/api/web3-eth/function/getTransactionCount); +- [`web3.eth.getStorageAt()`](/api/web3-eth/function/getStorageAt); +- [`web3.eth.call()`](/api/web3-eth/function/call); +- [`myContract.methods.myMethod().call()`](/libdocs/Contract#call); If a `blockNumber` parameter is provided to one of the above function calls, it will override this option. The default value of `defaultBlock` is "latest". #### All available choices for defaultBlock: + ```ts web3.defaultBlock = 20167235; // A block number -web3.defaultBlock = "earliest"; // The genesis block -web3.defaultBlock = "latest"; // The latest block (current head of the blockchain) -web3.defaultBlock = "pending"; // The block pending to be mined (including pending transactions) -web3.defaultBlock = "finalized"; // (For POS networks) The finalized block is one which has been accepted as canonical by greater than 2/3 of validators -web3.defaultBlock = "safe"; // (For POS networks) The safe head block is one which under normal network conditions, is expected to be included in the canonical chain. Under normal network conditions the safe head and the actual tip of the chain will be equivalent (with safe head trailing only by a few seconds). Safe heads will be less likely to be reorged than the proof of work network`s latest blocks. +web3.defaultBlock = 'earliest'; // The genesis block +web3.defaultBlock = 'latest'; // The latest block (current head of the blockchain) +web3.defaultBlock = 'pending'; // The block pending to be mined (including pending transactions) +web3.defaultBlock = 'finalized'; // (For POS networks) The finalized block is one which has been accepted as canonical by greater than 2/3 of validators +web3.defaultBlock = 'safe'; // (For POS networks) The safe head block is one which under normal network conditions, is expected to be included in the canonical chain. Under normal network conditions the safe head and the actual tip of the chain will be equivalent (with safe head trailing only by a few seconds). Safe heads will be less likely to be reorged than the proof of work network`s latest blocks. ``` ### [transactionBlockTimeout](/api/web3-core/class/Web3Config#transactionBlockTimeout) - This option defines the number of new blocks to wait for the **first confirmation**, otherwise the [`PromiEvent`](/api/web3/class/Web3PromiEvent) rejects with a timeout error. -The default value of `transactionBlockTimeout` is 50. +This option defines the number of new blocks to wait for the **first confirmation**, otherwise the [`PromiEvent`](/api/web3/class/Web3PromiEvent) rejects with a timeout error. + +The default value of `transactionBlockTimeout` is 50. ### [transactionConfirmationBlocks](/api/web3-core/class/Web3Config#transactionConfirmationBlocks) + This defines the number of blocks required for a transaction to be considered confirmed. Different chains have varying security considerations and requirements for confirmation block numbers. The default value of `transactionConfirmationBlocks` is 24. ### [transactionPollingInterval](/api/web3-core/class/Web3Config#transactionPollingInterval) + This option defines the number of seconds between Web3 calls for a receipt which confirms that a transaction was mined by the network. Modifying this value can reduce the wait time for confirmations or decrease the number of network requests. Setting the `transactionPollingInterval` would also set [`transactionReceiptPollingInterval`](/guides/web3_config/#transactionreceiptpollinginterval) and [`transactionConfirmationPollingInterval`](/guides/web3_config/#transactionconfirmationpollinginterval) to the same value. The default value of `transactionPollingInterval` is 1000 ms. @@ -289,95 +302,109 @@ console.log(web3.getContextObject().config); ``` ### [transactionPollingTimeout](/api/web3-core/class/Web3Config#transactionPollingTimeout) + This option defines the number of seconds Web3 will wait for a receipt which confirms that a transaction was mined by the network. It can be set based on the average transaction confirmation time on the network. Note: If the `transactionPollingTimeout` is exceeded, the transaction may still be pending. The default value of `transactionPollingTimeout` is 750 seconds (12.5 minutes). ### [transactionReceiptPollingInterval](/api/web3-core/class/Web3Config#transactionReceiptPollingInterval) + This option defines the number of seconds between Web3 calls for a receipt which confirms that a transaction was mined by the network. Compared to [`transactionPollingInterval`](/guides/web3_config/#transactionpollinginterval), it takes higher precedence. When this value is set, it will be read first. The default value of `transactionReceiptPollingInterval` is `undefined`. ### [transactionSendTimeout](/api/web3-core/class/Web3Config#transactionSendTimeout) + The `transactionSendTimeout` option is used to specify how long to wait for the network to return the sent transaction result. Note: If the RPC call times out, the transaction may still be pending or even mined by the network. It is recommended that the pending transactions be checked in such a case. The default value of `transactionSendTimeout` is 750 seconds (12.5 minutes). ### [transactionConfirmationPollingInterval](/api/web3-core/class/Web3Config#transactionConfirmationPollingInterval) + The `transactionConfirmationPollingInterval` option is deprecated. Please use [`transactionReceiptPollingInterval`](/guides/web3_config/#transactionreceiptpollinginterval) or [`transactionPollingInterval`](/guides/web3_config/#transactionpollinginterval) instead. ### [blockHeaderTimeout](/api/web3-core/class/Web3Config#blockHeaderTimeout) + After sending a transaction, Web3 will listen for the appearance of new blocks and proceed with subsequent operations based on the transaction results within them. This option defines the number of seconds Web3 should wait for the appearance of new blocks before reverting to polling to fetch the transaction receipt. The default value of `blockHeaderTimeout` is 10 seconds. ### [maxListenersWarningThreshold](/api/web3-core/class/Web3Config#maxListenersWarningThreshold) + The `maxListenersWarningThreshold` is used to set the `maxListeners` property in [`EventEmitter`](/api/web3-utils/class/EventEmitter). The default value of `maxListenersWarningThreshold` is 100. ### [contractDataInputFill](/api/web3-core/class/Web3Config#contractDataInputFill) + The `contractDataInputFill` option allows users to specify whether the [`data`](/api/web3/namespace/types#data) or [`input`](/api/web3/namespace/types#input) property (or both properties) should be set to the hash of the method signature and encoded parameters. This will affect the contracts [`send`](/libdocs/Contract#send), [`call`](/libdocs/Contract#call) and [`estimateGas`](/libdocs/Contract#estimategas) methods. The default value of `contractDataInputFill` is `data`. #### All available choices for contractDataInputFill: + ```ts -'data' -'input' -'both' +'data'; +'input'; +'both'; ``` ### [defaultNetworkId](/api/web3-core/class/Web3Config#defaultNetworkId) + Each network has its own [network ID](https://docs.goquorum.consensys.io/concepts/network-and-chain-id). The `defaultNetworkId` option allows users to set the default network ID. If this option is not set, Web3 will fetch the network ID with an RPC request. The default value of `defaultNetworkId` is `undefined`. ### [defaultChain](/api/web3-core/class/Web3Config#defaultChain) + The `defaultChain` option is used to set the [`Common`](/api/web3-eth-contract/class/Contract#defaultCommon) `baseChain` property. The value of this option should be consistent with [`defaultCommon.baseChain`](/guides/web3_config/#defaultcommon) if both options are set. The default value of `defaultChain` is `mainnet`. #### All available choices for defaultChain: + ```ts -'goerli' -'kovan' -'mainnet' -'rinkeby' -'ropsten' -'sepolia' +'goerli'; +'kovan'; +'mainnet'; +'rinkeby'; +'ropsten'; +'sepolia'; ``` ### [defaultHardfork](/api/web3-core/class/Web3Config#defaultHardfork) + The `defaultHardfork` option is used to set the [`Common`](/api/web3-eth-contract/class/Contract#defaultCommon) `hardfork` property. The value of this option should be consistent with [`defaultCommon.hardfork`](/guides/web3_config/#defaultcommon) if both options are set. The default value of `defaultHardfork` is `london`. #### All available choices for defaultHardFork: + ```ts -'chainstart' -'frontier' -'homestead' -'dao' -'tangerineWhistle' -'spuriousDragon' -'byzantium' -'constantinople' -'petersburg' -'istanbul' -'muirGlacier' -'berlin' -'london' -'altair' -'arrowGlacier' -'grayGlacier' -'bellatrix' -'merge' -'capella' -'sharding' +'chainstart'; +'frontier'; +'homestead'; +'dao'; +'tangerineWhistle'; +'spuriousDragon'; +'byzantium'; +'constantinople'; +'petersburg'; +'istanbul'; +'muirGlacier'; +'berlin'; +'london'; +'altair'; +'arrowGlacier'; +'grayGlacier'; +'bellatrix'; +'merge'; +'capella'; +'sharding'; ``` ### [defaultCommon](/api/web3-core/class/Web3Config#defaultCommon) + The `defaultCommon` option is used to set the [`defaultCommon`](/libdocs/Contract#defaultcommon) value for smart contract transactions. It should be consistent with the [`defaultHardfork`](/guides/web3_config/#defaulthardfork) and [`defaultChain`](/guides/web3_config/#defaultchain) options if they are set. The default value of `defaultCommon` is `undefined`. @@ -387,59 +414,66 @@ import { Web3, Hardfork } from 'web3'; const web3 = new Web3('http://127.0.0.1:7545'); -web3.defaultHardfork = 'berlin' -web3.defaultChain = 'goerli' +web3.defaultHardfork = 'berlin'; +web3.defaultChain = 'goerli'; web3.defaultCommon = { - baseChain: 'goerli', - hardfork: 'berlin' as Hardfork, - customChain: { - networkId: 1, - chainId: 1, - }, + baseChain: 'goerli', + hardfork: 'berlin' as Hardfork, + customChain: { + networkId: 1, + chainId: 1, + }, }; console.log(web3.getContextObject().config); ``` ### [defaultTransactionType](/api/web3-core/class/Web3Config#defaultTransactionType) + The `defaultTransactionType` option is used to set the transaction type. Transactions with type 0x0 are legacy transactions that use the transaction format that existed before [typed transactions](https://ethereum.org/en/developers/docs/transactions/#typed-transaction-envelope) were introduced in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). Transactions with type 0x1 are transactions introduced in [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930). Transactions with type 0x2 are transactions introduced in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559), included in Ethereum's London fork. The default value of `defaultTransactionType` is `0x02`. ### [defaultMaxPriorityFeePerGas](/api/web3-core/class/Web3Config#defaultMaxPriorityFeePerGas) + The `defaultMaxPriorityFeePerGas` option is used to set the [`defaultMaxPriorityFeePerGas`](/api/web3-eth-contract/class/Contract#defaultMaxPriorityFeePerGas) value for [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) smart contract transactions ([transaction type](#defaulttransactiontype) 0x2). The default value of `defaultMaxPriorityFeePerGas` is 2500000000 (2.5gwei) in hexstring format. ### [customTransactionSchema](/api/web3-core/class/Web3Config#customTransactionSchema) + The `customTransactionSchema` option is used to allow [`formatTransaction`](/api/web3-eth/function/formatTransaction) to accept a custom schema to validate transactions. A use-case could be: your chain has an extra field in its transactions and you want to write a plugin that makes sending these transactions easier. ### [defaultReturnFormat](/api/web3-core/class/Web3Config#defaultReturnFormat) + The `defaultReturnFormat` option allows users to specify the format in which certain types of data should be returned by default. It is a configuration parameter that can be set at the global level and affects how data is returned across the entire library. + ```ts import { Web3, FMT_NUMBER, FMT_BYTES } from 'web3'; web3.defaultReturnFormat = { - number: FMT_NUMBER.BIGINT, - bytes: FMT_BYTES.HEX, + number: FMT_NUMBER.BIGINT, + bytes: FMT_BYTES.HEX, }; - ``` #### All available choices for numeric data: -```ts + +```ts export enum FMT_NUMBER { - NUMBER = 'NUMBER_NUMBER', - HEX = 'NUMBER_HEX', - STR = 'NUMBER_STR', - BIGINT = 'NUMBER_BIGINT', -}; + NUMBER = 'NUMBER_NUMBER', + HEX = 'NUMBER_HEX', + STR = 'NUMBER_STR', + BIGINT = 'NUMBER_BIGINT', +} ``` -#### All available choices for bytes data: + +#### All available choices for bytes data: + ```ts export enum FMT_BYTES { - HEX = 'BYTES_HEX', - UINT8ARRAY = 'BYTES_UINT8ARRAY', -}; + HEX = 'BYTES_HEX', + UINT8ARRAY = 'BYTES_UINT8ARRAY', +} ``` diff --git a/docs/docs/guides/web3_eth/_category_.yml b/docs/docs/guides/10_web3_eth/_category_.yml similarity index 85% rename from docs/docs/guides/web3_eth/_category_.yml rename to docs/docs/guides/10_web3_eth/_category_.yml index 197604038d5..10c784c3350 100644 --- a/docs/docs/guides/web3_eth/_category_.yml +++ b/docs/docs/guides/10_web3_eth/_category_.yml @@ -2,4 +2,4 @@ label: '📦 Web3 Eth module' collapsible: true collapsed: true link: null -position: 8 \ No newline at end of file +position: 10 diff --git a/docs/docs/guides/web3_eth/eth.md b/docs/docs/guides/10_web3_eth/eth.md similarity index 66% rename from docs/docs/guides/web3_eth/eth.md rename to docs/docs/guides/10_web3_eth/eth.md index 5db4eef6919..5b97adea208 100644 --- a/docs/docs/guides/web3_eth/eth.md +++ b/docs/docs/guides/10_web3_eth/eth.md @@ -33,7 +33,7 @@ Before we start writing and deploying our contract, we need to set up our enviro 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 +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/) @@ -118,43 +118,43 @@ 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); + //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(); + await interact(); })(); ``` @@ -217,56 +217,56 @@ In the next example, we are going to use `estimateGas` function to see the expec 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); + // 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(); + await estimate(); })(); ``` @@ -298,29 +298,29 @@ const privateKey = '0x0fed6f64e01bc9fac9587b6e7245fd9d056c3c004ad546a17d3d029977 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); + 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(); + await sendSigned(); })(); ``` @@ -419,43 +419,43 @@ 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 - // } + 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(); + await test(); })(); ``` @@ -476,48 +476,48 @@ EIP-2930 is part of Ethereum's ongoing efforts to improve the network's efficien To send EIP-2930 transaction use code below: ```typescript -import {Web3} from 'web3'; +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 - // } + 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(); + await test(); })(); ``` @@ -528,78 +528,78 @@ The code of `Greeter` contract you can find [here](https://github.com/web3/web3. ::: ```typescript -import {Web3} from 'web3'; +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 - // } + 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(); + await test(); })(); ``` @@ -631,44 +631,44 @@ 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 - // } + 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(); + await test(); })(); ``` @@ -699,4 +699,3 @@ The Ethereum ecosystem is constantly evolving, and there is always more to learn - 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/10_web3_eth/methods.md similarity index 97% rename from docs/docs/guides/web3_eth/methods.md rename to docs/docs/guides/10_web3_eth/methods.md index cc0f2f21df0..1a147916d48 100644 --- a/docs/docs/guides/web3_eth/methods.md +++ b/docs/docs/guides/10_web3_eth/methods.md @@ -7,7 +7,6 @@ sidebar_label: '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. @@ -100,7 +99,7 @@ The [sendTransaction](/api/web3-eth/function/sendTransaction) method is used to :::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. +[Here](/guides/transactions/transactions) you can find more examples how to send transaction. ::: ## sign @@ -116,5 +115,5 @@ The [signTransaction](/api/web3-eth/function/signTransaction) method is used to 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 +[Here](/guides/transactions/transactions) you can find more examples how to send transaction. +::: diff --git a/docs/docs/guides/ens/index.md b/docs/docs/guides/11_ens/index.md similarity index 94% rename from docs/docs/guides/ens/index.md rename to docs/docs/guides/11_ens/index.md index a55f9662799..a98e899ad3a 100644 --- a/docs/docs/guides/ens/index.md +++ b/docs/docs/guides/11_ens/index.md @@ -1,14 +1,12 @@ --- -sidebar_position: 8 -sidebar_label: 'Mastering the Web3 ENS package' +sidebar_label: '📦 Web3 ENS module' title: Mastering the Web3 ENS package +position: 11 --- -# Using web3.js ENS Package - -In this tutorial, we'll explore how to use the web3.js ENS (Ethereum Name Service) package. The Ethereum Name Service (ENS) is a decentralized domain system built on the Ethereum blockchain. It serves as a distributed, secure, and human-readable naming system designed to map Ethereum addresses, smart contracts, and various other services to easily understandable names. +In this tutorial, we'll explore how to use the web3.js ENS (Ethereum Name Service) package. The Ethereum Name Service (ENS) is a decentralized domain system built on the Ethereum blockchain. It serves as a distributed, secure, and human-readable naming system designed to map Ethereum addresses, smart contracts, and various other services to easily understandable names. ## Installing web3.js @@ -30,7 +28,6 @@ const web3 = new Web3('http://localhost:8545'); // You can use ENS with web3 object: const ens = await web3.eth.ens.getAddress('alice.eth'); - ``` ## Installing web3.js ENS @@ -44,10 +41,9 @@ npm install web3-eth-ens ```typescript import { ENS } from 'web3-eth-ens'; -const ens = new ENS(undefined,'https://127.0.0.1:4545'); +const ens = new ENS(undefined, 'https://127.0.0.1:4545'); console.log(await ens.getAddress('vitalik.eth')); - ``` ## ENS Examples diff --git a/docs/docs/guides/web3_utils_module/mastering_web3-utils.md b/docs/docs/guides/12_web3_utils_module/index.md similarity index 62% rename from docs/docs/guides/web3_utils_module/mastering_web3-utils.md rename to docs/docs/guides/12_web3_utils_module/index.md index b60d2a50deb..8a55f7bfe85 100644 --- a/docs/docs/guides/web3_utils_module/mastering_web3-utils.md +++ b/docs/docs/guides/12_web3_utils_module/index.md @@ -1,12 +1,18 @@ -# Mastering Utility Functions +--- +sidebar_label: '📦 Web3 Utils module' +title: Mastering Utility Functions +position: 12 +--- ## Introduction + In this guide, you'll learn about the different functions of the web3 utils package, it contains the methods to know how to generate random bytes in different formats, how to perform conversion between Hex values and numbers, hashing functions, addresses, packing padding and in the last part you will see how to compare block numbers. ## Installation Install only the web3 package + ```bash npm i web3-utils ``` @@ -25,41 +31,40 @@ There are three different ways to import utils package. ```js // import web3 module -import { Web3 } from "web3"; +import { Web3 } from 'web3'; // no need to initialize a provider -Web3.utils.toHex("web3"); +Web3.utils.toHex('web3'); //=> 0x77656233 // initializing a provider -const web3 = new Web3("https:// eth.llamarpc.com"); +const web3 = new Web3('https:// eth.llamarpc.com'); // access the utils package -web3.utils.toHex("web3"); +web3.utils.toHex('web3'); //=> 0x77656233 ``` - ### Import utils module -```js +```js // import utils module -import { utils } from "web3"; +import { utils } from 'web3'; // access the utils package -utils.toWei("1", "ether") +utils.toWei('1', 'ether'); ``` ### Import specific methods ```js // import toWei and toHex functions -import { toWei, toHex } from"web3-utils"; +import { toWei, toHex } from 'web3-utils'; // usage -toWei("1", "ether") -toHex("") -``` +toWei('1', 'ether'); +toHex(''); +``` ## Methods example @@ -82,8 +87,8 @@ console.log(web3.utils.randomHex(32)); /* => hex string format 0x594386dc9b2e150979416f9b2a093e01f84a37c4f8db5fc1b0d9b1dc83a12c1f */ - ``` + :::info If you don't give any arguments then both of these functions will have a default value as 32. ::: @@ -93,10 +98,10 @@ If you don't give any arguments then both of these functions will have a default We've got two different functions to perform conversions between Ethereum denominations. ```js -console.log(web3.utils.fromWei("1", "ether")); +console.log(web3.utils.fromWei('1', 'ether')); // 0.000000000000000001 -console.log(web3.utils.toWei("1", "ether")); +console.log(web3.utils.toWei('1', 'ether')); // 1_000_000_000_000_000_000 ``` @@ -128,48 +133,48 @@ console.log(web3.utils.bytesToHex(arr)); ### Conversions UTF and ASCII ```js -console.log(web3.utils.utf8ToHex("😊")); +console.log(web3.utils.utf8ToHex('😊')); // 0xf09f988a -console.log(web3.utils.fromUtf8("😊")); +console.log(web3.utils.fromUtf8('😊')); // 0xf09f988a -console.log(web3.utils.asciiToHex("😊")); +console.log(web3.utils.asciiToHex('😊')); // 0xd83dde0a -console.log(web3.utils.toUtf8("0xf09f988a")); +console.log(web3.utils.toUtf8('0xf09f988a')); // 😊 -console.log(web3.utils.hexToUtf8("0xf09f988a")); +console.log(web3.utils.hexToUtf8('0xf09f988a')); // 😊 -console.log(web3.utils.hexToString("0xf09f988a")); +console.log(web3.utils.hexToString('0xf09f988a')); // 😊 // emojis are not ASCII character, that's why it won't work -console.log(web3.utils.toAscii("0x4869")); +console.log(web3.utils.toAscii('0x4869')); // Hi -console.log(web3.utils.hexToAscii("0x4869")); +console.log(web3.utils.hexToAscii('0x4869')); // Hi ``` ### Conversions - Numbers and Bigint ```js -console.log(web3.utils.toNumber("0xa")); +console.log(web3.utils.toNumber('0xa')); // 10 (number) -console.log(web3.utils.hexToNumber("0xa")); +console.log(web3.utils.hexToNumber('0xa')); // 10 (number) -console.log(web3.utils.toDecimal("0xa")); +console.log(web3.utils.toDecimal('0xa')); // 10 (number) -console.log(web3.utils.hexToNumberString("0xa")); +console.log(web3.utils.hexToNumberString('0xa')); // 10 (string) -console.log(web3.utils.toBigInt("0xa")); +console.log(web3.utils.toBigInt('0xa')); // 10n (bigint) ``` @@ -177,10 +182,10 @@ console.log(web3.utils.toBigInt("0xa")); ```js // both will return undefined if an empty string is passed as an argument -console.log(web3.utils.sha3("hello web3")); +console.log(web3.utils.sha3('hello web3')); // 0x6c171485a0138b7b0a49d72b570e1d9c589d42a79ae57329d90671d1ac702d74 -console.log(web3.utils.soliditySha3({ type: "string", value: "hello web3" })); +console.log(web3.utils.soliditySha3({ type: 'string', value: 'hello web3' })); // 0x6c171485a0138b7b0a49d72b570e1d9c589d42a79ae57329d90671d1ac702d74 ``` @@ -191,11 +196,11 @@ console.log(web3.utils.soliditySha3({ type: "string", value: "hello web3" })); // to see if the hex string we are passing is a correct ethereum address // passing an address with all characters lowercase -console.log(web3.utils.toChecksumAddress("0xa3286628134bad128faeef82f44e99aa64085c94")); +console.log(web3.utils.toChecksumAddress('0xa3286628134bad128faeef82f44e99aa64085c94')); // 0xA3286628134baD128faeef82F44e99AA64085C94 // passing an wrong address -console.log(web3.utils.toChecksumAddress("0xa3286628134bad128faeef82f44e99aa64085c9")); +console.log(web3.utils.toChecksumAddress('0xa3286628134bad128faeef82f44e99aa64085c9')); // InvalidAddressError: Invalid value given "0xa286628134bad128faeef82f44e99aa64085c94". Error: invalid ethereum address. ``` @@ -204,10 +209,9 @@ console.log(web3.utils.toChecksumAddress("0xa3286628134bad128faeef82f44e99aa6408 ```js // same as abi.encodePacked() in solidity (must be strings) // converts everything to hex and packs everything without padding -console.log(web3.utils.encodePacked("1", "1", "1")); +console.log(web3.utils.encodePacked('1', '1', '1')); // 0x313131 - // it will convert the number `10` to hex('a') and add 0s until it's 32 characters long // the third argument will be the one that will fill/pad the whole hex string, in this case is '0' console.log(web3.utils.padRight(10, 32, 0)); @@ -227,13 +231,13 @@ console.log(web3.utils.leftPad(10, 32, 0)); ```js // accepts numbers and formats as well -console.log(web3.utils.compareBlockNumbers("pending", "latest")); +console.log(web3.utils.compareBlockNumbers('pending', 'latest')); // 1 -console.log(web3.utils.compareBlockNumbers("latest", "pending")); +console.log(web3.utils.compareBlockNumbers('latest', 'pending')); // -1 -console.log(web3.utils.compareBlockNumbers("latest", "latest")); +console.log(web3.utils.compareBlockNumbers('latest', 'latest')); // 0 console.log(web3.utils.compareBlockNumbers(2, 2)); @@ -247,50 +251,50 @@ The [`format` function](/api/web3-utils/function/format) in the `web3-utils` pac Here are some example that demonstrate the use of the `format` function: ```js -import { format } from "web3-utils"; -import { FMT_BYTES, FMT_NUMBER } from "web3-types"; +import { format } from 'web3-utils'; +import { FMT_BYTES, FMT_NUMBER } from 'web3-types'; // format a primitive number as a hexidecimal string -console.log(format({ format: "uint" }, 221, { number: FMT_NUMBER.HEX })); +console.log(format({ format: 'uint' }, 221, { number: FMT_NUMBER.HEX })); // ↳ 0xdd // format a primitive number as a BigInt -console.log(format({ format: "uint" }, 221, { number: FMT_NUMBER.BIGINT })); +console.log(format({ format: 'uint' }, 221, { number: FMT_NUMBER.BIGINT })); // ↳ 221n // format a stringified number as a hexidecimal string -console.log(format({ format: "uint" }, "221", { number: FMT_NUMBER.HEX })); +console.log(format({ format: 'uint' }, '221', { number: FMT_NUMBER.HEX })); // ↳ 0xdd // format a Uint8Array of bytes as a hexidecimal string console.log( - format({ format: "bytes" }, new Uint8Array([2, 33]), { - bytes: FMT_BYTES.HEX, - }), + format({ format: 'bytes' }, new Uint8Array([2, 33]), { + bytes: FMT_BYTES.HEX, + }), ); // ↳ 0x0221 // format an array of values console.log( - format({ type: "array", items: { format: "uint" } }, ["221", 1983], { - number: FMT_NUMBER.HEX, - }), + format({ type: 'array', items: { format: 'uint' } }, ['221', 1983], { + number: FMT_NUMBER.HEX, + }), ); // ↳ [ '0xdd', '0x7bf' ] // format an object with multiple properties console.log( - format( - { - type: "object", - properties: { - aNumber: { format: "uint" }, - someBytes: { format: "bytes" }, - }, - }, - { aNumber: "221", someBytes: new Uint8Array([2, 33]) }, - { bytes: FMT_BYTES.UINT8ARRAY, number: FMT_NUMBER.HEX }, - ), + format( + { + type: 'object', + properties: { + aNumber: { format: 'uint' }, + someBytes: { format: 'bytes' }, + }, + }, + { aNumber: '221', someBytes: new Uint8Array([2, 33]) }, + { bytes: FMT_BYTES.UINT8ARRAY, number: FMT_NUMBER.HEX }, + ), ); // ↳ { aNumber: '0xdd', someBytes: Uint8Array(2) [ 2, 33 ] } ``` @@ -299,11 +303,11 @@ console.log( The following return formats are supported: -- Bytes - - [`FMT_BYTES.HEX`](/api/web3-types/enum/FMT_BYTES#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) - - [`FMT_BYTES.UINT8ARRAY`](/api/web3-types/enum/FMT_BYTES#UINT8ARRAY): [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) (e.g. `[ 2, 33 ]`) -- Numbers - - [`FMT_NUMBER.BIGINT`](/api/web3-types/enum/FMT_NUMBER#BIGINT): [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (e.g. `221n`) - - [`FMT_NUMBER.HEX`](/api/web3-types/enum/FMT_NUMBER#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) - - [`FMT_NUMBER.NUMBER`](/api/web3-types/enum/FMT_NUMBER#NUMBER): [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) (e.g. `221`) - - [`FMT_NUMBER.STR`](/api/web3-types/enum/FMT_NUMBER#STR): [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"221"`) +- Bytes + - [`FMT_BYTES.HEX`](/api/web3-types/enum/FMT_BYTES#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + - [`FMT_BYTES.UINT8ARRAY`](/api/web3-types/enum/FMT_BYTES#UINT8ARRAY): [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) (e.g. `[ 2, 33 ]`) +- Numbers + - [`FMT_NUMBER.BIGINT`](/api/web3-types/enum/FMT_NUMBER#BIGINT): [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (e.g. `221n`) + - [`FMT_NUMBER.HEX`](/api/web3-types/enum/FMT_NUMBER#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) + - [`FMT_NUMBER.NUMBER`](/api/web3-types/enum/FMT_NUMBER#NUMBER): [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) (e.g. `221`) + - [`FMT_NUMBER.STR`](/api/web3-types/enum/FMT_NUMBER#STR): [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"221"`) diff --git a/docs/docs/guides/advanced/_category_.yml b/docs/docs/guides/13_advanced/_category_.yml similarity index 83% rename from docs/docs/guides/advanced/_category_.yml rename to docs/docs/guides/13_advanced/_category_.yml index c6ab4f48016..f427d428cc2 100644 --- a/docs/docs/guides/advanced/_category_.yml +++ b/docs/docs/guides/13_advanced/_category_.yml @@ -2,4 +2,4 @@ label: '🧠 Advanced' collapsible: true collapsed: true link: null -position: 11 +position: 13 diff --git a/docs/docs/guides/advanced/custom_RPC.md b/docs/docs/guides/13_advanced/custom_RPC.md similarity index 100% rename from docs/docs/guides/advanced/custom_RPC.md rename to docs/docs/guides/13_advanced/custom_RPC.md diff --git a/docs/docs/guides/advanced/extend.md b/docs/docs/guides/13_advanced/extend.md similarity index 100% rename from docs/docs/guides/advanced/extend.md rename to docs/docs/guides/13_advanced/extend.md diff --git a/docs/docs/guides/advanced/tree_shaking.md b/docs/docs/guides/13_advanced/tree_shaking.md similarity index 100% rename from docs/docs/guides/advanced/tree_shaking.md rename to docs/docs/guides/13_advanced/tree_shaking.md diff --git a/docs/docs/guides/web3_plugin_guide/_category_.yml b/docs/docs/guides/14_web3_plugin_guide/_category_.yml similarity index 85% rename from docs/docs/guides/web3_plugin_guide/_category_.yml rename to docs/docs/guides/14_web3_plugin_guide/_category_.yml index 8ab333571fd..8f57d7b3e6f 100644 --- a/docs/docs/guides/web3_plugin_guide/_category_.yml +++ b/docs/docs/guides/14_web3_plugin_guide/_category_.yml @@ -2,4 +2,4 @@ label: '🛠️ Web3 Plugin 🧩' collapsible: true collapsed: true link: null -position: 12 +position: 14 diff --git a/docs/docs/guides/web3_plugin_guide/assets/web3_context_augmentation.png b/docs/docs/guides/14_web3_plugin_guide/assets/web3_context_augmentation.png similarity index 100% rename from docs/docs/guides/web3_plugin_guide/assets/web3_context_augmentation.png rename to docs/docs/guides/14_web3_plugin_guide/assets/web3_context_augmentation.png diff --git a/docs/docs/guides/web3_plugin_guide/index.mdx b/docs/docs/guides/14_web3_plugin_guide/index.mdx similarity index 99% rename from docs/docs/guides/web3_plugin_guide/index.mdx rename to docs/docs/guides/14_web3_plugin_guide/index.mdx index ef1942c53fc..52f826601a7 100644 --- a/docs/docs/guides/web3_plugin_guide/index.mdx +++ b/docs/docs/guides/14_web3_plugin_guide/index.mdx @@ -277,7 +277,7 @@ class MyPlugin extends Web3PluginBase { } ``` :::info -All web3 config params [here](https://docs.web3js.org/guides/web3_config/) +All web3 config params [here](https://docs.web3js.org/guides/web3_config/index) ::: diff --git a/docs/docs/guides/web3_plugin_guide/plugin_authors.md b/docs/docs/guides/14_web3_plugin_guide/plugin_authors.md similarity index 82% rename from docs/docs/guides/web3_plugin_guide/plugin_authors.md rename to docs/docs/guides/14_web3_plugin_guide/plugin_authors.md index 4100882e67f..5a01ceed8de 100644 --- a/docs/docs/guides/web3_plugin_guide/plugin_authors.md +++ b/docs/docs/guides/14_web3_plugin_guide/plugin_authors.md @@ -19,7 +19,7 @@ To provide type safety and IntelliSense for your plugin users, please refer to t At the minimum, your plugin should depend on `web3` package version `4.0.2`. This will allow your plugin class to extend the provided `Web3PluginBase` abstract class. However, `web3` shouldn't be listed as a regular dependency, instead it should be listed in your plugin's `package.json` as a [peer dependency](https://nodejs.org/en/blog/npm/peer-dependencies/). :::important -It is important to note that the plugin name should be structured as `@/web3-plugin-` or `web3-plugin-`. +It is important to note that the plugin name should be structured as `@/web3-plugin-` or `web3-plugin-`. ::: ```json @@ -38,24 +38,23 @@ When your users install your plugin, this will allow the package manager to make Furthermore, you have the flexibility to expand your range of transaction types, enhancing compatibility with the `web3.js` library. - ```typescript // create new TransactionType class which extends BaseTransaction class 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 +89,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 +119,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 +160,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,32 +189,39 @@ 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, + ); + } } ``` @@ -243,24 +249,22 @@ Request middleware allows plugins to modify RPC requests before they are sent to ```ts export class RequestMiddleware implements RequestManagerMiddleware { - public async processRequest( - request: JsonRpcPayload - ): Promise> { - const reqObj = { ...request } as JsonRpcPayload; - console.log("Request:", reqObj); - return Promise.resolve(reqObj as JsonRpcPayload); - } - - public async processResponse< - Method extends Web3APIMethod, - ResponseType = Web3APIReturnType - >( - response: JsonRpcResponse - ): Promise> { - const resObj = { ...response }; - console.log("Response:", resObj); - return Promise.resolve(resObj); - } + public async processRequest( + request: JsonRpcPayload, + ): Promise> { + const reqObj = { ...request } as JsonRpcPayload; + console.log('Request:', reqObj); + return Promise.resolve(reqObj as JsonRpcPayload); + } + + public async processResponse< + Method extends Web3APIMethod, + ResponseType = Web3APIReturnType, + >(response: JsonRpcResponse): Promise> { + const resObj = { ...response }; + console.log('Response:', resObj); + return Promise.resolve(resObj); + } } ``` @@ -279,13 +283,13 @@ Transaction middleware allows plugins to modify transaction data before it is se ```ts export class TxnMiddleware implements TransactionMiddleware { - public async processTransaction( - transaction: TransactionMiddlewareData - ): Promise { - const txObj = { ...transaction }; - console.log("Transaction data:", txObj); - return Promise.resolve(txObj); - } + public async processTransaction( + transaction: TransactionMiddlewareData, + ): Promise { + const txObj = { ...transaction }; + console.log('Transaction data:', txObj); + return Promise.resolve(txObj); + } } ``` @@ -315,20 +319,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; + } } ``` @@ -360,10 +364,10 @@ But, the user who does not call `.registerPlugin`, before accessing your plugin, // code written by the plugin **developer** declare module 'web3' { - // Here is where you're adding your plugin inside Web3Context - interface Web3Context { - customRpcMethods: CustomRpcMethodsPlugin; - } + // Here is where you're adding your plugin inside Web3Context + interface Web3Context { + customRpcMethods: CustomRpcMethodsPlugin; + } } ``` @@ -373,9 +377,9 @@ Your the plugin class: // code written by the plugin **developer** export class CustomRpcMethodsPlugin extends Web3PluginBase { - public pluginNamespace = 'customRpcMethods'; + public pluginNamespace = 'customRpcMethods'; - //... + //... } ``` diff --git a/docs/docs/guides/web3_plugin_guide/plugin_users.md b/docs/docs/guides/14_web3_plugin_guide/plugin_users.md similarity index 83% rename from docs/docs/guides/web3_plugin_guide/plugin_users.md rename to docs/docs/guides/14_web3_plugin_guide/plugin_users.md index 3c900d9e2a3..585f27699ad 100644 --- a/docs/docs/guides/web3_plugin_guide/plugin_users.md +++ b/docs/docs/guides/14_web3_plugin_guide/plugin_users.md @@ -34,8 +34,8 @@ For illustration purposes, let's assume a plugin developer has the following cod - + ```typescript // code written by the plugin **developer** @@ -43,18 +43,18 @@ 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; + } } ``` @@ -63,25 +63,24 @@ declare module 'web3' { - ```typescript // code written by the plugin **developer** 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; + } } ``` @@ -92,8 +91,8 @@ Here is an example of how to register the `PluginExample` onto an instance of `W - + ```javascript // code written by the plugin **user** @@ -112,7 +111,6 @@ web3.pluginExample.sampleMethod(); - ```typescript // code written by the plugin **user** @@ -126,4 +124,4 @@ web3.pluginExample.sampleMethod(); ``` - \ No newline at end of file + diff --git a/docs/docs/guides/migration_from_other_libs/_category_.yml b/docs/docs/guides/15_web3_upgrade_guide/_category_.yml similarity index 62% rename from docs/docs/guides/migration_from_other_libs/_category_.yml rename to docs/docs/guides/15_web3_upgrade_guide/_category_.yml index 59fb5de8cdc..635cb9d743a 100644 --- a/docs/docs/guides/migration_from_other_libs/_category_.yml +++ b/docs/docs/guides/15_web3_upgrade_guide/_category_.yml @@ -1,4 +1,4 @@ -label: '🔄 Migration Guides' +label: '⬆️ Upgrading from 1.x' collapsible: true collapsed: true link: null diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/abi_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/abi_migration_guide.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/abi_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/abi_migration_guide.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/accounts_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/accounts_migration_guide.md similarity index 99% rename from docs/docs/guides/web3_upgrade_guide/1.x/accounts_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/accounts_migration_guide.md index f6505e460f8..ec18f7e7f9c 100644 --- a/docs/docs/guides/web3_upgrade_guide/1.x/accounts_migration_guide.md +++ b/docs/docs/guides/15_web3_upgrade_guide/accounts_migration_guide.md @@ -43,5 +43,4 @@ In 1.x `stripHexPrefix` method is located in the `web3-utils` package, in 4.x th import { stripHexPrefix } from 'web3-eth-accounts'; console.log(stripHexPrefix('0x123')); // "123" - ``` diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/contracts_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/contracts_migration_guide.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/contracts_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/contracts_migration_guide.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/index.md b/docs/docs/guides/15_web3_upgrade_guide/index.md similarity index 95% rename from docs/docs/guides/web3_upgrade_guide/1.x/index.md rename to docs/docs/guides/15_web3_upgrade_guide/index.md index b375a63974f..d6c099804c9 100644 --- a/docs/docs/guides/web3_upgrade_guide/1.x/index.md +++ b/docs/docs/guides/15_web3_upgrade_guide/index.md @@ -3,7 +3,6 @@ sidebar_position: 1 sidebar_label: 'Introduction' --- - import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; @@ -28,8 +27,8 @@ And the correct usage now is: - + ```javascript const { Web3 } = require('web3'); @@ -57,11 +56,10 @@ Passing callbacks to functions is no longer supported, except for event listener For example, the approach to subscribing-to and listening-for blockchain events has changed in version 4.x. Detailed instructions can be found in the [**`web3.eth.subscribe` Migration Guide**](./subscribe_migration_guide.md#subscribing-to-events). -However, the approach to subscribing to Provider events remains the same, utilizing callbacks as explained in the [Providers Events Listening guide](../../web3_providers_guide/events_listening.md). It is important to note that Providers have undergone some breaking changes, including the renaming of the `on('close', ...)` to `on('disconnect', ...)`. +However, the approach to subscribing to Provider events remains the same, utilizing callbacks as explained in the [Providers Events Listening guide](/guides/02_web3_providers_guide/events_listening.md). It is important to note that Providers have undergone some breaking changes, including the renaming of the `on('close', ...)` to `on('disconnect', ...)`. ### Not Available - - [web3.bzz](https://web3js.readthedocs.io/en/v1.7.3/web3-bzz.html) Package for interacting with Swarm is not implemented - [web3.shh](https://web3js.readthedocs.io/en/v1.7.3/web3-shh.html) Package for interacting with Whisper is not implemented @@ -82,6 +80,7 @@ It will not have: :::warning In version 4.x, all numbers return as BigInt instead of string or number, which constitutes a breaking change for users accustomed to handling numbers as string or number in their code. For instance, web3.eth.getBalance will now return BigInt instead of string or number. If you wish to retain numbers as number or string, you can refer to [this guide](/guides/web3_config/#defaultreturnformat) on how to set returning types in web3js 4.x. ::: + ### Web3 BatchRequest ```ts diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/net_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/net_migration_guide.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/net_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/net_migration_guide.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/personal_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/personal_migration_guide.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/personal_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/personal_migration_guide.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/providers_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/providers_migration_guide.md similarity index 99% rename from docs/docs/guides/web3_upgrade_guide/1.x/providers_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/providers_migration_guide.md index 46375cdd0df..990ec6a989d 100644 --- a/docs/docs/guides/web3_upgrade_guide/1.x/providers_migration_guide.md +++ b/docs/docs/guides/15_web3_upgrade_guide/providers_migration_guide.md @@ -4,7 +4,7 @@ sidebar_position: 2 sidebar_label: web3.providers --- -For full description about the providers, their priorities and their types, you can check [web3.js Providers Guide](../../web3_providers_guide/). +For full description about the providers, their priorities and their types, you can check [web3.js Providers Guide](/guides/web3_providers_guide/). ### Provider Options Changes diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/subscribe_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/subscribe_migration_guide.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/subscribe_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/subscribe_migration_guide.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_ens.md b/docs/docs/guides/15_web3_upgrade_guide/web3_eth_ens.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_ens.md rename to docs/docs/guides/15_web3_upgrade_guide/web3_eth_ens.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_iban.md b/docs/docs/guides/15_web3_upgrade_guide/web3_eth_iban.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_iban.md rename to docs/docs/guides/15_web3_upgrade_guide/web3_eth_iban.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/web3_eth_migration_guide.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/web3_eth_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/web3_eth_migration_guide.md diff --git a/docs/docs/guides/web3_upgrade_guide/1.x/web3_utils_migration_guide.md b/docs/docs/guides/15_web3_upgrade_guide/web3_utils_migration_guide.md similarity index 100% rename from docs/docs/guides/web3_upgrade_guide/1.x/web3_utils_migration_guide.md rename to docs/docs/guides/15_web3_upgrade_guide/web3_utils_migration_guide.md diff --git a/docs/docs/guides/16_wagmi_usage/index.md b/docs/docs/guides/16_wagmi_usage/index.md new file mode 100644 index 00000000000..4d57030bf9e --- /dev/null +++ b/docs/docs/guides/16_wagmi_usage/index.md @@ -0,0 +1,127 @@ +--- +sidebar_label: '🔄 Wagmi usage' +title: 'Wagmi Web3.js Adapter' +position: 16 +--- + +### Reference Implementation + +If you're using [Wagmi](https://wagmi.sh/react/getting-started#use-wagmi) and want to add web3.js, use this code in your project. This snippet will help you to convert a `Viem` client to a `web3.js` instance for signing transactions and interacting with the blockchain: + +```typescript +import { Web3 } from 'web3'; +import { useMemo } from 'react'; +import type { Chain, Client, Transport } from 'viem'; +import { type Config, useClient, useConnectorClient } from 'wagmi'; + +export function clientToWeb3js(client?: Client) { + if (!client) { + return new Web3(); + } + + const { transport } = client; + + if (transport.type === 'fallback') { + return new Web3(transport.transports[0].value.url); + } + return new Web3(transport); +} + +/** Action to convert a viem Client to a web3.js Instance. */ +export function useWeb3js({ chainId }: { chainId?: number } = {}) { + const client = useClient({ chainId }); + return useMemo(() => clientToWeb3js(client), [client]); +} + +/** Action to convert a viem ConnectorClient to a web3.js Instance. */ +export function useWeb3jsSigner({ chainId }: { chainId?: number } = {}) { + const { data: client } = useConnectorClient({ chainId }); + return useMemo(() => clientToWeb3js(client), [client]); +} +``` + +### Usage examples + +Get block data example: + +```typescript +import { useWeb3js } from '../web3/useWeb3js'; +import { mainnet } from 'wagmi/chains'; +import { useEffect, useState } from 'react'; + +type Block = { + hash: string; + extraData: string; + miner: string; +}; + +function Block() { + const web3js = useWeb3js({ chainId: mainnet.id }); + const [block, setBlock] = useState(); + + useEffect(() => { + web3js.eth + .getBlock(19235006) + .then(b => { + setBlock(b as Block); + }) + .catch(console.error); + }, [setBlock]); + + if (!block) return
Loading...
; + + return ( + <> +
{block.hash}
+
{block.extraData}
+
{block.miner}
+ + ); +} + +export default Block; +``` + +Send transaction example: + +```typescript +import { mainnet } from 'wagmi/chains'; +import { useAccount, useConnect } from 'wagmi'; +import { useWeb3jsSigner } from '../web3/useWeb3js'; +import { useEffect } from 'react'; + +function SendTransaction() { + const account = useAccount(); + const { connectors, connect } = useConnect(); + const web3js = useWeb3jsSigner({ chainId: mainnet.id }); + + useEffect(() => { + if (account && account.address) { + web3js.eth + .sendTransaction({ + from: account.address, + to: '0x', // some address + value: '0x1', // set your value + }) + .then(console.log) + .catch(console.error); + } + }, [account]); + + return ( + <> + {connectors.map(connector => ( + + ))} + + ); +} + +export default SendTransaction; +``` + +:::tip +[This repository](https://github.com/avkos/wagmi-web3js-example-app) contains an example Wagmi app that demonstrates how to interact with the Ethereum blockchain using the web3.js library +::: diff --git a/docs/docs/guides/migration_from_other_libs/ethers.md b/docs/docs/guides/17_migration_from_other_libs/index.md similarity index 79% rename from docs/docs/guides/migration_from_other_libs/ethers.md rename to docs/docs/guides/17_migration_from_other_libs/index.md index 3d924499972..78e1f48d20c 100644 --- a/docs/docs/guides/migration_from_other_libs/ethers.md +++ b/docs/docs/guides/17_migration_from_other_libs/index.md @@ -1,7 +1,7 @@ --- -sidebar_position: 1 -sidebar_label: 'Migration from ethers.js' +sidebar_label: '🔄 Migration from ethers.js' title: 'Migration from ethers.js' +position: 17 --- Follow this guide, if you're currently using the ethers.js library to interact with the Ethereum blockchain and want to migrate to web3.js. This guide is for ethers v5 and v6. And, if there are differences, code for both would be provided. And, if you find something missing, or worth adding, feel free to open a PR, please. @@ -51,21 +51,21 @@ 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 title='BigInt Tip' import { Web3, DEFAULT_RETURN_FORMAT, FMT_NUMBER } from 'web3'; const blockNumber = web3.eth.getBlockNumber({ - ...DEFAULT_RETURN_FORMAT, - number: FMT_NUMBER.HEX, // to get the block number in hex format + ...DEFAULT_RETURN_FORMAT, + number: FMT_NUMBER.HEX, // to get the block number in hex format }); // outputs something like: 0x11B3BA4 blockNumber.then(console.log); - const blockNumber = web3.eth.getBlockNumber({ - ...DEFAULT_RETURN_FORMAT, - number: FMT_NUMBER.STR, // to get the block number as a string + ...DEFAULT_RETURN_FORMAT, + number: FMT_NUMBER.STR, // to get the block number as a string }); // the value would like: '18561956' blockNumber.then(console.log); @@ -89,7 +89,6 @@ With web3.js: const web3 = new Web3(window.ethereum); ``` - ## Wallets and Accounts ### Generate Private Key @@ -111,15 +110,16 @@ With web3.js: // (Be sure to store it encrypted in a safe place) const privateKey = web3.eth.accounts.create().privateKey; ``` + ### Create a wallet In ethers.js: ```typescript const wallet = new ethers.Wallet( - // A private key that you might had generated with: - // ethers.Wallet.createRandom().privateKey - privateKey, + // A private key that you might had generated with: + // ethers.Wallet.createRandom().privateKey + privateKey, ); // outputs: 0x6f7D735dFB514AA1778E8D97EaCE72BfECE71865 @@ -131,8 +131,8 @@ With web3.js: ```typescript const web3 = new Web3(); const wallet = web3.eth.accounts.wallet.add( - // you can generate a private key using web3.eth.accounts.create().privateKey - privateKey, + // you can generate a private key using web3.eth.accounts.create().privateKey + privateKey, ); // outputs: 0x6f7D735dFB514AA1778E8D97EaCE72BfECE71865 @@ -140,12 +140,12 @@ console.log(wallet[0].address); ``` :::info - In web3.js, if you want to use a private key to later sign and send transactions, you first need to add this private key to the accounts with, for example, one of the methods: - `web3.eth.accounts.create()`, or `web3.eth.accounts.wallet.add(privateKey)`. - - And then whenever you provide the public address of that private key, web3.js will use that private key to sign. For example, you would pass the public key at `web3.eth.sendTransaction({from: publicAddress,...})` and web3.`eth.signTransaction({from: publicAddress,...})` then the privateKey of that publicAddress will be lookup and used to sign. +In web3.js, if you want to use a private key to later sign and send transactions, you first need to add this private key to the accounts with, for example, one of the methods: +`web3.eth.accounts.create()`, or `web3.eth.accounts.wallet.add(privateKey)`. - However, it is not advised to use the privatekey directly. And you are advised to use a secret storage or a vault instead. +And then whenever you provide the public address of that private key, web3.js will use that private key to sign. For example, you would pass the public key at `web3.eth.sendTransaction({from: publicAddress,...})` and web3.`eth.signTransaction({from: publicAddress,...})` then the privateKey of that publicAddress will be lookup and used to sign. + +However, it is not advised to use the privatekey directly. And you are advised to use a secret storage or a vault instead. ::: ### Get unlocked account @@ -162,7 +162,6 @@ With web3.js: const account = (await web3.eth.getAccounts())[0]; ``` - ### Signing a string message with ethers.js: @@ -174,13 +173,11 @@ const signature = await signer.signMessage('Some data'); // Outputs something like: // 0xb475e02218d7d6a16f3575de789996d0a57f900f240d73ed792672256d63913840c1da0dd3e7fe2e79485b7a1d81e8cc163f405c3df22d496f28f1dd148faebf1b console.log(signature); - ``` With web3.js: ```typescript - // Sign with web3.js, using a private key: const signature = web3.eth.accounts.sign('Some data', privateKey).signature; @@ -190,8 +187,8 @@ console.log(signature); // Sign using an account managed by the connected provider (for example the RPC client or a browser-injected provider) const signature = await web3.eth.sign( - web3.utils.utf8ToHex('Some data'), // data to be signed (4.x only supports Hex Strings) - '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', // the address that its private key would be used to sign + web3.utils.utf8ToHex('Some data'), // data to be signed (4.x only supports Hex Strings) + '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', // the address that its private key would be used to sign ); // Outputs something like: @@ -209,8 +206,8 @@ Sending a transaction with ethers.js: const signer = new ethers.Wallet(privateKey, provider); const tx = await signer.sendTransaction({ - to: '0x92d3267215Ec56542b985473E73C8417403B15ac', - value: ethers.parseUnits('0.001', 'ether'), + to: '0x92d3267215Ec56542b985473E73C8417403B15ac', + value: ethers.parseUnits('0.001', 'ether'), }); console.log(tx); ``` @@ -220,7 +217,7 @@ With web3.js: :::info The method `web3.eth.sendTransaction` will use the account that you pass the public address at `from` to sign the transaction. -So, the `from` needs to be the public address of a private key that you added previously to the web3.eth.accounts. Or, else, it would pass it to the provider where an unlocked account would be used. +So, the `from` needs to be the public address of a private key that you added previously to the web3.eth.accounts. Or, else, it would pass it to the provider where an unlocked account would be used. And for the case when you did not add the private key early, and so the `from` was just passed to the provider. Then if the provider was a browser-injected provider like metamask, for example, it will ask the user to sign. And, if you are using a local dev node as a provider, it should be one of the accounts that were already unlocked at the node. However, note that it is highly risky and not recommended to unlock an account at a production or even a test node. ::: @@ -238,9 +235,9 @@ const wallet = web3.eth.accounts.wallet.add(privateKey); const account = wallet[0].address; const tx = await web3.eth.sendTransaction({ - from: account, - to: '0x92d3267215Ec56542b985473E73C8417403B15ac', - value: web3.utils.toWei('0.00000000001', 'ether'), + from: account, + to: '0x92d3267215Ec56542b985473E73C8417403B15ac', + value: web3.utils.toWei('0.00000000001', 'ether'), }); console.log(tx); ``` @@ -251,7 +248,7 @@ Posting a signed transaction to the node with ethers.js: ```typescript // in v5 -provider.sendTransaction(signedTx) +provider.sendTransaction(signedTx); // in v6 provider.broadcastTransaction(signedTx); @@ -261,28 +258,21 @@ With web3.js: ```typescript const transaction: Transaction = { - from: senderPublicAddress, - to: receiverPublicAddress, - value: 1, - gas: 21000, - type: 0, + from: senderPublicAddress, + to: receiverPublicAddress, + value: 1, + gas: 21000, + type: 0, }; // you might also use below `web3.eth.personal.signMessage`, depending on your use case. -const signedTransaction = await web3.eth.accounts.signTransaction( - transaction, - privateKey, -); +const signedTransaction = await web3.eth.accounts.signTransaction(transaction, privateKey); -const tx = await web3.eth.sendSignedTransaction( - signedTransaction.rawTransaction, -); +const tx = await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction); console.log(tx); ``` - - ## Contracts ### Contracts Deployment @@ -303,23 +293,24 @@ In web3.js: ```typescript const contractObject = new web3.eth.Contract(abi); -const deployedContract = await contractObject.deploy({ - data: bytecode, - arguments: ['constructor param'] -}).send({ - from: '0x12598d2Fd88B420ED571beFDA8dD112624B5E730', - gas: '1000000', - // other transaction's params -}); +const deployedContract = await contractObject + .deploy({ + data: bytecode, + arguments: ['constructor param'], + }) + .send({ + from: '0x12598d2Fd88B420ED571beFDA8dD112624B5E730', + gas: '1000000', + // other transaction's params + }); -console.log('contract address', deployedContract.options.address) +console.log('contract address', deployedContract.options.address); ``` :::tip -📝 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/) +📝 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/) ::: - ### Calling Contracts' Methods To interact with contracts in ethers.js: @@ -335,9 +326,9 @@ In web3.js: const web3 = new Web3(provider); const contract = new web3.eth.Contract(ABI, CONTRACT_ADDRESS); -// If the method was only to read form the Blockchain: +// If the method was only to read form the Blockchain: const result = await contract.methods.someFunction().call(); -// Or, if the method would need a transaction to be sent: +// Or, if the method would need a transaction to be sent: const result = await contract.methods.someFunction().send(); ``` @@ -348,9 +339,9 @@ 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); // for ambiguous functions (two functions with the same @@ -360,13 +351,13 @@ message = await contract['getMessage(string)']('nice'); message = await contract['getMessage()'](); // in v6 -contract.foo(Typed.string('nice')) +contract.foo(Typed.string('nice')); ``` In web3.js: ```typescript -// in web3.js the overloaded method implementation is automatically picked based on the passed datatype +// in web3.js the overloaded method implementation is automatically picked based on the passed datatype message = await contract.methods.getMessage('nice').call(); // To call the overladed method without a parameter: message = await contract.methods.getMessage().call(); @@ -378,7 +369,7 @@ To interact with contracts in ethers.js: ```typescript // Estimate the gas -contract.myMethod.estimateGas(123) +contract.myMethod.estimateGas(123); ``` In web3.js: @@ -386,18 +377,17 @@ In web3.js: ```typescript // Estimate the gas const gasAmount = await myContract.methods.myMethod(123).estimateGas( - { gas: 5000000, from: transactionSenderAddress } // optional + { gas: 5000000, from: transactionSenderAddress }, // optional ); ``` - ### Handling Events Handling events with ethers.js: ```typescript contract.on('SomeEvent', (arg1, arg2, event) => { - // event handling + // event handling }); ``` @@ -405,37 +395,36 @@ With web3.js: ```typescript const event = contract.events.SomeEvent({ - filter: { - filter: { val: 100 }, - }, - fromBlock: 0, + filter: { + filter: { val: 100 }, + }, + fromBlock: 0, }); event.on('data', resolve); event.on('error', reject); ``` - ## Utility methods ### Hashing -Here is how to compute `keccak256` hash of a UTF-8 string with web3 and ethers. +Here is how to compute `keccak256` hash of a UTF-8 string with web3 and ethers. With ethers.js: ```typescript // hash of a string -ethers.utils.id('hello world') +ethers.utils.id('hello world'); // hash of binary data -ethers.utils.keccak256('0x4242') +ethers.utils.keccak256('0x4242'); ``` With web3.js: ```typescript // computes the Keccak-256 hash of the input and returns a hexstring: -// the `utils.sha3` accepts: string and Uint8Array +// the `utils.sha3` accepts: string and Uint8Array web3.utils.sha3('hello world'); // the `utils.keccak256` accepts: string, Uint8Array, Numbers and ReadonlyArray web3.utils.keccak256('hello world'); diff --git a/docs/docs/guides/resources_and_troubleshooting/index.md b/docs/docs/guides/18_resources_and_troubleshooting/index.md similarity index 96% rename from docs/docs/guides/resources_and_troubleshooting/index.md rename to docs/docs/guides/18_resources_and_troubleshooting/index.md index 2dd82f1e5b6..8cf7327d828 100644 --- a/docs/docs/guides/resources_and_troubleshooting/index.md +++ b/docs/docs/guides/18_resources_and_troubleshooting/index.md @@ -1,7 +1,8 @@ --- -sidebar_position: 16 +sidebar_position: 18 sidebar_label: '📚 Resources & Troubleshooting' --- + # Resources & Troubleshooting ## Troubleshooting @@ -13,26 +14,30 @@ Occasionally, users encounter errors in web3.js due to external dependencies, wh **Resolution Steps:** 1. Install `rn-nodeify` as a development dependency: + ```bash yarn add --dev rn-nodeify ``` 2. Add the `big-integer` package: + ```bash yarn add big-integer ``` 3. Create a file named `shim.js` at the root of your project and include the following polyfill: + ```ts if (typeof BigInt === 'undefined') { - global.BigInt = require('big-integer'); + global.BigInt = require('big-integer'); } ``` 4. Import shim.js at the top of your App.js: + ```ts // Make sure you use `import` and not `require`! -import './shim.js' +import './shim.js'; ``` Additional Info: @@ -47,7 +52,6 @@ This comprehensive 14-part video course from ChainSafe equips you with the skill [![Web3.js v4 course](https://img.youtube.com/vi/3ZO_t-Kyr1g/0.jpg)](https://www.youtube.com/watch?v=3ZO_t-Kyr1g&list=PLPn3rQCo3XrP4LbQcOyyHQR8McV7w3HZT) - ### [Web3.js series](https://www.youtube.com/watch?v=BQ_bDH91S4k&list=PLPn3rQCo3XrNf__8irs4-MjMt4fJqW2I_) This series of 3 videos takes you on a journey through web3.js. Whether you're a complete beginner or want to refine your skills, these videos have something for you: diff --git a/docs/docs/guides/feedback/index.md b/docs/docs/guides/19_feedback/index.md similarity index 97% rename from docs/docs/guides/feedback/index.md rename to docs/docs/guides/19_feedback/index.md index 228003d5a6e..05ae7d90fef 100644 --- a/docs/docs/guides/feedback/index.md +++ b/docs/docs/guides/19_feedback/index.md @@ -1,5 +1,5 @@ --- -sidebar_position: 17 +sidebar_position: 19 sidebar_label: '🗣️ Feedback' --- @@ -24,5 +24,3 @@ Please reach out to us: [💬 Discord: `#web3js-general` channel](https://discord.gg/f5QhHUswtr) [🐦 Twitter: `@web3_js`](https://twitter.com/web3_js) - - diff --git a/docs/docs/guides/ens/_category_.yml b/docs/docs/guides/ens/_category_.yml deleted file mode 100644 index 6aaeb5a8a78..00000000000 --- a/docs/docs/guides/ens/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -label: '📦 Web3 ENS module' -collapsible: true -collapsed: true -link: null -position: 9 \ No newline at end of file diff --git a/docs/docs/guides/getting_started/introduction.md b/docs/docs/guides/getting_started/introduction.md deleted file mode 100644 index 303401639f9..00000000000 --- a/docs/docs/guides/getting_started/introduction.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -slug: / -sidebar_position: 1 -sidebar_label: Introduction ---- - -# Introduction - -Web3.js is a robust and flexible collection of **TypeScript and JavaScript** libraries that allows developers to interact with local or remote [Ethereum](https://ethereum.org/en/) nodes (or **any EVM-compatible blockchain**) over **HTTP, IPC or WebSocket** connections. It is a powerful and efficient toolkit for crafting applications within the Ethereum ecosystem and beyond. - -This documentation is the entrypoint to Web3.js for developers. It covers [basic](/guides/getting_started/quickstart) and [advanced](/guides/smart_contracts/mastering_smart_contracts) usage with examples, and includes comprehensive [API documentation](/api) as well as guides for common tasks, like [upgrading](/guides/web3_upgrade_guide/x/) from older versions. - -## Features of Web3.js v4 - -- Flexible - - ECMAScript (ESM) and CommonJS (CJS) builds - - [Plugins](/guides/web3_plugin_guide/) for extending functionality -- Efficient - - Modular, [package](/#packages)-based design reduces unneeded dependencies - - [Tree shakable with ESM](/guides/advanced/tree_shaking) - - Use of native [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (instead of large [BigNumber](https://mikemcl.github.io/bignumber.js/) libraries) - - Efficient ABI [encoding](/api/web3-eth-abi/function/encodeFunctionCall) & [decoding](/api/web3-eth-abi/function/decodeParameter) -- Developer-Friendly - - [Dynamic contract types](/guides/smart_contracts/infer_contract_types/) & full API in TypeScript - - Custom output [formatters](https://docs.web3js.org/api/web3-utils/function/format) - - In compliance with the [Ethereum JSON-RPC Specification](https://ethereum.github.io/execution-apis/api-documentation/) - -## Using These Docs - -There is a lot to learn about Web3.js! Here are some tips for developers of different skill levels. Remember, you can always [reach out directly](/guides/feedback/#urgent-questions-or-concerns) with Discord or Twitter if you're feeling stuck. - -### For Beginner Web3.js Developers - -New Web3.js developers should proceed to the [Quickstart](/guides/getting_started/quickstart) section to learn how to get started with Web3.js. Once you understand the basics, you may want to consider learning more about [providers](/guides/web3_providers_guide/), [wallets and accounts](/guides/wallet/), [smart contracts](/guides/smart_contracts/smart_contracts_guide), and how to [use Web3.js with the Hardhat development environment](/guides/hardhat_tutorial/). - -### For Intermediate & Advanced Web3.js Developers - -If you're already familiar with Ethereum and Web3.js development, you may want to review the Web3.js [package structure](#packages--plugins) and proceed directly to the [package-level documentation](/libdocs/ABI) and [API documentation](/api). Application developers may wish to review the [Web3.js configuration guide](/guides/web3_config/) or learn how to use Web3.js with tools like the [MetaMask](/guides/wallet/metamask-react) wallet or the [WalletConnect](/guides/wallet/web3_modal_guide/) wallet selection modal. Don't forget to review the [list of available plugins](https://web3js.org/plugins) or even [learn how to build your own Web3.js plugin](/guides/web3_plugin_guide/plugin_authors)! - -## Packages & Plugins - -Web3.js is a modular collection of packages, each of which serves a specific needs. This means developers don't need to install the entire Web3 library for most use cases. Instead, necessary packages are selectively installed for a more efficient development experience. Here is an overview of a selection of available packages: - -- [**Web3Eth:**](/libdocs/Web3Eth) The `web3-eth` package is the entrypoint to Web3.js - it's the control center for managing interactions with Ethereum and other EVM-compatible networks. - -- [**Net:**](/libdocs/Net) The `web3-net` package provides discovery and interactions for an **Ethereum node's network properties.** - -- [**Accounts:**](/libdocs/Accounts) The `web3-eth-accounts` package has tools for creating Ethereum accounts and the **secure signing** of transactions and data. - -- [**Personal:**](/libdocs/Personal) Use `web3-eth-personal` for **direct communication about your accounts with the Ethereum node**, which streamlines account management during development. - - **NOTE:** *For enhanced security in production and when interacting with public nodes, consider using `web3-eth-accounts` for local signing operations, which keeps your private keys and sensitive information secure on your local machine* - -- [**Utils:**](/libdocs/Utils) The `web3-utils` package provides helpers to perform a range of essential Ethereum development tasks, including **converting data formats, checking addresses, encoding and decoding data, hashing, handling numbers, and much more.**. - -- [**Contract:**](/libdocs/Contract) The `web3-eth-contract` package makes it easy to **interact with smart contracts through JavaScript or TypeScript,** which streamlines the development process and makes it less error-prone. - -- [**ABI:**](/libdocs/ABI) The `web3-eth-abi` package simplifies decoding logs and parameters, encoding function calls and signatures, and inferring types for efficient Ethereum **smart contract interactions.** - -- [**ENS:**](/libdocs/ENS) The `web3-eth-ens` package makes it easy for developers to communicate with the **Ethereum Name Service (ENS).** - -- [**Iban:**](/libdocs/Iban) The `web3-eth-iban` package allows you to switch between **Ethereum addresses and special banking-like addresses** (IBAN or BBAN) and simplifies conversion between the types. - -### Additional Supporting Packages - -- [**Web3 Core:**](/api/web3-core) subscriptions, request management, and configuration used by other Web3 packages - -- [**Web3 Types:**](/api/web3-types) data structures, objects, interfaces and types used by Web3 - -- [**Web3 Validator:**](/api/web3-validator) runtime type validation against predefined types or custom schemas - -- [**Web3 Errors:**](/api/web3-errors) error codes and common error classes that are used by other Web3 packages - -- [**Web3 RPC Methods:**](/api/web3/namespace/rpcMethods) functions for making RPC requests to Ethereum using a given provider - -### Plugins - -Web3.js supports [plugins](/guides/web3_plugin_guide/), which are another way to encapsulate capabilities that support a specific need. There are plugins that exist to support native features, like those described by [EIPs](https://eips.ethereum.org/) as well as plugins that are designed to support specific smart contracts, middleware, or even other Ethereum-compatible networks. Visit the [Web3.js plugins homepage](https://web3js.org/plugins) to view a list of the most important Web3.js plugins, which includes: - -- [EIP-4337 (Account Abstraction) Plugin](https://www.npmjs.com/package/@chainsafe/web3-plugin-eip4337) - -- [EIP-4844 (Blob Transactions) Plugin](https://www.npmjs.com/package/web3-plugin-blob-tx) - -- [zkSync Plugin](https://www.npmjs.com/package/web3-plugin-zksync) - -## Advantages Over Other Libraries - -- **Extensive Documentation and Community**: Web3.js is one of the most established Ethereum libraries, which means it benefits from extensive documentation and a large, active community. Web3.js is widely adopted and has been thoroughly tested in various production environments, and is compatible with a broad range of other tools and services in the Ethereum ecosystem. - -- **Modular Design**: Web3.js is designed to be modular, which allows developers to use specific packages according to their needs. This leads to smaller bundle sizes and faster load times for web applications. - -- **Active Development and Support**: Web3.js sees regular updates and active development. This support is crucial for developers needing assurance that the library they're using will keep pace with the evolving Ethereum landscape. diff --git a/docs/docs/guides/getting_started/return-formats.md b/docs/docs/guides/getting_started/return-formats.md deleted file mode 100644 index ae4287a8336..00000000000 --- a/docs/docs/guides/getting_started/return-formats.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -sidebar_position: 3 -sidebar_label: Return Formats ---- - -# Return Formats - -By default, Web3.js formats byte values as hexadecimal strings (e.g. `"0x221`") and number values as [`BigInt`s](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt). The default formats can be configured at the global level by updating the [`defaultReturnFormat` configuration option](/guides/web3_config/#defaultreturnformat). Many Web3.js functions (e.g. [`getBlock`](/api/web3-eth/function/getBlock), [`sendTransaction`](/api/web3-eth/function/sendTransaction)) accept an optional parameter named `returnFormat` of the [type `DataFormat`](/api/web3-types#DataFormat) that can be used to configure the format for data returned by that single function invocation. - -The following example demonstrates working with return formats: - -```ts -import { Block, FMT_BYTES, FMT_NUMBER, Numbers, Web3 } from "web3"; - -const web3 = new Web3("https://eth.llamarpc.com"); - -// use the default return format -web3.eth.getBlock().then((block: Block) => { - console.log(`Block #${block.number} Hash: ${block.hash}`); -}); -// ↳ Block #20735255 Hash: 0xbaea6dbd46fa810a27be4c9eac782602f8efe7512fb30a8455c127b101a23e22 - -// specify the return format for a single function invocation -web3.eth - .getBlockNumber({ - bytes: FMT_BYTES.HEX, - number: FMT_NUMBER.HEX, - }) - .then((blockNumber: Numbers) => { - console.log(`Block #${blockNumber}`); - }); -// ↳ Block #0x13c6517 - -// configure default return format for the web3-eth package -web3.eth.defaultReturnFormat = { - bytes: FMT_BYTES.UINT8ARRAY, - number: FMT_NUMBER.HEX, -}; - -web3.eth.getBlock().then((block: Block) => { - console.log(`Block #${block.number} Hash: [${block.hash}]`); -}); -// ↳ Block #0x13c6517 Hash: [186,234,109,...,162,62,34] -``` - -The supported return formats are: - -- Bytes - - [`FMT_BYTES.HEX`](/api/web3-types/enum/FMT_BYTES#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) - ```ts - web3.eth - .getBlock(undefined, undefined, { - bytes: FMT_BYTES.HEX, - number: FMT_NUMBER.BIGINT, - }) - .then((block: Block) => { - console.log(`Block hash: ${block.hash}`); - }); - // ↳ Block hash: 0xbaea6dbd46fa810a27be4c9eac782602f8efe7512fb30a8455c127b101a23e22 - ``` - - [`FMT_BYTES.UINT8ARRAY`](/api/web3-types/enum/FMT_BYTES#UINT8ARRAY): [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) (e.g. `[ 2, 33 ]`) - ```ts - web3.eth - .getBlock(undefined, undefined, { - bytes: FMT_BYTES.UINT8ARRAY, - number: FMT_NUMBER.BIGINT, - }) - .then((block: Block) => { - console.log(`Block hash: [${block.hash}]`); - }); - // ↳ Block hash: [186,234,109,...,162,62,34] - ``` -- Numbers - - [`FMT_NUMBER.BIGINT`](/api/web3-types/enum/FMT_NUMBER#BIGINT): [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (e.g. `221n`) - ```ts - web3.eth - .getBlockNumber({ - bytes: FMT_BYTES.HEX, - number: FMT_NUMBER.BIGINT, - }) - .then((blockNumber: Numbers) => { - console.log(`Block #${blockNumber}`); - }); - // ↳ Block #20735255 - ``` - - [`FMT_NUMBER.HEX`](/api/web3-types/enum/FMT_NUMBER#HEX): hexadecimal [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"0xdd"`) - ```ts - web3.eth - .getBlockNumber({ - bytes: FMT_BYTES.HEX, - number: FMT_NUMBER.HEX, - }) - .then((blockNumber: Numbers) => { - console.log(`Block #${blockNumber}`); - }); - // ↳ Block #0x13c6517 - ``` - - [`FMT_NUMBER.NUMBER`](/api/web3-types/enum/FMT_NUMBER#NUMBER): [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) (e.g. `221`) - ```ts - web3.eth - .getBlockNumber({ - bytes: FMT_BYTES.HEX, - number: FMT_NUMBER.NUMBER, - }) - .then((blockNumber: Numbers) => { - console.log(`Block #${blockNumber}`); - }); - // ↳ Block #20735255 - ``` - - [`FMT_NUMBER.STR`](/api/web3-types/enum/FMT_NUMBER#STR): [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) (e.g. `"221"`) - ```ts - web3.eth - .getBlockNumber({ - bytes: FMT_BYTES.HEX, - number: FMT_NUMBER.STR, - }) - .then((blockNumber: Numbers) => { - console.log(`Block #${blockNumber}`); - }); - // ↳ Block #20735255 - ``` diff --git a/docs/docs/guides/hardhat_tutorial/_category_.yml b/docs/docs/guides/hardhat_tutorial/_category_.yml deleted file mode 100644 index 8493ca97d6e..00000000000 --- a/docs/docs/guides/hardhat_tutorial/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -label: '⛑️ Hardhat Tutorial' -collapsible: true -collapsed: true -link: null -position: 6 diff --git a/docs/docs/guides/wagmi_usage/_category_.yml b/docs/docs/guides/wagmi_usage/_category_.yml deleted file mode 100644 index ee90c923e38..00000000000 --- a/docs/docs/guides/wagmi_usage/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -label: '🔄 Wagmi usage' -collapsible: true -collapsed: true -link: null -position: 14 diff --git a/docs/docs/guides/wagmi_usage/wagmi.md b/docs/docs/guides/wagmi_usage/wagmi.md deleted file mode 100644 index 9a3044c3767..00000000000 --- a/docs/docs/guides/wagmi_usage/wagmi.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: 'Wagmi Web3js Adapter' -title: 'Wagmi Web3js Adapter' ---- - - -### Reference Implementation -If you're using [Wagmi](https://wagmi.sh/react/getting-started#use-wagmi) and want to add web3.js, use this code in your project. This snippet will help you to convert a `Viem` client to a `web3.js` instance for signing transactions and interacting with the blockchain: - - -```typescript -import {Web3} from 'web3' -import {useMemo} from 'react' -import type {Chain, Client, Transport} from 'viem' -import {type Config, useClient, useConnectorClient} from 'wagmi' - -export function clientToWeb3js(client?: Client) { - if (!client) { - return new Web3() - } - - const {transport} = client - - if (transport.type === 'fallback') { - return new Web3(transport.transports[0].value.url) - } - return new Web3(transport) -} - -/** Action to convert a viem Client to a web3.js Instance. */ -export function useWeb3js({chainId}: { chainId?: number } = {}) { - const client = useClient({chainId}) - return useMemo(() => clientToWeb3js(client), [client]) -} - -/** Action to convert a viem ConnectorClient to a web3.js Instance. */ -export function useWeb3jsSigner({chainId}: { chainId?: number } = {}) { - const {data: client} = useConnectorClient({chainId}) - return useMemo(() => clientToWeb3js(client), [client]) -} -``` - -### Usage examples -Get block data example: - -```typescript -import {useWeb3js} from '../web3/useWeb3js' -import {mainnet} from 'wagmi/chains' -import {useEffect, useState} from "react"; - -type Block = { - hash: string - extraData: string - miner: string - -} - -function Block() { - const web3js = useWeb3js({chainId: mainnet.id}) - const [block, setBlock] = useState() - - useEffect(() => { - web3js.eth.getBlock(19235006).then((b) => { - setBlock(b as Block) - }).catch(console.error) - }, [setBlock]); - - - if (!block) return (
Loading...
) - - return ( - <> -
{block.hash}
-
{block.extraData}
-
{block.miner}
- - -) -} - -export default Block - -``` - -Send transaction example: - -```typescript -import {mainnet} from 'wagmi/chains' -import {useAccount, useConnect} from "wagmi"; -import {useWeb3jsSigner} from "../web3/useWeb3js"; -import {useEffect} from "react"; - -function SendTransaction() { - const account = useAccount() - const {connectors, connect,} = useConnect() - const web3js = useWeb3jsSigner({chainId: mainnet.id}) - - useEffect(() => { - if (account && account.address) { - web3js.eth.sendTransaction({ - from: account.address, - to: '0x', // some address - value: '0x1' // set your value - }).then(console.log).catch(console.error) - } - }, [account]) - - return ( - <> - {connectors.map((connector) => ( - - ))} - - ) -} - -export default SendTransaction - -``` - - -:::tip -[This repository](https://github.com/avkos/wagmi-web3js-example-app) contains an example Wagmi app that demonstrates how to interact with the Ethereum blockchain using the web3.js library -::: diff --git a/docs/docs/guides/wallet/_category_.yml b/docs/docs/guides/wallet/_category_.yml deleted file mode 100644 index dde0bddd9ed..00000000000 --- a/docs/docs/guides/wallet/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -label: '🔑 Wallet and Accounts ' -collapsible: true -collapsed: true -link: null -position: 3 diff --git a/docs/docs/guides/wallet/metamask-react.md b/docs/docs/guides/wallet/metamask-react.md deleted file mode 100644 index 8cdd7c70ba8..00000000000 --- a/docs/docs/guides/wallet/metamask-react.md +++ /dev/null @@ -1,626 +0,0 @@ ---- -sidebar_position: 5 -sidebar_label: 'Tutorial: Connecting to Metamask with React' ---- - -# Connecting to Metamask with React - - - -This tutorial builds on the previous tutorial that used [vanilla JavaScript with Web3.js and MetaMask](/guides/wallet/metamask-vanilla). In this tutorial, [React](https://react.dev/) and TypeScript will be used to implement similar capabilities. - -## Overview - -Here is a high-level overview of the steps we will be taking in this tutorial: - -1. Review prerequisites -2. Initialize a new React project and add Web3.js -3. Use MetaMask as the Web3.js provider -4. Request access to the MetaMask accounts -5. Sign a message with a MetaMask account -6. Verify the account used to sign a message - -:::tip -If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. -::: - -## Step 1: Prerequisites - -This tutorial assumes basic familiarity with the command line as well as familiarity with React and [Node.js](https://nodejs.org/). Before starting this tutorial, ensure that Node.js and its package manager, npm, are installed. - -```bash -$: node -v -# your version may be different, but it's best to use the current stable version -v18.16.1 -$: npm -v -9.5.1 -``` - -Make sure that MetaMask is [installed](https://metamask.io/download/) as a browser extension and the steps to create an account (e.g. create a password, review the seed phrase) have been completed. - -## Step 2: Initialize a New React Project and Add Web3.js - -Initialize a new React project and navigate into the new project directory: - -```bash -npx create-react-app web3-metamask-react --template typescript -cd web3-metamask-react -``` - -Add Web3.js to the project with the following command: - -```bash -npm i web3 -``` - -## Step 3: Use MetaMask as the Web3.js Provider - -MetaMask will inject the Ethereum provider as an `ethereum` property on the [global `Window` object](https://developer.mozilla.org/en-US/docs/Web/API/Window). To communicate this change to the TypeScript compiler, update `src/react-app-env.d.ts` as follows: - -```ts -import { MetaMaskProvider } from "web3"; - -/// - -declare global { - interface Window { - ethereum: MetaMaskProvider; - } -} -``` - -Replace the contents of `src/App.tsx` with the following: - -```tsx -import { useEffect, useState } from "react"; -import { Web3 } from "web3"; - -function App() { - const [web3, setWeb3] = useState(null); - const [warning, setWarning] = useState(null); - const [provider, setProvider] = useState(null); - const [chainId, setChainId] = useState(null); - const [latestBlock, setLatestBlock] = useState(null); - useEffect(() => { - // ensure that there is an injected the Ethereum provider - if (window.ethereum) { - // use the injected Ethereum provider to initialize Web3.js - setWeb3(new Web3(window.ethereum)); - // check if Ethereum provider comes from MetaMask - if (window.ethereum.isMetaMask) { - setProvider("Connected to Ethereum with MetaMask."); - } else { - setProvider("Non-MetaMask Ethereum provider detected."); - } - } else { - // no Ethereum provider - instruct user to install MetaMask - setWarning("Please install MetaMask"); - } - }, []); - - useEffect(() => { - async function getChainId() { - if (web3 === null) { - return; - } - - // get chain ID and populate placeholder - setChainId(`Chain ID: ${await web3.eth.getChainId()}`); - } - - async function getLatestBlock() { - if (web3 === null) { - return; - } - - // get latest block and populate placeholder - setLatestBlock(`Latest Block: ${await web3.eth.getBlockNumber()}`); - - // subscribe to new blocks and update UI when a new block is created - const blockSubscription = await web3.eth.subscribe("newBlockHeaders"); - blockSubscription.on("data", (block) => { - setLatestBlock(`Latest Block: ${block.number}`); - }); - } - - getChainId(); - getLatestBlock(); - }, [web3]); - return ( - <> -
- {warning} -
-
{provider}
-
{chainId}
-
{latestBlock}
- - ); -} - -export default App; -``` - -Review the comments in `src/App.tsx`. This file defines a component with several placeholders that will be used to display network information, and also provides two `useEffect` hooks for populating those placeholders. The first `useEffect` hook checks for an [injected provider](/guides/web3_providers_guide/#injected-provider). If an injected provider is found, it's used to construct a new `Web3` instance and connect to the Ethereum network. A check is performed to ensure that the injected provider is coming from MetaMask and the result of this check is displayed to the user. If no injected provider is found, the user is instructed to install MetaMask. The second `useEffect` hook uses the injected provider to update the placeholders with the chain ID and latest block number, and creates an event subscription to update the block number as new blocks are created. - -To start the React app, execute the following command in the project directory: - -```bash -npm start -``` - -This should automatically open the page in a web browser (make sure it's the browser with the MetaMask extension). If everything is set up correctly, the webpage should state that it is connected to the Ethereum network with MetaMask and list the chain ID (for the default Ethereum Mainnet network this value should be `1`) and latest block number. The latest block number should change when new blocks are created. - -## Step 4: Request Access to the MetaMask Accounts - -Replace the contents of `src/App.tsx` with the following (take note of the highlighted sections, which are new): - -```tsx -import { useEffect, useState } from "react"; -import { Web3 } from "web3"; - -function App() { - const [web3, setWeb3] = useState(null); - const [warning, setWarning] = useState(null); - const [provider, setProvider] = useState(null); - const [chainId, setChainId] = useState(null); - const [latestBlock, setLatestBlock] = useState(null); - // highlight-start - const [accountButtonDisabled, setAccountButtonDisabled] = - useState(false); - const [accounts, setAccounts] = useState(null); - const [connectedAccount, setConnectedAccount] = useState(null); - // highlight-end - useEffect(() => { - // ensure that there is an injected the Ethereum provider - if (window.ethereum) { - // use the injected Ethereum provider to initialize Web3.js - setWeb3(new Web3(window.ethereum)); - // check if Ethereum provider comes from MetaMask - if (window.ethereum.isMetaMask) { - setProvider("Connected to Ethereum with MetaMask."); - } else { - setProvider("Non-MetaMask Ethereum provider detected."); - } - } else { - // no Ethereum provider - instruct user to install MetaMask - setWarning("Please install MetaMask"); - // highlight-next-line - setAccountButtonDisabled(true); - } - }, []); - - useEffect(() => { - async function getChainId() { - if (web3 === null) { - return; - } - - // get chain ID and populate placeholder - setChainId(`Chain ID: ${await web3.eth.getChainId()}`); - } - - async function getLatestBlock() { - if (web3 === null) { - return; - } - - // get latest block and populate placeholder - setLatestBlock(`Latest Block: ${await web3.eth.getBlockNumber()}`); - - // subscribe to new blocks and update UI when a new block is created - const blockSubscription = await web3.eth.subscribe("newBlockHeaders"); - blockSubscription.on("data", (block) => { - setLatestBlock(`Latest Block: ${block.number}`); - }); - } - - getChainId(); - getLatestBlock(); - }, [web3]); - - // highlight-start - // click event for "Request MetaMask Accounts" button - async function requestAccounts() { - if (web3 === null) { - return; - } - - // request accounts from MetaMask - await window.ethereum.request({ method: "eth_requestAccounts" }); - document.getElementById("requestAccounts")?.remove(); - - // get list of accounts - const allAccounts = await web3.eth.getAccounts(); - setAccounts(allAccounts); - // get the first account and populate placeholder - setConnectedAccount(`Account: ${allAccounts[0]}`); - } - // highlight-end - return ( - <> -
- {warning} -
-
{provider}
-
{chainId}
-
{latestBlock}
- // highlight-start -
{connectedAccount}
-
- -
- // highlight-end - - ); -} - -export default App; -``` - -The component has been updated to include a placeholder for the MetaMask account, as well as a button that is used to request the accounts from MetaMask. If no Ethereum provider is found, the button to request the MetaMask accounts is disabled. - -A function named `requestAccounts` has been defined as the click-handler for the new button. The accounts are requested by invoking `window.ethereum.request({ method: ["eth_requestAccounts"] })` and once the request has been approved, the account addresses are available by calling [`web3.eth.getAccounts()`](https://docs.web3js.org/api/web3-eth/class/Web3Eth#getAccounts). MetaMask can be used to manage multiple accounts, but this tutorial only makes use of a single account. More information about the [`window.ethereum.request`](https://docs.metamask.io/wallet/reference/provider-api/#request) function and [`eth_requestAccounts`](https://docs.metamask.io/wallet/reference/eth_requestaccounts/) RPC call can be found in the MetaMask documentation. - -Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. Click the button that says "Request MetaMask Accounts", which should activate MetaMask. After accepting the MetaMask notifications, the address of the MetaMask account should be displayed on the webpage. MetaMask will remember that the webpage has been given permission to access its accounts and it will not be necessary to accept any confirmations when requesting accounts in the future. - -## Step #5: Sign a Message with a MetaMask Account - -Replace the contents of `src/App.tsx` with the following (take note of the highlighted sections, which are new): - -```tsx -import { useEffect, useState } from "react"; -import { Web3 } from "web3"; - -function App() { - const [web3, setWeb3] = useState(null); - const [warning, setWarning] = useState(null); - const [provider, setProvider] = useState(null); - const [chainId, setChainId] = useState(null); - const [latestBlock, setLatestBlock] = useState(null); - const [accountButtonDisabled, setAccountButtonDisabled] = - useState(false); - const [accounts, setAccounts] = useState(null); - const [connectedAccount, setConnectedAccount] = useState(null); - // highlight-start - const [messageToSign, setMessageToSign] = useState(null); - const [signingResult, setSigningResult] = useState(null); - // highlight-end - useEffect(() => { - // ensure that there is an injected the Ethereum provider - if (window.ethereum) { - // use the injected Ethereum provider to initialize Web3.js - setWeb3(new Web3(window.ethereum)); - // check if Ethereum provider comes from MetaMask - if (window.ethereum.isMetaMask) { - setProvider("Connected to Ethereum with MetaMask."); - } else { - setProvider("Non-MetaMask Ethereum provider detected."); - } - } else { - // no Ethereum provider - instruct user to install MetaMask - setWarning("Please install MetaMask"); - setAccountButtonDisabled(true); - } - }, []); - - useEffect(() => { - async function getChainId() { - if (web3 === null) { - return; - } - - // get chain ID and populate placeholder - setChainId(`Chain ID: ${await web3.eth.getChainId()}`); - } - - async function getLatestBlock() { - if (web3 === null) { - return; - } - - // get latest block and populate placeholder - setLatestBlock(`Latest Block: ${await web3.eth.getBlockNumber()}`); - - // subscribe to new blocks and update UI when a new block is created - const blockSubscription = await web3.eth.subscribe("newBlockHeaders"); - blockSubscription.on("data", (block) => { - setLatestBlock(`Latest Block: ${block.number}`); - }); - } - - getChainId(); - getLatestBlock(); - }, [web3]); - - // click event for "Request MetaMask Accounts" button - async function requestAccounts() { - if (web3 === null) { - return; - } - - // request accounts from MetaMask - await window.ethereum.request({ method: "eth_requestAccounts" }); - document.getElementById("requestAccounts")?.remove(); - - // get list of accounts - const allAccounts = await web3.eth.getAccounts(); - setAccounts(allAccounts); - // get the first account and populate placeholder - setConnectedAccount(`Account: ${allAccounts[0]}`); - } - - // highlight-start - // click event for "Sign Message" button - async function signMessage() { - if (web3 === null || accounts === null || messageToSign === null) { - return; - } - - // sign message with first MetaMask account - const signature = await web3.eth.personal.sign( - messageToSign, - accounts[0], - "", - ); - - setSigningResult(signature); - } - // highlight-end - return ( - <> -
- {warning} -
-
{provider}
-
{chainId}
-
{latestBlock}
-
{connectedAccount}
-
- -
- // highlight-start -
- { - setMessageToSign(e.target.value); - }} - id="messageToSign" - placeholder="Message to Sign" - disabled={connectedAccount === null} - /> - -
{signingResult}
-
- // highlight-end - - ); -} - -export default App; -``` - -`src/App.tsx` has been updated to include inputs for signing a message with the MetaMask account. Initially, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the signing operation. - -A function named `signMessage` has been defined as the click-handler for the "Sign Message" button. This function calls the [`web3.eth.personal.sign`](/api/web3-eth-personal/class/Personal#sign) method. The first parameter to this method is the message to be signed, which is taken from the input field. The second parameter is the address of the account to use for signing. The third parameter is the passphrase to decrypt the account, which is not used in this example since MetaMask is managing the account. Once the message has been signed, the placeholder is updated with the signed message. - -Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be disabled input fields below the "Request MetaMask Accounts" button. Click the button to request the accounts (remember, it will not be necessary to accept any MetaMask notifications this time). If everything is working properly, the address of the MetaMask account should be displayed on the webpage and the input fields should become enabled. Type a message (e.g. "Hello, Web3.js!") in the input field and click the "Sign Message" button. If everything is working properly, a MetaMask notification will appear. After the notification has been accepted, the signed message should appear beneath the input fields. - -## Step #6: Verify the Account Used to Sign a Message - -Replace the contents of `src/App.tsx` with the following (take note of the highlighted sections, which are new): - -```tsx -import { useEffect, useState } from "react"; -import { Web3 } from "web3"; - -function App() { - const [web3, setWeb3] = useState(null); - const [warning, setWarning] = useState(null); - const [provider, setProvider] = useState(null); - const [chainId, setChainId] = useState(null); - const [latestBlock, setLatestBlock] = useState(null); - const [accountButtonDisabled, setAccountButtonDisabled] = - useState(false); - const [accounts, setAccounts] = useState(null); - const [connectedAccount, setConnectedAccount] = useState(null); - const [messageToSign, setMessageToSign] = useState(null); - const [signingResult, setSigningResult] = useState(null); - // highlight-start - const [originalMessage, setOriginalMessage] = useState(null); - const [signedMessage, setSignedMessage] = useState(null); - const [signingAccount, setSigningAccount] = useState(null); - // highlight-end - useEffect(() => { - // ensure that there is an injected the Ethereum provider - if (window.ethereum) { - // use the injected Ethereum provider to initialize Web3.js - setWeb3(new Web3(window.ethereum)); - // check if Ethereum provider comes from MetaMask - if (window.ethereum.isMetaMask) { - setProvider("Connected to Ethereum with MetaMask."); - } else { - setProvider("Non-MetaMask Ethereum provider detected."); - } - } else { - // no Ethereum provider - instruct user to install MetaMask - setWarning("Please install MetaMask"); - setAccountButtonDisabled(true); - } - }, []); - - useEffect(() => { - async function getChainId() { - if (web3 === null) { - return; - } - - // get chain ID and populate placeholder - setChainId(`Chain ID: ${await web3.eth.getChainId()}`); - } - - async function getLatestBlock() { - if (web3 === null) { - return; - } - - // get latest block and populate placeholder - setLatestBlock(`Latest Block: ${await web3.eth.getBlockNumber()}`); - - // subscribe to new blocks and update UI when a new block is created - const blockSubscription = await web3.eth.subscribe("newBlockHeaders"); - blockSubscription.on("data", (block) => { - setLatestBlock(`Latest Block: ${block.number}`); - }); - } - - getChainId(); - getLatestBlock(); - }, [web3]); - - // click event for "Request MetaMask Accounts" button - async function requestAccounts() { - if (web3 === null) { - return; - } - - // request accounts from MetaMask - await window.ethereum.request({ method: "eth_requestAccounts" }); - document.getElementById("requestAccounts")?.remove(); - - // get list of accounts - const allAccounts = await web3.eth.getAccounts(); - setAccounts(allAccounts); - // get the first account and populate placeholder - setConnectedAccount(`Account: ${allAccounts[0]}`); - } - - // click event for "Sign Message" button - async function signMessage() { - if (web3 === null || accounts === null || messageToSign === null) { - return; - } - - // sign message with first MetaMask account - const signature = await web3.eth.personal.sign( - messageToSign, - accounts[0], - "", - ); - - setSigningResult(signature); - } - - // highlight-start - // click event for "Recover Account" button - async function recoverAccount() { - if (web3 === null || originalMessage === null || signedMessage === null) { - return; - } - // recover account from signature - const account = await web3.eth.personal.ecRecover( - originalMessage, - signedMessage, - ); - - setSigningAccount(account); - } - // highlight-end - return ( - <> -
- {warning} -
-
{provider}
-
{chainId}
-
{latestBlock}
-
{connectedAccount}
-
- -
-
- { - setMessageToSign(e.target.value); - }} - id="messageToSign" - placeholder="Message to Sign" - disabled={connectedAccount === null} - /> - -
{signingResult}
-
- // highlight-start -
- { - setOriginalMessage(e.target.value); - }} - id="originalMessage" - placeholder="Original Message" - disabled={connectedAccount === null} - /> - { - setSignedMessage(e.target.value); - }} - id="signedMessage" - placeholder="Signed Message" - disabled={connectedAccount === null} - /> - -
{signingAccount}
-
- // highlight-end - - ); -} - -export default App; -``` - -As in the previous step, `src/App.tsx` has been updated to include inputs for recovering the account that was used to sign a message. As before, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the recovery operation. - -A function named `recoverAccount` has been defined as the click-handler for the "Recover Account" button. This function calls the [`web3.eth.personal.ecRecover`](/api/web3-eth-personal/class/Personal#ecRecover) method. The first parameter to this method is the original unsigned message, which is taken from the first input field. The second parameter is the signed message, which is taken from the second input field. Once the account has been recovered, the placeholder is updated with the address of the account. - -Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be additional disabled input fields below those from the previous step. Follow the same steps as before to request the accounts from MetaMask and sign a message, then copy and paste the original message and message signature (starting with the leading `0x` characters) into the new input fields. Click the "Recover Account" button. If everything is working properly, the address of the account that was used to sign the message should appear below the new input fields. This address should match the one that is displayed above the input fields that were used to sign the message. - -## Conclusion - -This tutorial demonstrated using Web3.js with MetaMask, including using the MetaMask injected provider and using a MetaMask account to sign a message. To use the MetaMask injected provider with Web3.js, simply construct a new instance of the `Web3` class with the `window.ethereum` property. To request access to the MetaMask accounts, use `window.ethereum.request({ method: "eth_requestAccounts" })` - once the user has confirmed this request, the MetaMask accounts will be available with `web3.eth.getAccounts()`. When the MetaMask injected provider handles a request that requires the use of a MetaMask account, MetaMask will prompt the user to confirm the request. diff --git a/docs/docs/guides/wallet/metamask-vanilla.md b/docs/docs/guides/wallet/metamask-vanilla.md deleted file mode 100644 index ef55e9bcf8c..00000000000 --- a/docs/docs/guides/wallet/metamask-vanilla.md +++ /dev/null @@ -1,480 +0,0 @@ ---- -sidebar_position: 4 -sidebar_label: 'Tutorial: Connecting to Metamask with Vanilla JS' ---- - -# Connecting to Metamask with Vanilla JS - -[MetaMask](https://metamask.io/) is a powerful [wallet application](https://ethereum.org/en/wallets/) that makes it easy for Ethereum users to securely manage their accounts. Web3.js developers who are building front-end user-facing applications ("[dApps](https://ethereum.org/en/dapps/#what-are-dapps)") can easily integrate their dApp with MetaMask to allow users to safely use their own accounts. This tutorial covers the basics of using Web3.js with MetaMask, including using MetaMask as the Web3.js [provider](/guides/web3_providers_guide/) and using a MetaMask account to [sign](https://ethereum.org/en/glossary/#digital-signatures) a message. - -## Overview - -Here is a high-level overview of the steps we will be taking in this tutorial: - -1. Review prerequisites -2. Create a new directory for the tutorial -3. Use MetaMask as the Web3.js provider -4. Request access to the MetaMask accounts -5. Sign a message with a MetaMask account -6. Verify the account used to sign a message - -:::tip -If you encounter any issues while following this guide or have any questions, don't hesitate to seek assistance. Our friendly community is ready to help you out! Join our [Discord](https://discord.gg/F4NUfaCC) server and head to the **#web3js-general** channel to connect with other developers and get the support you need. -::: - -## Step 1: Prerequisites - -This tutorial assumes basic familiarity with the command line as well as familiarity with JavaScript and HTML. [Node.js](https://nodejs.org/) is used to run a local HTTP server. Before starting this tutorial, ensure that Node.js and its package manager, npm, are installed. - -```bash -$: node -v -# your version may be different, but it's best to use the current stable version -v18.16.1 -$: npm -v -9.5.1 -``` - -Make sure that MetaMask is [installed](https://metamask.io/download/) as a browser extension and the steps to create an account (e.g. create a password, review the seed phrase) have been completed. - -## Step 2: Create a New Directory for the Tutorial - -Create a new directory for the tutorial and navigate into it: - -```bash -mkdir web3js-metamask-tutorial -cd web3js-metamask-tutorial -``` - -## Step 3: Use MetaMask as the Web3.js Provider - -Create a new file called `index.html` in your project directory and add the following HTML to it: - -```html - - - - - - Web3.js MetaMask Tutorial - - - - - -
-
-
-
- - - -``` - -Review the comments in `index.html`. This document imports Web3.js, creates several placeholders that will be used to display network information, and defines a script that checks for an [injected provider](/guides/web3_providers_guide/#injected-provider). If an injected provider is found, it's used to construct a new `Web3` instance and connect to the Ethereum network. A check is performed to ensure that the injected provider is coming from MetaMask and the result of this check is displayed to the user. Once connected through the injected provider, the script updates the placeholders with the chain ID and latest block number, and creates an event subscription to update the block number as new blocks are created. If no injected provider is found, the user is instructed to install MetaMask. - -To start a local HTTP server to serve `index.html`, execute the following command in the project directory: - -```bash -npx watch-http-server . -``` - -The output should look like: - -``` -Websocket Server Listening on Port: 8086 -Starting up http-server, serving . on: http://0.0.0.0:8080 -Hit CTRL-C to stop the server -Scanned working directory. ready for changes.. -``` - -The HTTP server needs to remain running in the terminal that was used to start it. Any changes that are made in the project directory will cause the webpage to automatically refresh. - -Use a MetaMask-enabled web browser to navigate to the URL from the output (http://0.0.0.0:8080 in the example above). If everything is set up correctly, the webpage should state that it is connected to the Ethereum network with MetaMask and list the chain ID (for the default Ethereum Mainnet network this value should be `1`) and latest block number. The latest block number should change when new blocks are created. - -## Step 4: Request Access to the MetaMask Accounts - -Replace the contents of `index.html` with the following (take note of the highlighted sections, which are new): - -```html - - - - - - Web3.js MetaMask Tutorial - - - - - -
-
-
- -
-
- - -
- -
- - - - -``` - -The file has been updated to include a placeholder for the MetaMask account, as well as a button that is used to request the accounts from MetaMask. - -Once connected to MetaMask, the script now registers a click event for the new button. The accounts are requested by invoking `window.ethereum.request({ method: ["eth_requestAccounts"] })` and once the request has been approved, the account addresses are available by calling [`web3.eth.getAccounts()`](https://docs.web3js.org/api/web3-eth/class/Web3Eth#getAccounts). MetaMask can be used to manage multiple accounts, but this tutorial only makes use of a single account. More information about the [`window.ethereum.request`](https://docs.metamask.io/wallet/reference/provider-api/#request) function and [`eth_requestAccounts`](https://docs.metamask.io/wallet/reference/eth_requestaccounts/) RPC call can be found in the MetaMask documentation. - -If no Ethereum provider is found, the button to request the MetaMask accounts is disabled. - -Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. Click the button that says "Request MetaMask Accounts", which should activate MetaMask. After accepting the MetaMask notifications, the address of the MetaMask account should be displayed on the webpage. MetaMask will remember that the webpage has been given permission to access its accounts and it will not be necessary to accept any confirmations when requesting accounts in the future. - -## Step #5: Sign a Message with a MetaMask Account - -Replace the contents of `index.html` with the following (take note of the highlighted sections, which are new): - -```html - - - - - - Web3.js MetaMask Tutorial - - - - - -
-
-
-
-
- -
- -
- - -
- - -
-
- - - - -``` - -`index.html` has been updated to include inputs for signing a message with the MetaMask account. Initially, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the signing operation. - -Inside the click event for the "Request MetaMask Accounts" button, the signing inputs are initialized. First, the inputs are enabled. Then, a click event is registered for the "Sign" button. This click event calls the [`web3.eth.personal.sign`](/api/web3-eth-personal/class/Personal#sign) method. The first parameter to this method is the message to be signed, which is taken from the input field. The second parameter is the address of the account to use for signing. The third parameter is the passphrase to decrypt the account, which is not used in this example since MetaMask is managing the account. Once the message has been signed, the placeholder is updated with the signed message. - -Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be disabled input fields below the "Request MetaMask Accounts" button. Click the button to request the accounts (remember, it will not be necessary to accept any MetaMask notifications this time). If everything is working properly, the address of the MetaMask account should be displayed on the webpage and the input fields should become enabled. Type a message (e.g. "Hello, Web3.js!") in the input field and click the "Sign Message" button. If everything is working properly, a MetaMask notification will appear. After the notification has been accepted, the signed message should appear beneath the input fields. - -## Step #6: Verify the Account Used to Sign a Message - -Replace the contents of `index.html` with the following (take note of the highlighted sections, which are new): - -```html - - - - - - Web3.js MetaMask Tutorial - - - - - -
-
-
-
-
- -
- -
- -
- - -
-
- - -
- - - -
-
- - - - -``` - -As in the previous step, `index.html` has been updated to include inputs for recovering the account that was used to sign a message. As before, these inputs are disabled - they will be enabled once the page has access to the MetaMask account. A placeholder has been added for the result of the recovery operation. - -Inside the click event for the "Request MetaMask Accounts" button, the recovery inputs are initialized. First, the inputs are enabled. Then, a click event is registered for the "Recover" button. This click event calls the [`web3.eth.personal.ecRecover`](/api/web3-eth-personal/class/Personal#ecRecover) method. The first parameter to this method is the original unsigned message, which is taken from the first input field. The second parameter is the signed message, which is taken from the second input field. Once the account has been recovered, the placeholder is updated with the address of the account. - -Go back to the MetaMask-enabled browser and review the webpage, which should have been automatically refreshed to display the changes. There should now be additional disabled input fields below those from the previous step. Follow the same steps as before to request the accounts from MetaMask and sign a message, then copy and paste the original message and message signature (starting with the leading `0x` characters) into the new input fields. Click the "Recover Account" button. If everything is working properly, the address of the account that was used to sign the message should appear below the new input fields. This address should match the one that is displayed above the input fields that were used to sign the message. - -## Conclusion - -This tutorial demonstrated using Web3.js with MetaMask, including using the MetaMask injected provider and using a MetaMask account to sign a message. To use the MetaMask injected provider with Web3.js, simply construct a new instance of the `Web3` class with the `window.ethereum` property. To request access to the MetaMask accounts, use `window.ethereum.request({ method: "eth_requestAccounts" })` - once the user has confirmed this request, the MetaMask accounts will be available with `web3.eth.getAccounts()`. When the MetaMask injected provider handles a request that requires the use of a MetaMask account, MetaMask will prompt the user to confirm the request. diff --git a/docs/docs/guides/wallet/tx-types.md b/docs/docs/guides/wallet/tx-types.md deleted file mode 100644 index 1e58a6b840a..00000000000 --- a/docs/docs/guides/wallet/tx-types.md +++ /dev/null @@ -1,280 +0,0 @@ ---- -sidebar_position: 3 -sidebar_label: 'Transaction Types' ---- - -# Transactions - -In this tutorial, we will explore how to send different types of [transactions](https://ethereum.org/en/developers/docs/transactions/) using web3.js, focusing on Ethereum's evolving transaction formats. We'll start with [legacy transactions (Transaction Type 0)](#transaction-type-0-legacy). Next, we'll delve into Transaction [Type 1 (EIP-2930)](#transaction-type-1-eip-2930), which introduces access lists to optimize gas usage. Finally, we'll cover [Transaction Type 2 (EIP-1559)](#transaction-type-2-eip-1559), the current default, which allows users to specify maximum fees and priority tips for more efficient and cost-effective transactions. Each section will include practical code examples to demonstrate sending raw transactions and interacting with ERC20 tokens on the Sepolia test network - -:::note -Web3.js uses transaction type 2 by default -::: - -## Transaction Type 0 (Legacy) - -### Raw Transaction - -A Legacy Transaction refers to a transaction that was created using an older version of Ethereum's transaction format, also known as "transaction type 0". This transaction format was used before the EIP-1559 upgrade, which was implemented in August 2021. - -```ts -import { Web3 } from "web3"; - -const web3 = new Web3("https://rpc2.sepolia.org"); // RPC node url - -async function txLegacy() { - const wallet = web3.eth.wallet.add("YOUR_PRIVATE_KEY"); // make sure you have funds - - const sender = wallet[0].address; - const recipient = "0x807BFe4940016B5a7FdA19482042917B02e68359"; - const value = 1; // wei - const nonce = await web3.eth.getTransactionCount(sender); - const gas = 21000; - const gasPrice = await web3.eth.getGasPrice(); - - const tx = { - from: sender, - to: recipient, - value, - nonce, - gas, - gasPrice, - // highlight-next-line - type: 0, - }; - - const txReceipt = await web3.eth.sendTransaction(tx); - console.log("Tx hash", txReceipt.transactionHash); -} - -txLegacy(); -``` - -### ERC20 Interaction - -```ts -import { Web3 } from "web3"; - -const web3 = new Web3("https://rpc2.sepolia.org"); - -//WETH token in Sepolia https://sepolia.etherscan.io/address/0xfff9976782d46cc05630d1f6ebab18b2324d6b14#code -const ADDRESS_WETH_SEPOLIA = "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14"; -const ABI = [ - { - constant: false, - inputs: [ - { - name: "dst", - type: "address", - }, - { - name: "wad", - type: "uint256", - }, - ], - name: "transfer", - outputs: [ - { - name: "", - type: "bool", - }, - ], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, -]; - -async function transfer() { - //initialize wallet - const wallet = web3.eth.accounts.wallet.add("YOUR_PRIVATE_KEY"); //make sure you have WETH tokens in the Sepolia network - //you can swap Sepolia tokens for WETH here https://app.uniswap.org/swap?chain=sepolia - - //initialize WETH contract in sepolia - const myERC20 = new web3.eth.Contract(ABI, ADDRESS_WETH_SEPOLIA); - - const TO = "0xEA9eEca67682Cd9c6Ce3DdD1681049D7A897289F"; //address to send the tokens to - const VALUE = 1; //wei value, dont forget to multiply by decimals - - //send transfer and specify the type - const txReceipt = await myERC20.methods.transfer(TO, VALUE).send({ - from: wallet[0].address, - // highlight-next-line - type: 0, - }); - - console.log(txReceipt.transactionHash); - //=> 0x5f2087c22166f3a1909c40ce537dd564dc3d4c70c5be02f35c6406a628123b16 -} - -transfer(); -``` - -## Transaction Type 1 (EIP-2930) - -This EIP was introduced in April 2021, it introduces a feature called 'Access List.' This improvement allows saving gas on cross-contract calls by declaring in advance which contract and storage slots will be accessed. - -### Raw Transaction - -```ts -import { Web3 } from "web3"; - -const web3 = new Web3("https://rpc2.sepolia.org"); - -async function txEIP2930() { - const wallet = web3.eth.wallet.add("YOUR_PRIVATE_KEY"); - - const sender = wallet[0].address; - const contractAddress1 = "0x..."; - const gas = 500000; //could be higher - const gasPrice = await web3.eth.getGasPrice(); - const data = "0x9a67c8b100000000000000000000000000000000000000000000000000000000000004d0" - - - // highlight-start - //create access list using web3.eth - const accessListData = await web3.eth.createAccessList({ - from: sender, - to: contractAddress1, - data, - }); - // highlight-end - - console.log(accessListData) - /* - => - { - // highlight-start - "accessList": [ - { - "address": "0x15859bdf5aff2080a9968f6a410361e9598df62f", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - // highlight-end - "gasUsed": "0x7671" - } - */ - - const tx = { - from: sender, - to: contractAddress1, //the contract we are calling - data, - gas, - gasPrice, - // highlight-next-line - type: 1, - // highlight-next-line - accessList: accessListData.accessList //access the object `accessList` - }; - - const txReceipt = await web3.eth.sendTransaction(tx); - - console.log("Tx hash", txReceipt.transactionHash); -} - -txEIP2930() -``` - -## Transaction Type 2 (EIP-1559) - -When a user creates an EIP-1559 transaction, they specify the maximum fee they are willing to pay `maxFeePerGas` as well as a tip `maxPriorityFeePerGas` to incentivize the miner. The actual fee paid by the user is then determined by the network based on the current demand for block space and the priority of the transaction. - -### Raw Transaction - -```ts -import { Web3 } from "web3"; - -const web3 = new Web3("https://rpc2.sepolia.org"); - -async function txEIP1559() { - const wallet = web3.eth.wallet.add("YOUR_PRIVATE_KEY"); //make sure you have funds - - const sender = wallet[0].address; - const recipient = "0x807BFe4940016B5a7FdA19482042917B02e68359"; - const value = 1; //wei - const nonce = await web3.eth.getTransactionCount(sender); - const gasLimit = 21000; - const maxFeePerGas = Number((await web3.eth.calculateFeeData()).maxFeePerGas); - const maxPriorityFeePerGas = Number((await web3.eth.calculateFeeData()).maxPriorityFeePerGas); - - const tx = { - from: sender, - to: recipient, - value, - nonce, - gasLimit, - maxFeePerGas, - maxPriorityFeePerGas, - // highlight-next-line - type: 2, - }; - - const txReceipt = await web3.eth.sendTransaction(tx); - console.log("Tx hash", txReceipt.transactionHash); -} - -txEIP1559(); -``` - -### ERC20 Interaction - -```ts -import { Web3 } from "web3"; - -const web3 = new Web3("https://rpc2.sepolia.org"); - -//WETH token in Sepolia https://sepolia.etherscan.io/address/0xfff9976782d46cc05630d1f6ebab18b2324d6b14#code -const ADDRESS_WETH_SEPOLIA = "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14"; -const ABI = [ - { - constant: false, - inputs: [ - { - name: "dst", - type: "address", - }, - { - name: "wad", - type: "uint256", - }, - ], - name: "transfer", - outputs: [ - { - name: "", - type: "bool", - }, - ], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, -]; - -async function transfer() { - //initialize wallet - const wallet = web3.eth.accounts.wallet.add("YOUR_PRIVATE_KEY"); //make sure you have WETH tokens in the Sepolia network - //you can swap Sepolia tokens for WETH here https://app.uniswap.org/swap?chain=sepolia - - //initialize WETH contract in sepolia - const myERC20 = new web3.eth.Contract(ABI, ADDRESS_WETH_SEPOLIA); - - const TO = "0xEA9eEca67682Cd9c6Ce3DdD1681049D7A897289F"; //address to send the tokens to - const VALUE = 1; //wei value, dont forget to multiply by decimals - - //send transfer and specify the type - const txReceipt = await myERC20.methods.transfer(TO, VALUE).send({ - from: wallet[0].address, - // highlight-next-line - type: 2, - }); - - console.log(txReceipt.transactionHash); - //=> 0x174bc88023be4af431fad1693a59f7a41135238510cdcd00f15f6409b5471d77 -} - -transfer(); -``` \ No newline at end of file diff --git a/docs/docs/guides/wallet/web3_modal_guide/react.md b/docs/docs/guides/wallet/web3_modal_guide/react.md deleted file mode 100644 index 1bcc69c6af7..00000000000 --- a/docs/docs/guides/wallet/web3_modal_guide/react.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: 'Web3Modal with React' ---- - -# Web3Modal with React and web3js - -## Live code editor - - - - - -## Installation - -For this guide we will be creating a new project will need to install dependancies. We will be using vite to locally host the app, React and web3modal-web3js - -```bash -npm install web3modal-web3js react react-dom -npm install --save-dev vite @vitejs/plugin-react -``` - -## Implementation - -Within the root of the project create `index.html` -```html - - - - - - React Web3 example - - -
- - - -``` - -Now we will add the Web3modal code within `src/Web3modal.tsx` -```typescript - -import { createWeb3Modal, defaultConfig } from 'web3modal-web3/react' - -// 1. Get projectId, Your Project ID can be obtained from walletconnect.com -const projectId = 'YOUR_PROJECT_ID' - -// 2. Set chains -const mainnet = { - chainId: 1, - name: 'Ethereum', - currency: 'ETH', - explorerUrl: 'https://etherscan.io', - rpcUrl: 'https://cloudflare-eth.com' -} - -// 3. Create a metadata object -const metadata = { - name: 'My Website', - description: 'My Website description', - url: 'https://mywebsite.com', // origin must match your domain & subdomain - icons: ['https://avatars.mywebsite.com/'] -} - -// 4. Create web3 config -const web3Config = defaultConfig({ - /*Required*/ - metadata, - - /*Optional*/ - enableEIP6963: true, // true by default - enableInjected: true, // true by default - enableCoinbase: true, // true by default - rpcUrl: '...', // used for the Coinbase SDK - defaultChainId: 1, // used for the Coinbase SDK -}) - -// 5. Create a Web3Modal instance -createWeb3Modal({ - web3Config, - chains: [mainnet], - projectId, - enableAnalytics: true // Optional - defaults to your Cloud configuration -}) - -export default function App() { - return -} -``` - -Set up vite configs within root `vite.config.js` -```javascript -import react from '@vitejs/plugin-react' -import { defineConfig } from 'vite' - -export default defineConfig({ - plugins: [react()] -}) -``` - -And finally add react to the app `src/main.tsx` -```typescript -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App.js' - -ReactDOM.createRoot(document.getElementById('app')!).render( - - - -) -``` - -You are finished and have successfully created Web3modal with React! - -:::info -- For additional information take a look into the interactive code editor above. -- Learn more about Web3modal [here](https://docs.walletconnect.com/web3modal/about) -::: - diff --git a/docs/docs/guides/web3_upgrade_guide/_category_.yml b/docs/docs/guides/web3_upgrade_guide/_category_.yml deleted file mode 100644 index 8335efbea79..00000000000 --- a/docs/docs/guides/web3_upgrade_guide/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -label: '⬆️ Upgrading' -collapsible: true -collapsed: true -link: null -position: 13 diff --git a/docs/docs/guides/web3_utils_module/_category_.yml b/docs/docs/guides/web3_utils_module/_category_.yml deleted file mode 100644 index 95a9529cfce..00000000000 --- a/docs/docs/guides/web3_utils_module/_category_.yml +++ /dev/null @@ -1,5 +0,0 @@ -label: '📦 Web3 Utils module' -collapsible: true -collapsed: true -link: null -position: 10 \ No newline at end of file diff --git a/packages/web3/src/types.ts b/packages/web3/src/types.ts index ef9bcc379cf..3b87896789c 100644 --- a/packages/web3/src/types.ts +++ b/packages/web3/src/types.ts @@ -52,7 +52,7 @@ export interface Web3EthInterface extends Eth { * Extended [Contract](/api/web3-eth-contract/class/Contract) constructor for main `web3` object. See [Contract](/api/web3-eth-contract/class/Contract) for further details. * * You can use `.setProvider` on this constructor to set provider for **all the instances** of the contracts which were created by `web3.eth.Contract`. - * Please check the {@doclink guides/web3_upgrade_guide/x/providers_migration_guide | following guide} to understand more about setting provider. + * Please check the {@doclink guides/web3_upgrade_guide/providers_migration_guide | following guide} to understand more about setting provider. * * ```ts * web3.eth.Contract.setProvider(myProvider)