From bbb4f407b34782c36ff93fa528e3b9f793987d4a Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Sat, 13 Jun 2020 21:26:50 -0400 Subject: [PATCH] Allow provider.ready to stall until the network is available (#882). --- packages/logger/src.ts/index.ts | 1 + packages/providers/src.ts/base-provider.ts | 19 +++++++++++++++---- .../providers/src.ts/json-rpc-provider.ts | 5 ++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/logger/src.ts/index.ts b/packages/logger/src.ts/index.ts index d174494ad..128ce0044 100644 --- a/packages/logger/src.ts/index.ts +++ b/packages/logger/src.ts/index.ts @@ -66,6 +66,7 @@ export enum ErrorCode { UNSUPPORTED_OPERATION = "UNSUPPORTED_OPERATION", // Network Error (i.e. Ethereum Network, such as an invalid chain ID) + // - event ("noNetwork" is not re-thrown in provider.ready; otherwise thrown) NETWORK_ERROR = "NETWORK_ERROR", // Some sort of bad response from the server diff --git a/packages/providers/src.ts/base-provider.ts b/packages/providers/src.ts/base-provider.ts index b60832930..0af4bef04 100644 --- a/packages/providers/src.ts/base-provider.ts +++ b/packages/providers/src.ts/base-provider.ts @@ -255,7 +255,7 @@ export class BaseProvider extends Provider { network.catch((error) => { }); // Trigger initial network setting (async) - this._ready(); + this._ready().catch((error) => { }); } else { const knownNetwork = getStatic<(network: Networkish) => Network>(new.target, "getNetwork")(network); @@ -315,7 +315,17 @@ export class BaseProvider extends Provider { // For "any", this can change (a "network" event is emitted before // any change is refelcted); otherwise this cannot change get ready(): Promise { - return this._ready(); + return poll(() => { + return this._ready().then((network) => { + return network; + }, (error) => { + // If the network isn't running yet, we will wait + if (error.code === Logger.errors.NETWORK_ERROR && error.event === "noNetwork") { + return undefined; + } + throw error; + }); + }); } // @TODO: Remove this and just create a singleton formatter @@ -334,7 +344,7 @@ export class BaseProvider extends Provider { // Fetches the blockNumber, but will reuse any result that is less // than maxAge old or has been requested since the last request async _getInternalBlockNumber(maxAge: number): Promise { - await this.ready; + await this._ready(); const internalBlockNumber = this._internalBlockNumber; @@ -401,6 +411,7 @@ export class BaseProvider extends Provider { logger.warn("network block skew detected; skipping block events"); this.emit("error", logger.makeError("network block skew detected", Logger.errors.NETWORK_ERROR, { blockNumber: blockNumber, + event: "blockSkew", previousBlockNumber: this._emitted.block })); this.emit("block", blockNumber); @@ -507,7 +518,7 @@ export class BaseProvider extends Provider { } async getNetwork(): Promise { - const network = await this.ready; + const network = await this._ready(); // Make sure we are still connected to the same network; this is // only an external call for backends which can have the underlying diff --git a/packages/providers/src.ts/json-rpc-provider.ts b/packages/providers/src.ts/json-rpc-provider.ts index 9a432c2bd..e11b51ccf 100644 --- a/packages/providers/src.ts/json-rpc-provider.ts +++ b/packages/providers/src.ts/json-rpc-provider.ts @@ -280,12 +280,15 @@ export class JsonRpcProvider extends BaseProvider { } catch (error) { return logger.throwError("could not detect network", Logger.errors.NETWORK_ERROR, { chainId: chainId, + event: "invalidNetwork", serverError: error }); } } - return logger.throwError("could not detect network", Logger.errors.NETWORK_ERROR); + return logger.throwError("could not detect network", Logger.errors.NETWORK_ERROR, { + event: "noNetwork" + }); } getSigner(addressOrIndex?: string | number): JsonRpcSigner {