Using TevmProvider
TevmProvider extends the ethers JsonRpcApiProvider.
Everything you know about ethers providers applies; the only difference is that the JSON-RPC
requests are answered by an EVM running in the same process.
Creating a provider
import { } from '@tevm/ethers'
const = await .createMemoryProvider({
: { : 'auto' },
})
.(await .getBlockNumber()) // 0createMemoryProvider accepts the full TevmNodeOptions object:
| Option | Purpose |
|---|---|
fork | { transport, blockTag } โ fork state lazily from another chain. |
miningConfig | { type: 'auto' } mines a block per transaction; { type: 'manual' } is the default. |
common | The chain definition (defaults to tevmDefault, chain id 900). |
loggingLevel | `'trace' |
Mining
By default Tevm mines manually: a transaction sits in the mempool until you mine. tx.wait() will
hang forever if you forget.
import { } from '@tevm/ethers'
import { } from '@tevm/utils'
import { , } from 'ethers'
const = await .createMemoryProvider({})
const = new ([0], )
const = await .({
: `0x${'42'.(20)}`,
: ('1'),
})
// Nothing is mined yet โ mine explicitly, then await the receipt.
await .tevm.mine({ : 1 })
const = await .()
.(?.) // 1
.(await .getBlockNumber()) // 1Pass miningConfig: { type: 'auto' } if you would rather have a block per transaction, which is the
closest analogue to anvil in automine mode.
Signers and wallets
Tevm prefunds a set of well-known accounts with 1000 ETH each. Use them with an ordinary
ethers.Wallet:
import { } from '@tevm/ethers'
import { , } from '@tevm/utils'
import { , } from 'ethers'
const = await .createMemoryProvider({ : { : 'auto' } })
const = new ([0], )
.(. === [0].) // true
.((await .getBalance(.))) // '1000.0'If you want an arbitrary address to be funded, give it a balance directly instead of transferring:
import { } from '@tevm/ethers'
import { , } from 'ethers'
const = await .createMemoryProvider({ : { : 'auto' } })
const = `0x${'42'.(20)}`
await .tevm.setAccount({ , : ('100') })
.((await .getBalance())) // '100.0'Raw JSON-RPC
provider.send accepts the standard eth_* methods and the Tevm tevm_* methods:
import { } from '@tevm/ethers'
import { } from '@tevm/utils'
const = await .createMemoryProvider({})
.(await .send('eth_chainId', [])) // '0x384'
await .send('tevm_setAccount', [
{ : `0x${'69'.(20)}`, : (1n), : (420n) },
])
const = await .send('tevm_getAccount', [{ : `0x${'69'.(20)}` }])
.(.balance) // '0x1a4'Sharing one EVM
Batching and response caching are disabled on TevmProvider (batchMaxCount: 1,
cacheTimeout: -1) precisely because the node is in-process: requests are cheap, and caching would
hide state you mutate through provider.tevm. That also makes it safe to point several providers at
the same node.
import { } from '@tevm/ethers'
import { , } from '@tevm/decorators'
import { } from '@tevm/node'
import { } from 'ethers'
const = ({ : { : 'auto' } })
.(())
.(())
const = new ()
const = new ()
await .tevm.setAccount({ : `0x${'42'.(20)}`, : ('1') })
// Both providers see the same state.
.(await .getBalance(`0x${'42'.(20)}`)) // 1000000000000000000n
