UNPKG

@metamask/network-controller

Version:

Provides an interface to the currently selected network via a MetaMask-compatible provider object

1 lines 22.6 kB
{"version":3,"file":"create-network-client.mjs","sourceRoot":"","sources":["../src/create-network-client.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CockatielFailureReason,\n InfuraNetworkType,\n} from '@metamask/controller-utils';\nimport { ChainId } from '@metamask/controller-utils';\nimport type { PollingBlockTrackerOptions } from '@metamask/eth-block-tracker';\nimport { PollingBlockTracker } from '@metamask/eth-block-tracker';\nimport { createInfuraMiddleware } from '@metamask/eth-json-rpc-infura';\nimport {\n createBlockCacheMiddleware,\n createBlockRefMiddleware,\n createBlockRefRewriteMiddleware,\n createBlockTrackerInspectorMiddleware,\n createInflightCacheMiddleware,\n createFetchMiddleware,\n createRetryOnEmptyMiddleware,\n} from '@metamask/eth-json-rpc-middleware';\nimport { InternalProvider } from '@metamask/eth-json-rpc-provider';\nimport { providerFromMiddlewareV2 } from '@metamask/eth-json-rpc-provider';\nimport { asV2Middleware } from '@metamask/json-rpc-engine';\nimport {\n createScaffoldMiddleware,\n JsonRpcEngineV2,\n} from '@metamask/json-rpc-engine/v2';\nimport type {\n JsonRpcMiddleware,\n MiddlewareContext,\n} from '@metamask/json-rpc-engine/v2';\nimport type { Hex, Json, JsonRpcRequest } from '@metamask/utils';\nimport type { Logger } from 'loglevel';\n\nimport type {\n NetworkClientId,\n NetworkControllerMessenger,\n} from './NetworkController';\nimport type { RpcServiceOptions } from './rpc-service/rpc-service';\nimport { RpcServiceChain } from './rpc-service/rpc-service-chain';\nimport type {\n BlockTracker,\n NetworkClientConfiguration,\n Provider,\n} from './types';\nimport { NetworkClientType } from './types';\n\nconst SECOND = 1000;\n\n/**\n * The pair of provider / block tracker that can be used to interface with the\n * network and respond to new activity.\n */\nexport type NetworkClient = {\n configuration: NetworkClientConfiguration;\n provider: Provider;\n blockTracker: BlockTracker;\n destroy: () => void;\n};\n\ntype RpcApiMiddleware = JsonRpcMiddleware<\n JsonRpcRequest,\n Json,\n MiddlewareContext<{ origin: string }>\n>;\n\n/**\n * Create a JSON RPC network client for a specific network.\n *\n * @param args - The arguments.\n * @param args.id - The ID that will be assigned to the new network client in\n * the registry.\n * @param args.configuration - The network configuration.\n * @param args.getRpcServiceOptions - Factory for constructing RPC service\n * options. See {@link NetworkControllerOptions.getRpcServiceOptions}.\n * @param args.getBlockTrackerOptions - Factory for constructing block tracker\n * options. See {@link NetworkControllerOptions.getBlockTrackerOptions}.\n * @param args.messenger - The network controller messenger.\n * @param args.isRpcFailoverEnabled - Whether or not requests sent to the\n * primary RPC endpoint for this network should be automatically diverted to\n * provided failover endpoints if the primary is unavailable. This effectively\n * causes the `failoverRpcUrls` property of the network client configuration\n * to be honored or ignored.\n * @param args.logger - A `loglevel` logger.\n * @returns The network client.\n */\nexport function createNetworkClient({\n id,\n configuration,\n getRpcServiceOptions,\n getBlockTrackerOptions,\n messenger,\n isRpcFailoverEnabled,\n logger,\n}: {\n id: NetworkClientId;\n configuration: NetworkClientConfiguration;\n getRpcServiceOptions: (\n rpcEndpointUrl: string,\n ) => Omit<RpcServiceOptions, 'failoverService' | 'endpointUrl'>;\n getBlockTrackerOptions: (\n rpcEndpointUrl: string,\n ) => Omit<PollingBlockTrackerOptions, 'provider'>;\n messenger: NetworkControllerMessenger;\n isRpcFailoverEnabled: boolean;\n logger?: Logger;\n}): NetworkClient {\n const primaryEndpointUrl =\n configuration.type === NetworkClientType.Infura\n ? `https://${configuration.network}.infura.io/v3/${configuration.infuraProjectId}`\n : configuration.rpcUrl;\n const rpcServiceChain = createRpcServiceChain({\n id,\n primaryEndpointUrl,\n configuration,\n getRpcServiceOptions,\n messenger,\n isRpcFailoverEnabled,\n logger,\n });\n\n let rpcApiMiddleware: RpcApiMiddleware;\n if (configuration.type === NetworkClientType.Infura) {\n rpcApiMiddleware = asV2Middleware(\n createInfuraMiddleware({\n rpcService: rpcServiceChain,\n options: {\n source: 'metamask',\n },\n }),\n );\n } else {\n rpcApiMiddleware = createFetchMiddleware({ rpcService: rpcServiceChain });\n }\n\n const rpcProvider = providerFromMiddlewareV2(rpcApiMiddleware);\n\n const blockTracker = createBlockTracker({\n networkClientType: configuration.type,\n endpointUrl: primaryEndpointUrl,\n getOptions: getBlockTrackerOptions,\n provider: rpcProvider,\n });\n\n const networkMiddleware =\n configuration.type === NetworkClientType.Infura\n ? createInfuraNetworkMiddleware({\n blockTracker,\n network: configuration.network,\n rpcProvider,\n rpcApiMiddleware,\n })\n : createCustomNetworkMiddleware({\n blockTracker,\n chainId: configuration.chainId,\n rpcApiMiddleware,\n });\n\n const provider: Provider = new InternalProvider({\n engine: JsonRpcEngineV2.create({\n middleware: [networkMiddleware],\n }),\n });\n\n const destroy = (): void => {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n blockTracker.destroy();\n };\n\n return { configuration, provider, blockTracker, destroy };\n}\n\n/**\n * Creates an RPC service chain, which represents the primary endpoint URL for\n * the network as well as its failover URLs.\n *\n * @param args - The arguments.\n * @param args.id - The ID that will be assigned to the new network client in\n * the registry.\n * @param args.primaryEndpointUrl - The primary endpoint URL.\n * @param args.configuration - The network configuration.\n * @param args.getRpcServiceOptions - Factory for constructing RPC service\n * options. See {@link NetworkControllerOptions.getRpcServiceOptions}.\n * @param args.messenger - The network controller messenger.\n * @param args.isRpcFailoverEnabled - Whether or not requests sent to the\n * primary RPC endpoint for this network should be automatically diverted to\n * provided failover endpoints if the primary is unavailable. This effectively\n * causes the `failoverRpcUrls` property of the network client configuration\n * to be honored or ignored.\n * @param args.logger - A `loglevel` logger.\n * @returns The RPC service chain.\n */\nfunction createRpcServiceChain({\n id,\n primaryEndpointUrl,\n configuration,\n getRpcServiceOptions,\n messenger,\n isRpcFailoverEnabled,\n logger,\n}: {\n id: NetworkClientId;\n primaryEndpointUrl: string;\n configuration: NetworkClientConfiguration;\n getRpcServiceOptions: (\n rpcEndpointUrl: string,\n ) => Omit<RpcServiceOptions, 'failoverService' | 'endpointUrl'>;\n messenger: NetworkControllerMessenger;\n isRpcFailoverEnabled: boolean;\n logger?: Logger;\n}): RpcServiceChain {\n const availableEndpointUrls: [string, ...string[]] = isRpcFailoverEnabled\n ? [primaryEndpointUrl, ...(configuration.failoverRpcUrls ?? [])]\n : [primaryEndpointUrl];\n const rpcServiceConfigurations = availableEndpointUrls.map((endpointUrl) => ({\n ...getRpcServiceOptions(endpointUrl),\n endpointUrl,\n logger,\n }));\n\n /**\n * Extracts the error from Cockatiel's `FailureReason` type received in\n * circuit breaker event handlers.\n *\n * The `FailureReason` object can have two possible shapes:\n * - `{ error: Error }` - When the RPC service throws an error (the common\n * case for RPC failures).\n * - `{ value: T }` - When the RPC service returns a value that the retry\n * filter policy considers a failure.\n *\n * @param value - The event data object from the circuit breaker event\n * listener (after destructuring known properties like `endpointUrl`). This\n * represents Cockatiel's `FailureReason` type.\n * @returns The error or failure value, or `undefined` if neither property\n * exists (which shouldn't happen in practice unless the circuit breaker is\n * manually isolated).\n */\n const getError = (\n value: CockatielFailureReason<unknown> | Record<never, never>,\n ): Error | unknown | undefined => {\n if ('error' in value) {\n return value.error;\n } else if ('value' in value) {\n return value.value;\n }\n return undefined;\n };\n\n const rpcServiceChain = new RpcServiceChain([\n rpcServiceConfigurations[0],\n ...rpcServiceConfigurations.slice(1),\n ]);\n\n rpcServiceChain.onBreak((data) => {\n const error = getError(data);\n\n if (error === undefined) {\n // This error shouldn't happen in practice because we never call `.isolate`\n // on the circuit breaker policy, but we need to appease TypeScript.\n throw new Error('Could not make request to endpoint.');\n }\n\n messenger.publish('NetworkController:rpcEndpointChainUnavailable', {\n chainId: configuration.chainId,\n networkClientId: id,\n error,\n });\n });\n\n rpcServiceChain.onServiceBreak(\n ({\n endpointUrl,\n primaryEndpointUrl: primaryEndpointUrlFromEvent,\n ...rest\n }) => {\n const error = getError(rest);\n\n if (error === undefined) {\n // This error shouldn't happen in practice because we never call `.isolate`\n // on the circuit breaker policy, but we need to appease TypeScript.\n throw new Error('Could not make request to endpoint.');\n }\n\n messenger.publish('NetworkController:rpcEndpointUnavailable', {\n chainId: configuration.chainId,\n networkClientId: id,\n primaryEndpointUrl: primaryEndpointUrlFromEvent,\n endpointUrl,\n error,\n });\n },\n );\n\n rpcServiceChain.onDegraded((data) => {\n const error = getError(data);\n messenger.publish('NetworkController:rpcEndpointChainDegraded', {\n chainId: configuration.chainId,\n networkClientId: id,\n error,\n });\n });\n\n rpcServiceChain.onServiceDegraded(\n ({\n endpointUrl,\n primaryEndpointUrl: primaryEndpointUrlFromEvent,\n ...rest\n }) => {\n const error = getError(rest);\n messenger.publish('NetworkController:rpcEndpointDegraded', {\n chainId: configuration.chainId,\n networkClientId: id,\n primaryEndpointUrl: primaryEndpointUrlFromEvent,\n endpointUrl,\n error,\n });\n },\n );\n\n rpcServiceChain.onAvailable(() => {\n messenger.publish('NetworkController:rpcEndpointChainAvailable', {\n chainId: configuration.chainId,\n networkClientId: id,\n });\n });\n\n rpcServiceChain.onServiceRetry(\n ({\n attempt,\n endpointUrl,\n primaryEndpointUrl: primaryEndpointUrlFromEvent,\n }) => {\n messenger.publish('NetworkController:rpcEndpointRetried', {\n chainId: configuration.chainId,\n networkClientId: id,\n primaryEndpointUrl: primaryEndpointUrlFromEvent,\n endpointUrl,\n attempt,\n });\n },\n );\n\n return rpcServiceChain;\n}\n\n/**\n * Create the block tracker for the network.\n *\n * @param args - The arguments.\n * @param args.networkClientType - The type of the network client (\"infura\" or\n * \"custom\").\n * @param args.endpointUrl - The URL of the endpoint.\n * @param args.getOptions - Factory for the block tracker options.\n * @param args.provider - The EIP-1193 provider for the network's JSON-RPC\n * middleware stack.\n * @returns The created block tracker.\n */\nfunction createBlockTracker({\n networkClientType,\n endpointUrl,\n getOptions,\n provider,\n}: {\n networkClientType: NetworkClientType;\n endpointUrl: string;\n getOptions: (\n rpcEndpointUrl: string,\n ) => Omit<PollingBlockTrackerOptions, 'provider'>;\n provider: InternalProvider;\n}): PollingBlockTracker {\n const testOptions =\n // Needed for testing.\n // eslint-disable-next-line no-restricted-globals\n process.env.IN_TEST && networkClientType === NetworkClientType.Custom\n ? { pollingInterval: SECOND }\n : {};\n\n return new PollingBlockTracker({\n ...testOptions,\n ...getOptions(endpointUrl),\n provider,\n });\n}\n\n/**\n * Create middleware for infura.\n *\n * @param args - The arguments.\n * @param args.blockTracker - The block tracker to use.\n * @param args.network - The Infura network to use.\n * @param args.rpcProvider - The RPC provider to use.\n * @param args.rpcApiMiddleware - Additional middleware.\n * @returns The collection of middleware that makes up the Infura client.\n */\nfunction createInfuraNetworkMiddleware({\n blockTracker,\n network,\n rpcProvider,\n rpcApiMiddleware,\n}: {\n blockTracker: PollingBlockTracker;\n network: InfuraNetworkType;\n rpcProvider: InternalProvider;\n rpcApiMiddleware: RpcApiMiddleware;\n}): JsonRpcMiddleware<\n JsonRpcRequest,\n Json,\n MiddlewareContext<{ origin: string; skipCache: boolean }>\n> {\n return JsonRpcEngineV2.create({\n middleware: [\n createNetworkAndChainIdMiddleware({ network }),\n createBlockCacheMiddleware({ blockTracker }),\n createInflightCacheMiddleware(),\n createBlockRefMiddleware({ blockTracker, provider: rpcProvider }),\n createRetryOnEmptyMiddleware({ blockTracker, provider: rpcProvider }),\n createBlockTrackerInspectorMiddleware({ blockTracker }),\n rpcApiMiddleware,\n ],\n }).asMiddleware();\n}\n\n/**\n * Creates static method middleware.\n *\n * @param args - The Arguments.\n * @param args.network - The Infura network to use.\n * @returns The middleware that implements the eth_chainId method.\n */\nfunction createNetworkAndChainIdMiddleware({\n network,\n}: {\n network: InfuraNetworkType;\n}): JsonRpcMiddleware<JsonRpcRequest> {\n return createScaffoldMiddleware({\n eth_chainId: ChainId[network],\n });\n}\n\nconst createChainIdMiddleware = (\n chainId: Hex,\n): JsonRpcMiddleware<JsonRpcRequest, Json> => {\n return ({ request, next }) => {\n if (request.method === 'eth_chainId') {\n return chainId;\n }\n return next();\n };\n};\n\n/**\n * Creates custom middleware.\n *\n * @param args - The arguments.\n * @param args.blockTracker - The block tracker to use.\n * @param args.chainId - The chain id to use.\n * @param args.rpcApiMiddleware - Additional middleware.\n * @returns The collection of middleware that makes up the Infura client.\n */\nfunction createCustomNetworkMiddleware({\n blockTracker,\n chainId,\n rpcApiMiddleware,\n}: {\n blockTracker: PollingBlockTracker;\n chainId: Hex;\n rpcApiMiddleware: RpcApiMiddleware;\n}): JsonRpcMiddleware<\n JsonRpcRequest,\n Json,\n MiddlewareContext<{ origin: string; skipCache: boolean }>\n> {\n // Needed for testing.\n // eslint-disable-next-line no-restricted-globals\n const testMiddlewares = process.env.IN_TEST\n ? [createEstimateGasDelayTestMiddleware()]\n : [];\n\n return JsonRpcEngineV2.create({\n middleware: [\n ...testMiddlewares,\n createChainIdMiddleware(chainId),\n createBlockRefRewriteMiddleware({ blockTracker }),\n createBlockCacheMiddleware({ blockTracker }),\n createInflightCacheMiddleware(),\n createBlockTrackerInspectorMiddleware({ blockTracker }),\n rpcApiMiddleware,\n ],\n }).asMiddleware();\n}\n\n/**\n * For use in tests only.\n * Adds a delay to `eth_estimateGas` calls.\n *\n * @returns The middleware for delaying gas estimation calls by 2 seconds when in test.\n */\nfunction createEstimateGasDelayTestMiddleware(): JsonRpcMiddleware<\n JsonRpcRequest,\n Json\n> {\n return async ({ request, next }) => {\n if (request.method === 'eth_estimateGas') {\n await new Promise((resolve) => setTimeout(resolve, SECOND * 2));\n }\n return next();\n };\n}\n"]}