Skip to content

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

This is what Fucory thought the day he started building Tevm. Fucory created Tevm to solve all UX and Devx issues blocking the delivery of great blockchain apps. The original idea was to put the foundry API in the browser and the library evolved from there. Because of Tevm's wide ambitious scope Tevm's use case is simply TypeScript+EVM. If you are building on the EVM and you are using TypeScript Tevm will help you. And here is why.

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, transaction simulation, and debugging.

๐Ÿ’ป Browser Compatibility

Enable sophisticated dApp features like offline capabilities, optimistic UI updates, and real-time simulations.

๐Ÿ” Debug Superpowers

Step through EVM execution opcode by opcode to understand exactly what's happening in your smart contracts.

๐Ÿ› ๏ธ Familiar Developer Experience

Works seamlessly with the libraries you already know - viem, ethers, or any EIP-1193 compatible tool.

Performance & Efficiency

โšก An optimized fork mode

Tevm is benchmarked to perform better than even Anvil at executing calls in forked mode. This is possible via more efficient storage slot retrieval.

โšก Zero Network Latency

Running the EVM locally eliminates round-trip delays to remote nodes, enabling near-instantaneous transaction simulations and gas estimations.

Local-first gas estimation

Imagine not having to show a user a loading spinner when estimating gas while saving on RPC credits.

๐Ÿ”„ Powerful JS interop

Simulate multiple transactions plugging directly into the evm with JS or even writing custom contracts in JS.

Optimistic updates

Oftentimes you want to show the user what the state of their account is expected to be. Possibly we want to show them the expected state changes from their transaction or series of transactions before they submit. Or maybe we are trying to build snappy UI so we want to show them the updated state right away with a pending icon. Tevm makes implementing 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

The estimate_gas example is the easiest example to illustrate this.

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 saved

Note: because Tevm can plug directly into wagmi this works as well via useGasEstimate

Enhanced User Experiences

JavaScript-based EVM execution enables entirely new categories of dApp features:

Maximally hackable

Tevm gives you complete control including it's deep internals in a way no other node does. Almost all use cases can be supported.

โšก Optimistic UI

Show users the likely outcome of transactions before they're mined on-chain.

๐Ÿ›ก๏ธ Reliable

Tevm has near 100% test coverage and a history of fixing most reported bugs in under 24 hours.

๐Ÿงฎ Transaction Simulation

Simulate complex interactions and preview results before sending transactions.

๐Ÿ” Enhanced Privacy

Process sensitive data locally without sending it to external services.

Top Tier Devx

Use the tools you already know

Tevm users report the library having great devx. A lot of this is owed to it's abilility to plug directly into the tools you are already using like wagmi, viem, and ethers.

Interop with contracts effortlessly

We cannot talk about developer experience in Tevm without bringing up the Tevm Bundler.

The Tevm Bundler is an optional addon to Tevm that makes TypeScript aware of how to process and compile Solidity. It is a tool in the same category as the Wagmi CLI or Typechain but even more powerful and ergonomic.

The devx using the bundler is optimized in following ways:

  • Natspec on hover
  • Typesafe contract
  • TRPC like experience. You will see red underlines before you even save a solidity file
  • No need to set up external build tools. Plugs directly into your existing js pipeline
  • Supports reading foundry config for remappings and lib

Import solidity directly

The Tevm Bundler doesn't require compiling your contracts as it has a compiler built in. You can import solidity directly.

import { MyContract } from "./MyContract.sol";
 
console.log(MyContract.abi);

You can also 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 you know your contract address and it's already deployed you don't need to manually specify anything. You can simply reference it by address and Tevm will pull the ABI at build time. This even works 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

Most tools like anvil run in a seperate process and you communicate over HTTP. Tevm runs in memory and gives you access directly to the node. This allows for powerful programmability not possible with any other tool.

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.

// Listen to every EVM instruction
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 what the EVM is doing as it executes if you choose to.

Mock EVM contracts with JavaScript contracts

Tevm offers the advanced ability to write a contract in JavaScript which can be powerful in advanced use cases.

Precompiles are similar to foundry cheat codes but rather than a standard library of cheat codes Tevm lets you write arbitrary JavaScript to do whatever you need to do.

It works very 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,
      };
    },
  }),
});
 
// then add your precompile to the evm
const memoryClient = createMemoryClient({
  precompiles: [precompile()],
});

Deterministic Testing ๐Ÿงช

While tevm is primarily built for applicaiton development it just so happens to be great at testing too. Create fully reproducible environments for testing with complete control over blockchain state, time, and mining.

Solidity Imports

Tevm Bundler (optional feature) creates the best devx for working with solidity files in TypeScript

// Import solidity files directly into TS files
import { MyContract } from "./MyContract.sol";

JavaScript Ecosystem Integration

๐Ÿ”ค TypeScript

Type-safe contract interactions with full IntelliSense support

โš›๏ธ 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

Access to millions of packages and libraries in the npm registry

๐ŸŒ Web APIs

Integration with browser storage, WebSockets, service workers, and more

Ready to Get Started?

๐Ÿ“ Getting Started Guide
๐Ÿ“„ Install Tevm
๐Ÿ“„ Configure Your Environment
๐Ÿ“„ Run Your First Code