text: from abc import abstractmethod
  from typing import Generic, TypeVar, Any, Dict, List, TYPE_CHECKING, Type
  import base64
  
  from bxcommon import constants
  from bxcommon.rpc import rpc_constants
  from bxcommon.rpc.bx_json_rpc_request import BxJsonRpcRequest
  from bxcommon.rpc.json_rpc_response import JsonRpcResponse
  from bxcommon.rpc.requests.abstract_rpc_request import AbstractRpcRequest
  from bxcommon.rpc.rpc_errors import RpcParseError, RpcError, RpcInternalError
  from bxcommon.rpc.rpc_request_type import RpcRequestType
  from bxutils import logging, log_messages
  from bxutils.encoding.json_encoder import Case
  
  logger = logging.get_logger(__name__)
  
  if TYPE_CHECKING:
      # noinspection PyUnresolvedReferences
      # pylint: disable=ungrouped-imports,cyclic-import
      from bxcommon.connections.abstract_node import AbstractNode
  
  Node = TypeVar("Node", bound="AbstractNode")
  Req = TypeVar("Req")
  Res = TypeVar("Res")
  
  
  class AbstractRpcHandler(Generic[Node, Req, Res]):
      node: Node
      request_handlers: Dict[RpcRequestType, Type[AbstractRpcRequest[Node]]]
      case: Case
  
      def __init__(self, node: Node, case: Case = Case.SNAKE) -> None:
          self.node = node
          self.request_handlers = {}
          self.case = case
  
      async def handle_request(self, request: Req) -> Res:
          try:
              payload = await self.parse_request(request)
          except Exception:
              raise RpcParseError(None, f"Unable to parse the request: {request}")
  
          rpc_request = BxJsonRpcRequest.from_json(payload)
  
          # request can be many types, not all of them have "headers"
          headers = getattr(request, "headers", None)
          account_cache_key = ""
          if headers and rpc_constants.AUTHORIZATION_HEADER_KEY in headers:
              request_auth_key = headers[rpc_constants.AUTHORIZATION_HEADER_KEY]
              account_cache_key = base64.b64decode(request_auth_key).decode(constants.DEFAULT_TEXT_ENCODING)
              rpc_request.account_cache_key = account_cache_key
  
          request_handler = self.get_request_handler(rpc_request)
          try:
              return self.serialize_response(
                  await request_handler.process_request()
              )
          except RpcError as e:
              raise e
          except Exception as e:
              logger.exception(
                  log_messages.INTERNAL_ERROR_HANDLING_RPC_REQUEST, e, rpc_request, account_cache_key
              )
              raise RpcInternalError(rpc_request.id, "Please contact bloXroute support.")
  
      async def help(self) -> List[Any]:
          return [
              {
                  "method": method.name.lower(),
                  "id": "Optional - [unique request identifier string].",
                  "params": self.request_handlers[method].help["params"],
                  "description": self.request_handlers[method].help["description"],
              }
              for method in self.request_handlers
          ]
  
      @abstractmethod
      async def parse_request(self, request: Req) -> Dict[str, Any]:
          pass
  
      @abstractmethod
      def get_request_handler(self, request: BxJsonRpcRequest) -> AbstractRpcRequest:
          pass
  
      @abstractmethod
      def serialize_response(self, response: JsonRpcResponse) -> Res:
          pass
  