docs: async def send_schema(self, schema_data_json: str) -> str:
          """
          Send schema to ledger, then retrieve it as written to the ledger and return it.
          Raise BadLedgerTxn on failure. Raise BadAttribute for attribute name with spaces or
          reserved for indy-sdk.
  
          If schema already exists on ledger, log error and return schema.
  
          :param schema_data_json: schema data json with name, version, attribute names; e.g.,
  
          ::
  
              {
                  'name': 'my-schema',
                  'version': '1.234',
                  'attr_names': ['favourite_drink', 'height', 'last_visit_date']
              }
  
          :return: schema json as written to ledger (or existed a priori)
          """
  
          LOGGER.debug('Origin.send_schema >>> schema_data_json: %s', schema_data_json)
  
          schema_data = json.loads(schema_data_json)
          for attr in schema_data['attr_names']:
              if not (re.match(r'(?=[^- ])[-_a-zA-Z0-9 ]+(?<=[^- ])$', attr)) or attr.strip().lower() == 'hash':
                  LOGGER.debug('Origin.send_schema <!< Bad attribute name [%s]', attr)
                  raise BadAttribute('Bad attribute name [{}]'.format(attr))
  
          s_id = schema_id(self.did, schema_data['name'], schema_data['version'])
          s_key = schema_key(s_id)
          rv_json = None
          with SCHEMA_CACHE.lock:
              try:
                  rv_json = await self.get_schema(s_key)
                  LOGGER.error(
                      'Schema %s version %s already exists on ledger for origin-did %s: not sending',
                      schema_data['name'],
                      schema_data['version'],
                      self.did)
              except AbsentSchema:  # OK - about to create and send it
                  (_, schema_json) = await anoncreds.issuer_create_schema(
                      self.did,
                      schema_data['name'],
                      schema_data['version'],
                      json.dumps(schema_data['attr_names']))
                  req_json = await ledger.build_schema_request(self.did, schema_json)
                  await self._sign_submit(req_json)
  
                  for _ in range(16):  # reasonable timeout
                      try:
                          rv_json = await self.get_schema(s_key)  # adds to cache
                          break
                      except AbsentSchema:
                          await sleep(1)
                          LOGGER.info('Sent schema %s to ledger, waiting 1s for its appearance', s_id)
  
                  if not rv_json:
                      LOGGER.debug('Origin.send_schema <!< timed out waiting on sent schema %s', s_id)
                      raise BadLedgerTxn('Timed out waiting on sent schema {}'.format(s_id))
  
          LOGGER.debug('Origin.send_schema <<< %s', rv_json)
          return rv_json