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_impersonateAccount
- Impersonate accountanvil_stopImpersonatingAccount
- Stop impersonating
Client Integration
Using with Viem
For more information, see the Viem Documentation.
import { createTevmNode } from 'tevm'
import { createPublicClient, custom } from 'viem'
import { requestEip1193 } from 'tevm/decorators'
const node = createTevmNode().extend(requestEip1193())
const client = createPublicClient({
chain: mainnet,
transport: custom(node.request),
})
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
)-32000
to-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_estimateGas
before 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
} 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...'
})
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)
})