diff --git a/src.ts/providers/default-provider.ts b/src.ts/providers/default-provider.ts index 9fe7bb6b0c..adac14fc79 100644 --- a/src.ts/providers/default-provider.ts +++ b/src.ts/providers/default-provider.ts @@ -11,6 +11,7 @@ import { QuickNodeProvider } from "./provider-quicknode.js"; import { FallbackProvider } from "./provider-fallback.js"; import { JsonRpcProvider } from "./provider-jsonrpc.js"; +import { Network } from "./network.js"; import { WebSocketProvider } from "./provider-websocket.js"; import type { AbstractProvider } from "./abstract-provider.js"; @@ -22,6 +23,8 @@ function isWebSocketLike(value: any): value is WebSocketLike { typeof(value.close) === "function"); } +const Testnets = "goerli kovan sepolia classicKotti optimism-goerli arbitrum-goerli matic-mumbai bnbt".split(" "); + export function getDefaultProvider(network: string | Networkish | WebSocketLike, options?: any): AbstractProvider { if (options == null) { options = { }; } @@ -33,6 +36,13 @@ export function getDefaultProvider(network: string | Networkish | WebSocketLike, return new WebSocketProvider(network); } + // Get the network name, if possible + let name: null | string = null; + try { + name = Network.from(network).name; + } catch (error) { } + + const providers: Array = [ ]; if (options.alchemy !== "-") { @@ -96,7 +106,19 @@ export function getDefaultProvider(network: string | Networkish | WebSocketLike, operation: "getDefaultProvider" }); + // No need for a FallbackProvider if (providers.length === 1) { return providers[0]; } - return new FallbackProvider(providers); + // We use the floor because public third-party providers can be unreliable, + // so a low number of providers with a large quorum will fail too often + let quorum = Math.floor(providers.length / 2); + + // Testnets don't need as strong a security gaurantee and speed is + // more useful during testing + if (name && Testnets.indexOf(name) !== -1) { quorum = 1; } + + // Provided override qorum takes priority + if (options && options.quorum) { quorum = options.quorum; } + + return new FallbackProvider(providers, undefined, { quorum }); } diff --git a/src.ts/providers/provider-fallback.ts b/src.ts/providers/provider-fallback.ts index 204e744063..aa99714777 100644 --- a/src.ts/providers/provider-fallback.ts +++ b/src.ts/providers/provider-fallback.ts @@ -165,16 +165,20 @@ async function waitForSync(config: Config, blockNumber: number): Promise { export type FallbackProviderOptions = { // How many providers must agree on a value before reporting // back the response - quorum: number; + quorum?: number; // How many providers must have reported the same event - // for it to be emitted - eventQuorum: number; + // for it to be emitted (currently unimplmented) + eventQuorum?: number; // How many providers to dispatch each event to simultaneously. // Set this to 0 to use getLog polling, which implies eventQuorum - // is equal to quorum. - eventWorkers: number; + // is equal to quorum. (currently unimplemented) + eventWorkers?: number; + + cacheTimeout?: number; + + pollingInterval?: number; }; type RunnerResult = { result: any } | { error: Error }; @@ -380,8 +384,9 @@ export class FallbackProvider extends AbstractProvider { * If a [[Provider]] is included in %%providers%%, defaults are used * for the configuration. */ - constructor(providers: Array, network?: Networkish) { - super(network); + constructor(providers: Array, network?: Networkish, options?: FallbackProviderOptions) { + super(network, options); + this.#configs = providers.map((p) => { if (p instanceof AbstractProvider) { return Object.assign({ provider: p }, defaultConfig, defaultState ); @@ -393,7 +398,15 @@ export class FallbackProvider extends AbstractProvider { this.#height = -2; this.#initialSyncPromise = null; - this.quorum = 2; //Math.ceil(providers.length / 2); + if (options && options.quorum != null) { + this.quorum = options.quorum; + } else { + this.quorum = Math.ceil(this.#configs.reduce((accum, config) => { + accum += config.weight; + return accum; + }, 0) / 2); + } + this.eventQuorum = 1; this.eventWorkers = 1;