esbuild
npm install --save-dev @tevm/esbuild-plugin @tevm/ts-plugin esbuild
npm install @tevm/contractConfiguration
build.ts
import { esbuildPluginTevm } from '@tevm/esbuild-plugin'
import { build } from 'esbuild'
await build({
entryPoints: ['src/index.ts'],
outdir: 'dist',
bundle: true,
format: 'esm',
platform: 'node',
plugins: [esbuildPluginTevm({ solc: '0.8.30' })],
})esbuildPluginTevm accepts one optional option, solc. Everything else comes
from tevm.config.json.
Complete example
src/contracts/Vault.s.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Vault {
mapping(address => uint256) public deposits;
function deposit() public payable {
deposits[msg.sender] += msg.value;
}
function withdraw(uint256 amount) public {
require(deposits[msg.sender] >= amount, "insufficient");
deposits[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
}
}src/index.ts
import { createMemoryClient } from 'tevm'
import { Vault } from './contracts/Vault.s.sol'
const depositor = '0x1234567890123456789012345678901234567890' as const
const client = createMemoryClient()
await client.setBalance({ address: depositor, value: 10_000_000_000_000_000_000n })
const deployed = await client.deployContract(Vault)
await client.mine({ blocks: 1 })
await client.writeContract({
...deployed.write.deposit(),
account: depositor,
value: 1_000_000_000_000_000_000n,
})
await client.mine({ blocks: 1 })
console.log(await client.readContract(deployed.read.deposits(depositor)))
// 1000000000000000000nRun it:
node build.ts && node dist/index.jsNotes
- esbuild has no watch-dependency API comparable to Rollup's, so incremental
rebuilds rely on the
.tevmcache rather than on a file-watch graph. A changed Solidity file changes the compile fingerprint, so the next build recompiles it. - esbuild does not type-check.
.solimports are typed for your editor and fortsc --noEmitby@tevm/ts-plugin; runtscseparately in CI. - The plugin only claims a
.solfile when no sidecar module (.sol.ts,.sol.js,.sol.d.ts, …) exists next to it.

