class MainnetTransactionValidator implements TransactionValidator {

  @Override
  public ValidationResult<TransactionInvalidReason> validate(
      final Transaction transaction, final Optional<Long> baseFee) {
    final ValidationResult<TransactionInvalidReason> signatureResult =
        validateTransactionSignature(transaction);
    if (!signatureResult.isValid()) {
      return signatureResult;
    }

    if (ExperimentalEIPs.eip1559Enabled && maybeEip1559.isPresent()) {
      final EIP1559 eip1559 = maybeEip1559.get();
      if (!eip1559.isValidFormat(transaction, acceptedTransactionTypes)) {
        return ValidationResult.invalid(
            TransactionInvalidReason.INVALID_TRANSACTION_FORMAT,
            String.format(
                "transaction format is invalid, accepted transaction types are %s",
                acceptedTransactionTypes.toString()));
      }
      if (transaction.isEIP1559Transaction()) {
        final Wei price = transactionPriceCalculator.orElseThrow().price(transaction, baseFee);
        if (price.compareTo(Wei.of(baseFee.orElseThrow())) < 0) {
          return ValidationResult.invalid(
              TransactionInvalidReason.INVALID_TRANSACTION_FORMAT,
              String.format("gasPrice is less than the current BaseFee"));
        }
      }
    }

    final Gas intrinsicGasCost = gasCalculator.transactionIntrinsicGasCost(transaction);
    if (intrinsicGasCost.compareTo(Gas.of(transaction.getGasLimit())) > 0) {
      return ValidationResult.invalid(
          TransactionInvalidReason.INTRINSIC_GAS_EXCEEDS_GAS_LIMIT,
          String.format(
              "intrinsic gas cost %s exceeds gas limit %s",
              intrinsicGasCost, transaction.getGasLimit()));
    }

    return ValidationResult.valid();
  }

  public  MainnetTransactionValidator(
      final GasCalculator gasCalculator,
      final boolean checkSignatureMalleability,
      final Optional<BigInteger> chainId);
  public  MainnetTransactionValidator(
      final GasCalculator gasCalculator,
      final Optional<TransactionPriceCalculator> transactionPriceCalculator,
      final boolean checkSignatureMalleability,
      final Optional<BigInteger> chainId,
      final Optional<EIP1559> maybeEip1559,
      final AcceptedTransactionTypes acceptedTransactionTypes);

}