Skip to content

Commit

Permalink
Merge branch '4.x' into 7196-refactor-some-parts-of-contract-accounts…
Browse files Browse the repository at this point in the history
…-and-eth-packages
  • Loading branch information
Muhammad-Altabba authored Aug 21, 2024
2 parents 9485485 + 4f8e8cc commit ec4fede
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 35 deletions.
3 changes: 2 additions & 1 deletion packages/web3-rpc-providers/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Updated rate limit error of QuickNode provider for HTTP transport
- Updated rate limit error of QuickNode provider for HTTP transport
- Added optional `HttpProviderOptions | SocketOptions` in `Web3ExternalProvider` and `QuickNodeProvider` for provider configs
14 changes: 13 additions & 1 deletion packages/web3-rpc-providers/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/

/* eslint-disable max-classes-per-file */

import { BaseWeb3Error } from 'web3-errors';

const ERR_QUICK_NODE_RATE_LIMIT = 1300;
Expand All @@ -24,4 +26,14 @@ export class QuickNodeRateLimitError extends BaseWeb3Error {
public constructor(error?: Error) {
super(`You've reach the rate limit of free RPC calls from our Partner Quick Nodes. There are two options you can either create a paid Quick Nodes account and get 20% off for 2 months using WEB3JS referral code, or use Free public RPC endpoint.`, error);
}
}
}

const ERR_PROVIDER_CONFIG_OPTIONS = 1301;
export class ProviderConfigOptionsError extends BaseWeb3Error {
public code = ERR_PROVIDER_CONFIG_OPTIONS;

public constructor(msg: string) {
super(`Invalid provider config options given for ${msg}`);
}
}
/* eslint-enable max-classes-per-file */
9 changes: 9 additions & 0 deletions packages/web3-rpc-providers/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/

import {ClientOptions, ClientRequestArgs} from "web3-providers-ws";
import { ReconnectOptions } from 'web3-utils';

