UNPKG

viem

Version:

TypeScript Interface for Ethereum

195 lines (185 loc) • 5.78 kB
import type { Address, Narrow } from 'abitype' import { type SendTransactionErrorType, sendTransaction, } from '../../../actions/wallet/sendTransaction.js' import type { Client } from '../../../clients/createClient.js' import type { Transport } from '../../../clients/transports/createTransport.js' import type { BaseError } from '../../../errors/base.js' import type { ErrorType } from '../../../errors/utils.js' import type { Account, GetAccountParameter } from '../../../types/account.js' import type { Batches, Calls } from '../../../types/calls.js' import type { Chain, DeriveChain, GetChainParameter, } from '../../../types/chain.js' import type { Hex } from '../../../types/misc.js' import type { UnionEvaluate, UnionPick } from '../../../types/utils.js' import type { FormattedTransactionRequest } from '../../../utils/formatters/transactionRequest.js' import { withCache } from '../../../utils/promise/withCache.js' import { ExecuteUnsupportedError } from '../errors.js' import { type EncodeExecuteBatchesDataErrorType, encodeExecuteBatchesData, } from '../utils/encodeExecuteBatchesData.js' import { type GetExecuteErrorReturnType, getExecuteError, } from '../utils/getExecuteError.js' import { supportsExecutionMode } from './supportsExecutionMode.js' /** @internal */ export type Batch = { calls: readonly unknown[]; opData?: Hex | undefined } export type ExecuteBatchesParameters< batches extends readonly Batch[] = readonly Batch[], chain extends Chain | undefined = Chain | undefined, account extends Account | undefined = Account | undefined, chainOverride extends Chain | undefined = Chain | undefined, _derivedChain extends Chain | undefined = DeriveChain<chain, chainOverride>, > = UnionEvaluate< UnionPick< FormattedTransactionRequest<_derivedChain>, | 'authorizationList' | 'gas' | 'gasPrice' | 'maxFeePerGas' | 'maxPriorityFeePerGas' > > & GetAccountParameter<account, Account | Address, true, true> & GetChainParameter<chain, chainOverride> & { /** Address that will execute the calls. */ address: Address /** Batches to execute. */ batches: Batches<Narrow<batches>, { opData?: Hex | undefined }> } export type ExecuteBatchesReturnType = Hex export type ExecuteBatchesErrorType = | GetExecuteErrorReturnType | EncodeExecuteBatchesDataErrorType | SendTransactionErrorType | ErrorType /** * Executes batches of call(s) using "batch of batches" mode on an [ERC-7821-compatible contract](https://eips.ethereum.org/EIPS/eip-7821). * * @example * ```ts * import { createClient, http, parseEther } from 'viem' * import { privateKeyToAccount } from 'viem/accounts' * import { mainnet } from 'viem/chains' * import { executeBatches } from 'viem/experimental/erc7821' * * const account = privateKeyToAccount('0x...') * * const client = createClient({ * chain: mainnet, * transport: http(), * }) * * const hash = await executeBatches(client, { * account, * batches: [ * { * calls: [ * { * to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8', * value: parseEther('1'), * }, * ], * }, * { * calls: [ * { * to: '0xcb98643b8786950F0461f3B0edf99D88F274574D', * value: parseEther('2'), * }, * { * data: '0xdeadbeef', * to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8', * }, * ], * }, * ], * to: account.address, * }) * ``` * * @example * ```ts * // Account Hoisting * import { createClient, http, parseEther } from 'viem' * import { privateKeyToAccount } from 'viem/accounts' * import { mainnet } from 'viem/chains' * import { executeBatches } from 'viem/experimental/erc7821' * * const account = privateKeyToAccount('0x...') * * const client = createClient({ * chain: mainnet, * transport: http(), * }) * * const hash = await executeBatches(client, { * batches: [ * { * calls: [ * { * to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8', * value: parseEther('1'), * }, * ], * }, * { * calls: [ * { * to: '0xcb98643b8786950F0461f3B0edf99D88F274574D', * value: parseEther('2'), * }, * { * data: '0xdeadbeef', * to: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8', * }, * ], * }, * ], * to: account.address, * }) * ``` * * @param client - Client to use. * @param parameters - {@link ExecuteBatchesParameters} * @returns Transaction hash. {@link ExecuteBatchesReturnType} */ export async function executeBatches< batches extends readonly Batch[], chain extends Chain | undefined, account extends Account | undefined, chainOverride extends Chain | undefined = undefined, >( client: Client<Transport, chain, account>, parameters: ExecuteBatchesParameters<batches, chain, account, chainOverride>, ): Promise<ExecuteBatchesReturnType> { const { authorizationList, batches } = parameters const address = authorizationList?.[0]?.address ?? parameters.address const supported = await withCache( () => supportsExecutionMode(client, { address, mode: 'batchOfBatches', }), { cacheKey: `supportsExecutionMode.${client.uid}.${address}.batchOfBatches`, }, ) if (!supported) throw new ExecuteUnsupportedError() try { return await sendTransaction(client, { ...parameters, to: parameters.address, data: encodeExecuteBatchesData({ batches }), } as any) } catch (e) { const calls = batches.flatMap((b) => b.calls) as Calls<Narrow<batches>> throw getExecuteError(e as BaseError, { calls }) } }