text: import datetime
  from dataclasses import asdict, dataclass
  from typing import Optional
  
  import clabe
  from lxml import etree
  
  from .client import Client
  from .cuenta import Cuenta
  
  
  @dataclass
  class Transferencia:
      fecha_operacion: datetime.datetime
      ordenante: Cuenta
      beneficiario: Cuenta
      monto: float
      concepto: str
      clave_rastreo: str
      emisor: str
      receptor: str
      sello: str
      cadena_original: str
  
      @classmethod
      def validar(
          cls,
          fecha: datetime.date,
          clave_rastreo: str,
          emisor: str,
          receptor: str,
          cuenta: str,
          monto: float,
      ):
          client = cls._validar(
              fecha, clave_rastreo, emisor, receptor, cuenta, monto
          )
          if not client:
              return None
          xml = cls._descargar(client, 'XML')
          resp = etree.fromstring(xml)
  
          ordenante = Cuenta.from_etree(resp.find('Ordenante'))
          beneficiario = Cuenta.from_etree(resp.find('Beneficiario'))
          concepto = resp.find('Beneficiario').get('Concepto')
          fecha_operacion = datetime.datetime.fromisoformat(
              str(fecha) + ' ' + resp.get('Hora')
          )
          transferencia = cls(
              fecha_operacion=fecha_operacion,
              ordenante=ordenante,
              beneficiario=beneficiario,
              monto=monto,
              concepto=concepto,
              clave_rastreo=clave_rastreo,
              emisor=emisor,
              receptor=receptor,
              sello=resp.get('sello'),
              cadena_original=resp.get('cadenaCDA')
          )
          setattr(transferencia, '__client', client)
          return transferencia
  
      def descargar(self, formato: str = 'PDF') -> bytes:
          """formato puede ser PDF, XML o ZIP"""
          client = getattr(self, '__client', None)
          if not client:
              client = self._validar(
                  self.fecha_operacion.date(),
                  self.clave_rastreo,
                  self.emisor,
                  self.receptor,
                  self.beneficiario.numero,
                  self.monto,
              )
          return self._descargar(client, formato)
  
      def to_dict(self) -> dict:
          return asdict(self)
  
      @staticmethod
      def _validar(
          fecha: datetime.date,
          clave_rastreo: str,
          emisor: str,
          receptor: str,
          cuenta: str,
          monto: float,
      ) -> Optional[Client]:
          assert emisor in clabe.BANKS.values()
          assert receptor in clabe.BANKS.values()
          client = Client()  # Use new client to ensure thread-safeness
          request_body = dict(
              fecha=fecha.strftime('%d-%m-%Y'),
              criterio=clave_rastreo,
              emisor=emisor,
              receptor=receptor,
              cuenta=cuenta,
              monto=monto,
          )
          resp = client.post('/valida.do', request_body)
          # None si no pudó validar
          return client if b'no encontrada' not in resp else None
  
      @staticmethod
      def _descargar(client: Client, formato: str = 'PDF') -> bytes:
          """formato puede ser PDF, XML o ZIP"""
          return client.get(f'/descarga.do?formato={formato}')
  