{"id":17598,"library":"eth-json-rpc-middleware","title":"Ethereum JSON-RPC Middleware for json-rpc-engine","description":"eth-json-rpc-middleware provides a collection of Ethereum-specific middleware functions designed to integrate with `@metamask/json-rpc-engine`. It facilitates common RPC patterns like block tracking, transaction handling, and EIP-standard implementations (e.g., EIP-5792, EIP-7715). Maintained by MetaMask, this library is actively developed, evidenced by its frequent major releases and updates to support the latest Ethereum specifications. The current stable version is v20.0.0, which notably introduced separate CommonJS and ESM distributions. Its key differentiators include tight integration within the MetaMask ecosystem and robust support for advanced wallet and RPC interactions, making it a foundational component for building dApps and Ethereum tooling.","status":"active","version":"9.0.1","language":"javascript","source_language":"en","source_url":"https://github.com/MetaMask/eth-json-rpc-middleware","tags":["javascript","typescript"],"install":[{"cmd":"npm install eth-json-rpc-middleware","lang":"bash","label":"npm"},{"cmd":"yarn add eth-json-rpc-middleware","lang":"bash","label":"yarn"},{"cmd":"pnpm add eth-json-rpc-middleware","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core dependency for creating and handling middleware pipelines.","package":"@metamask/json-rpc-engine","optional":false},{"reason":"Used by block-related middleware for tracking the latest blocks.","package":"@metamask/eth-block-tracker","optional":false},{"reason":"Required for the `rpcService` object when using `createFetchMiddleware` since v18.0.0.","package":"@metamask/network-controller","optional":false}],"imports":[{"note":"ESM is preferred since v20.0.0 due to changes in package exports. CommonJS require() might not work or require specific subpath imports.","wrong":"const createFetchMiddleware = require('eth-json-rpc-middleware').createFetchMiddleware;","symbol":"createFetchMiddleware","correct":"import { createFetchMiddleware } from 'eth-json-rpc-middleware';"},{"note":"Direct subpath imports from `dist` are generally not recommended after v20.0.0 due to the `exports` field usage.","wrong":"const createBlockRefMiddleware = require('eth-json-rpc-middleware/dist/block-ref');","symbol":"createBlockRefMiddleware","correct":"import { createBlockRefMiddleware } from 'eth-json-rpc-middleware';"},{"note":"This middleware provides hooks for EIP-5792 and EIP-7715; ensure options match the desired EIP version.","wrong":null,"symbol":"createWalletMiddleware","correct":"import { createWalletMiddleware } from 'eth-json-rpc-middleware';"},{"note":"A simple middleware to inject a `chainId` into requests if not present.","wrong":null,"symbol":"createChainIdMiddleware","correct":"import { createChainIdMiddleware } from 'eth-json-rpc-middleware';"}],"quickstart":{"code":"import { JsonRpcEngine } from 'json-rpc-engine';\nimport { createFetchMiddleware, createBlockRefMiddleware, createChainIdMiddleware } from 'eth-json-rpc-middleware';\n\n// Mock RPC service for createFetchMiddleware (required since v18.0.0)\nconst mockRpcService = {\n  provider: {\n    request: async ({ method, params }) => {\n      console.log(`Mock RPC request: ${method} ${JSON.stringify(params)}`);\n      // In a real application, this would forward to an actual RPC endpoint\n      // using a provider from @metamask/network-controller or similar.\n      if (method === 'eth_chainId') return '0x1'; // Mainnet\n      if (method === 'eth_blockNumber') return '0x' + (123456789).toString(16);\n      if (method === 'eth_sendRawTransaction') return '0xmockTxHash';\n      return null; // Handle other methods as needed\n    },\n  },\n  // Other properties like 'currentChainId' might be expected by some versions/integrations\n};\n\nasync function setupAndUseRpcEngine() {\n  const engine = new JsonRpcEngine();\n\n  // Add middleware\n  engine.add(createBlockRefMiddleware());\n  engine.add(createChainIdMiddleware('0x1')); // Example: force chainId to Ethereum Mainnet\n  engine.add(createFetchMiddleware({ rpcService: mockRpcService }));\n\n  // Example request\n  try {\n    const response = await engine.handle({ id: 1, jsonrpc: '2.0', method: 'eth_blockNumber' });\n    console.log('eth_blockNumber response:', response.result);\n\n    const chainIdResponse = await engine.handle({ id: 2, jsonrpc: '2.0', method: 'eth_chainId' });\n    console.log('eth_chainId response:', chainIdResponse.result);\n\n    // Example of a request that might pass through the fetch middleware\n    const sendTxResponse = await engine.handle({\n      id: 3,\n      jsonrpc: '2.0',\n      method: 'eth_sendRawTransaction',\n      params: ['0xmockrawtransactiondata'],\n    });\n    console.log('eth_sendRawTransaction response:', sendTxResponse.result);\n\n  } catch (error) {\n    console.error('RPC Error:', error);\n  }\n}\n\nsetupAndUseRpcEngine();","lang":"typescript","description":"This quickstart demonstrates how to set up a `json-rpc-engine` with common `eth-json-rpc-middleware` components, including `createFetchMiddleware`, `createBlockRefMiddleware`, and `createChainIdMiddleware`. It includes a mock RPC service, essential since `createFetchMiddleware` v18.0.0, to illustrate request handling."},"warnings":[{"fix":"Migrate CommonJS `require` statements to ESM `import` statements (e.g., `import { Name } from 'eth-json-rpc-middleware';`). Ensure your build system supports `package.json` `exports`.","message":"Version 20.0.0 introduced separate CommonJS and ESM distributions using the `exports` field in `package.json`. This breaks previously valid direct imports (e.g., from `dist/`) and may require updating `require()` statements to named imports.","severity":"breaking","affected_versions":">=20.0.0"},{"fix":"Refactor `createFetchMiddleware` initialization to pass an `rpcService` object. For example: `createFetchMiddleware({ rpcService: { provider: { request: async () => {} } } })`.","message":"The `createFetchMiddleware` signature changed significantly in v18.0.0. It no longer accepts `fetch`, `btoa`, `rpcUrl`, or `originHttpHeaderKey` directly. Instead, it now strictly requires an `rpcService` object, typically sourced from `@metamask/network-controller`.","severity":"breaking","affected_versions":">=18.0.0"},{"fix":"Review and update your EIP-5792 related data structures and validation logic to align with the 2.0.0 specification changes, particularly for `SendCallsStruct` and `GetCallsStatusResult`.","message":"Version 17.0.0 updated support for EIP-5792 to version 2.0.0, introducing changes like the `atomicRequired` property, making `from` optional in `SendCallsStruct`, and modifying error codes. This may require updates to dApps implementing EIP-5792.","severity":"breaking","affected_versions":">=17.0.0"},{"fix":"Upgrade to v16.0.1 or newer to ensure non-standard JSON-RPC error responses are correctly processed as errors.","message":"Prior to v16.0.1, `fetch` middleware could treat non-standard JSON-RPC error responses (those with an `error` field but unexpected additional properties) as successful. This could lead to incorrect error handling or silent failures.","severity":"gotcha","affected_versions":"<16.0.1"},{"fix":"Test block tracking intensive parts of your application after upgrading. Be aware that `getLatestBlock` will now reject on errors rather than potentially hanging, and `useCache: false` is no longer included in some calls.","message":"Changes in `PollingBlockTracker.getLatestBlock()` behavior in v19.0.1 and v17.0.1 (regarding `useCache` and error rejection vs. hanging) could affect dApps relying on specific block tracking update mechanisms.","severity":"gotcha","affected_versions":">=17.0.1 <19.0.0, >=19.0.1"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"Update imports to use the top-level package name and named imports (e.g., `import { createSomeMiddleware } from 'eth-json-rpc-middleware';`).","cause":"Attempting to import modules using paths that are no longer exposed directly (e.g., `eth-json-rpc-middleware/dist/something.js`) after v20.0.0's change to `package.json` `exports`.","error":"ERR_PACKAGE_PATH_NOT_EXPORTED"},{"fix":"Ensure `createFetchMiddleware` is called with an object containing an `rpcService` property, which itself has a `provider.request` method, as required since v18.0.0.","cause":"Calling `createFetchMiddleware` with an outdated signature (e.g., passing `rpcUrl` directly) after the v18.0.0 breaking change.","error":"TypeError: createFetchMiddleware is not a function"},{"fix":"Inspect the underlying RPC error; if using older versions, be aware that `getLatestBlock` might reject on errors now, which could be an upstream issue with your RPC provider or network configuration.","cause":"An error occurred during an RPC call to fetch the latest block, and this error is being wrapped by the `PollingBlockTracker`.","error":"Error: PollingBlockTracker - encountered an error while attempting to update latest block"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}