diff --git a/docs/docs/guides/getting_started/quickstart.md b/docs/docs/guides/getting_started/quickstart.md index c1db2a9fdc8..886b2690e19 100644 --- a/docs/docs/guides/getting_started/quickstart.md +++ b/docs/docs/guides/getting_started/quickstart.md @@ -43,7 +43,7 @@ import { Web3 } from 'web3'; ## Initialize `Web3` with a provider -[Providers](/guides/web3_providers_guide/) are objects that are responsible for enabling connectivity with the Ethereum network. The `Web3` object must be initialized with a valid provider to function as intended. Web3.js supports [HTTP](/guides/web3_providers_guide/#http-provider), [WebSocket](/guides/web3_providers_guide/#websocket-provider), and [IPC](/guides/web3_providers_guide/#ipc-provider) providers, and exposes packages for working with each type of provider. +[Providers](/guides/web3_providers_guide/) are services that are responsible for enabling connectivity with the Ethereum network. The `Web3` object must be initialized with a valid provider to function as intended. Web3.js supports [HTTP](/guides/web3_providers_guide/#http-provider), [WebSocket](/guides/web3_providers_guide/#websocket-provider), and [IPC](/guides/web3_providers_guide/#ipc-provider) providers, and exposes packages for working with each type of provider. 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. @@ -248,7 +248,7 @@ console.log(eventTransfer); Web3.js allows user to subscribe to events for real-time notification of important contract interactions. Here is an example of creating a subscription to the Uniswap token's `Transfer` event: :::note -You MUST initialize the `Web3` object with a [WebSocket](/guides/web3_providers_guide/#websocket-provider) provider to subscribe to live events. +HTTP providers do not support real-time event subscriptions. Use one of the other [provider types](/guides/web3_providers_guide/#providers-types) to subscribe to real-time events. ::: ```ts diff --git a/docs/docs/guides/web3_providers_guide/index.md b/docs/docs/guides/web3_providers_guide/index.md index e3ecc880cb0..1c1a0c334cb 100644 --- a/docs/docs/guides/web3_providers_guide/index.md +++ b/docs/docs/guides/web3_providers_guide/index.md @@ -5,20 +5,9 @@ sidebar_label: 'Mastering Providers' # Web3js providers overview +Providers are services that are responsible for enabling Web3.js connectivity with the Ethereum network. Using a provider to connect your application to an Ethereum node is necessary for querying data, sending transactions, and interacting with smart contracts. This guide will explore the different types of Web3.js providers, how to set them up, and how to use them in an application. -## Live code editor - - - -## Introduction - -web3.js providers are objects responsible for enabling connectivity with the Ethereum network in various ways. Connecting your web application to an Ethereum node is necessary for sending transactions, querying data, and interacting with smart contracts on the network. In this guide, we will explore the different types of providers available in web3.js, how to set them up, and how to use them in your code. - -Connecting to a chain happens through a provider. You can pass the provider to the constructor as in the following example: - -:::tip -If you want to subscribe to live events in the blockchain, you should use [`WebSocket provider`](#websocket-provider) or [`IPC provider`](#ipc-provider) -::: +A provider is typically supplied when constructing a new `Web3` object: ```typescript title='Initialize a provider' import { Web3 } from 'web3'; @@ -29,36 +18,38 @@ const web3 = new Web3(/* PROVIDER*/); await web3.eth.getBlockNumber(); ``` -The created `Web3` instance will use the passed provider to interact with the blockchain network. This interaction happens when sending a request and receiving the response, and possibly when listening to provider events (if the provider support this). +The new `Web3` instance will use the supplied provider to interact with the blockchain network. This interaction happens when sending requests and receiving responses, and possibly when listening to provider events (if the provider supports this). ## Providers Types -web3.js supports several types of providers, each with its own unique features or specific use cases. Here are the main types: +Web3.js supports several types of providers for different use cases. Here are the available types: -1. [HTTP Provider](/api/web3-providers-http/class/HttpProvider) -2. [WebSocket Provider](/api/web3-providers-ws/class/WebSocketProvider) -3. [IPC Provider (for Node.js)](/api/web3-providers-ipc/class/IpcProvider) -4. [Third-party Providers (Compliant with EIP 1193)](https://eips.ethereum.org/EIPS/eip-1193) +1. [HTTP Provider](#http-provider) +2. [WebSocket Provider](#websocket-provider) +3. [IPC Provider (for Node.js)](#ipc-provider) +4. [Injected Providers (Compliant with EIP 1193)](#injected-provider) -A string containing string url for `http`/`https` or `ws`/`wss` protocol. And when a string is passed, an instance of the compatible class above will be created accordingly. ex. WebSocketProvider instance will be created for string containing `ws` or `wss`. And you access this instance by calling `web3.provider` to read the provider and possibly register an event listener. +HTTP and WebSocket providers can be supplied as URL strings. All provider types can be supplied by constructing one of the [`SupportedProviders`](/api/web3/namespace/types#SupportedProviders) types. -:::tip -The passed provider can be either type `string` or one of the [`SupportedProviders`](/api/web3-core#SupportedProviders). And if it is passed as a string, then internally the compatible provider object will be created and used. -::: +Keep reading to learn more about the different types of providers and how to use them. ### HTTP Provider -``` ts title='Initialize HTTP Provider' +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' 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() // ↳ 18849658n -// or +// OR +//supply an HTTP provider by constructing a new HttpProvider //highlight-next-line const web3_2 = new Web3(new HttpProvider('https://mainnet.infura.io/v3/YOUR_INFURA_ID')); @@ -66,18 +57,53 @@ await web3.eth.getBlockNumber() // ↳ 18849658n ``` +#### Configuring HTTP Providers + +HTTP providers can be configured by including an [`HttpProviderOptions`](/api/web3-providers-http/interface/HttpProviderOptions/) object in the [`HttpProvider` constructor](/api/web3-providers-http/class/HttpProvider#constructor). The `HttpProviderOptions` type has a single property, `providerOptions`, which is a standard TypeScript [`RequestInit`](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules_typedoc_node_modules_typescript_lib_lib_dom_d_.requestinit.html) object. + +```ts title='Configuring an HTTP Provider' +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, +}; + +const web3 = new Web3(new HttpProvider('https://eth.llamarpc.com', httpOptions)); +``` + ### WebSocket provider +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' 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(); // ↳ 18849658n -// or +// OR + +//supply a WebSocket provider by constructing a new WebSocketProvider //highlight-next-line const web3_2 = new Web3(new WebSocketProvider('wss://mainnet.infura.io/ws/v3/YOUR_INFURA_ID')); @@ -85,8 +111,43 @@ await web3.eth.getBlockNumber(); // ↳ 18849658n ``` +#### Configuring WebSocket Providers + +The [`WebSocketProvider` constructor](/api/web3-providers-ws/class/WebSocketProvider#constructor) accepts two optional parameters that can be used to configure the behavior of the `WebSocketProvider`: the first parameter must be of type [`ClientRequestArgs`](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_http_d_._http_.clientrequestargs.html) or of [`ClientOptions`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e5ee5eae6a592198e469ad9f412bab8d223fcbb6/types/ws/index.d.ts#L243) and the second parameter must be of type [`ReconnectOptions`](/api/web3/namespace/utils#ReconnectOptions). + +```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, + } +); + +//OR include only ReconnectOptions +const provider = new WebSocketProvider( + `ws://localhost:8545`, + {}, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + } +); +``` + ### IPC Provider +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' import { Web3 } from 'web3'; //highlight-next-line @@ -99,27 +160,49 @@ await web3.eth.getBlockNumber(); // ↳ 18849658n ``` -## Providers Priorities +#### Configuring IPC Providers + +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). -There are multiple ways to set the provider. -```ts title='Setting a provider' -web3.setProvider(myProvider); -web3.eth.setProvider(myProvider); -web3.Contract.setProvider(myProvider); -contractInstance.setProvider(myProvider); + +```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, + } +); + +//OR include only ReconnectOptions +const provider = new IpcProvider( + '/Users/myuser/Library/Ethereum/geth.ipc', + {}, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + } +); ``` -The key rule for setting provider is as follows: +### Injected Provider -1. Any provider set on the higher level will be applied to all lower levels. e.g. Any provider set using `web3.setProvider` will also be applied to `web3.eth` object. -2. For contracts `web3.Contract.setProvider` can be used to set provider for **all instances** of contracts created by `web3.eth.Contract`. +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. ---- +## Provider Origins + +A provider may be local to an application (i.e. running on the same machine) or remote (i.e. running on a third-party server). Injected providers are a third alternative that 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. Keep reading for more examples that illustrate how to work with local, remote, and injected providers. -## Usage Scenarios +### Local Provider -### Local Geth Node +Local providers can usually be accessed via IPC, HTTP, or WebSocket. The following examples demonstrates using a local Geth node to supply the Web3.js provider. ```typescript title='IPC, HTTP and WS provider' import { Web3 } from 'web3'; @@ -144,7 +227,9 @@ web3.setProvider('ws://localhost:8546'); web3.setProvider(new Web3.providers.WebsocketProvider('ws://localhost:8546')); ``` -### Remote Node Provider +### Remote Provider + +Services like [Alchemy](https://www.alchemy.com/), [Infura](https://www.infura.io/), and [QuickNode](https://www.quicknode.com/) offer Ethereum node services that can be accessed via HTTP or Websocket. ```ts title='Alchemy, Infura, etc' // like Alchemy (https://www.alchemyapi.io/supernode) @@ -155,9 +240,11 @@ const web3 = new Web3('https://eth-mainnet.alchemyapi.io/v2/your-api-key'); ### Injected Provider -As stated above, the injected provider should be in compliance with [EIP-1193](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md). And it is tested with Ganache provider, Hardhat provider, and Incubed (IN3) as a provider. +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). -The web3.js 4.x Provider specifications are defined in [web3 base provider](https://github.com/ChainSafe/web3.js/blob/4.x/packages/web3-types/src/web3_base_provider.ts) for Injected Providers. +:::note +The following example should be run in a browser with the MetaMask extension installed. +::: ```html title='E.g, Metamask' @@ -186,197 +273,3 @@ The web3.js 4.x Provider specifications are defined in [web3 base provider](http }); ``` - -Note that the above code should be hosted in a web server (that could be a simple local web server), because many browser does not support this feature for static files located on your machine. - -## Provider Options - -There are differences in the objects that could be passed in the Provider constructors. - -### HttpProvider - -The options is of type `HttpProviderOptions`, which is an object with a single key named `providerOptions` and its value is an object of type `RequestInit`. -Regarding `RequestInit` see [microsoft's github](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules_typedoc_node_modules_typescript_lib_lib_dom_d_.requestinit.html). - -```ts title='HTTP Provider example' -const httpOptions = { - providerOptions: { - body: undefined, - cache: 'force-cache', - credentials: 'same-origin', - headers: { - 'Content-Type': 'application/json', - }, - integrity: 'foo', - keepalive: true, - method: 'GET', - mode: 'same-origin', - redirect: 'error', - referrer: 'foo', - referrerPolicy: 'same-origin', - signal: undefined, - window: undefined, - } as RequestInit, -}; -``` - -### WebSocketProvider - -Use WebSocketProvider to connect to a Node using a WebSocket connection, i.e. over the `ws` or `wss` protocol. - -The options object is of type `ClientRequestArgs` or of `ClientOptions`. See [here](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_http_d_._http_.clientrequestargs.html) for `ClientRequestArgs` and [here](https://github.com/websockets/ws) for `ClientOptions`. - -The second option parameter can be given regarding reconnecting. And here is its type: - -```ts title='WebSocket Provider example' -// this is the same options interface used for both WebSocketProvider and IpcProvider -type ReconnectOptions = { - autoReconnect: boolean, // default: `true` - delay: number, // default: `5000` - maxAttempts: number, // default: `5` -}; - -``` - -```ts title='Instantiation of WebSocket Provider' -const provider = new WebSocketProvider( - `ws://localhost:8545`, - { - headers: { - // to provide the API key if the Node requires the key to be inside the `headers` for example: - 'x-api-key': '', - }, - }, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } -); -``` - -The second and the third parameters are both optional. And, for example, the second parameter could be an empty object or undefined, like in the following example: - -```ts title='Instantiation of WebSocket Provider' -const provider = new WebSocketProvider( - `ws://localhost:8545`, - {}, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } -); -``` - -Below is an example for the passed options: - -```ts title='WS Provider options example' -let clientOptions: ClientOptions = { - // Useful for credentialed urls, e.g: ws://username:password@localhost:8546 - headers: { - authorization: 'Basic username:password', - }, - maxPayload: 100000000, -}; - -const reconnectOptions: ReconnectOptions = { - autoReconnect: true, - delay: 5000, - maxAttempts: 5, -}; -``` - -### IpcProvider - -The IPC Provider could be used in node.js dapps when running a local node. And it provide the most secure connection. - -It accepts a second parameter called `socketOptions`. And, its type is `SocketConstructorOpts`. See [here](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_net_d_._net_.socketconstructoropts.html) for full details. And here is its interface: - -```ts title='IPC Provider options' -// for more check https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_net_d_._net_.socketconstructoropts.html -interface SocketConstructorOpts { - fd?: number | undefined; - allowHalfOpen?: boolean | undefined; - readable?: boolean | undefined; - writable?: boolean | undefined; -} -``` - -And, the third parameter is called `reconnectOptions` that is of the type `ReconnectOptions`. It can be given to control: auto-reconnecting, delay and max tries attempts. And here its type: - -```ts -// this is the same options interface used for both WebSocketProvider and IpcProvider -type ReconnectOptions = { - autoReconnect: boolean, // default: `true` - delay: number, // default: `5000` - maxAttempts: number, // default: `5` -}; -``` - -Below is an example for the passed options for each version: - -```ts title='Options Example' -let clientOptions: SocketConstructorOpts = { - allowHalfOpen: false; - readable: true; - writable: true; -}; - -const reconnectOptions: ReconnectOptions = { - autoReconnect: true, - delay: 5000, - maxAttempts: 5, -}; -``` - -And here is a sample instantiation for the `IpcProvider`: - -```ts title='IPC Provider example' -const provider = new IpcProvider( - `path.ipc`, - { - writable: false, - }, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } -); -``` - -The second and the third parameters are both optional. And, for example, the second parameter could be an empty object or undefined. - -```ts title='IPC Provider example' -const provider = new IpcProvider( - `path.ipc`, - {}, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } -); -``` - -:::info -This section applies for both `IpcProvider` and `WebSocketProvider`. -::: - -The error message, for the max reconnect attempts, will contain the value of the variable `maxAttempts` as follows: - -`` `Maximum number of reconnect attempts reached! (${maxAttempts})` `` - -And here is how to catch the error, if max attempts reached when there is auto reconnecting: - -```ts title='Error message for reconnect attempts' -provider.on('error', (error) => { - if (error.message.startsWith('Maximum number of reconnect attempts reached!')) { - // the `error.message` will be `Maximum number of reconnect attempts reached! (${maxAttempts})` - // the `maxAttempts` is equal to the provided value by the user, or the default value `5`. - } -}); -``` - -