<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 async def get_cred_info_by_id(self, cred_id: str) -> str: """ Return cred-info json from wallet by wallet credential identifier. Raise AbsentCred for no such credential. Raise WalletState if the wallet is closed. :param cred_id: credential identifier of interest :return: json with cred for input credential identifier :return: cred-info json; i.e., :: { "referent": string, # credential identifier in the wallet "attrs": { "attr1" : {"raw": "value1", "encoded": "value1_as_int" }, "attr2" : {"raw": "value2", "encoded": "value2_as_int" }, } "schema_id": string, "cred_def_id": string, "rev_reg_id": Optional<string>, "cred_rev_id": Optional<string> } """


        LOGGER.debug('HolderProver.get_cred_info_by_id >>> cred_id: %s', cred_id)

        if not self.wallet.handle:
            LOGGER.debug('HolderProver.get_cred_info_by_id <!< Wallet %s is closed', self.name)
            raise WalletState('Wallet {} is closed'.format(self.name))

        try:
            rv_json = await anoncreds.prover_get_credential(self.wallet.handle, cred_id)
        except IndyError as x_indy:  # no such cred
            if x_indy.error_code == ErrorCode.WalletItemNotFound:
                LOGGER.debug(
                    'HolderProver.get_cred_info_by_id <!< no cred in wallet %s for cred id %s',
                    self.name,
                    cred_id)
                raise AbsentCred('No cred in wallet for {}'.format(cred_id))
            LOGGER.debug(
                'HolderProver.get_cred_info_by_id <!< wallet %s, cred id %s: indy error code %s',
                self.name,
                cred_id,
                x_indy.error_code)
            raise

        LOGGER.debug('HolderProver.get_cred_info_by_id <<< %s', rv_json)
        return rv_json