Skip to content

Commit

Permalink
📝 Docs: Update memoryClient jsdoc
Browse files Browse the repository at this point in the history
  • Loading branch information
William Cory authored and William Cory committed Jun 21, 2024
1 parent a170f0f commit af2d591
Show file tree
Hide file tree
Showing 4 changed files with 296 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/large-zoos-knock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tevm/memory-client": patch
---

Add more jsdoc to MemoryClient docs
15 changes: 14 additions & 1 deletion packages/memory-client/src/MemoryClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { TevmActions } from './TevmActions.js'

/**
* A local EVM instance running in JavaScript. Similar to Anvil in your browser/node/bun environments
* It wraps the viem [public client](https://viem.sh/docs/clients/public#public-client) and [test client](https://viem.sh/docs/clients/test)
* It wraps the viem [public client](https://viem.sh/docs/clients/public#public-client)
*
* @see {@link TevmClient}
* @see {@link https://todo.todo WrappedEvm} for an remote client
Expand Down Expand Up @@ -36,6 +36,19 @@ import type { TevmActions } from './TevmActions.js'
* )
* console.log(balance) // 1n
* ```
*
* Test actions can be added with `client.extend`
*
* ```ts
* import {testActions} from 'viem'
*
* const tevm = createMemoryClient().extend(testActions({mode: 'anvil'}))
*
* tevm.setBytecode({
* address: `0x${'0'.repeat(40)}`,
* bytecode: '0x608060405234801561001057600080fd5b5060405',
* })
* ```
*/
export type MemoryClient = Prettify<
Client<
Expand Down
223 changes: 221 additions & 2 deletions packages/memory-client/src/TevmActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,245 @@ import type { BaseClient } from '@tevm/base-client'
import { type EIP1193RequestFn, type Eip1193RequestProvider, type TevmActionsApi } from '@tevm/decorators'
import type { TevmJsonRpcBulkRequestHandler, TevmJsonRpcRequestHandler } from '@tevm/procedures'