export enum Transport {
HTTPS = "https",
WebSocket = "wss"
Expand All @@ -41,4 +44,10 @@ export enum Network {

BNB_MAINNET = "bnb_mainnet",
BNB_TESTNET = "bnb_testnet"
};

// Combining the ws types
export type SocketOptions = {
socketOptions?: ClientOptions | ClientRequestArgs;
reconnectOptions?: Partial<ReconnectOptions>;
};
34 changes: 28 additions & 6 deletions packages/web3-rpc-providers/src/web3_provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ You should have received a copy of the GNU Lesser General Public License
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/

import HttpProvider from "web3-providers-http";
import HttpProvider, { HttpProviderOptions } from "web3-providers-http";
import WebSocketProvider from "web3-providers-ws";
import {
EthExecutionAPI, JsonRpcResult, ProviderConnectInfo, ProviderMessage,
Expand All @@ -27,7 +27,8 @@ import {
JsonRpcResponseWithResult,
} from "web3-types";
import { Eip1193Provider } from "web3-utils";
import { Transport, Network } from "./types.js";
import { Transport, Network, SocketOptions } from "./types.js";
import { ProviderConfigOptionsError } from "./errors.js";

/*
This class can be used to create new providers only when there is custom logic required in each Request method like
Expand All @@ -50,16 +51,36 @@ export abstract class Web3ExternalProvider<
network: Network,
transport: Transport,
token: string,
host: string) {
host: string,
providerConfigOptions?: HttpProviderOptions | SocketOptions) {

super();

if(providerConfigOptions!== undefined &&
transport === Transport.HTTPS &&
!('providerOptions' in providerConfigOptions)){

throw new ProviderConfigOptionsError("HTTP Provider");
}
else if(providerConfigOptions!== undefined &&
transport === Transport.WebSocket &&
!( 'socketOptions' in providerConfigOptions ||
'reconnectOptions' in providerConfigOptions
)){
throw new ProviderConfigOptionsError("Websocket Provider");
}

this.transport = transport;
if (transport === Transport.HTTPS) {
this.provider = new HttpProvider(this.getRPCURL(network, transport, token, host));
this.provider = new HttpProvider(
this.getRPCURL(network, transport, token, host),
providerConfigOptions as HttpProviderOptions);
}
else if (transport === Transport.WebSocket) {
this.provider = new WebSocketProvider(this.getRPCURL(network, transport, token, host));
this.provider = new WebSocketProvider(
this.getRPCURL(network, transport, token, host),
(providerConfigOptions as SocketOptions)?.socketOptions,
(providerConfigOptions as SocketOptions)?.reconnectOptions);
}
}

Expand Down Expand Up @@ -133,4 +154,5 @@ export abstract class Web3ExternalProvider<
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
this.provider.removeListener(_type as any, _listener as any);
}
}
}

12 changes: 5 additions & 7 deletions packages/web3-rpc-providers/src/web3_provider_quicknode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ along with web3.js. If not, see <http://www.gnu.org/licenses/>.

import { EthExecutionAPI, JsonRpcResponseWithResult, Web3APIMethod, Web3APIPayload, Web3APIReturnType, Web3APISpec } from "web3-types";
import { ResponseError } from "web3-errors";
import { Transport, Network } from "./types.js";
import { HttpProviderOptions } from "web3-providers-http";
import { Transport, Network, SocketOptions } from "./types.js";
import { Web3ExternalProvider } from "./web3_provider.js";
import { QuickNodeRateLimitError } from "./errors.js";

Expand All @@ -27,13 +28,10 @@ export class QuickNodeProvider<
API extends Web3APISpec = EthExecutionAPI,
> extends Web3ExternalProvider {

public constructor(
network: Network = Network.ETH_MAINNET,
transport: Transport = Transport.HTTPS,
token = "",
host = "") {
// 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);
super(network, transport, token, host, providerConfigOptions);

}

Expand Down
87 changes: 75 additions & 12 deletions packages/web3-rpc-providers/test/unit/constructor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/


import HttpProvider from 'web3-providers-http';
import HttpProvider, { HttpProviderOptions } from 'web3-providers-http';
import WebSocketProvider from 'web3-providers-ws';
import WebSocket from 'isomorphic-ws';

import { Web3ExternalProvider } from '../../src/web3_provider';
import { Network, Transport } from '../../src/types';
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
jest.mock('isomorphic-ws', () => {
Expand Down Expand Up @@ -60,11 +61,11 @@ jest.mock('isomorphic-ws', () => {
});

class MockWeb3ExternalProviderA extends Web3ExternalProvider {
public constructor(network: Network, transport: Transport, token: string){
super(network, transport, token, "");
public constructor(network: Network, transport: Transport, token: string, host?: string, providerConfigOptions?: HttpProviderOptions | SocketOptions) {
super(network, transport, token, host ?? "", providerConfigOptions);
}
// eslint-disable-next-line class-methods-use-this
public getRPCURL(_network: Network, _transport: Transport, _token: string, _host=""): string {
public getRPCURL(_network: Network, _transport: Transport, _token: string, _host = ""): string {
let transport = "";
if (_transport === Transport.HTTPS)
transport = "http://";
Expand All @@ -76,23 +77,85 @@ class MockWeb3ExternalProviderA extends Web3ExternalProvider {
}

describe('Web3ExternalProvider', () => {
const network: Network = Network.ETH_MAINNET;
const transport: Transport = Transport.HTTPS;
const token = 'test-token';
const host = 'test-host';

it('should initialize the provider correctly', () => {
const network: Network = Network.ETH_MAINNET;
const transport: Transport = Transport.HTTPS;
const token = 'your-token';

const provider = new MockWeb3ExternalProviderA(network, transport, token);

expect(provider.provider).toBeInstanceOf(HttpProvider);
});

it('should initialize the provider with WebSocketProvider for WebSocket transport', () => {
const network: Network = Network.ETH_MAINNET;
const transport: Transport = Transport.WebSocket;
const token = 'your-token';
const transport1: Transport = Transport.WebSocket;

const provider = new MockWeb3ExternalProviderA(network, transport, token);
const provider = new MockWeb3ExternalProviderA(network, transport1, token);
expect(provider.provider).toBeInstanceOf(WebSocketProvider);
});

it('should throw ProviderConfigOptionsError for HTTP provider with missing providerOptions', () => {
const providerConfigOptions: HttpProviderOptions | SocketOptions = { /* missing providerOptions */ };
expect(() => new MockWeb3ExternalProviderA(network, transport, token, host, providerConfigOptions)).toThrow(ProviderConfigOptionsError);
});

