Creating a Tevm Node
createTevmNode
is the main entry point for spinning up a local Tevm Node instance. With a flexible configuration API, you can customize your node's behavior to fit various development, testing, and production scenarios.
Install Dependencies
First, install the required packages:
npm install tevm
Using Yarn or pnpm?
# Yarn
yarn add tevm
# pnpm
pnpm add tevm
Create a Basic Node
Instantiate a node with default configuration:
import { createTevmNode } from 'tevm'
// Create the node instance
const node = createTevmNode()
// Always wait for the node to be ready before using it
await node.ready()
// Your node is now ready to use!
Configure to Your Needs
Tailor the node with powerful configuration options:
import { createTevmNode, http } from 'tevm'
const node = createTevmNode({
// Fork from a live network
fork: {
transport: http('https://mainnet.infura.io/v3/YOUR-KEY'),
},
// Configure automatic mining
miningConfig: { type: 'auto' },
// Set logging verbosity
loggingLevel: 'debug'
})
await node.ready()
Configuration Options
Tevm Node offers extensive configuration options to adapt to different use cases. Here's a complete breakdown:
Fork Configuration
The fork
option creates a node that connects to an existing network:
import { createTevmNode, http } from 'tevm'
const node = createTevmNode({
fork: {
// Use any EIP-1193 compatible provider
transport: http('https://mainnet.infura.io/v3/YOUR-KEY'),
// Optional: Fork from a specific block
blockTag: 17_000_000n,
},
})
await node.ready()
Mining Configuration
Control how and when blocks are produced with various mining modes:
// Auto-mining: Mine a block for every transaction
const node = createTevmNode({
miningConfig: {
type: 'auto',
},
})
// Interval-based mining: Mine at regular intervals
const intervalNode = createTevmNode({
miningConfig: {
type: 'interval',
interval: 12_000, // Mine every 12 seconds
},
})
await node.ready()
await intervalNode.ready()
Chain Configuration
Customize the chain parameters or use pre-configured chains:
import { createTevmNode } from 'tevm'
import { Common } from 'tevm/common'
// Custom chain configuration
const customNode = createTevmNode({
common: Common.custom({
chainId: 1337,
networkId: 1337,
// Other chain parameters
}),
})
await customNode.ready()
Or use one of the pre-configured chains:
import { createTevmNode } from 'tevm'
import { mainnet, optimism, arbitrum, base } from 'tevm/common'
// Create a node with Optimism chain configuration
const optimismNode = createTevmNode({
common: optimism,
})
await optimismNode.ready()
Want to add your own network?
If you need support for a network not included in Tevm, first add it to viem/chains
and then open an issue on the Tevm repository to request the network to be added.
Logging Configuration
Configure the internal logger to match your needs:
const node = createTevmNode({
loggingLevel: 'debug', // 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace'
})
// Later use the logger directly
node.logger.debug('Detailed debugging information')
node.logger.info('Informational message')
node.logger.warn('Warning!')
node.logger.error('Error encountered', { details: 'Something went wrong' })
await node.ready()
Custom Precompiles
Add your own precompiled contracts to unlock powerful capabilities:
import { definePrecompile, createContract, parseAbi } from 'tevm'
const calculatorPrecompile = definePrecompile({
// Define contract interface
contract: createContract({
abi: parseAbi([
'function add(uint256 a, uint256 b) returns (uint256)',
'function subtract(uint256 a, uint256 b) returns (uint256)'
]),
address: '0xf2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2'
}),
// Implement the precompile logic
call: async ({ data, gasLimit }) => {
// Precompile implementation goes here
console.log('Precompile called with data:', data, 'gas limit:', gasLimit)
return {
returnValue: new Uint8Array([0x01]), // Example return value
executionGasUsed: 200n,
}
},
})
// Register the precompile with the node
const node = createTevmNode({
customPrecompiles: [calculatorPrecompile.precompile()],
})
await node.ready()
Performance Profiling
Enable the built-in profiler for detailed execution metrics:
const node = createTevmNode({
profiler: true,
})
await node.ready()
// Run a transaction or call
// ...
// Access profiling data
const vm = await node.getVm()
const performanceLogs = vm.evm.getPerformanceLogs()
console.log('Performance data:', performanceLogs)
Complete Configuration Reference
Property | Type | Default | Description |
---|---|---|---|
fork | { transport: EIP1193RequestFn; blockTag?: BlockTag; } | - | Enables forking from a live network or another Tevm instance |
common | Common | tevmDevnet | Chain configuration object |
loggingLevel | "fatal" | "error" | "warn" | "info" | "debug" | "trace" | "info" | Logging verbosity level |
miningConfig | { type: 'auto' } | { type: 'interval', interval: number } | { type: 'auto' } | Block mining behavior |
profiler | boolean | false | Enables performance logging |
customPrecompiles | Precompile[] | [] | Additional precompiled contracts |
allowUnlimitedContractSize | boolean | false | Disables EIP-170 contract size checks |
Best Practices
Always await node.ready()
const node = createTevmNode()
await node.ready() // Essential: Ensures node is fully initialized
// Now safe to use the node
Choose the Right Mining Configuration
// For testing: Mine after each transaction
const testNode = createTevmNode({
miningConfig: { type: 'auto' }
})
// For simulation: Mine at intervals to mimic real networks
const simulationNode = createTevmNode({
miningConfig: { type: 'interval', interval: 12_000 } // 12 seconds like Ethereum
})
await testNode.ready()
await simulationNode.ready()
Handle Initialization Errors
try {
const node = createTevmNode()
await node.ready()
console.log('Node successfully initialized')
} catch (error) {
console.error('Node initialization failed:', error)
// Implement proper error handling
}
Usage Scenarios
- Fresh Node: Fast, auto-mining configuration with unlimited contract sizes for rapid local development
- Forked Node: Realistic forked environment with precise error handling for production simulation
- Testing Environment: Performance-focused configuration for CI/CD and test automation
Fresh Node
import { createTevmNode } from 'tevm'
const freshNode = createTevmNode({
miningConfig: { type: 'auto' },
loggingLevel: 'debug', // See detailed logs during development
allowUnlimitedContractSize: true, // No contract size limits during development
})
await freshNode.ready()
// Node is ready for local development
console.log('Fresh node ready!')
Forked Node
import { createTevmNode, http } from 'tevm'
const forkedNode = createTevmNode({
fork: {
transport: http('https://mainnet.infura.io/v3/YOUR-KEY'),
blockTag: 'latest', // Always use the latest block
},
miningConfig: {
type: 'interval',
interval: 12000 // Mine every 12 seconds like Ethereum mainnet
},
loggingLevel: 'error', // Only show errors
})
await forkedNode.ready()
console.log('Forked node ready!')
Testing Node
import { createTevmNode } from 'tevm'
const testNode = createTevmNode({
miningConfig: { type: 'auto' }, // Immediate mining for faster tests
profiler: true, // Enable profiling for performance testing
})
await testNode.ready()
// Run your tests with profiling enabled
console.log('Testing node with profiling ready!')
Next Steps
- Node Interface - Explore the complete TevmNode interface and its capabilities
- Forking & Reforking - Learn how to fork from live networks and efficiently manage forks
- State Management - Understand how to manipulate blockchain state
- Custom Precompiles - Create your own precompiled contracts to extend EVM functionality