diff --git a/packages/network-controller/package.json b/packages/network-controller/package.json index 0e6291e23dc..6f23a3b0d24 100644 --- a/packages/network-controller/package.json +++ b/packages/network-controller/package.json @@ -31,18 +31,24 @@ "dependencies": { "@metamask/base-controller": "workspace:~", "@metamask/controller-utils": "workspace:~", + "@metamask/eth-json-rpc-infura": "^7.0.0", "async-mutex": "^0.2.6", "babel-runtime": "^6.26.0", + "eth-block-tracker": "^6.0.0", "eth-json-rpc-infura": "^5.1.0", + "eth-json-rpc-middleware": "^9.0.1", "eth-query": "^2.1.2", "immer": "^9.0.6", + "json-rpc-engine": "^6.1.0", "web3-provider-engine": "^16.0.3" }, "devDependencies": { "@metamask/auto-changelog": "^3.1.0", + "@metamask/safe-event-emitter": "^2.0.0", "@types/jest": "^26.0.22", "deepmerge": "^4.2.2", "jest": "^26.4.2", + "nock": "^13.2.9", "sinon": "^9.2.4", "ts-jest": "^26.5.2", "typedoc": "^0.22.15", diff --git a/packages/network-controller/src/NetworkController.test.ts b/packages/network-controller/src/NetworkController.test.ts index a49fbfa1bf1..de956240ce8 100644 --- a/packages/network-controller/src/NetworkController.test.ts +++ b/packages/network-controller/src/NetworkController.test.ts @@ -1,16 +1,62 @@ import * as sinon from 'sinon'; -import Web3ProviderEngine from 'web3-provider-engine'; import { ControllerMessenger } from '@metamask/base-controller'; import { NetworkType, NetworksChainId } from '@metamask/controller-utils'; +import SafeEventEmitter from '@metamask/safe-event-emitter'; +import nock from 'nock'; import { NetworkController, NetworkControllerMessenger, NetworkControllerOptions, - ProviderConfig, } from './NetworkController'; const RPC_TARGET = 'http://foo'; +type WithMockedBlockTrackerOptions = { + nextBlockNumber?: () => string; +}; + +const withMockedBlockTracker = async ( + options: WithMockedBlockTrackerOptions = {}, +) => { + const nextBlockNumber = options.nextBlockNumber + ? options.nextBlockNumber + : () => '0x42'; + + const urlRegex = /https:\/\/.*/u; + const anyRegex = /.*/u; + nock(urlRegex) + .post(anyRegex, { + jsonrpc: '2.0', + id: anyRegex, + method: "eth_blockNumber", + params: [], + }) + .reply((_, reqBody: any) => { + console.log(reqBody); + return [ + 200, + { jsonrpc: '2.0', id: reqBody.id, result: nextBlockNumber() }, + ]; + }) + .persist(); + + nock(urlRegex) + .post(anyRegex, { + jsonrpc: '2.0', + id: anyRegex, + method: "eth_getBlockByNumber", + params: ["0x42", false], + }) + .reply((_, reqBody: any) => { + console.log(reqBody); + return [ + 200, + { jsonrpc: '2.0', id: reqBody.id, result: {} }, + ]; + }) + .persist(); +}; + const setupController = ( pType: NetworkType, messenger: NetworkControllerMessenger, @@ -28,7 +74,6 @@ const setupController = ( messenger, }; const controller = new NetworkController(networkControllerOpts); - controller.providerConfig = {} as ProviderConfig; return controller; }; @@ -45,6 +90,8 @@ describe('NetworkController', () => { afterEach(() => { sinon.restore(); + nock.restore(); + nock.cleanAll(); }); it('should set default state', () => { @@ -56,7 +103,9 @@ describe('NetworkController', () => { expect(controller.state).toStrictEqual({ network: 'loading', isCustomNetwork: false, - properties: { isEIP1559Compatible: false }, + properties: { + isEIP1559Compatible: false + }, provider: { type: 'mainnet', chainId: '1', @@ -70,23 +119,42 @@ describe('NetworkController', () => { messenger, }; const controller = new NetworkController(networkControllerOpts); - controller.providerConfig = {} as ProviderConfig; - expect(controller.provider instanceof Web3ProviderEngine).toBe(true); + const setupInfuraProvider = jest.spyOn(NetworkController.prototype as any, 'setupInfuraProvider'); + setupInfuraProvider.mockImplementationOnce(() => { }); + + controller.setProviderType(controller.state.provider.type); + expect(setupInfuraProvider).toHaveBeenCalled(); }); ( - ['kovan', 'rinkeby', 'ropsten', 'mainnet', 'localhost'] as NetworkType[] + ['kovan', 'rinkeby', 'ropsten', 'mainnet'] as NetworkType[] ).forEach((n) => { it(`should create a provider instance for ${n} infura network`, () => { const networkController = setupController(n, messenger); - expect(networkController.provider instanceof Web3ProviderEngine).toBe( - true, - ); + + const setupInfuraProvider = jest.spyOn(NetworkController.prototype as any, 'setupInfuraProvider'); + setupInfuraProvider.mockImplementationOnce(() => { }); expect(networkController.state.isCustomNetwork).toBe(false); + networkController.setProviderType(n); + expect(setupInfuraProvider).toHaveBeenCalled(); }); }); - it('should create a provider instance for optimism network', () => { + it(`should create a provider instance for localhost network`, () => { + const networkController = setupController('localhost', messenger); + + const setupStandardProvider = jest.spyOn( + NetworkController.prototype as any, + 'setupStandardProvider' + ); + setupStandardProvider.mockImplementationOnce(() => { }); + + expect(networkController.state.isCustomNetwork).toBe(false); + networkController.setProviderType('localhost'); + expect(setupStandardProvider).toHaveBeenCalled(); + }); + + it.only('should create a provider instance for optimism network', () => { const networkControllerOpts: NetworkControllerOptions = { infuraProjectId: 'foo', state: { @@ -100,13 +168,21 @@ describe('NetworkController', () => { }, messenger, }; + const controller = new NetworkController(networkControllerOpts); - controller.providerConfig = {} as ProviderConfig; - expect(controller.provider instanceof Web3ProviderEngine).toBe(true); + + const setupStandardProvider = jest.spyOn( + NetworkController.prototype as any, + 'setupStandardProvider' + ); + setupStandardProvider.mockImplementationOnce(() => { }); + + controller.setProviderType(controller.state.provider.type); expect(controller.state.isCustomNetwork).toBe(true); + expect(setupStandardProvider).toHaveBeenCalled(); }); - it('should create a provider instance for rpc network', () => { + it.only('should create a provider instance for rpc network', () => { const networkControllerOpts: NetworkControllerOptions = { infuraProjectId: 'foo', state: { @@ -120,20 +196,33 @@ describe('NetworkController', () => { messenger, }; const controller = new NetworkController(networkControllerOpts); - controller.providerConfig = {} as ProviderConfig; - expect(controller.provider instanceof Web3ProviderEngine).toBe(true); + + const setupStandardProvider = jest.spyOn( + NetworkController.prototype as any, + 'setupStandardProvider' + ); + setupStandardProvider.mockImplementationOnce(() => { }); + + controller.setProviderType(controller.state.provider.type); expect(controller.state.isCustomNetwork).toBe(false); + expect(setupStandardProvider).toHaveBeenCalled(); }); it('should set new RPC target', () => { - const controller = new NetworkController({ messenger }); + const controller = new NetworkController({ + messenger, + infuraProjectId: 'potate', + }); controller.setRpcTarget(RPC_TARGET, NetworksChainId.rpc); expect(controller.state.provider.rpcTarget).toBe(RPC_TARGET); expect(controller.state.isCustomNetwork).toBe(false); }); it('should set new provider type', () => { - const controller = new NetworkController({ messenger }); + const controller = new NetworkController({ + messenger, + infuraProjectId: 'potate', + }); controller.setProviderType('localhost'); expect(controller.state.provider.type).toBe('localhost'); expect(controller.state.isCustomNetwork).toBe(false); @@ -180,7 +269,10 @@ describe('NetworkController', () => { }); it('should throw when setting an unrecognized provider type', () => { - const controller = new NetworkController({ messenger }); + const controller = new NetworkController({ + messenger, + infuraProjectId: 'potate', + }); expect(() => controller.setProviderType('junk' as NetworkType)).toThrow( "Unrecognized network type: 'junk'", ); @@ -194,8 +286,11 @@ describe('NetworkController', () => { network: 'loading', }, }); - controller.providerConfig = {} as ProviderConfig; + controller.setProviderType(controller.state.provider.type); controller.lookupNetwork = sinon.stub(); + if (controller.provider === undefined) { + throw new Error('provider is undefined'); + } controller.provider.emit('error', {}); expect((controller.lookupNetwork as any).called).toBe(true); }); @@ -218,7 +313,7 @@ describe('NetworkController', () => { }; messenger.subscribe(event, handleProviderChange); - controller.providerConfig = {} as ProviderConfig; + controller.setProviderType(controller.state.provider.type); }); }); }); diff --git a/packages/network-controller/src/NetworkController.ts b/packages/network-controller/src/NetworkController.ts index a0f9aaccef3..04ce892fe98 100644 --- a/packages/network-controller/src/NetworkController.ts +++ b/packages/network-controller/src/NetworkController.ts @@ -1,7 +1,4 @@ import EthQuery from 'eth-query'; -import Subprovider from 'web3-provider-engine/subproviders/provider'; -import createInfuraProvider from 'eth-json-rpc-infura/src/createProvider'; -import createMetamaskProvider from 'web3-provider-engine/zero'; import { Mutex } from 'async-mutex'; import type { Patch } from 'immer'; import { @@ -15,6 +12,16 @@ import { NetworksChainId, NetworkType, } from '@metamask/controller-utils'; +import { JsonRpcEngine, JsonRpcMiddleware } from 'json-rpc-engine'; +import { + providerFromEngine, + SafeEventEmitterProvider, +} from 'eth-json-rpc-middleware'; +import { PollingBlockTracker } from 'eth-block-tracker'; +import createInfuraClient, { + InfuraNetworkType, +} from './clients/createInfuraClient'; +import createJsonRpcClient from './clients/createJsonRpcClient'; /** * @type ProviderConfig @@ -114,8 +121,6 @@ export class NetworkController extends BaseControllerV2< > { private ethQuery: EthQuery; - private internalProviderConfig: ProviderConfig = {} as ProviderConfig; - private infuraProjectId: string | undefined; private mutex = new Mutex(); @@ -164,13 +169,13 @@ export class NetworkController extends BaseControllerV2< type: NetworkType, rpcTarget?: string, chainId?: string, - ticker?: string, - nickname?: string, ) { this.update((state) => { state.isCustomNetwork = this.getIsCustomNetwork(chainId); }); - + console.log("initialize provider:"); + console.log(type); + console.log(chainId); switch (type) { case 'kovan': case MAINNET: @@ -183,8 +188,7 @@ export class NetworkController extends BaseControllerV2< this.setupStandardProvider(LOCALHOST_RPC_URL); break; case RPC: - rpcTarget && - this.setupStandardProvider(rpcTarget, chainId, ticker, nickname); + rpcTarget && this.setupStandardProvider(rpcTarget, chainId as string); break; default: throw new Error(`Unrecognized network type: '${type}'`); @@ -197,33 +201,37 @@ export class NetworkController extends BaseControllerV2< state.network = 'loading'; state.properties = {}; }); - const { rpcTarget, type, chainId, ticker } = this.state.provider; - this.initializeProvider(type, rpcTarget, chainId, ticker); + const { rpcTarget, type, chainId } = this.state.provider; + this.initializeProvider(type, rpcTarget, chainId); this.lookupNetwork(); } private registerProvider() { + if (this.provider === undefined) { + throw new Error( + 'dont call registerProvider when networkController.provider is unset', + ); + } + this.provider.on('error', this.verifyNetwork.bind(this)); this.ethQuery = new EthQuery(this.provider); } private setupInfuraProvider(type: NetworkType) { - const infuraProvider = createInfuraProvider({ - network: type, - projectId: this.infuraProjectId, - }); - const infuraSubprovider = new Subprovider(infuraProvider); - const config = { - ...this.internalProviderConfig, - ...{ - dataSubprovider: infuraSubprovider, - engineParams: { - blockTrackerProvider: infuraProvider, - pollingInterval: 12000, - }, - }, - }; - this.updateProvider(createMetamaskProvider(config)); + const { networkMiddleware, blockTracker } = createInfuraClient( + type as InfuraNetworkType, + this.infuraProjectId as string, + ); + this.updateProvider(networkMiddleware, blockTracker); + } + + private setupStandardProvider(rpcTarget: string, chainId?: string) { + const { networkMiddleware, blockTracker } = createJsonRpcClient( + rpcTarget, + chainId, + ); + + this.updateProvider(networkMiddleware, blockTracker); } private getIsCustomNetwork(chainId?: string) { @@ -237,28 +245,26 @@ export class NetworkController extends BaseControllerV2< ); } - private setupStandardProvider( - rpcTarget: string, - chainId?: string, - ticker?: string, - nickname?: string, + // extensions network controller saves a copy of the blockTracker. + // need to figure out if we migrate this functionality or not. + private updateProvider( + networkMiddleware: JsonRpcMiddleware, + blockTracker: PollingBlockTracker, ) { - const config = { - ...this.internalProviderConfig, - ...{ - chainId, - engineParams: { pollingInterval: 12000 }, - nickname, - rpcUrl: rpcTarget, - ticker, - }, - }; - this.updateProvider(createMetamaskProvider(config)); - } - - private updateProvider(provider: any) { this.safelyStopProvider(this.provider); + + const engine = new JsonRpcEngine(); + engine.push(networkMiddleware); + const provider = providerFromEngine(engine); + this.provider = provider; + this.blockTracker = blockTracker; + + this.messagingSystem.publish( + `NetworkController:providerChange`, + this.state.provider, + ); + this.registerProvider(); } @@ -272,29 +278,13 @@ export class NetworkController extends BaseControllerV2< this.state.network === 'loading' && this.lookupNetwork(); } - /** - * Ethereum provider object for the current network - */ - provider: any; + blockTracker: PollingBlockTracker | undefined; /** - * Sets a new configuration for web3-provider-engine. - * - * TODO: Replace this wth a method. - * - * @param providerConfig - The web3-provider-engine configuration. + * Ethereum provider object for the current network + * todo: should never be undefined (definitely assigned in constructor) */ - set providerConfig(providerConfig: ProviderConfig) { - this.internalProviderConfig = providerConfig; - const { type, rpcTarget, chainId, ticker, nickname } = this.state.provider; - this.initializeProvider(type, rpcTarget, chainId, ticker, nickname); - this.registerProvider(); - this.lookupNetwork(); - } - - get providerConfig() { - throw new Error('Property only used for setting'); - } + provider: SafeEventEmitterProvider | undefined; /** * Refreshes the current network code. @@ -339,7 +329,7 @@ export class NetworkController extends BaseControllerV2< // If testnet the ticker symbol should use a testnet prefix const ticker = type in TESTNET_NETWORK_TYPE_TO_TICKER_SYMBOL && - TESTNET_NETWORK_TYPE_TO_TICKER_SYMBOL[type].length > 0 + TESTNET_NETWORK_TYPE_TO_TICKER_SYMBOL[type].length > 0 ? TESTNET_NETWORK_TYPE_TO_TICKER_SYMBOL[type] : 'ETH'; diff --git a/packages/network-controller/src/clients/createInfuraClient.ts b/packages/network-controller/src/clients/createInfuraClient.ts new file mode 100644 index 00000000000..11b88bf94e4 --- /dev/null +++ b/packages/network-controller/src/clients/createInfuraClient.ts @@ -0,0 +1,91 @@ +import { + createScaffoldMiddleware, + JsonRpcMiddleware, + mergeMiddleware, +} from 'json-rpc-engine'; +import { + createBlockRefMiddleware, + createRetryOnEmptyMiddleware, + createBlockCacheMiddleware, + createInflightCacheMiddleware, + createBlockTrackerInspectorMiddleware, + providerFromMiddleware, +} from 'eth-json-rpc-middleware'; + +import { createInfuraMiddleware } from '@metamask/eth-json-rpc-infura'; +import { PollingBlockTracker } from 'eth-block-tracker'; + +import { NetworksChainId, NetworkType } from '@metamask/controller-utils'; +import { CreateClientResult } from './types'; + +export type InfuraNetworkType = + | 'kovan' + | 'mainnet' + | 'rinkeby' + | 'goerli' + | 'ropsten'; + +/** + * Create client middleware for infura. + * + * @param network - the network name. + * @param projectId - infura project id. + * @returns The network middleware and the block tracker. + */ +export default function createInfuraClient( + network: InfuraNetworkType, + projectId: string, +): CreateClientResult { + const infuraMiddleware = createInfuraMiddleware({ + network, + projectId, + maxAttempts: 5, + source: 'metamask', + }); + const infuraProvider = providerFromMiddleware(infuraMiddleware); + // there is a type mismatch for Provider & SafeEventEmitter. + const blockTracker = new PollingBlockTracker({ + provider: infuraProvider as any, + }); + + const networkMiddleware = mergeMiddleware([ + createNetworkAndChainIdMiddleware(network), + createBlockCacheMiddleware({ blockTracker: blockTracker as any }) as any, // something wrong with typing + createInflightCacheMiddleware(), + createBlockRefMiddleware({ + blockTracker: blockTracker as any, + provider: infuraProvider, + }), + createRetryOnEmptyMiddleware({ + blockTracker: blockTracker as any, + provider: infuraProvider, + }), + createBlockTrackerInspectorMiddleware({ + blockTracker: blockTracker as any, + }), + infuraMiddleware, + ]); + return { networkMiddleware, blockTracker }; +} + +/** + * Create middleware that will trap calls to get network or chain id. + * + * @param network - network type that we are connecting to. + * @returns json-rpc-engine middleware + */ +function createNetworkAndChainIdMiddleware( + network: NetworkType, +): JsonRpcMiddleware { + const chainId = NetworksChainId[network] === undefined; + + if (typeof chainId === undefined) { + throw new Error(`createInfuraClient - unknown network "${network}"`); + } + + // For infura networks, networkId is always the same as chainId. + return createScaffoldMiddleware({ + eth_chainId: chainId, + net_version: chainId, + }); +} diff --git a/packages/network-controller/src/clients/createJsonRpcClient.ts b/packages/network-controller/src/clients/createJsonRpcClient.ts new file mode 100644 index 00000000000..67caf1370ac --- /dev/null +++ b/packages/network-controller/src/clients/createJsonRpcClient.ts @@ -0,0 +1,50 @@ +import { createScaffoldMiddleware, mergeMiddleware } from 'json-rpc-engine'; +import { + createFetchMiddleware, + createBlockRefRewriteMiddleware, + createBlockCacheMiddleware, + createInflightCacheMiddleware, + createBlockTrackerInspectorMiddleware, + providerFromMiddleware, +} from 'eth-json-rpc-middleware'; +import { PollingBlockTracker } from 'eth-block-tracker'; +import { CreateClientResult } from './types'; + +/** + * Create client middleware for a custom rpc endpoint. + * + * @param rpcUrl - url of the rpc endpoint. + * @param chainId - the chain id for the rpc endpoint. This value will always be returned by eth_chainId. + * @returns The network middleware and the block tracker. + */ +export default function createJsonRpcClient( + rpcUrl: string, + chainId?: string, +): CreateClientResult { + const fetchMiddleware = createFetchMiddleware({ rpcUrl }); + const blockProvider = providerFromMiddleware(fetchMiddleware); + const blockTracker = new PollingBlockTracker({ + provider: blockProvider as any, + }); + + const scaffolded = []; + + if (chainId !== undefined) { + scaffolded.push(createScaffoldMiddleware({ eth_chainId: chainId })); + } + + const networkMiddleware = mergeMiddleware([ + ...scaffolded, + createBlockRefRewriteMiddleware({ + blockTracker: blockTracker as any, + }) as any, + createBlockCacheMiddleware({ blockTracker: blockTracker as any }), + createInflightCacheMiddleware(), + createBlockTrackerInspectorMiddleware({ + blockTracker: blockTracker as any, + }), + fetchMiddleware, + ]); + + return { networkMiddleware, blockTracker }; +} diff --git a/packages/network-controller/src/clients/types.ts b/packages/network-controller/src/clients/types.ts new file mode 100644 index 00000000000..c330b5fdeb4 --- /dev/null +++ b/packages/network-controller/src/clients/types.ts @@ -0,0 +1,7 @@ +import { PollingBlockTracker } from 'eth-block-tracker'; +import { JsonRpcMiddleware } from 'json-rpc-engine'; + +export type CreateClientResult = { + networkMiddleware: JsonRpcMiddleware; + blockTracker: PollingBlockTracker; +}; diff --git a/yarn.lock b/yarn.lock index 53185a7d73c..11433c50621 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1668,6 +1668,19 @@ __metadata: languageName: node linkType: hard +"@metamask/eth-json-rpc-infura@npm:^7.0.0": + version: 7.0.0 + resolution: "@metamask/eth-json-rpc-infura@npm:7.0.0" + dependencies: + "@metamask/utils": ^3.0.1 + eth-json-rpc-middleware: ^8.1.0 + eth-rpc-errors: ^4.0.3 + json-rpc-engine: ^6.1.0 + node-fetch: ^2.6.7 + checksum: 6230cb289b66db39d27f08ffc72cfb79274e632e4e14eb52ca72d19167d17bbf22c58718d80f801818058631dec0638bcc21ef4b229fa8d53e7f9328be870fc6 + languageName: node + linkType: hard + "@metamask/eth-sig-util@npm:^4.0.0": version: 4.0.1 resolution: "@metamask/eth-sig-util@npm:4.0.1" @@ -1681,6 +1694,20 @@ __metadata: languageName: node linkType: hard +"@metamask/eth-sig-util@npm:^5.0.0": + version: 5.0.2 + resolution: "@metamask/eth-sig-util@npm:5.0.2" + dependencies: + "@ethereumjs/util": ^8.0.0 + bn.js: ^4.11.8 + ethereum-cryptography: ^1.1.2 + ethjs-util: ^0.1.6 + tweetnacl: ^1.0.3 + tweetnacl-util: ^0.15.1 + checksum: 1fbf1a0f5e654058f0219c9018dbebadf53036c9c3b47c8faf1cac54816532bb18996821736f526ac4e3d579afcaf502af4ad07e88158a50f015141858b08a90 + languageName: node + linkType: hard + "@metamask/gas-fee-controller@workspace:packages/gas-fee-controller": version: 0.0.0-use.local resolution: "@metamask/gas-fee-controller@workspace:packages/gas-fee-controller" @@ -1776,14 +1803,18 @@ __metadata: "@metamask/auto-changelog": ^3.1.0 "@metamask/base-controller": "workspace:~" "@metamask/controller-utils": "workspace:~" + "@metamask/eth-json-rpc-infura": ^7.0.0 + "@metamask/safe-event-emitter": ^2.0.0 "@types/jest": ^26.0.22 async-mutex: ^0.2.6 babel-runtime: ^6.26.0 deepmerge: ^4.2.2 eth-json-rpc-infura: ^5.1.0 + eth-json-rpc-middleware: ^9.0.1 eth-query: ^2.1.2 immer: ^9.0.6 jest: ^26.4.2 + nock: ^13.2.9 sinon: ^9.2.4 ts-jest: ^26.5.2 typedoc: ^0.22.15 @@ -1970,6 +2001,17 @@ __metadata: languageName: node linkType: hard +"@metamask/utils@npm:^3.0.1": + version: 3.3.1 + resolution: "@metamask/utils@npm:3.3.1" + dependencies: + "@types/debug": ^4.1.7 + debug: ^4.3.4 + superstruct: ^0.16.7 + checksum: 5b6b6b54fdff4bc3f77b31ef50c23adca8fdf21d81d4f68d3d9c2b383b145cd61c2435f5ba0a11344484ae1f6d2355fab82eec58ce6b19eb35b476928b2e4ee6 + languageName: node + linkType: hard + "@metamask/utils@npm:^3.0.3": version: 3.2.0 resolution: "@metamask/utils@npm:3.2.0" @@ -4919,6 +4961,17 @@ __metadata: languageName: node linkType: hard +"eth-block-tracker@npm:^5.0.1": + version: 5.0.1 + resolution: "eth-block-tracker@npm:5.0.1" + dependencies: + "@metamask/safe-event-emitter": ^2.0.0 + json-rpc-random-id: ^1.0.1 + pify: ^3.0.0 + checksum: 83b2dd28fb7f12d644f1c1bc72011fb6bb683012489973e31171d445a34ddf6a1c167be4e4232bf7eb65144f08d92705795cf6b371c5aa6a8e78ebf48e4d5654 + languageName: node + linkType: hard + "eth-ens-namehash@npm:^2.0.8": version: 2.0.8 resolution: "eth-ens-namehash@npm:2.0.8" @@ -4974,6 +5027,43 @@ __metadata: languageName: node linkType: hard +"eth-json-rpc-middleware@npm:^8.1.0": + version: 8.1.0 + resolution: "eth-json-rpc-middleware@npm:8.1.0" + dependencies: + "@metamask/safe-event-emitter": ^2.0.0 + btoa: ^1.2.1 + clone: ^2.1.1 + eth-block-tracker: ^5.0.1 + eth-rpc-errors: ^4.0.3 + eth-sig-util: ^1.4.2 + json-rpc-engine: ^6.1.0 + json-stable-stringify: ^1.0.1 + node-fetch: ^2.6.7 + pify: ^3.0.0 + checksum: ec10bbc04e3b7696f82db2db528b052c8f6de811c90a12d4eb32f23cbe6ea198d86656afa5b53c52de06b631fef633cf29409bb56c04a16f173da94ee1d89ab6 + languageName: node + linkType: hard + +"eth-json-rpc-middleware@npm:^9.0.1": + version: 9.0.1 + resolution: "eth-json-rpc-middleware@npm:9.0.1" + dependencies: + "@metamask/eth-sig-util": ^5.0.0 + "@metamask/safe-event-emitter": ^2.0.0 + "@metamask/utils": ^3.0.3 + btoa: ^1.2.1 + clone: ^2.1.1 + eth-block-tracker: ^5.0.1 + eth-rpc-errors: ^4.0.3 + json-rpc-engine: ^6.1.0 + json-stable-stringify: ^1.0.1 + node-fetch: ^2.6.7 + pify: ^3.0.0 + checksum: 9512829a6958df6ef739b891a0c0804b51a140407fd2e3ddaaa6b18d975796646cfcf7f7305a18beb7903db09e0c7a91b06dc5434b6bd2d6cdb85d992d9fd3ab + languageName: node + linkType: hard + "eth-keyring-controller@npm:^7.0.2": version: 7.0.2 resolution: "eth-keyring-controller@npm:7.0.2" @@ -5043,6 +5133,15 @@ __metadata: languageName: node linkType: hard +"eth-rpc-errors@npm:^4.0.3": + version: 4.0.3 + resolution: "eth-rpc-errors@npm:4.0.3" + dependencies: + fast-safe-stringify: ^2.0.6 + checksum: 5fa31d1a10fdb340733b9a55e38e7687222c501052ca20743cef4d0c911a9bbcc0cad54aa6bf3e4b428604c071ff519803060e1cbc79ddb7c9257c11d407d32a + languageName: node + linkType: hard + "eth-sig-util@npm:^1.4.2": version: 1.4.2 resolution: "eth-sig-util@npm:1.4.2" @@ -8732,6 +8831,18 @@ __metadata: languageName: node linkType: hard +"nock@npm:^13.2.9": + version: 13.2.9 + resolution: "nock@npm:13.2.9" + dependencies: + debug: ^4.1.0 + json-stringify-safe: ^5.0.1 + lodash: ^4.17.21 + propagate: ^2.0.0 + checksum: 04a2dc60b4b55fd1240f28fe34865bbc744088a4570db3781fcf66021644cc3cc9178fd86a0cb0c1f28ea77b83e8f1c9288535f6b39a6d07100059f156ccc23b + languageName: node + linkType: hard + "node-addon-api@npm:^2.0.0": version: 2.0.2 resolution: "node-addon-api@npm:2.0.2" @@ -11015,6 +11126,13 @@ __metadata: languageName: node linkType: hard +"superstruct@npm:^0.16.7": + version: 0.16.7 + resolution: "superstruct@npm:0.16.7" + checksum: c8c855ff6945da8a41048c6d236de7b1af5d4d9c31742b3ee54d65647c31597488620281f65e095d5efc9e2fbdaad529b8c8f2506c12569d428467c835a21477 + languageName: node + linkType: hard + "supports-color@npm:^5.3.0": version: 5.5.0 resolution: "supports-color@npm:5.5.0"