/**
* Powerful actions for interacting with the EVM
*/
export type TevmActions = {
/**
* Low level access to tevm can be accessed via `tevm_tevm`. These apis are not guaranteed to be stable
* @see {@link BaseClient}
* @example
* ```typescript
* import { createMemoryClient } from 'tevm'
*
* const memoryClient = createMemoryClient()
*
* // low level access to the tevm vm, blockchain, evm, stateManager, mempool, receiptsManager and more are available
* const vm = await memoryClient._tevm.getVm()
* vm.runBlocl(...)
* const {blockchain, evm, stateManager} = vm
* blockchain.addBlock(...)
* evm.runCall(...)
* stateManager.putAccount(...)
*
* const mempool = await memoryClient._tevm.getTxPool()
* const receiptsManager = await memoryClient._tevm.getReceiptsManager()
* ````
*/
_tevm: BaseClient &
Eip1193RequestProvider &
TevmActionsApi & {
send: TevmJsonRpcRequestHandler
sendBulk: TevmJsonRpcBulkRequestHandler
request: EIP1193RequestFn
}
tevmForkUrl?: string
/**
* Returns a promise that resolves when the tevm is ready
* This is not needed to explicitly be called as all actions will wait for the tevm to be ready
* @example
* ```typescript
* import { createMemoryClient } from 'tevm'
*
* const client = createMemoryClient()
*
* await client.tevmReady()
* ```
* Same as calling `client._tevm.ready()`
*/
tevmReady: () => Promise<true>
/**
* A powerful low level api for executing calls and sending transactions
* See [CallParams](https://tevm.sh/reference/tevm/actions/type-aliases/callparams/) for options reference
* See [CallResult](https://tevm.sh/reference/tevm/precompiles/type-aliases/callresult/) for return values reference
* Remember, you must set `createTransaction: true` to send a transaction. Otherwise it will be a call`. You must also mine the transaction
* before it updates the cannonical head state.` This can be avoided by setting mining mode to `auto` when using createMemoryClient`
* @example
* ```typescript`
* import { createMemoryClient } from 'tevm'
* import { ERC20 } from 'tevm/contract'
*
* const client = createMemoryClient()
*
* const token = ERC20.withAddress(`0x${'0721'.repeat(10)}`)
*
* await client.setAccount(token)
*
* const balance = await client.tevmCall({
* to: token.address,
* data: encodeFunctionData(token.read.balanceOf, [token.address]),
* })
* ```
* In addiiton to making basic call, you can also do advanced things like
* - impersonate accounts via passing in `from`, `caller`, or `origin`
* - set the call depth via `depth`
* - Create a trace or access list using `createTrace: true` or `createAccessList: true`
* - send as a transaction with `createTransaction: true`
* For all options see [CallParams](https://tevm.sh/reference/tevm/actions/type-aliases/callparams/)
* Same as calling `client._tevm.call`
* `
*/
tevmCall: TevmActionsApi['call']
/**
* A powerful low level api for calling contracts. Similar to `tevmCall` but takes care of encoding and decoding data, revert messages, etc.
* See [ContractParams](https://tevm.sh/reference/tevm/actions/type-aliases/contractparams/) for options reference]
* See [ContractResult](https://tevm.sh/reference/tevm/actions/type-aliases/contractresult/) for return values reference
* Remember, you must set `createTransaction: true` to send a transaction. Otherwise it will be a call`. You must also mine the transaction
* before it updates the cannonical head state.` This can be avoided by setting mining mode to `auto` when using createMemoryClient`
* @example
* ```typescript
* import { createMemoryClient } from 'tevm'
* import { ERC20 } from './MyERC721.sol'
*
* const client = createMemoryClient()
* const token = ERC20.withAddress(`0x${'0721'.repeat(10)}`)
* await client.setAccount(token)
* const balance = await client.tevmContract({
* contract: token,
* method: token.read.balanceOf,
* args: [token.address],
* })
* ```
* In addiiton to making basic call, you can also do advanced things like
* - impersonate accounts via passing in `from`, `caller`, or `origin`
* - set the call depth via `depth`
* - Create a trace or access list using `createTrace: true` or `createAccessList: true`
* - send as a transaction with `createTransaction: true`
* For all options see [ContractParams](https://tevm.sh/reference/tevm/actions/type-aliases/contractparams/)
*/
tevmContract: TevmActionsApi['contract']
/**
* @deprecated in favor of tevmContract
* @deprecated in favor of tevmContract. To migrate simply replace `tevmScript` with `tevmContract` as the api is supported and more
* tevmContract also now supports deploying contracts with constructor arguments too via `params.code`. TevmScript previously did not support this
* and only supported deployedBytecode with no constructor arguments. tevmContract supports using deployedBytecode as waell.
* Remember, you must set `createTransaction: true` to send a transaction. Otherwise it will be a call`. You must also mine the transaction
* before it updates the cannonical head state.` This can be avoided by setting mining mode to `auto` when using createMemoryClient`
* @example
* ```typescript
* import { createMemoryClient } from 'tevm'`
* import { ERC20 } from './MyERC721.sol'
*
* const client = createMemoryClient()
*
* const balance = await client.tevmContract({
* createTransaction: true,
* deployedBytecode: ERC20.deployedBytecode,
* abi: ERC20.abi,
* method: 'mint',
* args: [client.address, 1n],
* })
* ```
* Same as calling `client._tevm.script`
* `
*/
tevmScript: TevmActionsApi['script']
/**
* Deploys a contract to the EVM with encoded constructor arguments. Extends `tevmCall` so it supports all advanced options
* @see [DeployParams](https://tevm.sh/reference/tevm/actions/type-aliases/deployparams/) for options reference
* @see [DeployResult](https://tevm.sh/reference/tevm/actions/type-aliases/deployresult/) for return values reference
* Remember, you must set `createTransaction: true` to send a transaction. Otherwise it will be a call`. You must also mine the transaction
* before it updates the cannonical head state.` This can be avoided by setting mining mode to `auto` when using createMemoryClient`
* @example
* ```typescript
* import { createMemoryClient } from 'tevm'
* import { ERC20 } from './MyERC721.sol'
*
* const client = createMemoryClient()
* const token = ERC20.withAddress(`0x${'0721'.repeat(10)}`)
*
* const deploymentResult = await client.tevmDeploy({
* abi: token.abi,
* bytecode: token.bytecode,
* args: ['TokenName', 18, 'SYMBOL'],
* })
*
* console.log(deployedResult.createdAddressess)
*/
tevmDeploy: TevmActionsApi['deploy']
/**
* Mines a new block with all pending transactions. In `manual` mode you must call this manually before the cannonical head state is updated
* @example
* ```typescript
* import { createMemoryClient } from 'tevm'
*
* const client = createMemoryClient()
*
* await client.tevmMine()
* ```
*/
tevmMine: TevmActionsApi['mine']
/**
* Loads a json serializable state into the evm. This can be useful for persisting and restoring state between processes
* @example
* ```typescript
* import { createMemoryClient } from 'tevm'
* import fs from 'fs'
*
* const client = createMemoryClient()
*
* const state = fs.readFileSync('state.json', 'utf8')
*
* await client.tevmLoadState(state)
* ````
*/
tevmLoadState: TevmActionsApi['loadState']
/**
* Dumps a json serializable state from the evm. This can be useful for persisting and restoring state between processes
* @example
* ```typescript
* import { createMemoryClient } from 'tevm'
* import fs from 'fs'
* const client = createMemoryClient()
* const state = await client.tevmDumpState()
* fs.writeFileSync('state.json', JSON.stringify(state))
* ```
*/
tevmDumpState: TevmActionsApi['dumpState']
/**
* Sets any property of an account including
* - it's balance
* - It's nonce
* - It's contract deployedBytecode
* - It's contract state
* - more
* @see [SetAccountParams](https://tevm.sh/reference/tevm/actions/type-aliases/setaccountparams/) for options reference]
* @see [SetAccountResult](https://tevm.sh/reference/tevm/actions/type-aliases/setaccountresult/) for return values reference
* @example
* ```typescript
* import { createMemoryClient, numberToHex } from 'tevm'
* import { SimpleContract } from 'tevm/contract'
*
* const client = createMemoryClient()
*
* await client.tevmSetAccount({
* address: `0x${'0123'.repeat(10)}`,
* balance: 100n,
* nonce: 1n,
* deployedBytecode: SimpleContract.deployedBytecode,
* state: {
* [`0x${'0'.repeat(64)}`]: numberToHex(420n),
* }
* })
* ```
*
*/
tevmSetAccount: TevmActionsApi['setAccount']
/**
* Gets the account state of an account
* It does not return the storage state by default but can if `returnStorage` is set to `true`. In forked mode the storage is only the storage
* Tevm has cached and may not represent all the onchain storage.
* @see [GetAccountParams](https://tevm.sh/reference/tevm/actions/type-aliases/getaccountparams/) for options reference
* @see [GetAccountResult](https://tevm.sh/reference/tevm/actions/type-aliases/getaccountresult/) for return values reference
* @example
* ```typescript
* import { createMemoryClient } from 'tevm'
*
* const client = createMemoryClient()
*
* const account = await client.tevmGetAccount({
* address: `0x${'0000'.repeat(10)}`,
* returnStorage: true,
* })
* ```
*/
tevmGetAccount: TevmActionsApi['getAccount']
}
57 changes: 56 additions & 1 deletion packages/memory-client/src/createMemoryClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { createClient, createTransport, publicActions } from 'viem'
// TODO strongly type this! Currently it's return type is inferred

