UNPKG

@tevm/actions

Version:

A typesafe library for writing forge scripts in typescript

72 lines (70 loc) 2.53 kB
import { BaseError, InternalError } from '@tevm/errors' import { bytesToHex } from '@tevm/utils' import { getPendingClient } from '../internal/getPendingClient.js' import { maybeThrowOnFail } from '../internal/maybeThrowOnFail.js' /** * Creates a handler for dumping the TEVM state. * * @param {import("@tevm/node").TevmNode} client - The TEVM client instance. * @param {object} [options] - Optional settings. * @param {boolean} [options.throwOnFail] - Whether to throw an error if the state dump fails. * @returns {import('../DumpState/DumpStateHandlerType.js').DumpStateHandler} - The state dump handler function. * * @example * ```typescript * import { createTevmNode } from 'tevm/node' * import { dumpStateHandler } from 'tevm/actions' * * const client = createTevmNode() * * const dumpState = dumpStateHandler(client) * * const { state, errors } = await dumpState() * if (errors) { * console.error(errors) * } else { * console.log(state) * } * ``` */ export const dumpStateHandler = (client, options = {}) => async ({ throwOnFail = options.throwOnFail, blockTag = 'latest' } = {}) => { try { const vm = blockTag === 'pending' ? await getPendingClient(client).then((mineResult) => { if (mineResult.errors) { throw mineResult.errors[0] } return mineResult.pendingClient.getVm() }) : await client.getVm() if ('dumpCanonicalGenesis' in vm.stateManager) { if (blockTag === 'latest' || blockTag === 'pending') { return { state: await vm.stateManager.dumpCanonicalGenesis() } } const block = await vm.blockchain.getBlockByTag(blockTag) if (await vm.stateManager.hasStateRoot(block.header.stateRoot)) { return { state: vm.stateManager._baseState.stateRoots.get(bytesToHex(block.header.stateRoot)) ?? {} } } client.logger.warn(`State root does not exist for block ${blockTag}. Returning empty state`) return { state: {} } } throw new InternalError( 'Unsupported state manager. Must use a TEVM state manager from `@tevm/state` package. This may indicate a bug in TEVM internal code.', ) } catch (e) { if (/** @type {BaseError}*/ (e)._tag) { return maybeThrowOnFail(throwOnFail ?? true, { state: {}, // TODO we need to strongly type errors better here errors: [/**@type {any} */ (e)], }) } return maybeThrowOnFail(throwOnFail ?? true, { state: {}, errors: [e instanceof InternalError ? e : new InternalError('Unexpected error', { cause: e })], }) } }