import { Network, Networkish } from '@ethersproject/networks'; import { BaseProvider, getDefaultProvider, InfuraProvider, JsonRpcProvider } from '@ethersproject/providers'; import { ConnectionInfo } from '@ethersproject/web'; import { EthereumNetwork, ExtendedNetwork } from './types'; import { lookupAliasesByNetworkName, networks } from './util'; import * as R from 'ramda'; export const getNetworkDetails = (networkName: EthereumNetwork): ExtendedNetwork => { // Check if we have network details for this name or any of its aliases. // This is case-insensitive. const aliases = lookupAliasesByNetworkName(networkName).map(R.toLower); const aliasedNetworkName: EthereumNetwork = Object.keys(networks).find((key) => aliases.includes(key.toLowerCase()) ) as EthereumNetwork; if (!aliasedNetworkName || !networks[aliasedNetworkName]) { throw new Error(`Could not find Provider network details for network ${networkName}`); } return { ...networks[aliasedNetworkName], name: aliasedNetworkName } as ExtendedNetwork; }; export class ExtendedInfuraProvider extends InfuraProvider { static getUrl(network: Network, apiKey: { projectId: string; projectSecret: string }): ConnectionInfo { return { allowGzip: true, url: (network as ExtendedNetwork).url + apiKey.projectId, password: apiKey.projectSecret, }; } static getNetwork(network: Networkish): Network { if (typeof network === 'string') { return { ...getNetworkDetails(network as EthereumNetwork), name: network as string, }; } return network as Network; } } const getLocalhostProvider = (): JsonRpcProvider => new JsonRpcProvider(); export const getProvider = function ( network: EthereumNetwork, apiKey?: { projectId: string; projectSecret: string } ): BaseProvider { if (network === 'localhost') return getLocalhostProvider(); // The given network may be an alias for another one, e.g. matic => polygonMainnet. // In this case, 'finalNetworkName' will be the network that was being pointed to by the alias, which may differ from the passed-in network name. const { name: finalNetworkName, url, chainId } = getNetworkDetails(network); if (url.includes('infura') && !!apiKey) return new ExtendedInfuraProvider(finalNetworkName, apiKey); const provider = getDefaultProvider(url); provider.getNetwork = (): Promise => Promise.resolve({ name: finalNetworkName, chainId }); return provider; };