JSON-RPC Support
Tevm Node provides comprehensive JSON-RPC support through an EIP-1193 compatible interface. This allows seamless integration with popular Ethereum libraries and tools.
EIP-1193 Provider
The node can be extended to expose an EIP-1193 compatible request interface:
import { createTevmNode } from 'tevm'
import { requestEip1193 } from 'tevm/decorators'
const node = createTevmNode().extend(requestEip1193())
// Use standard JSON-RPC methods
const blockNum = await node.request({
method: 'eth_blockNumber',
params: [],
})Supported Methods
Core Ethereum Methods
-
Block & Chain
eth_blockNumber- Get current block numbereth_getBlockByHash- Get block by hasheth_getBlockByNumber- Get block by numbereth_chainId- Get current chain ID
-
State & Account
eth_getBalance- Get account balanceeth_getCode- Get contract codeeth_getStorageAt- Get storage valueeth_getTransactionCount- Get account nonce
-
Transaction
eth_call- Execute contract calleth_estimateGas- Estimate gas usageeth_sendTransaction- Send transactioneth_sendRawTransaction- Send signed transactioneth_getTransactionByHash- Get transaction detailseth_getTransactionReceipt- Get transaction receipt
-
Logs & Events
eth_getLogs- Get event logseth_newFilter- Create new filtereth_newBlockFilter- Create block filtereth_getFilterChanges- Get filter updateseth_getFilterLogs- Get all filter logseth_uninstallFilter- Remove filter
Extended Methods
Tevm also supports additional methods commonly found in development environments:
-
Debug Methods
debug_traceTransaction- Trace transaction executiondebug_dumpState- Dump current state
-
Anvil Methods (For Foundry compatibility)
anvil_setCode- Set contract codeanvil_setBalance- Set account balanceanvil_setNonce- Set account nonceanvil_setStorageAt- Set storage valueanvil_deal- Add native ETH or ERC20 tokens to an accountanvil_impersonateAccount- Impersonate accountanvil_stopImpersonatingAccount- Stop impersonating
Client Integration
Using with Viem
For more information, see the Viem Documentation.
import { createTevmTransport } from 'tevm/memory-client'
import { createPublicClient, custom } from 'viem'
import { requestEip1193 } from 'tevm/decorators'
const tevmTransport = createTevmTransport()
const client = createPublicClient({
chain: mainnet,
transport: tevmTransport,
})Using with Ethers
For more information, see the Ethers Documentation.
import { createTevmNode } from 'tevm'
import { BrowserProvider } from 'ethers'
import { requestEip1193 } from 'tevm/decorators'
const node = createTevmNode().extend(requestEip1193())
const provider = new BrowserProvider(node)Error Handling
JSON-RPC errors follow the standard format and are fully typed. See the error types documentation for more details:
interface JsonRpcError {
code: number
message: string
data?: unknown
}Common error codes (see Error Types):
-32700: Parse error (ParseError)-32600: Invalid request (InvalidRequest)-32601: Method not found (MethodNotFound)-32602: Invalid params (InvalidParams)-32603: Internal error (InternalError)-32000to-32099: Server error (ServerError)
For detailed error handling examples and best practices, see the Error Handling Guide.
Best Practices
-
Error Handling: Always wrap RPC calls in try-catch blocks to handle potential errors gracefully. See Error Types for all possible errors.
-
Gas Estimation: For transactions, use
eth_estimateGasbefore sending to ensure sufficient gas:
const gasEstimate = await node.request({
method: 'eth_estimateGas',
params: [tx],
})- Receipt Confirmation: Wait for transaction receipts to confirm state changes using
eth_getTransactionReceipt:
const txHash = await node.request({
method: 'eth_sendTransaction',
params: [tx],
})
const receipt = await node.request({
method: 'eth_getTransactionReceipt',
params: [txHash],
})- Event Filtering: Use filters efficiently by:
- Setting appropriate block ranges
- Using specific topics
- Cleaning up unused filters with
eth_uninstallFilter
For more examples and detailed API documentation, see:
Related Topics
- Using with Viem
- Using with Ethers
- Managing State
- Receipts & Logs
- Ethereum JSON-RPC Specification
- EIP-1193: Ethereum Provider JavaScript API
- Tevm API Documentation
Using Tevm Actions
Tevm provides a set of high-level actions that can be imported from tevm/actions. See the complete actions documentation for all available actions.
import {
tevmCall, // See: https://github.com/evmts/tevm-monorepo/blob/main/packages/actions/docs/functions/callHandler.md
tevmMine, // See: https://github.com/evmts/tevm-monorepo/blob/main/packages/actions/docs/functions/mineHandler.md
tevmGetAccount, // See: https://github.com/evmts/tevm-monorepo/blob/main/packages/actions/docs/functions/getAccountHandler.md
tevmSetAccount, // See: https://github.com/evmts/tevm-monorepo/blob/main/packages/actions/docs/functions/setAccountHandler.md
tevmDeal // See: https://github.com/evmts/tevm-monorepo/blob/main/packages/actions/docs/functions/anvilDealHandler.md
} from 'tevm/actions'
import { createTevmNode } from 'tevm'
const node = createTevmNode()
// Call a contract
const result = await tevmCall(node, {
to: '0x...',
data: '0x...',
value: 0n,
createTransaction: true
})
// Mine pending transactions
await tevmMine(node)
// Get account state
const account = await tevmGetAccount(node, {
address: '0x...',
blockTag: 'latest'
})
// Set account state
await tevmSetAccount(node, {
address: '0x...',
balance: 100n,
nonce: 0n,
deployedBytecode: '0x...'
})
// Deal tokens to an account
// For native ETH:
await tevmDeal(node, {
account: '0x...',
amount: 1000000000000000000n // 1 ETH
})
// For ERC20 tokens:
await tevmDeal(node, {
erc20: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC on mainnet
account: '0x...',
amount: 1000000n // 1 USDC (6 decimals)
})For detailed type information, see:
Note: By default, tevm actions require manual mining via tevmMine(). If you want transactions to be automatically applied, you can either:
- Use the lower level API
vm.runCall - Configure the client with
miningConfig: { type: 'auto' }
Optimistic Updates with Receipt Manager
For more information on transaction receipts and logs, see the Ethereum Receipts Documentation.
import { createTevmNode } from 'tevm'
import { tevmCall, tevmMine } from 'tevm/actions'
const node = createTevmNode()
const receiptsManager = await node.getReceiptsManager()
// Submit transaction
const { txHash } = await tevmCall(node, {
method: 'eth_sendTransaction',
params: [tx],
createTransaction: true
})
// Get optimistic receipt
const pendingReceipt = await receiptsManager.getReceiptByTxHash(txHash)
// Update UI optimistically
updateUI(pendingReceipt)
// Wait for real receipt
const realReceipt = await node.request({
method: 'eth_getTransactionReceipt',
params: [txHash]
})
// Eject optimistic tx if real receipt differs
if (receiptsAreDifferent(pendingReceipt, realReceipt)) {
await receiptsManager.removeReceipt(txHash)
updateUI(realReceipt)
}
// Advanced: Rebase on new blocks
node.on('block', async (blockNumber) => {
// Get new block
const block = await node.request({
method: 'eth_getBlockByNumber',
params: [blockNumber, true]
})
// Get our pending transactions
const pendingTxs = await receiptsManager.getPendingTransactions()
// Rebase our transactions on top of new block
for (const tx of pendingTxs) {
const result = await tevmCall(node, {
...tx,
blockTag: 'pending'
})
// Update receipt
await receiptsManager.putReceipt(tx.hash, result)
}
// Mine rebased transactions
await tevmMine(node)
})