it('should throw ProviderConfigOptionsError for HTTP provider with WS providerOptions', () => {
const providerConfigOptions: SocketOptions = {
socketOptions: { /* options */ },
reconnectOptions: { /* options */ },
};
expect(() => new MockWeb3ExternalProviderA(network, transport, token, host, providerConfigOptions)).toThrow(ProviderConfigOptionsError);
});

it('should throw ProviderConfigOptionsError for WebSocket provider with missing socketOptions and reconnectOptions', () => {
const providerConfigOptions: HttpProviderOptions | SocketOptions = { /* missing socketOptions and reconnectOptions */ };
expect(() => new MockWeb3ExternalProviderA(network, Transport.WebSocket, token, host, providerConfigOptions)).toThrow(ProviderConfigOptionsError);
});

it('should throw ProviderConfigOptionsError for WebSocket provider with HTTP options', () => {
const providerConfigOptions: HttpProviderOptions = { providerOptions: { /* options */ } };
expect(() => new MockWeb3ExternalProviderA(network, Transport.WebSocket, token, host, providerConfigOptions)).toThrow(ProviderConfigOptionsError);
});

it('should create provider instance and not throw ProviderConfigOptionsError for WebSocket provider with missing reconnectOptions', () => {
const providerConfigOptions: SocketOptions = {
socketOptions: { /* options */ },
};

// Create an instance of the MockWeb3ExternalProviderA
const provider = new MockWeb3ExternalProviderA(network, Transport.WebSocket, token, host, providerConfigOptions);

// Expect that the provider is created successfully
expect(provider).toBeInstanceOf(MockWeb3ExternalProviderA);
});

it('should create provider instance and not throw ProviderConfigOptionsError for WebSocket provider with missing socketOptions', () => {
const providerConfigOptions: SocketOptions = {
reconnectOptions: { /* options */ },
};

// Create an instance of the MockWeb3ExternalProviderA
const provider = new MockWeb3ExternalProviderA(network, Transport.WebSocket, token, host, providerConfigOptions);

// Expect that the provider is created successfully
expect(provider).toBeInstanceOf(MockWeb3ExternalProviderA);
});

it('should create an HttpProvider with providerOptions', () => {
const providerConfigOptions: HttpProviderOptions = { providerOptions: { /* options */ } };
const provider = new MockWeb3ExternalProviderA(network, transport, token, host, providerConfigOptions);
expect(provider.provider).toBeInstanceOf(HttpProvider);
});

it('should create a WebSocketProvider with socketOptions and reconnectOptions', () => {
const providerConfigOptions: SocketOptions = {
socketOptions: { /* options */ },
reconnectOptions: { /* options */ },
};
const provider = new MockWeb3ExternalProviderA(network, Transport.WebSocket, token, host, providerConfigOptions);
expect(provider.provider).toBeInstanceOf(WebSocketProvider);
});
});

16 changes: 8 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3373,11 +3373,11 @@ aws4@^1.8.0:
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==

axios@^1.0.0:
version "1.6.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.2.tgz#de67d42c755b571d3e698df1b6504cde9b0ee9f2"
integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==
version "1.7.4"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.4.tgz#4c8ded1b43683c8dd362973c393f3ede24052aa2"
integrity sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==
dependencies:
follow-redirects "^1.15.0"
follow-redirects "^1.15.6"
form-data "^4.0.0"
proxy-from-env "^1.1.0"

Expand Down Expand Up @@ -6072,10 +6072,10 @@ follow-redirects@^1.0.0, follow-redirects@^1.12.1:
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5"
integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==

follow-redirects@^1.15.0:
version "1.15.2"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
follow-redirects@^1.15.6:
version "1.15.6"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==

for-each@^0.3.3:
version "0.3.3"
Expand Down

0 comments on commit ec4fede

Please sign in to comment.