public Optional<CallResult> getCall(final DataFetchingEnvironment environment) {
    // until the miner can expose the current "proposed block" we have no
    // speculative environment, so estimate against latest.
    final Map<String, Object> callData = environment.getArgument("data");
    final Optional<Address> from = Optional.ofNullable((Address) callData.get("from"));
    final Optional<Address> to = Optional.ofNullable((Address) callData.get("to"));
    final var gasParam = callData.get("gas");
    final OptionalLong gas =
        gasParam != null ? OptionalLong.of((Long) gasParam) : OptionalLong.empty();
    final Optional<Wei> gasPrice =
        Optional.ofNullable((UInt256) callData.get("gasPrice")).map(Wei::of);
    final Optional<Wei> value = Optional.ofNullable((UInt256) callData.get("value")).map(Wei::of);
    final Optional<Bytes> data = Optional.ofNullable((Bytes) callData.get("data"));
    final Optional<Wei> maxFeePerGas =
        Optional.ofNullable((UInt256) callData.get("maxFeePerGas")).map(Wei::of);
    final Optional<Wei> maxPriorityFeePerGas =
        Optional.ofNullable((UInt256) callData.get("maxPriorityFeePerGas")).map(Wei::of);

    final BlockchainQueries query = getBlockchainQueries(environment);
    final ProtocolSchedule protocolSchedule =
        environment.getGraphQlContext().get(GraphQLContextType.PROTOCOL_SCHEDULE);
    final TransactionSimulator transactionSimulator =
        environment.getGraphQlContext().get(GraphQLContextType.TRANSACTION_SIMULATOR);

    final CallParameter callParameters =
        ImmutableCallParameter.builder()
            .sender(from)
            .to(to)
            .gas(gas)
            .gasPrice(gasPrice)
            .value(value)
            .maxPriorityFeePerGas(maxPriorityFeePerGas)
            .maxFeePerGas(maxFeePerGas)
            .input(data)
            .build();

    return transactionSimulator.process(
        callParameters,
        TransactionValidationParams.transactionSimulatorAllowExceedingBalanceAndFutureNonce(),
        OperationTracer.NO_TRACING,
        (mutableWorldState, transactionSimulatorResult) ->
            transactionSimulatorResult.map(
                result -> {
                  long status = 0;
                  if (result.isSuccessful()) {
                    status = 1;
                  }
                  return new CallResult(status, result.getGasEstimate(), result.getOutput());
                }),
        query.getBlockchain().getChainHeadHeader());
  }
Simulates the execution of a transaction.

<p>This method retrieves the transaction parameters from the data fetching environment, creates
a CallParameter object, and then uses a TransactionSimulator to simulate the execution of the
transaction. The simulation is done against the latest block as there is currently no way to
expose the current "proposed block" for a speculative environment.

@param environment the data fetching environment.
@return an Optional containing the result of the transaction simulation, or an empty Optional
    if the transaction simulation was not successful.
ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java