/**
* A local EVM instance running in JavaScript. Similar to Anvil in your browser
* Creates a {@link MemoryClient} which is an viem client with an in-memory ethereum client as it's transport.
* It wraps the viem [public client](https://viem.sh/docs/clients/public#public-client) and [test client](https://viem.sh/docs/clients/test)
* @param {import('@tevm/base-client').BaseClientOptions} [options]
* @returns {import('./MemoryClient.js').MemoryClient}
Expand Down Expand Up @@ -36,6 +36,61 @@ import { createClient, createTransport, publicActions } from 'viem'
* )
* console.log(balance) // 1n
* ```
* @see {@link https://tevm.sh/learn/clients/}
*
* ## Actions API
*
* MemoryClient supports the following actions
*
* - [Tevm actions api](https://tevm.sh/reference/tevm/memory-client/type-aliases/tevmactions/)
*
* ```typescript
* import { createMemoryClient } from "tevm"
* import { testActions } from "tevm/decorators"
*
* const tevm = createMemoryClient()
* await tevm.setAccount({address: `0x${'01'.repeat(20)}`, balance: 100n})
* ```
* - [Viem public actions api](https://viem.sh/docs/actions/public/introduction) such as [getBlockNumber}(https://viem.sh/docs/actions/public/getBlockNumber)
*
* ```typescript
* import { createMemoryClient } from "tevm"
* import { testActions } from "tevm/decorators"
*
* const tevm = createMemoryClient()
* const bn = await tevm.getBlockNumber()
* ```
*
* - [test actions](https://viem.sh/docs/actions/test/introduction) are not included by default but can be added via calling `.extend` on the client.`
*
* ```typescript
* import { createMemoryClient } from "tevm"
* import { testActions } from "tevm/decorators"
*
* const tevm = createMemoryClient().extend(testActions({mode: 'anvil'}))
* tevm.setBalance({address: `0x${'01'.repeat(20)}`, balance: 100n})
* ```
*
* ## Forking
*
* To fork an existing network simply pass an eip-1193 transport to the fork.transport option with an optional block tag.
* When you fork tevm will pin the block tag and lazily cache state from the fork transport.
* It's highly recomended to pass in a `common` object that matches the chain. This will increase the performance of forking with known values.
*
* ```typescript
* import { createMemoryClient, http } from "tevm"
* import { optimism } from "tevm/common"
*
* const forkedClient = createMemoryClient({
* fork: {
* transport: http("https://mainnet.optimism.io")({}),
* },
* common: optimism,
* })
* ```
*
* Tevm clients are themselves EIP-1193 transports. This means you can fork a client with another client.
*
*/
export const createMemoryClient = (options) => {
const tevm = createBaseClient(options).extend(tevmSend()).extend(requestEip1193()).extend(tevmActions())
Expand Down

0 comments on commit af2d591

Please sign in to comment.