def run(self):
        # read configuration files
        config_root = self.ENV.get("CONFIG_ROOT", "../config")
        config_schemas = config.load_config(config_root + "/schemas.yml",
                                            env=self.ENV)
        config_services = config.load_config(config_root + "/services.yml",
                                             env=self.ENV)

        # print("schemas.yml -->", json.dumps(config_schemas))
        # print("services.yml -->", json.dumps(config_services))

        agent_admin_url = self.ENV.get("AGENT_ADMIN_URL")
        if not agent_admin_url:
            raise RuntimeError(
                "Error AGENT_ADMIN_URL is not specified, can't connect to Agent."
            )
        app_config["AGENT_ADMIN_URL"] = agent_admin_url

        # get public DID from our agent
        response = requests.get(agent_admin_url + "/wallet/did/public",
                                headers=ADMIN_REQUEST_HEADERS)
        result = response.json()
        did = result["result"]
        print("Fetched DID from agent: ", did)
        app_config["DID"] = did["did"]

        # determine pre-registered schemas and cred defs
        existing_schemas = agent_schemas_cred_defs(agent_admin_url)
        print("Existing schemas:", json.dumps(existing_schemas))

        # register schemas and credential definitions
        for schema in config_schemas:
            schema_name = schema["name"]
            schema_version = schema["version"]
            schema_key = schema_name + "::" + schema_version
            if schema_key not in existing_schemas:
                schema_attrs = []
                schema_descs = {}
                if isinstance(schema["attributes"], dict):
                    # each element is a dict
                    for attr, desc in schema["attributes"].items():
                        schema_attrs.append(attr)
                        schema_descs[attr] = desc
                else:
                    # assume it's an array
                    for attr in schema["attributes"]:
                        schema_attrs.append(attr)

                # register our schema(s) and credential definition(s)
                schema_request = {
                    "schema_name": schema_name,
                    "schema_version": schema_version,
                    "attributes": schema_attrs,
                }
                response = agent_post_with_retry(
                    agent_admin_url + "/schemas",
                    json.dumps(schema_request),
                    headers=ADMIN_REQUEST_HEADERS,
                )
                response.raise_for_status()
                schema_id = response.json()
            else:
                schema_id = {
                    "schema_id": existing_schemas[schema_key]["schema"]["id"]
                }
            app_config["schemas"]["SCHEMA_" + schema_name] = schema
            app_config["schemas"]["SCHEMA_" + schema_name + "_" +
                                  schema_version] = schema_id["schema_id"]
            print("Registered schema: ", schema_id)

            if (schema_key not in existing_schemas
                    or "cred_def" not in existing_schemas[schema_key]):
                cred_def_request = {"schema_id": schema_id["schema_id"]}
                response = agent_post_with_retry(
                    agent_admin_url + "/credential-definitions",
                    json.dumps(cred_def_request),
                    headers=ADMIN_REQUEST_HEADERS,
                )
                response.raise_for_status()
                credential_definition_id = response.json()
            else:
                credential_definition_id = {
                    "credential_definition_id":
                    existing_schemas[schema_key]["cred_def"]["id"]
                }
            app_config["schemas"]["CRED_DEF_" + schema_name + "_" +
                                  schema_version] = credential_definition_id[
                                      "credential_definition_id"]
            print("Registered credential definition: ",
                  credential_definition_id)

        # what is the TOB connection name?
        tob_connection_params = config_services["verifiers"]["bctob"]

        # check if we have a TOB connection
        response = requests.get(
            agent_admin_url + "/connections?alias=" +
            tob_connection_params["alias"],
            headers=ADMIN_REQUEST_HEADERS,
        )
        response.raise_for_status()
        connections = response.json()["results"]
        tob_connection = None
        for connection in connections:
            # check for TOB connection
            if connection["alias"] == tob_connection_params["alias"]:
                tob_connection = connection

        if not tob_connection:
            # if no tob connection then establish one
            tob_agent_admin_url = tob_connection_params["connection"][
                "agent_admin_url"]
            if not tob_agent_admin_url:
                raise RuntimeError(
                    "Error TOB_AGENT_ADMIN_URL is not specified, can't establish a TOB connection."
                )

            response = requests.post(
                tob_agent_admin_url + "/connections/create-invitation",
                headers=TOB_REQUEST_HEADERS,
            )
            response.raise_for_status()
            invitation = response.json()

            response = requests.post(
                agent_admin_url + "/connections/receive-invitation?alias=" +
                tob_connection_params["alias"],
                json.dumps(invitation["invitation"]),
                headers=ADMIN_REQUEST_HEADERS,
            )
            response.raise_for_status()
            tob_connection = response.json()

            print("Established tob connection: ", tob_connection)
            time.sleep(5)

        app_config["TOB_CONNECTION"] = tob_connection["connection_id"]
        synced[tob_connection["connection_id"]] = False

        for issuer_name, issuer_info in config_services["issuers"].items():
            # register ourselves (issuer, schema(s), cred def(s)) with TOB
            issuer_config = {
                "name": issuer_name,
                "did": app_config["DID"],
                "config_root": config_root,
            }
            issuer_config.update(issuer_info)
            issuer_spec = config.assemble_issuer_spec(issuer_config)

            credential_types = []
            for credential_type in issuer_info["credential_types"]:
                schema_name = credential_type["schema"]
                schema_info = app_config["schemas"]["SCHEMA_" + schema_name]
                ctype_config = {
                    "schema_name":
                    schema_name,
                    "schema_version":
                    schema_info["version"],
                    "issuer_url":
                    issuer_config["url"],
                    "config_root":
                    config_root,
                    "credential_def_id":
                    app_config["schemas"]["CRED_DEF_" + schema_name + "_" +
                                          schema_info["version"]],
                }
                credential_type['attributes'] = schema_info["attributes"]
                ctype_config.update(credential_type)
                ctype = config.assemble_credential_type_spec(
                    ctype_config, schema_info.get("attributes"))
                if ctype is not None:
                    credential_types.append(ctype)

            issuer_request = {
                "connection_id": app_config["TOB_CONNECTION"],
                "issuer_registration": {
                    "credential_types": credential_types,
                    "issuer": issuer_spec,
                },
            }

            print(json.dumps(issuer_request))
            response = requests.post(
                agent_admin_url + "/issuer_registration/send",
                json.dumps(issuer_request),
                headers=ADMIN_REQUEST_HEADERS,
            )
            response.raise_for_status()
            response.json()
            print("Registered issuer: ", issuer_name)

        synced[tob_connection["connection_id"]] = True
        print("Connection {} is synchronized".format(tob_connection))
    def run(self):
        # read configuration files
        config_root = self.ENV.get("CONFIG_ROOT", "../config")
        config_schemas = config.load_config(config_root + "/schemas.yml",
                                            env=self.ENV)
        config_services = config.load_config(config_root + "/services.yml",
                                             env=self.ENV)

        # print("schemas.yml -->", json.dumps(config_schemas))
        # print("services.yml -->", json.dumps(config_services))

        agent_admin_url = self.ENV.get("AGENT_ADMIN_URL")
        if not agent_admin_url:
            raise RuntimeError(
                "Error AGENT_ADMIN_URL is not specified, can't connect to Agent."
            )
        app_config["AGENT_ADMIN_URL"] = agent_admin_url

        # ensure DID is registered
        ledger_url = self.ENV.get("LEDGER_URL")
        auto_register_did = self.ENV.get("AUTO_REGISTER_DID", False)
        if auto_register_did and ledger_url:
            # gt seed and alias to register
            seed = self.ENV.get("WALLET_SEED_VONX")
            alias = list(config_services["issuers"].keys())[0]

            # register DID
            response = requests.post(
                ledger_url + "/register",
                json.dumps({
                    "alias": alias,
                    "seed": seed,
                    "role": "TRUST_ANCHOR"
                }),
            )
            response.raise_for_status()
            did = response.json()
            print("Registered did: ", did)
            app_config["DID"] = did["did"]
            time.sleep(5)

        # register schemas and credential definitions
        for schema in config_schemas:
            schema_name = schema["name"]
            schema_version = schema["version"]
            schema_attrs = []
            schema_descs = {}
            if isinstance(schema["attributes"], dict):
                # each element is a dict
                for attr, desc in schema["attributes"].items():
                    schema_attrs.append(attr)
                    schema_descs[attr] = desc
            else:
                # assume it's an array
                for attr in schema["attributes"]:
                    schema_attrs.append(attr)

            # register our schema(s) and credential definition(s)
            schema_request = {
                "schema_name": schema_name,
                "schema_version": schema_version,
                "attributes": schema_attrs,
            }
            response = requests.post(
                agent_admin_url + "/schemas",
                json.dumps(schema_request),
                headers=ADMIN_REQUEST_HEADERS,
            )
            response.raise_for_status()
            schema_id = response.json()
            app_config["schemas"]["SCHEMA_" + schema_name] = schema
            app_config["schemas"]["SCHEMA_" + schema_name + "_" +
                                  schema_version] = schema_id["schema_id"]
            print("Registered schema: ", schema_id)

            cred_def_request = {"schema_id": schema_id["schema_id"]}
            response = requests.post(
                agent_admin_url + "/credential-definitions",
                json.dumps(cred_def_request),
                headers=ADMIN_REQUEST_HEADERS,
            )
            response.raise_for_status()
            credential_definition_id = response.json()
            app_config["schemas"]["CRED_DEF_" + schema_name + "_" +
                                  schema_version] = credential_definition_id[
                                      "credential_definition_id"]
            print("Registered credential definition: ",
                  credential_definition_id)

        # what is the TOB connection name?
        tob_connection_params = config_services["verifiers"]["bctob"]

        # check if we have a TOB connection
        response = requests.get(
            agent_admin_url + "/connections?alias=" +
            tob_connection_params["alias"],
            headers=ADMIN_REQUEST_HEADERS,
        )
        response.raise_for_status()
        connections = response.json()["results"]
        tob_connection = None
        for connection in connections:
            # check for TOB connection
            if connection["alias"] == tob_connection_params["alias"]:
                tob_connection = connection

        if not tob_connection:
            # if no tob connection then establish one
            tob_agent_admin_url = tob_connection_params["connection"][
                "agent_admin_url"]
            if not tob_agent_admin_url:
                raise RuntimeError(
                    "Error TOB_AGENT_ADMIN_URL is not specified, can't establish a TOB connection."
                )

            response = requests.post(
                tob_agent_admin_url + "/connections/create-invitation",
                headers=TOB_REQUEST_HEADERS,
            )
            response.raise_for_status()
            invitation = response.json()

            response = requests.post(
                agent_admin_url + "/connections/receive-invitation?alias=" +
                tob_connection_params["alias"],
                json.dumps(invitation["invitation"]),
                headers=ADMIN_REQUEST_HEADERS,
            )
            response.raise_for_status()
            tob_connection = response.json()

            print("Established tob connection: ", tob_connection)
            time.sleep(5)

        app_config["TOB_CONNECTION"] = tob_connection["connection_id"]
        synced[tob_connection["connection_id"]] = False

        for issuer_name, issuer_info in config_services["issuers"].items():
            # register ourselves (issuer, schema(s), cred def(s)) with TOB
            issuer_config = {
                "name": issuer_name,
                "did": app_config["DID"],
                "config_root": config_root,
            }
            issuer_config.update(issuer_info)
            issuer_spec = config.assemble_issuer_spec(issuer_config)

            credential_types = []
            for credential_type in issuer_info["credential_types"]:
                schema_name = credential_type["schema"]
                schema_info = app_config["schemas"]["SCHEMA_" + schema_name]
                ctype_config = {
                    "schema_name":
                    schema_name,
                    "schema_version":
                    schema_version,
                    "issuer_url":
                    issuer_config["url"],
                    "config_root":
                    config_root,
                    "credential_def_id":
                    app_config["schemas"]["CRED_DEF_" + schema_name + "_" +
                                          schema_info["version"]],
                }
                ctype_config.update(credential_type)
                ctype = config.assemble_credential_type_spec(ctype_config)
                if ctype is not None:
                    credential_types.append(ctype)

            issuer_request = {
                "connection_id": app_config["TOB_CONNECTION"],
                "issuer_registration": {
                    "credential_types": credential_types,
                    "issuer": issuer_spec,
                },
            }

            response = requests.post(
                agent_admin_url + "/issuer_registration/send",
                json.dumps(issuer_request),
                headers=ADMIN_REQUEST_HEADERS,
            )
            response.raise_for_status()
            response.json()
            print("Registered issuer: ", issuer_name)

        synced[tob_connection["connection_id"]] = True
        print("Connection {} is synchronized".format(tob_connection))