import { type IsAddressErrorType, isAddress } from '../address/isAddress.js' import { versionedHashVersionKzg } from '../constants/kzg.js' import { size } from '../data/size.js' import { slice } from '../data/slice.js' import { hexToNumber } from '../encoding/fromHex.js' import { InvalidAddressError, type InvalidAddressErrorType, } from '../errors/address.js' import type { BaseErrorType } from '../errors/base.js' import { EmptyBlobError, type EmptyBlobErrorType, InvalidVersionedHashSizeError, type InvalidVersionedHashSizeErrorType, InvalidVersionedHashVersionError, type InvalidVersionedHashVersionErrorType, } from '../errors/blob.js' import { InvalidChainIdError, type InvalidChainIdErrorType, } from '../errors/chain.js' import { FeeCapTooHighError, type FeeCapTooHighErrorType, TipAboveFeeCapError, type TipAboveFeeCapErrorType, } from '../errors/node.js' import type { ErrorType } from '../errors/utils.js' import type { TransactionEnvelopeEip1559, TransactionEnvelopeEip2930, TransactionEnvelopeEip4844, TransactionEnvelopeEip7702, TransactionEnvelopeLegacy, } from '../types/transactionEnvelope.js' export type AssertTransactionEip7702ErrorType = | AssertTransactionEip1559ErrorType | InvalidAddressErrorType | InvalidChainIdErrorType | ErrorType export function assertTransactionEip7702( transaction: TransactionEnvelopeEip7702, ) { const { authorizationList } = transaction if (authorizationList) { for (const authorization of authorizationList) { const { contractAddress, chainId } = authorization if (!isAddress(contractAddress)) throw new InvalidAddressError({ address: contractAddress }) if (Number(chainId) <= 0) throw new InvalidChainIdError({ chainId }) } } assertTransactionEip1559(transaction as {} as TransactionEnvelopeEip1559) } export type AssertTransactionEip4844ErrorType = | AssertTransactionEip1559ErrorType | EmptyBlobErrorType | InvalidVersionedHashSizeErrorType | InvalidVersionedHashVersionErrorType | ErrorType export function assertTransactionEip4844( transaction: TransactionEnvelopeEip4844, ) { const { blobVersionedHashes } = transaction if (blobVersionedHashes) { if (blobVersionedHashes.length === 0) throw new EmptyBlobError() for (const hash of blobVersionedHashes) { const size_ = size(hash) const version = hexToNumber(slice(hash, 0, 1)) if (size_ !== 32) throw new InvalidVersionedHashSizeError({ hash, size: size_ }) if (version !== versionedHashVersionKzg) throw new InvalidVersionedHashVersionError({ hash, version, }) } } assertTransactionEip1559(transaction as {} as TransactionEnvelopeEip1559) } export type AssertTransactionEip1559ErrorType = | BaseErrorType | IsAddressErrorType | InvalidAddressErrorType | InvalidChainIdErrorType | FeeCapTooHighErrorType | TipAboveFeeCapErrorType | ErrorType export function assertTransactionEip1559( transaction: TransactionEnvelopeEip1559, ) { const { chainId, maxPriorityFeePerGas, maxFeePerGas, to } = transaction if (chainId <= 0) throw new InvalidChainIdError({ chainId }) if (to && !isAddress(to)) throw new InvalidAddressError({ address: to }) if (maxFeePerGas && BigInt(maxFeePerGas) > 2n ** 256n - 1n) throw new FeeCapTooHighError({ maxFeePerGas }) if ( maxPriorityFeePerGas && maxFeePerGas && maxPriorityFeePerGas > maxFeePerGas ) throw new TipAboveFeeCapError({ maxFeePerGas, maxPriorityFeePerGas }) } export type AssertTransactionEip2930ErrorType = | BaseErrorType | IsAddressErrorType | InvalidAddressErrorType | InvalidChainIdErrorType | FeeCapTooHighErrorType | ErrorType export function assertTransactionEip2930( transaction: TransactionEnvelopeEip2930, ) { const { chainId, gasPrice, to } = transaction if (chainId <= 0) throw new InvalidChainIdError({ chainId }) if (to && !isAddress(to)) throw new InvalidAddressError({ address: to }) if (gasPrice && BigInt(gasPrice) > 2n ** 256n - 1n) throw new FeeCapTooHighError({ maxFeePerGas: gasPrice }) } export type AssertTransactionLegacyErrorType = | BaseErrorType | IsAddressErrorType | InvalidAddressErrorType | InvalidChainIdErrorType | FeeCapTooHighErrorType | ErrorType export function assertTransactionLegacy( transaction: TransactionEnvelopeLegacy, ) { const { chainId, gasPrice, to } = transaction if (to && !isAddress(to)) throw new InvalidAddressError({ address: to }) if (typeof chainId !== 'undefined' && chainId <= 0) throw new InvalidChainIdError({ chainId }) if (gasPrice && BigInt(gasPrice) > 2n ** 256n - 1n) throw new FeeCapTooHighError({ maxFeePerGas: gasPrice }) }