Web3 ProviderEngine

raw JSON →
17.0.1 verified Thu Apr 23 auth: no javascript deprecated

Web3 ProviderEngine is a JavaScript library designed for composing custom Ethereum provider objects using a stack of middleware-like modules called 'sub-providers'. It enables fine-grained control over RPC requests, facilitating features like caching and custom transaction signing workflows. Originally developed for MetaMask, this package has been officially deprecated since version 17.0.0, released in March 2023. Development has largely ceased, and the current stable version is 17.0.1. Users are strongly advised to migrate to modern alternatives such as `@metamask/json-rpc-engine`, `@metamask/eth-json-rpc-middleware`, and `@metamask/eth-json-rpc-provider`. Its key differentiator was its highly modular architecture, allowing developers to assemble a customized provider pipeline for diverse DApp requirements, acting as a 'zero-client' that processes local requests and passes data lookups to a data source.

error TypeError: ProviderEngine is not a constructor
cause This error typically occurs when attempting to import `ProviderEngine` using named ESM import syntax (e.g., `import { ProviderEngine } from 'web3-provider-engine';`) in an ESM module, but the package is a CommonJS module with a default export.
fix
For CommonJS modules, use require syntax: const ProviderEngine = require('web3-provider-engine');. For ESM compatibility, use the import * as syntax: import * as ProviderEngine from 'web3-provider-engine';.
error Error: Invalid JSON RPC response: {"jsonrpc":"2.0","error":{"code":-32003,"message":"project ID is required"}}
cause Using `RpcSubprovider` to connect to Infura after `web3-provider-engine` v16.0.0 without providing a valid Infura API key.
fix
Ensure you have an Infura API key and include it in the rpcUrl configuration for RpcSubprovider, e.g., rpcUrl: 'https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID'.
error Node.js version must be ^16.20 || ^18.16 || >=20
cause Attempting to run `web3-provider-engine` version 17.0.0 or higher on an unsupported Node.js version, as the minimum requirement was increased.
fix
Upgrade your Node.js environment to a compatible version (e.g., Node.js 16.20, 18.16, 20, or newer) as indicated in the package's engines field.
breaking This package has been officially deprecated since version 17.0.0 (March 2023). It is no longer actively maintained. All users are strongly advised to migrate to the recommended `@metamask/json-rpc-engine` and related packages for continued support, security updates, and new features.
fix Plan a migration strategy to the `@metamask/json-rpc-engine` ecosystem. The `web3-provider-engine` README provides an example of how to recreate similar functionality with the modern MetaMask packages.
breaking Version 17.0.0 increased the minimum required Node.js version to 16. Applications running on older Node.js versions (e.g., 14 or lower) will encounter runtime errors or fail to install.
fix Upgrade your Node.js environment to version 16.20, 18.16, 20, or newer, as specified in the package's `engines` field.
breaking Version 16.0.0 introduced a breaking change where the Infura provider (used via `RpcSubprovider`) now explicitly requires an API key for the Infura V3 API. Attempts to use Infura without a valid API key will result in RPC errors.
fix Obtain an API key from Infura.io and ensure it is passed in the `rpcUrl` when configuring `RpcSubprovider`, e.g., `rpcUrl: 'https://mainnet.infura.io/v3/YOUR_API_KEY'`.
gotcha Multiple security vulnerabilities related to the `request` dependency were addressed in versions 16.0.6 and 16.0.7 by replacing it with the patched `@cypress/request`. Older versions may be exposed to known vulnerabilities.
fix Upgrade `web3-provider-engine` to version 16.0.7 or later to incorporate these security fixes.
gotcha A security vulnerability discovered in the `cross-fetch` dependency was patched in version 16.0.4. Applications using older versions could be at risk.
fix Upgrade `web3-provider-engine` to version 16.0.4 or later to mitigate this vulnerability.
npm install web3-provider-engine
yarn add web3-provider-engine
pnpm add web3-provider-engine

