diff --git a/FUNDING.json b/FUNDING.json index c9df9ba5e72..da00866a57f 100644 --- a/FUNDING.json +++ b/FUNDING.json @@ -1,7 +1,7 @@ { - "drips": { - "ethereum": { - "ownedBy": "0x04E504Acb5f6A9CB387fa37ec5Fc457A9D36D371" - } - } + "drips": { + "ethereum": { + "ownedBy": "0x04E504Acb5f6A9CB387fa37ec5Fc457A9D36D371" + } + } } diff --git a/packages/web3-rpc-providers/CHANGELOG.md b/packages/web3-rpc-providers/CHANGELOG.md index 110b620707d..0511d7dfc0d 100644 --- a/packages/web3-rpc-providers/CHANGELOG.md +++ b/packages/web3-rpc-providers/CHANGELOG.md @@ -62,4 +62,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- InfuraProvider was added (#7286) - PublicNodeProvider was added (#7322) diff --git a/packages/web3-rpc-providers/src/index.ts b/packages/web3-rpc-providers/src/index.ts index f7c0e6c2613..1eaffe648f1 100644 --- a/packages/web3-rpc-providers/src/index.ts +++ b/packages/web3-rpc-providers/src/index.ts @@ -19,6 +19,7 @@ import { QuickNodeProvider } from './web3_provider_quicknode.js'; export * from './types.js'; export * from './web3_provider_quicknode.js'; +export * from './web3_provider_infura.js'; export * from './web3_provider_publicnode.js'; export * from './web3_provider.js'; export * from './errors.js'; diff --git a/packages/web3-rpc-providers/src/types.ts b/packages/web3-rpc-providers/src/types.ts index 258d6411c57..c4718d3572c 100644 --- a/packages/web3-rpc-providers/src/types.ts +++ b/packages/web3-rpc-providers/src/types.ts @@ -26,8 +26,27 @@ export enum Transport { export enum Network { ETH_MAINNET = 'eth_mainnet', ETH_SEPOLIA = 'eth_sepolia', + ETH_GOERLI = 'eth_goerli', ETH_HOLESKY = 'eth_holesky', + PALM_MAINNET = 'palm_mainnet', + PALM_TESTNET = 'palm_testnet', + + BLAST_MAINNET = 'blast_mainnet', + BLAST_SEPOLIA = 'blast_sepolia', + + STARKNET_MAINNET = 'starknet_mainnet', + STARKNET_SEPOLIA = 'starknet_sepolia', + + ZKSYNC_MAINNET = 'zksync_mainnet', + ZKSYNC_SEPOLIA = 'zksync_sepolia', + + CELO_MAINNET = 'celo_mainnet', + CELO_ALFAJORES = 'celo_alfajores', + + AVALANCHE_MAINNET = 'avalanche_mainnet', + AVALANCHE_FUJI = 'avalanche_fuji', + POLYGON_MAINNET = 'polygon_mainnet', POLYGON_AMOY = 'polygon_amoy', @@ -37,12 +56,15 @@ export enum Network { ARBITRUM_MAINNET = 'arbitrum_mainnet', ARBITRUM_SEPOLIA = 'arbitrum_sepolia', + ARBITRUM_GOERLI = 'arbitrum_goerli', BASE_MAINNET = 'base_mainnet', BASE_SEPOLIA = 'base_sepolia', + BASE_GOERLI = 'base_foerli', OPTIMISM_MAINNET = 'optimism_mainnet', OPTIMISM_SEPOLIA = 'optimism_sepolia', + OPTIMISM_GOERLI = 'optimism_goerli', FANTOM_MAINNET = 'fantom_mainnet', FANTOM_TESTNET = 'fantom_testnet', @@ -56,12 +78,16 @@ export enum Network { BSC_MAINNET = 'bsc_mainnet', BSC_TESTNET = 'bsc_testnet', + MANTLE_SEPOLIA = 'mantle_sepolia', + + LINEA_MAINNET = 'linea_mainnet', + LINEA_SEPOLIA = 'linea_sepolia', + LINEA_GOERLI = 'linea_goerli', ARBITRUM_ONE = 'arbitrum_one', ARBITRUM_NOVA = 'arbitrum_nova', AVALANCHE_FUJI_C = 'avalanche_fuji_c', AVALANCHE_FUJI_P = 'avalanche_fuji_p', AVALANCHE_FUJI_X = 'avalanche_fuji_x', - BLAST_MAINNET = 'blast_mainnet', OPBNB_MAINNET = 'opbnb_mainnet', OPBNB_TESTNET = 'opbnb_testnet', GNOSIS_MAINNET = 'gnosis_mainnet', @@ -76,8 +102,6 @@ export enum Network { MOONBEAM_MAINNET = 'moonbeam_mainnet', TAIKO_MAINNET = 'taiko_mainnet', TAIKO_HEKLA = 'taiko_hekla', - LINEA_MAINNET = 'linea_mainnet', - LINEA_SEPOLIA = 'linea_sepolia', BAHAMUT_MAINNET = 'bahamut_mainnet', SCROLL_MAINNET = 'scroll_mainnet', SCROLL_SEPOLIA = 'scroll_sepolia', diff --git a/packages/web3-rpc-providers/src/web3_provider_infura.ts b/packages/web3-rpc-providers/src/web3_provider_infura.ts new file mode 100644 index 00000000000..04e7fa6d0db --- /dev/null +++ b/packages/web3-rpc-providers/src/web3_provider_infura.ts @@ -0,0 +1,83 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import { EthExecutionAPI, Web3APISpec } from 'web3-types'; +import { HttpProviderOptions } from 'web3-providers-http'; +import { Network, SocketOptions, Transport } from './types.js'; +import { Web3ExternalProvider } from './web3_provider.js'; + +const isValid = (str: string) => str !== undefined && str.trim().length > 0; + +export class InfuraProvider< + API extends Web3APISpec = EthExecutionAPI, +> extends Web3ExternalProvider { + // eslint-disable-next-line default-param-last + public constructor( + network: Network = Network.ETH_MAINNET, + transport: Transport = Transport.HTTPS, + token = '', + host = '', + providerConfigOptions?: HttpProviderOptions | SocketOptions, + ) { + super(network, transport, token, host, providerConfigOptions); + } + public static readonly networkHostMap: { [key: string]: string } = { + [Network.PALM_MAINNET]: 'palm-mainnet', + [Network.PALM_TESTNET]: 'palm-testnet', + [Network.BLAST_MAINNET]: 'blast-mainnet', + [Network.BLAST_SEPOLIA]: 'blast-sepolia', + [Network.AVALANCHE_MAINNET]: 'avalanche-mainnet', + [Network.AVALANCHE_FUJI]: 'avalanche-fuji', + [Network.STARKNET_MAINNET]: 'starknet-mainnet', + [Network.STARKNET_SEPOLIA]: 'starknet-sepolia', + [Network.ZKSYNC_MAINNET]: 'zksync-mainnet', + [Network.ZKSYNC_SEPOLIA]: 'zksync-sepolia', + [Network.CELO_MAINNET]: 'celo-mainnet', + [Network.CELO_ALFAJORES]: 'celo-alfajores', + [Network.BSC_MAINNET]: 'bsc-mainnet', + [Network.BSC_TESTNET]: 'bsc-testnet', + [Network.MANTLE_MAINNET]: 'mantle-mainnet', + [Network.MANTLE_SEPOLIA]: 'mantle-sepolia', + [Network.ETH_MAINNET]: 'mainnet', + [Network.ETH_HOLESKY]: 'holesky', + [Network.ETH_SEPOLIA]: 'sepolia', + [Network.ARBITRUM_MAINNET]: 'arbitrum-mainnet', + [Network.ARBITRUM_SEPOLIA]: 'arbitrum-sepolia', + [Network.BASE_MAINNET]: 'base-mainnet', + [Network.BASE_SEPOLIA]: 'base-sepolia', + [Network.BNB_MAINNET]: 'opbnb-mainnet', + [Network.BNB_TESTNET]: 'opbnb-testnet', + [Network.LINEA_MAINNET]: 'linea-mainnet', + [Network.LINEA_SEPOLIA]: 'linea-sepolia', + [Network.POLYGON_MAINNET]: 'polygon-mainnet', + [Network.POLYGON_AMOY]: 'polygon-amoy', + [Network.OPTIMISM_MAINNET]: 'optimism-mainnet', + [Network.OPTIMISM_SEPOLIA]: 'optimism-sepolia', + }; + // eslint-disable-next-line class-methods-use-this + public getRPCURL(network: Network, transport: Transport, token: string, _host: string) { + if (!InfuraProvider.networkHostMap[network]) { + throw new Error('Network info not avalible.'); + } + const defaultHost = `${InfuraProvider.networkHostMap[network]}.infura.io`; + const host = isValid(_host) ? _host : defaultHost; + + return `${transport}://${host}/${ + transport === Transport.WebSocket ? 'ws/' : '' + }v3/${token}`; + } +} diff --git a/packages/web3-rpc-providers/test/unit/constructor.test.ts b/packages/web3-rpc-providers/test/unit/constructor.test.ts index cc34cb1fcd3..dfc0e4b25c2 100644 --- a/packages/web3-rpc-providers/test/unit/constructor.test.ts +++ b/packages/web3-rpc-providers/test/unit/constructor.test.ts @@ -23,7 +23,7 @@ import { Web3ExternalProvider } from '../../src/web3_provider'; import { Network, SocketOptions, Transport } from '../../src/types'; import { ProviderConfigOptionsError } from '../../src/errors'; -// Mock implementation so ws doesnt have openhandle after test exits as it attempts to connects at start +// Mock implementation so ws doesnt have openhandle after test exits as it attempts to connect at start jest.mock('isomorphic-ws', () => { return { __esModule: true, diff --git a/packages/web3-rpc-providers/test/unit/request.test.ts b/packages/web3-rpc-providers/test/unit/request.test.ts index da07c2a578c..29a0372b808 100644 --- a/packages/web3-rpc-providers/test/unit/request.test.ts +++ b/packages/web3-rpc-providers/test/unit/request.test.ts @@ -83,7 +83,7 @@ describe('Web3ExternalProvider', () => { expect(result).toEqual({ result: 'mock-result' }); }); - it('should throw a rate limiting error when status code is 429', async () => { + it('QuickNodeProvider: should throw a rate limiting error when status code is 429', async () => { const network: Network = Network.ETH_MAINNET; const transport: Transport = Transport.HTTPS; const token = 'your-token'; diff --git a/packages/web3/test/integration/external-providers/infura-rpc.test.ts b/packages/web3/test/integration/external-providers/infura-rpc.test.ts deleted file mode 100644 index 479949c06f8..00000000000 --- a/packages/web3/test/integration/external-providers/infura-rpc.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* -This file is part of web3.js. - -web3.js is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -web3.js is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with web3.js. If not, see . -*/ - -import Web3 from '../../../src/index'; -import { describeIf, isIpc, itIf } from '../../shared_fixtures/system_tests_utils'; - -describeIf(!isIpc)('compatibility with `infura` remote rpc providers', () => { - itIf( - process.env.INFURA_GOERLI_WS - ? process.env.INFURA_GOERLI_WS.toString().includes('ws') - : false, - )('should create Web3 class instance with `ws` string connection', () => { - const web3 = new Web3(process.env.INFURA_GOERLI_WS); - // eslint-disable-next-line jest/no-standalone-expect - expect(web3).toBeInstanceOf(Web3); - }); - - itIf( - process.env.INFURA_GOERLI_HTTP - ? process.env.INFURA_GOERLI_HTTP.toString().includes('http') - : false, - )('should create Web3 class instance with `http` string connection', () => { - const web3 = new Web3(process.env.INFURA_GOERLI_HTTP); - // eslint-disable-next-line jest/no-standalone-expect - expect(web3).toBeInstanceOf(Web3); - }); -}); diff --git a/packages/web3/test/integration/web3RPCProviders.test.ts b/packages/web3/test/integration/web3RPCProviders.test.ts index 6e6d2994f9c..6b60097da3d 100644 --- a/packages/web3/test/integration/web3RPCProviders.test.ts +++ b/packages/web3/test/integration/web3RPCProviders.test.ts @@ -20,13 +20,15 @@ import { Network, QuickNodeProvider, Transport, + InfuraProvider, PublicNodeProvider, } from 'web3-rpc-providers'; import { Web3 } from '../../src/index'; +jest.setTimeout(10000); describe('Web3 RPC Provider Integration tests', () => { const transports = Object.values(Transport); - const networks = [ + const quickNodeNetworks = [ Network.ETH_MAINNET, Network.ETH_HOLESKY, Network.ETH_SEPOLIA, @@ -39,7 +41,7 @@ describe('Web3 RPC Provider Integration tests', () => { ]; transports.forEach(transport => { - networks.forEach(network => { + quickNodeNetworks.forEach(network => { it(`QuickNodeProvider should work with ${transport} transport and ${network} network`, async () => { const provider = new QuickNodeProvider(network, transport); const web3 = new Web3(provider); @@ -55,6 +57,85 @@ describe('Web3 RPC Provider Integration tests', () => { }); }); + const infuraNetworks = [ + Network.PALM_MAINNET, + Network.PALM_TESTNET, + Network.BLAST_MAINNET, + Network.BLAST_SEPOLIA, + Network.AVALANCHE_MAINNET, + Network.AVALANCHE_FUJI, + Network.STARKNET_MAINNET, + Network.STARKNET_SEPOLIA, + Network.ZKSYNC_MAINNET, + Network.ZKSYNC_SEPOLIA, + Network.CELO_MAINNET, + Network.CELO_ALFAJORES, + Network.BSC_MAINNET, + Network.BSC_TESTNET, + Network.MANTLE_MAINNET, + Network.MANTLE_SEPOLIA, + Network.ETH_MAINNET, + Network.ETH_HOLESKY, + Network.ETH_SEPOLIA, + Network.ARBITRUM_MAINNET, + Network.ARBITRUM_SEPOLIA, + Network.BASE_MAINNET, + Network.BASE_SEPOLIA, + Network.BNB_MAINNET, + Network.BNB_TESTNET, + Network.LINEA_MAINNET, + Network.LINEA_SEPOLIA, + Network.POLYGON_MAINNET, + Network.POLYGON_AMOY, + Network.OPTIMISM_MAINNET, + Network.OPTIMISM_SEPOLIA, + ]; + transports.forEach(transport => { + infuraNetworks.forEach(network => { + // skip not exists endpoints + if ( + !( + [ + Network.PALM_MAINNET, + Network.PALM_TESTNET, + Network.BLAST_SEPOLIA, + Network.STARKNET_MAINNET, + Network.STARKNET_SEPOLIA, + Network.ZKSYNC_SEPOLIA, + Network.BSC_TESTNET, + Network.MANTLE_SEPOLIA, + Network.BNB_TESTNET, + ].includes(network) && transport === Transport.WebSocket + ) + ) { + it.skip(`InfuraProvider should work with ${transport} transport and ${network} network`, async () => { + const provider = new InfuraProvider( + network, + transport, + process.env.INFURA_PROVIDER_KEY, + ); + + const web3 = new Web3(provider); + const result = + network === Network.STARKNET_MAINNET || network === Network.STARKNET_SEPOLIA + ? BigInt( + await web3.requestManager.send({ + method: 'starknet_blockNumber', + params: [], + }), + ) + : await web3.eth.getBlockNumber(); + expect(typeof result).toBe('bigint'); + expect(result > 0).toBe(true); + + if (transport === Transport.WebSocket) { + web3.provider?.disconnect(); + } + }); + } + }); + }); + const publicNodeNetworks = [ Network.POLYGON_AMOY, Network.POLYGON_MAINNET,