/tevm-monorepo

An ecosystem of ethereum tools to build robust TypeScript applications

Primary LanguageTypeScriptMIT LicenseMIT

An ecosystem of tools to build robust Ethereum applications in TypeScript for Viem

CI NPM Version Tevm Downloads Tevm Bundler Downloads Minzipped Size

tevm-monorepo

Tevm tools include an Ethereum devnet that can run in the Browser and Node.js along with a solidity bundler that allows you to import solidity directly into TypeScript files. All built on top of the viem API.

// import solidity directly into typescript
import { ERC20 } from '@openzeppelin/contracts/token/ERC20/ERC20.sol'
import { createMemoryClient, http } from 'tevm'
import { optimism } from 'tevm/common'

// create a anvil-like devnet directly in TypeScript
const client = createMemoryClient({
  common: optimism,
  fork: {transport: http('https://mainnet.optimism.io')()}
})

// execute the EVM locally in the browser, node.js, deno and Bun
const balance = await client.readContract(
  ERC20
    .withAddress('0x4200000000000000000000000000000000000042')
    .read
    .balanceOf('0xd8da6bf26964af9d7eed9e03e53415d37aa96045')
)

Table of Contents

Overview

Tevm is modular, easy to pick up, and built on top of viem.

Tevm consists of the following modular tools:

  • MemoryClient: An anvil-like client built on top of viem and specially crafted for TypeScript applications and tests.
  • TevmBundler: A JavaScript bundler that allows you to build your contracts using Webpack, Vite, ESBuild, Bun, and other major bundlers.
  • TevmLSP: Brings Solidity awareness to all major editors for full end-to-end contract-to-TypeScript type safety.
  • Contracts: A lightweight interface for interacting with contracts using Tevm, Viem, and Wagmi.
  • Scripting: Similar to Foundry scripting, allowing you to execute arbitrary Solidity and JavaScript in an easy and type-safe manner.

These tools are modular and can be used by themselves but they also compose very well together with each other and with viem/wagmi.

Examples

  • For a tutorial of all of Tevm's major features, check out the getting started guide.
  • For a minimal live example you can edit in the browser, check out the live StackBlitz.
  • Try out svvy.sh by 0xpolarzero for an example of using Tevm and whatsabi to build a network forking and transaction simulating tool. Forked code from it is kept up to date with the latest release here.

ethereum simulator preview

MemoryClient

MemoryClient is an anvil-like Ethereum devnet specially crafted for TypeScript applications and tests.

✅  Built on top of viem and supports all Viem APIs
✅  Runs in the browser, Node.js, and Bun
✅  Supports forking akin to anvil --fork-url
✅  Can generate EVM traces and access lists
✅  HTTP handlers for running as a server in tests or backends
✅  Full support for the Ethereum JSON-RPC API and anvil_ API

With MemoryClient, you can easily solve a lot of previously tough-to-solve problems:

  • Executing contract logic locally
  • Simulating the result of one or more transactions
  • Submitting impersonated transactions before estimating gas for a future transaction. E.g., mock approving a token before estimating the cost of transferring it.
  • Executing view methods that you wrote yourself and don't exist on the contract
  • Running the EVM in the browser without the need for a backend RPC
  • And more

MemoryClient Example

import { createMemoryClient, http } from 'tevm'
import { optimism } from 'tevm/common'

// To start the MemoryClient, simply call `createMemoryClient`
const client = createMemoryClient({
  // MemoryClient supports anvil-like forking
  fork: { transport: http('https://mainnet.optimism.io') },
  common: optimism,
})

// MemoryClient supports the entire viem API
const blockNumber = await client.getBlockNumber()

// MemoryClient can arbitrarily modify accounts
client.tevmSetAccount({
  address: `0x${'69'.repeat(20)}`,
  nonce: 9,
  balance: 420n,
  deployedBytecode: '0x...',
  // ...
})

const { data, errors, events, executionGasUsed, logs } = client.tevmContract({
  createTransaction: true,
  // MemoryClient can impersonate any account
  from: `0x${'69'.repeat(20)}`,
  abi: [...],
  functionName: 'transferFrom',
  args: [...],
})

const { blockHash } = await client.tevmMine()

Tevm Bundler + LSP

Tevm Bundler

The Tevm Bundler is the next-generation build-time tool version of tools like Typechain. The Tevm Bundler removes the need to copy-paste ABIs or set up complicated build pipelines. With the Bundler, you can directly import Solidity contracts into your TypeScript files. This brings a TRPC-like experience to Contract-TypeScript code.

Tevm also supports code-generation of TypeScript from Solidity contracts, similar to TypeChain.

The Tevm Bundler builds Contracts and Scripts that modularly work with Viem, Wagmi, and Tevm.

// Import Solidity directly into TypeScript. The Tevm Bundler will compile the contracts to TevmContracts and TevmScripts
import { ERC20 } from '@openzeppelin/contracts/token/ERC20/ERC20.sol'

console.log(ERC20.abi)
console.log(ERC20.humanReadableAbi)

// Use the contracts with Wagmi, Viem, or Tevm. In this example, Wagmi
const { data } = useReadContract(
  ERC20.read.balanceOf(`0x${'01'.repeat(20)}`)
)

image image image

Tevm LSP

The Tevm LSP is a ts-plugin that allows your code editor to pick up types from your Solidity imports if using the Tevm Bundler.

  • Enables end-to-end type safety with Solidity and TypeScript
  • Shows contract NatSpec on hover in your TypeScript files
  • Go-to-definition takes you directly to the contract definition

image

Tevm Contracts

Tevm contracts are an extremely lightweight modular abstraction for interacting with viem, wagmi, and tevm. They are created automatically if using the Tevm Bundler via importing Solidity but can also be created manually.

They can also be used with ethers to create type-safe contracts.

import { createContract } from 'tevm/contract'

const script = createContract({
  name: 'MyScript',
  humanReadableAbi: ['function exampleRead() returns (uint256)', ...],
  bytecode: '0x123...',
  deployedBytecode: '0x123...',
  address: '0x123...'
})

// Use with Wagmi
useReadContract(script.read.exampleRead())

// Use with Viem/Tevm
client.readContract(script.read.exampleRead())

// Even use with ethers to create a type-safe contract
import { Contract } from '@tevm/ethers'
const contract = new Contract(script.address, script.abi, provider)
// This will be type-safe
const res = await contract.read()

Tevm Scripting

Tevm scripting allows arbitrary Solidity execution similar to Forge scripts. Instead of cheat codes, Tevm allows you to very easily bring your own cheat codes via executing arbitrary JavaScript. See the Tevm scripting guide for information on how to build scripts.

Because Tevm also allows scripts to execute arbitrary JavaScript, scripts can be extremely powerful. For example, one could build a library for writing servers in Solidity.

Visit Docs (under construction) for docs, guides, API, and more! 📄

Contributing 💻

Contributions are encouraged, but please open an issue before making any major changes to ensure your changes will be accepted.

See CONTRIBUTING.md for contributing information.

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 and are all in the @tevm/state, @tevm/blockchain, and other packages that wrap ethereumjs libraries.