DataFetcher<Optional<List<LogAdapter>>> getLogsDataFetcher() {
    return dataFetchingEnvironment -> {
      final BlockchainQueries blockchainQuery =
          dataFetchingEnvironment.getGraphQlContext().get(GraphQLContextType.BLOCKCHAIN_QUERIES);

      final Map<String, Object> filter = dataFetchingEnvironment.getArgument("filter");

      final long currentBlock = blockchainQuery.getBlockchain().getChainHeadBlockNumber();
      final long fromBlock = (Long) filter.getOrDefault("fromBlock", currentBlock);
      final long toBlock = (Long) filter.getOrDefault("toBlock", currentBlock);

      if (fromBlock > toBlock) {
        throw new GraphQLException(GraphQLError.INVALID_PARAMS);
      }

      @SuppressWarnings("unchecked")
      final List<Address> addrs = (List<Address>) filter.get("addresses");
      @SuppressWarnings("unchecked")
      final List<List<Bytes32>> topics = (List<List<Bytes32>>) filter.get("topics");

      final List<List<LogTopic>> transformedTopics = new ArrayList<>();
      for (final List<Bytes32> topic : topics) {
        if (topic.isEmpty()) {
          transformedTopics.add(Collections.singletonList(null));
        } else {
          transformedTopics.add(topic.stream().map(LogTopic::of).collect(Collectors.toList()));
        }
      }

      final LogsQuery query =
          new LogsQuery.Builder().addresses(addrs).topics(transformedTopics).build();

      final List<LogWithMetadata> logs =
          blockchainQuery.matchingLogs(
              fromBlock,
              toBlock,
              query,
              dataFetchingEnvironment.getGraphQlContext().get(GraphQLContextType.IS_ALIVE_HANDLER));
      final List<LogAdapter> results = new ArrayList<>();
      for (final LogWithMetadata log : logs) {
        results.add(new LogAdapter(log));
      }
      return Optional.of(results);
    };
  }
Returns a DataFetcher that fetches a specific block in the Ethereum blockchain.

<p>The DataFetcher is a functional interface. It has a single method that takes a
DataFetchingEnvironment object as input. This method fetches a block based on either a block
number or a block hash. If both a block number and a block hash are provided, it throws a
GraphQLException with INVALID_PARAMS error. If neither a block number nor a block hash is
provided, it fetches the latest block.

<p>The fetched block is then wrapped in a {@link NormalBlockAdapter} and returned as an {@code
Optional<NormalBlockAdapter>}.

@return a DataFetcher that fetches a specific block in the Ethereum blockchain
ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetchers.java