This quickstart demonstrates how to initialize `Web3 ProviderEngine`, configure a stack of diverse subproviders including caching, filtering, a mocked wallet, and an Infura-based RPC data source. It then connects the engine to a `Web3.js` instance, showcases basic event handling for new blocks, and makes a sample `eth_chainId` RPC request, emphasizing the modular design and the requirement for an Infura API key since version 16.0.0.

const ProviderEngine = require('web3-provider-engine');
const CacheSubprovider = require('web3-provider-engine/subproviders/cache.js');
const FixtureSubprovider = require('web3-provider-engine/subproviders/fixture.js');
const FilterSubprovider = require('web3-provider-engine/subproviders/filters.js');
const VmSubprovider = require('web3-provider-engine/subproviders/vm.js');
const HookedWalletSubprovider = require('web3-provider-engine/subproviders/hooked-wallet.js');
const NonceSubprovider = require('web3-provider-engine/subproviders/nonce-tracker.js');
const RpcSubprovider = require('web3-provider-engine/subproviders/rpc.js');
const Web3 = require('web3'); // Ensure web3 is installed: npm install web3

// Create a new ProviderEngine instance
var engine = new ProviderEngine();
// Connect it to a Web3.js instance
var web3 = new Web3(engine);

// Add various subproviders to the engine stack:

// 1. Static results for common RPC methods
engine.addProvider(new FixtureSubprovider({
  web3_clientVersion: 'ProviderEngine/v0.0.0/javascript',
  net_listening: true,
  eth_hashrate: '0x00',
  eth_mining: false,
  eth_syncing: true,
}));

// 2. Caching layer for RPC results
engine.addProvider(new CacheSubprovider());

// 3. Filter handling for log and block subscriptions
engine.addProvider(new FilterSubprovider());

// 4. Nonce tracking for transaction management
engine.addProvider(new NonceSubprovider());

// 5. Ethereum Virtual Machine (VM) for local execution
engine.addProvider(new VmSubprovider());

// 6. Hooked wallet for identity management and transaction signing
engine.addProvider(new HookedWalletSubprovider({
  getAccounts: function(cb){ console.log('getAccounts called'); cb(null, ['0x9E75379dE05C552E5C9A367E9FfF1B9C7e5A83D0']); }, // Placeholder account
  approveTransaction: function(cb){ console.log('approveTransaction called'); cb(null, true); }, // Auto-approve for demo
  signTransaction: function(cb){ console.log('signTransaction called'); cb(null, '0xf86180808094000000000000000000000000000000000000000080801ba0483c6d860d843825a0a4c0384737d9953835032a76f23e74c1067e812d4d8cae6a053c8c7344933a3889151c76c0e5272a7281c7e949d212a4507119e075c12891'); }, // Placeholder signed tx
}));

// 7. RPC data source (Infura) - requires an API key since v16.0.0
engine.addProvider(new RpcSubprovider({
  rpcUrl: 'https://mainnet.infura.io/v3/' + (process.env.INFURA_API_KEY ?? ''), // Replace with your Infura project ID
}));

// Set up event listeners
engine.on('block', function(block){
  console.log('================================');
  console.log('BLOCK CHANGED:', '#'+block.number.toString('hex'), '0x'+block.hash.toString('hex'));
  console.log('================================');
});

// Handle network connectivity errors
engine.on('error', function(err){
  console.error('ProviderEngine error:', err.stack);
});

// Start the ProviderEngine
engine.start();

// Example usage: Make a simple request using web3.js
web3.eth.getChainId().then(chainId => {
  console.log('Successfully connected to Chain ID:', chainId);
}).catch(error => {
  console.error('Failed to get Chain ID:', error);
});

// Keep the process alive for a short period to observe block events
// In a real application, you would manage engine lifecycle based on usage.
setTimeout(() => {
  console.log('Stopping ProviderEngine after 30 seconds.');
  engine.stop();
}, 30000);