UNPKG

@tevm/actions

Version:

A typesafe library for writing forge scripts in typescript

73 lines (70 loc) 2.72 kB
import { MissingAccountError } from './ethSignHandler.js' /** * Creates a handler for the `eth_signTransaction` JSON-RPC method that signs transactions using the specified accounts * * This handler enables signing Ethereum transactions without broadcasting them to the network. It creates an EIP-2930 * transaction signature using the private key of the specified account. The handler automatically retrieves the * current chain ID from the node. * * @param {object} options - Configuration options for the handler * @param {ReadonlyArray<import('@tevm/utils').HDAccount>} options.accounts - Array of HD accounts that can be used for signing * @param {() => Promise<number>} options.getChainId - Function to retrieve the current chain ID * @returns {import('./EthHandler.js').EthSignTransactionHandler} A handler function for eth_signTransaction requests * @throws {MissingAccountError} If the requested account (from address) is not found in the provided accounts list * * @example * ```javascript * import { ethSignTransactionHandler } from '@tevm/actions' * import { mnemonicToAccount, parseGwei } from '@tevm/utils' * * // Create accounts from a mnemonic * const mnemonic = 'test test test test test test test test test test test junk' * const accounts = Array.from(Array(10).keys()).map( * (i) => mnemonicToAccount(mnemonic, { addressIndex: i }) * ) * * // Create the handler * const handler = ethSignTransactionHandler({ * accounts, * getChainId: async () => 1 // Mainnet * }) * * // Sign a transaction * try { * const signedTx = await handler({ * from: accounts[0].address, * to: '0x1234567890123456789012345678901234567890', * value: 1000000000000000000n, // 1 ETH * gas: 21000n, * gasPrice: parseGwei('20'), * nonce: 0n, * data: '0x' * }) * * console.log('Signed transaction:', signedTx) * // Can be used with eth_sendRawTransaction * } catch (error) { * if (error.name === 'MissingAccountError') { * console.error('Account not found:', error.message) * } else { * console.error('Unexpected error:', error) * } * } * ``` */ export const ethSignTransactionHandler = ({ getChainId, accounts }) => { const accountsByAddress = Object.fromEntries(accounts.map((account) => [account.address, account])) return async ({ nonce, ...params }) => { // TODO validate params with zod const account = accountsByAddress[params.from] if (!account) { throw new MissingAccountError(`Account ${params.from} not found`) } return account.signTransaction({ ...params, type: 'eip2930', chainId: Number(await getChainId()), ...(typeof nonce === 'bigint' ? { nonce: Number(nonce) } : {}), }) } }