Skip to content

evmts/tevm-monorepo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Tevm Logo

A JavaScript-native Ethereum Virtual Machine

CI NPM Version Tevm Downloads Tevm Bundler Downloads Minzipped Size

Tevm Node

Tevm is a complete Ethereum execution environment implemented entirely in JavaScript that runs across any JS environment, including browsers, Node.js, Deno, and Bun. It provides the full functionality of an Ethereum node without requiring any blockchain client installation or native dependencies.

Conceptually, it works similarly to Anvil and Hardhat, but with more powerful TypeScript-native interoperability and cross-platform compatibility.

✨ Key Features

  • JavaScript-Native EVM - Run an Ethereum environment anywhere JavaScript runs
  • Cross-Platform Compatibility - The same code works in browsers, Node.js, Deno, and Bun
  • Zero Native Dependencies - Pure JavaScript implementation with no compilation required
  • Network Forking - Create local sandboxes of any EVM-compatible chain
  • Fine-grained EVM Control - Access execution at any level of detail, from transactions to opcodes
  • Direct Solidity Imports - Import .sol files directly into TypeScript with the bundler
  • Type-safe Interactions - Full TypeScript support throughout the entire API surface

πŸš€ Getting Started

# Install Tevm in your project
npm install tevm viem@latest

Create your first Tevm client:

// In-memory client (fastest, fully isolated)
import { createMemoryClient } from "tevm";
const client = createMemoryClient();

// OR: Fork client (use existing chain state)
import { createMemoryClient, http } from "tevm";
import { mainnet } from "tevm/chains";
const forkClient = createMemoryClient({
  fork: {
    transport: http("https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY"),
    common: mainnet,
  },
});

πŸ“‹ Complete Example

import { createMemoryClient, http, PREFUNDED_ACCOUNTS } from "tevm";
import { optimism } from "tevm/common";
import { parseAbi } from "viem";

// Create a client as a fork of Optimism mainnet
const client = createMemoryClient({
  common: optimism,
  fork: {
    transport: http("https://mainnet.optimism.io")
  },
});

// Wait for the fork to be ready
await client.tevmReady();

// Setup a test account with funds
const account = "0x" + "baD60A7".padStart(40, "0");
await client.setBalance({
  address: account,
  value: 10000000000000000000n // 10 ETH
});

// Define contract interface
const greeterAbi = parseAbi([
  'function greet() view returns (string)',
  'function setGreeting(string memory _greeting) public'
]);
const greeterAddress = "0x10ed0b176048c34d69ffc0712de06CbE95730748";

// Read from contract
const greeting = await client.readContract({
  address: greeterAddress,
  abi: greeterAbi,
  functionName: 'greet',
});
console.log(`Current greeting: ${greeting}`);

// Write to contract
const txHash = await client.writeContract({
  account,
  address: greeterAddress,
  abi: greeterAbi,
  functionName: 'setGreeting',
  args: ["Hello from Tevm!"],
});

// Mine a block to include our transaction
await client.mine({ blocks: 1 });

// Verify the updated greeting
const newGreeting = await client.readContract({
  address: greeterAddress,
  abi: greeterAbi,
  functionName: 'greet',
});
console.log(`Updated greeting: ${newGreeting}`);

πŸ”„ Import Solidity Contracts Directly

One of Tevm's most powerful features is the ability to import Solidity files directly into your TypeScript code using the Tevm Bundler:

// Import a .sol file directly 
import { ERC20 } from '@openzeppelin/contracts/token/ERC20/ERC20.sol';
import { createMemoryClient } from 'tevm';

const client = createMemoryClient();

// With full TypeScript support
const tokenContract = ERC20.withAddress('0x123...');

// Type-safe contract methods
const balance = await client.readContract(
  tokenContract.read.balanceOf('0x456...')
);

See the Bundler Quickstart guide for setup instructions.

πŸ§ͺ Why Run Ethereum in JavaScript?

  • Performance: Eliminate network latency with local execution
  • Enhanced UX: Enable offline capabilities, optimistic UI updates, and sophisticated simulations
  • Developer Experience: Advanced debugging, deterministic testing, and portable environments
  • Ecosystem Integration: Leverage the entire JavaScript ecosystem and tooling

πŸ”§ Advanced Features

EVM Execution Hooks

await client.tevmContract({
  address: contractAddress,
  abi: contractAbi,
  functionName: 'transfer',
  args: ['0x...', 100n],
  // Step through execution
  onStep: (data, next) => {
    console.log(`Opcode: ${data.opcode.name}`);
    console.log(`Stack: ${data.stack.join(', ')}`);
    next();
  }
});

Chain Forking

import { createMemoryClient, http } from 'tevm';
import { optimism } from 'tevm/chains';

// Fork from Optimism mainnet
const client = createMemoryClient({
  fork: {
    transport: http('https://mainnet.optimism.io'),
    common: optimism
  }
});

// Access any contract or account state from the forked network
const balance = await client.getBalance({ 
  address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' // vitalik.eth
});

Flexible Mining Control

// Manual mining (default)
await client.sendTransaction({ /* ... */ });
await client.mine({ blocks: 1 }); // Explicitly mine when ready

// Auto-mining
client.setMining({ mode: 'auto' }); // Mine on each transaction

// Interval mining
client.setMining({ 
  mode: 'interval',
  interval: 5000 // Mine every 5 seconds
});

πŸ“š Documentation

For comprehensive documentation, visit node.tevm.sh for:

πŸ‘₯ Community

🀝 Contributing

Contributions are welcome! Please see CONTRIBUTING.md for details on how to contribute.

πŸ“„ License

Most files are licensed under the MIT license. Some files copied from ethereumjs inherit the MPL-2.0 license. These files are individually marked at the top.