Prool
Prool is a TypeScript-first library designed to provide programmatic HTTP testing instances for various Ethereum components. It enables developers to spin up local execution nodes (like Anvil and Tempo) and ERC-4337 bundler nodes (like Alto) within testing environments such as Vitest. The library is currently at version `0.2.4` and maintains an active release cadence with frequent patch and minor updates. A key differentiator is its focus on streamlining the setup and teardown of these instances for reliable, isolated tests, abstracting away the complexities of managing external processes or Docker containers. Users can utilize pre-configured instances or define custom ones to suit specific testing needs, requiring Node.js >=22. It integrates with `testcontainers` for containerized instances.
Common errors
-
TypeError: Instance.tempoDocker is not a function
cause After upgrading to `prool` v0.2.0 or later, the `tempoDocker` instance was moved and renamed.fixUpdate your import statement to `import { Instance } from 'prool/testcontainers'` and change `Instance.tempoDocker` to `Instance.tempo`. -
Error [ERR_REQUIRE_ESM]: require() of ES Module ... not supported. Instead, change the require of index.js in ... to a dynamic import() call.
cause Attempting to use CommonJS `require()` syntax with Prool, which is an ESM-first library requiring Node.js >=22.fixSwitch to ESM `import` statements: `import { Server } from 'prool'` instead of `const { Server } = require('prool')`. -
Error: Tempo container failed to start: Error: connect ECONNREFUSED 127.0.0.1:XXXX
cause On macOS, prior to `v0.2.4`, containerized instances like Tempo might have issues with port binding and host networking, leading to connection refusals.fixUpgrade Prool to `v0.2.4` or newer to leverage the fix for macOS host networking. Ensure Docker Desktop is running and healthy. -
Error: Command failed with exit code 1: foundryup
cause The `Instance.anvil()` relies on the `anvil` executable from Foundry, which is not found in the system's PATH.fixInstall Foundry globally by running `curl -L https://foundry.paradigm.xyz | bash` and ensure it's added to your shell's PATH.
Warnings
- breaking The `Instance.tempoDocker` property was removed and its functionality was moved to a new entrypoint `prool/testcontainers`. The method itself was renamed to `Instance.tempo`.
- breaking Several pre-configured instances, specifically `silius`, `stackup`, and `rundler`, were removed from the library.
- gotcha Prool requires Node.js version 22 or higher due to its use of modern JavaScript features and ESM-first design.
- gotcha For containerized instances (e.g., Tempo via `prool/testcontainers`), macOS users might experience connectivity issues if running versions older than `v0.2.4` due to host networking configurations. Prior versions might not correctly bind to `127.0.0.1`.
- gotcha Using instances like `Instance.anvil()` or `Instance.tempo()` requires the respective CLI tools (Foundry or Tempo CLI) to be installed globally on your system, or accessible in your PATH.
Install
-
npm install prool -
yarn add prool -
pnpm add prool
Imports
- Server
const { Server } = require('prool')import { Server } from 'prool' - Instance
const { Instance } = require('prool')import { Instance } from 'prool' - Instance.tempo
import { Instance } from 'prool'; Instance.tempoDockerimport { Instance } from 'prool/testcontainers'
Quickstart
import { Instance, Server } from 'prool';
// NOTE: Requires Foundry to be installed globally:
// `curl -L https://foundry.paradigm.xyz | bash`
async function runAnvilServer() {
const server = Server.create({
instance: Instance.anvil(),
port: 8545 // Optional, default is 8545
});
try {
console.log('Starting Anvil server...');
await server.start();
console.log('Anvil server started successfully!');
console.log('Instances accessible at:');
// Access the base URL for instances, e.g., for direct RPC calls
// `server.url` returns 'http://localhost:8545/'
// The specific instances are accessed via paths, e.g., 'http://localhost:8545/1'
console.log(` Base URL: ${server.url}`);
console.log(' Example instance URL: http://localhost:8545/1');
// Simulate some work or keep it running for a test suite
await new Promise(resolve => setTimeout(resolve, 5000)); // Keep alive for 5 seconds
} catch (error) {
console.error('Failed to start Anvil server:', error);
} finally {
console.log('Stopping Anvil server...');
await server.stop();
console.log('Anvil server stopped.');
}
}
runAnvilServer();