diff --git a/packages/network/src/index.ts b/packages/network/src/index.ts index a905837..a8859fd 100644 --- a/packages/network/src/index.ts +++ b/packages/network/src/index.ts @@ -5,15 +5,28 @@ import { Connector } from '@web3-react/types' type url = string | ConnectionInfo +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function isUrl(url: url | any): url is url { + return typeof url === 'string' || ('url' in url && !('connection' in url) && !('quorum' in url)) +} + +function isJsonRpcProvider(url: url | JsonRpcProvider | FallbackProvider): url is JsonRpcProvider { + return !isUrl(url) && 'connection' in url && !('quorum' in url) +} + +function isFallbackProvider(url: url | JsonRpcProvider | FallbackProvider): url is FallbackProvider { + return !isUrl(url) && 'quorum' in url && !('connection' in url) +} + export class Network extends Connector { /** {@inheritdoc Connector.provider} */ - public provider: undefined + public readonly provider: undefined /** {@inheritdoc Connector.customProvider} */ public customProvider: JsonRpcProvider | FallbackProvider | undefined - private urlMap: Record - private defaultChainId: number - private providerCache: Record | undefined> = {} + private readonly urlMap: Record + private readonly defaultChainId: number + private readonly providerCache: Record | undefined> = {} /** * @param urlMap - A mapping from chainIds to RPC urls. @@ -22,7 +35,7 @@ export class Network extends Connector { */ constructor( actions: Actions, - urlMap: { [chainId: number]: url | url[] }, + urlMap: { [chainId: number]: url | url[] | JsonRpcProvider | JsonRpcProvider[] | FallbackProvider }, connectEagerly = false, defaultChainId = Number(Object.keys(urlMap)[0]) ) { @@ -32,9 +45,15 @@ export class Network extends Connector { throw new Error('connectEagerly = true is invalid for SSR, instead use the activate method in a useEffect') } - this.urlMap = Object.keys(urlMap).reduce<{ [chainId: number]: url[] }>((accumulator, chainId) => { + this.urlMap = Object.keys(urlMap).reduce((accumulator, chainId) => { const urls = urlMap[Number(chainId)] - accumulator[Number(chainId)] = Array.isArray(urls) ? urls : [urls] + + if (Array.isArray(urls)) { + accumulator[Number(chainId)] = urls + } else { + accumulator[Number(chainId)] = isFallbackProvider(urls) ? urls : isJsonRpcProvider(urls) ? [urls] : [urls] + } + return accumulator }, {}) this.defaultChainId = defaultChainId @@ -45,16 +64,24 @@ export class Network extends Connector { private async isomorphicInitialize(chainId: number): Promise { if (this.providerCache[chainId]) return this.providerCache[chainId] as Promise + const urls = this.urlMap[chainId] + + if (Array.isArray(urls)) { + // early return if we have a single jsonrpc provider already + if (urls.length === 1 && isJsonRpcProvider(urls[0])) + return (this.providerCache[chainId] = Promise.resolve(urls[0])) + } else { + // if we're here we know urls is a FallbackProvider + return (this.providerCache[chainId] = Promise.resolve(urls)) + } + return (this.providerCache[chainId] = import('@ethersproject/providers') .then(({ JsonRpcProvider, FallbackProvider }) => ({ JsonRpcProvider, FallbackProvider, })) .then(({ JsonRpcProvider, FallbackProvider }) => { - const urls = this.urlMap[chainId] - - const providers = urls.map((url) => new JsonRpcProvider(url, chainId)) - + const providers = urls.map((url) => (isUrl(url) ? new JsonRpcProvider(url, chainId) : url)) return providers.length === 1 ? providers[0] : new FallbackProvider(providers) })) } diff --git a/packages/url/src/index.ts b/packages/url/src/index.ts index 21fb1d2..fba85b1 100644 --- a/packages/url/src/index.ts +++ b/packages/url/src/index.ts @@ -5,20 +5,24 @@ import { Connector } from '@web3-react/types' type url = string | ConnectionInfo +function isUrl(url: url | JsonRpcProvider): url is url { + return typeof url === 'string' || ('url' in url && !('connection' in url)) +} + export class Url extends Connector { /** {@inheritdoc Connector.provider} */ - public provider: undefined + public readonly provider: undefined /** {@inheritdoc Connector.customProvider} */ public customProvider: JsonRpcProvider | undefined private eagerConnection?: Promise - private url: url + private readonly url: url | JsonRpcProvider /** - * @param url - An RPC url. + * @param url - An RPC url or a JsonRpcProvider. * @param connectEagerly - A flag indicating whether connection should be initiated when the class is constructed. */ - constructor(actions: Actions, url: url, connectEagerly = false) { + constructor(actions: Actions, url: url | JsonRpcProvider, connectEagerly = false) { super(actions) if (connectEagerly && typeof window === 'undefined') { @@ -33,8 +37,10 @@ export class Url extends Connector { private async isomorphicInitialize() { if (this.eagerConnection) return this.eagerConnection + if (!isUrl(this.url)) return this.url + return (this.eagerConnection = import('@ethersproject/providers').then(({ JsonRpcProvider }) => { - return new JsonRpcProvider(this.url) + return new JsonRpcProvider(this.url as url) })) }