class DebugStorageRangeAt implements JsonRpcMethod {

  @Override
  public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
    final BlockParameterOrBlockHash blockParameterOrBlockHash =
        requestContext.getRequiredParameter(0, BlockParameterOrBlockHash.class);
    final int transactionIndex = requestContext.getRequiredParameter(1, Integer.class);
    final Address accountAddress = requestContext.getRequiredParameter(2, Address.class);
    final Hash startKey =
        Hash.fromHexStringLenient(requestContext.getRequiredParameter(3, String.class));
    final int limit = requestContext.getRequiredParameter(4, Integer.class);

    final Optional<Hash> blockHashOptional = hashFromParameter(blockParameterOrBlockHash);
    if (blockHashOptional.isEmpty()) {
      return emptyResponse(requestContext);
    }
    final Hash blockHash = blockHashOptional.get();
    final Optional<BlockHeader> blockHeaderOptional =
        blockchainQueries.get().blockByHash(blockHash).map(BlockWithMetadata::getHeader);
    if (blockHeaderOptional.isEmpty()) {
      return emptyResponse(requestContext);
    }

    final Optional<TransactionWithMetadata> optional =
        blockchainQueries.get().transactionByBlockHashAndIndex(blockHash, transactionIndex);

    return optional
        .map(
            transactionWithMetadata ->
                (blockReplay
                    .get()
                    .afterTransactionInBlock(
                        blockHash,
                        transactionWithMetadata.getTransaction().getHash(),
                        (transaction, blockHeader, blockchain, worldState, transactionProcessor) ->
                            extractStorageAt(
                                requestContext, accountAddress, startKey, limit, worldState))
                    .orElseGet(() -> emptyResponse(requestContext))))
        .orElseGet(
            () ->
                blockchainQueries
                    .get()
                    .getWorldState(blockHeaderOptional.get().getNumber())
                    .map(
                        worldState ->
                            extractStorageAt(
                                requestContext, accountAddress, startKey, limit, worldState))
                    .orElseGet(() -> emptyResponse(requestContext)));
  }

  public  DebugStorageRangeAt(
      final BlockchainQueries blockchainQueries, final BlockReplay blockReplay);
  public  DebugStorageRangeAt(
      final Supplier<BlockchainQueries> blockchainQueries,
      final Supplier<BlockReplay> blockReplay,
      final boolean shortValues);

}