Why Run An Ethereum Node in JavaScript?
You know what would make solving all these problems trivially easy? If we just were able to use Foundry in the browser
That's what Fucory thought the day he started building Tevm โ putting the Foundry API in the browser, then growing from there. Tevm's use case is simply TypeScript + EVM.
We believe every TypeScript user of the EVM who installs Viem will also install Tevm alongside it in the future
- ๐ Enhanced Performance โ Execute transactions locally with near-zero latency for gas estimation, simulation, and debugging.
- ๐ป Browser Compatibility โ Enable offline capabilities, optimistic UI, and real-time simulations in dApps.
- ๐ Debug Superpowers โ Step through EVM execution opcode by opcode; inspect memory and stack.
- ๐ ๏ธ Familiar Developer Experience โ Works with viem, ethers, or any EIP-1193 compatible tool.
Performance & Efficiency
- โก Optimized fork mode โ Benchmarked to outperform Anvil at executing calls in
forkedmode via more efficient storage slot retrieval. - โก Zero network latency โ Local EVM execution eliminates RPC round-trips for near-instant simulations and gas estimation.
- Local-first gas estimation โ No loading spinner, no RPC credits burned.
- ๐ Powerful JS interop โ Simulate multiple transactions, plug directly into the EVM, or write custom contracts in JS.
Optimistic updates
Show users the expected state of their account โ pending transactions, state changes, or snappy UI with a pending icon. Tevm makes optimistic state simple.
// create a client in rebase mode so it updates optimistic state as new blocks come in
const client = createMemoryClient({
fork: {
transport: http("https://mainnet.optimism.io"),
rebase: true,
},
common: optimism,
});
// When we send a transaction to the network send it to Tevm too
// We do not mine the transaction as we want it to just be in our mempool
const txHash = await client.sendRawTransaction(tx);
client.waitForTransactionReceipt({ hash: txHash }).then(() => {
// remove the tx from optimistic state after it is included in chain
const mempool = await client.transport.tevm.getTxPool();
await mempool.removeTxByHash(txHash);
});
// continue to query the latest state by default
await client.getBalance({ address, blockTag: "latest" });
// or query optimistic state with 'pending' block tag
await client.getBalance({ address, blockTag: "pending" });Real-World Performance Benefits
const gasEstimate0 = await client.estimateGas({ ... }) // ~200ms as it fetches state (unless you prewarmed the cache)
const gasEstimate0 = await client.estimateGas({ ... }) // ~Instant on future estimations with cache saved
const gasEstimate0 = await client.estimateGas({ ... }) // ~Instant on future estimations with cache savedBecause Tevm plugs directly into wagmi this works via useGasEstimate too.
Enhanced User Experiences
JavaScript-based EVM execution enables new categories of dApp features:
- Maximally hackable โ Complete control including deep internals; supports almost any use case.
- โก Optimistic UI โ Show users the likely outcome of transactions before they're mined.
- ๐ก๏ธ Reliable โ Near 100% test coverage; most reported bugs fixed in under 24 hours.
- ๐งฎ Transaction Simulation โ Preview results of complex interactions before sending.
- ๐ Enhanced Privacy โ Process sensitive data locally without sending it to external services.
Top Tier Devx
Use the tools you already know
Tevm plugs directly into wagmi, viem, and ethers.
Interop with contracts effortlessly
The Tevm Bundler (optional) makes TypeScript aware of how to process and compile Solidity. It's in the same category as Wagmi CLI or Typechain, but more powerful:
- Natspec on hover
- Typesafe contracts
- tRPC-like experience โ red underlines before you save the Solidity file
- No external build tools โ plugs into your existing JS pipeline
- Reads foundry config for remappings and lib
Import Solidity directly
The bundler has a compiler built in โ no precompilation needed:
import { MyContract } from "./MyContract.sol";
console.log(MyContract.abi);You can import from node_modules or foundry projects. Tevm supports remappings, lib, and other advanced options. Unlike Foundry, Tevm supports node_module resolution by default.
Use contracts via address
If your contract is deployed, just reference it by address โ Tevm pulls the ABI at build time (even for unverified contracts):
// create a macro file for your contracts
import { client } from "./clients.js";
export const MyContract = await client.whatsabi(`0x...`);// import your macro using tevm and Tevm will fetch your contracts at buildtime
import {MyContract} from './MyContract.js' as {type: 'tevm'}Low level control of the EVM
Tools like anvil run in a separate process over HTTP. Tevm runs in memory with direct node access โ enabling programmability no other tool offers.
Run callbacks on every EVM step ๐ฌ
Step through EVM execution opcode by opcode, inspect memory and stack, and see exactly what happens in your contracts.
vm.evm.events.on("step", (data, next) => {
console.log(
`${data.pc.toString().padStart(5)}:`,
`${data.opcode.name.padEnd(10)}`,
`gas: ${data.gasLeft.toString().padStart(8)}`,
`stack: ${data.stack.join(", ")}`,
);
next();
});You can even modify EVM execution as it runs.
Mock EVM contracts with JavaScript contracts
Write contracts in JavaScript. Precompiles are like Foundry cheat codes, but instead of a standard library you write arbitrary JS. Works nicely with the Tevm Bundler:
import {
defineCall,
definePrecompile,
createContract,
createMemoryClient,
} from "tevm";
import { readFile } from "fs/promises";
const contract = createContract({
address: `0x${"1234".repeat(10)}`,
humanReadableAbi: ["function readFile(string fileName) returns string"],
});
const { precompile } = definePrecompile({
contract,
call: defineCall(contract.abi, {
readFile: ({ args }) => {
return {
data: await readFile(args.fileName, "utf8"),
gasUsed: 0n,
};
},
}),
});
const memoryClient = createMemoryClient({
precompiles: [precompile()],
});Deterministic Testing ๐งช
Though built for application development, Tevm is great for testing too โ fully reproducible environments with complete control over blockchain state, time, and mining.
Solidity Imports
Tevm Bundler (optional) creates the best devx for Solidity files in TypeScript:
import { MyContract } from "./MyContract.sol";JavaScript Ecosystem Integration
- ๐ค TypeScript โ Type-safe contract interactions with full IntelliSense
- โ๏ธ UI Frameworks โ React, Vue, Svelte and other frontend libraries
- ๐๏ธ Build Tools โ Vite, Webpack, ESBuild and other bundlers
- ๐งช Testing โ Vitest support via Vite
- ๐ Runtimes โ Node.js, browsers, Electron, serverless functions
- ๐ฆ NPM Ecosystem โ Millions of packages in the npm registry
- ๐ Web APIs โ Browser storage, WebSockets, service workers, and more
Ready to Get Started?
Next: Install Tevm ยท Create a Tevm Node ยท Run examples ยท GitHub

