Beispiel #1
0
async def handle_create_invitation(request):
    global agent
    connection = await agent.admin_POST("/connections/create-invitation")
    agent._connection_ready = asyncio.Future()
    agent.connection_id = connection["connection_id"]
    log_msg("Invitation has been created !!")
    return web.json_response(connection["invitation"])
    async def input_invitation(self, invite_details: dict, wait: bool = False):
        self._connection_ready = asyncio.Future()
        with log_timer("Connect duration:"):
            connection = await self.receive_invite(invite_details)
            log_json(connection, label="Invitation response:")

        if wait:
            log_msg("Waiting for connection...")
            await self.detect_connection()
Beispiel #3
0
async def main(start_port: int, show_timing: bool = False):
    global agent
    genesis = await default_genesis_txns()
    if not genesis:
        print("Error retrieving ledger genesis transactions")
        sys.exit(1)

    try:
        log_status(
            "Provision an agent and wallet, get back configuration details")
        agent = MSPAgent(start_port,
                         start_port + 1,
                         genesis_data=genesis,
                         timing=show_timing)
        await agent.listen_webhooks(start_port + 2)
        # await agent.register_did()

        with log_timer("Startup duration:"):
            await agent.start_process()
        log_msg("Admin url is at:", agent.admin_url)
        log_msg("Endpoint url is at:", agent.endpoint)

        app = web.Application()
        app.add_routes([
            web.get('/create_invitation', handle_create_invitation),
            web.post('/verify_signature', handle_verify_signature),
            web.post('/verify_proof', handle_verify_proof),
        ])

        cors = aiohttp_cors.setup(
            app,
            defaults={
                "*":
                aiohttp_cors.ResourceOptions(
                    allow_credentials=True,
                    expose_headers="*",
                    allow_headers="*",
                    allow_methods="*",
                )
            },
        )
        for route in app.router.routes():
            cors.add(route)

        setup_aiohttp_apispec(app=app,
                              title="Aries Cloud Agent two",
                              version="v1",
                              swagger_path="/api/doc")
        app.on_startup.append(on_startup)

        return app

    except Exception:
        log_status(
            "Error while provision an agent and wallet, get back configuration details"
        )
Beispiel #4
0
 async def handle_connections(self, message):
     conn_id = message["connection_id"]
     if message["rfc23_state"] == "invitation-sent":
         self.connection_id = conn_id
     if conn_id == self.connection_id:
         if (message["rfc23_state"] in ["completed", "response-sent"]
                 and not self._connection_ready.done()):
             self.log("Connected")
             log_msg("connection id: ", conn_id)
             self._connection_ready.set_result(True)
    async def handle_present_proof(self, message):
        state = message["state"]
        presentation_exchange_id = message["presentation_exchange_id"]
        presentation_request = message["presentation_request"]

        log_msg(
            "Presentation: state =",
            state,
            ", presentation_exchange_id =",
            presentation_exchange_id,
        )
Beispiel #6
0
async def main(start_port: int, show_timing: bool = False):
    global agent
    genesis = await default_genesis_txns()
    agent = None
    if not genesis:
        print("Error retrieving ledger genesis transactions")
        sys.exit(1)
    try:
        agent = CI_MSPAgent(start_port,
                            start_port + 1,
                            genesis_data=genesis,
                            timing=show_timing)
        await agent.listen_webhooks(start_port + 2)
        await agent.register_did()
        with log_timer("Startup duration:"):
            await agent.start_process()
        log_msg("Admin url is at:", agent.admin_url)
        log_msg("Endpoint url is at:", agent.endpoint)

        app = web.Application()

        app.add_routes([
            # These are api's for ci and msp
            web.get('/create_invitation', handle_create_invitation),
            # These are api's for ci
            web.post('/create_schema_cred_def',
                     handle_create_schema_credential_definition),
            web.post('/send_credential_offer', handle_send_credential_offer),
            web.get('/issue_credential', handle_issue_credential),
            web.get('/get_connection_list', handle_get_connection_list),
            web.get('/get_cred_def_list', handle_get_cred_def_list),
            #These are the api's for msp
            web.post('/verify_signature', handle_verify_signature),
            web.post('/verify_proof', handle_verify_proof),
        ])

        cors = aiohttp_cors.setup(
            app,
            defaults={
                "*":
                aiohttp_cors.ResourceOptions(
                    allow_credentials=True,
                    expose_headers="*",
                    allow_headers="*",
                    allow_methods="*",
                )
            },
        )
        for route in app.router.routes():
            cors.add(route)

        return app
    except Exception:
        print("Error when starting to run server!!")
async def handle_create_invitation(request):
    global agent
    connection = await agent.admin_POST("/connections/create-invitation")
    agent.connection_id = connection["connection_id"]
    agent._connection_ready = asyncio.Future()
    log_json(connection, label="Invitation response:")
    log_msg(json.dumps(connection["invitation"]),
            label="Invitation:",
            color=None)

    return web.json_response(connection["invitation"])
Beispiel #8
0
async def main(start_port: int, show_timing: bool = False, container_name: str = "Simple_client"):
    global agent
    global client_name
    genesis = await default_genesis_txns()
    if not genesis:
        print("Error retrieving ledger genesis transactions")
        sys.exit(1)
    try:
        log_status("Provision an agent and wallet, get back configuration details")
        label=container_name
        client_name=label
        agent = ClientAgent(
            label, start_port, start_port + 1, genesis_data=genesis, timing=show_timing
        )
        await agent.listen_webhooks(start_port + 2)
        # await agent.register_did()
        with log_timer("Startup duration:"):
            await agent.start_process()
        log_msg("Admin url is at:", agent.admin_url)
        log_msg("Endpoint url is at:", agent.endpoint)

        async with aiofile.AIOFile("client_logger.csv", 'w') as afp:
            writer = aiofile.Writer(afp)
            await writer("")
            await afp.fsync()

        app = web.Application()
        app.add_routes([
            web.get('/get_client_name', handle_get_client_name),
            web.get('/get_connections', handle_get_connections),
            web.post('/input_invitation', handle_input_invitation),
            web.post('/sign_message', handle_sign_message),
            web.get('/get_signing_did', handle_get_signing_did),
            web.get('/readCommentsFromLogger', readCommentsFromLogger),
        ])

        cors = aiohttp_cors.setup(
            app,
            defaults={
                "*": aiohttp_cors.ResourceOptions(
                    allow_credentials=True,
                    expose_headers="*",
                    allow_headers="*",
                    allow_methods="*",
                )
            },
        )
        for route in app.router.routes():
            cors.add(route)

        return app
    except Exception:
        print("Error when starting to run server!!")
Beispiel #9
0
async def main(start_port: int, show_timing: bool = False):
    global agent
    genesis = await default_genesis_txns()
    agent = None
    if not genesis:
        print("Error retrieving ledger genesis transactions")
        sys.exit(1)
    try:
        agent = CredentialIssuerAgent(
            start_port, start_port + 1, genesis_data=genesis, timing=show_timing
        )
        await agent.listen_webhooks(start_port + 2)
        await agent.register_did()
        with log_timer("Startup duration:"):
            await agent.start_process()
        log_msg("Admin url is at:", agent.admin_url)
        log_msg("Endpoint url is at:", agent.endpoint)

        async with aiofile.AIOFile("issuer_logger.csv", 'w') as afp:
            writer = aiofile.Writer(afp)
            await writer("")
            await afp.fsync()

        app = web.Application()
        app.add_routes([
            web.get('/create_invitation', handle_create_invitation),
            web.post('/create_schema_cred_def', handle_create_schema_credential_definition),
            web.post('/send_credential_offer', handle_send_credential_offer),
            web.get('/issue_credential', handle_issue_credential),
            web.get('/get_connection_list', handle_get_connection_list),
            web.get('/get_cred_def_list', handle_get_cred_def_list),
            web.get('/readCommentsFromLogger', readCommentsFromLogger),
        ])

        cors = aiohttp_cors.setup(
            app,
            defaults={
                "*": aiohttp_cors.ResourceOptions(
                    allow_credentials=True,
                    expose_headers="*",
                    allow_headers="*",
                    allow_methods="*",
                )
            },
        )
        for route in app.router.routes():
            cors.add(route)

        return app
    except Exception:
        print("Error when starting to run server!!")
Beispiel #10
0
async def input_invitation(agent):
    agent._connection_ready = asyncio.Future()
    async for details in prompt_loop("Invite details: "):
        b64_invite = None
        try:
            url = urlparse(details)
            query = url.query
            if query and "c_i=" in query:
                pos = query.index("c_i=") + 4
                b64_invite = query[pos:]
            elif query and "oob=" in query:
                pos = query.index("oob=") + 4
                b64_invite = query[pos:]
            else:
                b64_invite = details
        except ValueError:
            b64_invite = details

        if b64_invite:
            try:
                padlen = 4 - len(b64_invite) % 4
                if padlen <= 2:
                    b64_invite += "=" * padlen
                invite_json = base64.urlsafe_b64decode(b64_invite)
                details = invite_json.decode("utf-8")
            except binascii.Error:
                pass
            except UnicodeDecodeError:
                pass

        if details:
            try:
                details = json.loads(details)
                break
            except json.JSONDecodeError as e:
                log_msg("Invalid invitation:", str(e))

    with log_timer("Connect duration:"):
        if "/out-of-band/" in details.get("@type", ""):
            connection = await agent.admin_POST(
                "/out-of-band/receive-invitation", details
            )
        else:
            connection = await agent.admin_POST(
                "/connections/receive-invitation", details
            )
        agent.connection_id = connection["connection_id"]
        log_json(connection, label="Invitation response:")

        await agent.detect_connection()
async def main(start_port: int,
               show_timing: bool = False,
               container_name: str = "Simple_client"):
    global temp_message
    global temp_data
    global agent
    genesis = await default_genesis_txns()
    if not genesis:
        print("Error retrieving ledger genesis transactions")
        sys.exit(1)
    try:
        log_status(
            "#7 Provision an agent and wallet, get back configuration details")
        label = container_name
        agent = ClientAgent(label,
                            start_port,
                            start_port + 1,
                            genesis_data=genesis,
                            timing=show_timing)
        await agent.listen_webhooks(start_port + 2)

        with log_timer("Startup duration:"):
            await agent.start_process()
        log_msg("Admin url is at:", agent.admin_url)
        log_msg("Endpoint url is at:", agent.endpoint)
        app = web.Application()

        app.add_routes([
            web.post('/input_invitation', handle_input_invitation),
        ])

        cors = aiohttp_cors.setup(
            app,
            defaults={
                "*":
                aiohttp_cors.ResourceOptions(
                    allow_credentials=True,
                    expose_headers="*",
                    allow_headers="*",
                    allow_methods="*",
                )
            },
        )
        for route in app.router.routes():
            cors.add(route)

        return app
    except Exception:
        print("Error when starting to run server!!")
Beispiel #12
0
async def handle_get_signing_did(request):
    log_status("Function for creating and getting common did has been called")
    global signing_did
    global signing_vk
    global agent

    if signing_did==None:
        result = await agent.admin_POST("/connections/create-signing-did")
        log_status("Signing did and verification key created")
        log_msg("Singing did : "+str(result['signing_did']))
        log_msg("Singing verkey : "+str(result['signing_vk']))
        signing_did=result['signing_did']
        signing_vk=result['signing_vk']

    return web.json_response({"signing_did" : signing_did})
async def input_invitation(agent):
    async for details in prompt_loop("Invite details: "):
        if details:
            try:
                json.loads(details)
                break
            except json.JSONDecodeError as e:
                log_msg("Invalid JSON:", str(e))
                pass

    with log_timer("Connect duration:"):
        connection = await agent.admin_POST("/connections/receive-invitation", details)
        agent.connection_id = connection["connection_id"]
        log_json(connection, label="Invitation response:")

        await agent.detect_connection()
Beispiel #14
0
    async def handle_basicmessages(self, message):
        self.log(message)
        # self.log("Received message:", message["content"])

        if message["connection_id"] in self.trusted_researcher_connection_ids:
            self.log("Research is trusted", message["connection_id"])
            cwd = os.getcwd()
            self.log("Open file")
            try:
                f = open(cwd + "/model/untrained_model.pt", "wb+")
                # self.log(bytes.fromhex(message["content"]))
                byte_message = bytes.fromhex(message["content"])
                f.write(byte_message)
                f.close()

            except Exception as e:
                self.log("Error writing file", e)
                return

            self.log("Import file")
            self.log("learning")

            learnt = await hospital_learn()
            self.log("Learnt : ", learnt)

            trained_model = None
            try:
                trained_file = open(cwd + "/model/trained_model.pt", "rb")
                self.log("Trained file open")
                trained_model = trained_file.read()
                trained_file.close()
            except:
                self.log("Unable to open trained model")

            connection_id = message["connection_id"]

            log_msg("Connection ID", message["connection_id"])
            if trained_model:
                await self.admin_POST(
                    f"/connections/{connection_id}/send-message",
                    {"content": trained_model.hex()})
        else:
            self.log(
                "Untrusted Researcher - Must first authenticate as being certified by Regulator"
            )
    async def terminate(self):
        """Shut down any running agents."""

        terminated = True
        try:
            if self.mediator_agent:
                log_msg("Shutting down mediator agent ...")
                await self.mediator_agent.terminate()
            if self.agent:
                log_msg("Shutting down agent ...")
                await self.agent.terminate()
        except Exception:
            LOGGER.exception("Error terminating agent:")
            terminated = False

        await asyncio.sleep(3.0)

        return terminated
async def generate_new_connection(agent):
    # handle new invitation
    with log_timer("Generate invitation duration:"):
        # Generate an invitation
        log_status(
            "#5 Create a connection to alice and print out the invite details"
        )
        connection = await agent.admin_POST("/connections/create-invitation")

    agent.active_connection_id = connection["connection_id"]
    agent.connection_list.append(connection["connection_id"])
    log_msg("all connections :", agent.connection_list)
    log_json(connection, label="Invitation response:")
    log_msg("*****************")
    log_msg(json.dumps(connection["invitation"]), label="Invitation:", color=None)
    log_msg("*****************")

    log_msg("Waiting for connection...")
    await agent.detect_connection()
    async def generate_invitation(
        self,
        use_did_exchange: bool,
        auto_accept: bool = True,
        display_qr: bool = False,
        wait: bool = False,
    ):
        self._connection_ready = asyncio.Future()
        with log_timer("Generate invitation duration:"):
            # Generate an invitation
            log_status(
                "#7 Create a connection to alice and print out the invite details"
            )
            invi_rec = await self.get_invite(use_did_exchange, auto_accept)

        if display_qr:
            qr = QRCode(border=1)
            qr.add_data(invi_rec["invitation_url"])
            log_msg(
                "Use the following JSON to accept the invite from another demo agent."
                " Or use the QR code to connect from a mobile agent.")
            log_msg(json.dumps(invi_rec["invitation"]),
                    label="Invitation Data:",
                    color=None)
            qr.print_ascii(invert=True)

        if wait:
            log_msg("Waiting for connection...")
            await self.detect_connection()

        return invi_rec
async def main(start_port: int, show_timing: bool = False):

    genesis = await default_genesis_txns()
    if not genesis:
        print("Error retrieving ledger genesis transactions")
        sys.exit(1)

    agent = None

    try:
        log_status("#7 Provision an agent and wallet, get back configuration details")
        agent = AliceAgent(
            start_port, start_port + 1, genesis_data=genesis, timing=show_timing
        )
        await agent.listen_webhooks(start_port + 2)

        with log_timer("Startup duration:"):
            await agent.start_process()
        log_msg("Admin url is at:", agent.admin_url)
        log_msg("Endpoint url is at:", agent.endpoint)

        log_status("#9 Input faber.py invitation details")
        await input_invitation(agent)

        async for option in prompt_loop(
            "(3) Send Message (4) Input New Invitation (X) Exit? [3/4/X]: "
        ):
            if option is None or option in "xX":
                break
            elif option == "3":
                msg = await prompt("Enter message: ")
                if msg:
                    await agent.admin_POST(
                        f"/connections/{agent.connection_id}/send-message",
                        {"content": msg},
                    )
            elif option == "4":
                # handle new invitation
                log_status("Input new invitation details")
                await input_invitation(agent)

        if show_timing:
            timing = await agent.fetch_timing()
            if timing:
                for line in agent.format_timing(timing):
                    log_msg(line)

    finally:
        terminated = True
        try:
            if agent:
                await agent.terminate()
        except Exception:
            LOGGER.exception("Error terminating agent:")
            terminated = False

    await asyncio.sleep(0.1)

    if not terminated:
        os._exit(1)
async def generate_invitation(agent, use_did_exchange: bool):
    agent._connection_ready = asyncio.Future()
    with log_timer("Generate invitation duration:"):
        # Generate an invitation
        log_status(
            "#7 Create a connection to alice and print out the invite details")
        if use_did_exchange:
            invi_rec = await agent.admin_POST(
                "/out-of-band/create-invitation",
                {"include_handshake": True},
            )
        else:
            invi_rec = await agent.admin_POST("/connections/create-invitation")

    qr = QRCode(border=1)
    qr.add_data(invi_rec["invitation_url"])
    log_msg(
        "Use the following JSON to accept the invite from another demo agent."
        " Or use the QR code to connect from a mobile agent.")
    log_msg(json.dumps(invi_rec["invitation"]),
            label="Invitation Data:",
            color=None)
    qr.print_ascii(invert=True)

    log_msg("Waiting for connection...")
    await agent.detect_connection()
Beispiel #20
0
async def handle_verify_signature(request):
    global agent

    data = await request.json()
    resp = {}

    #Check if any attribute not there.
    for element in ['message', 'their_did', 'signature']:
        if element not in data:
            return web.json_response({"status": "Attribute missing"})
    #Check if any attribute has not value.
    if (data['message'] == None or data['message'] == '') or (
            data['their_did'] == None or data['their_did']
            == '') or (data['signature'] == None or data['signature'] == ''):
        return web.json_response({"status": "Enter valid details"})

    message = data['message']
    their_did = data['their_did']
    signature = data['signature']

    log_msg("message : " + message)
    log_msg("their_did : " + their_did)
    log_msg("signature : " + signature)
    try:
        temp = signature.encode('iso-8859-15')
        temp1 = base64.b64decode(temp)
        signature = temp1.decode('utf-8')
    except:
        return web.json_response({"status": "Invalid signature"})

    while True:
        verify = await agent.admin_POST("/connections/verify-transaction", {
            "message": message,
            "their_did": their_did,
            "signature": signature
        })
        if verify['status'] != 'operation not complete':
            break
        else:
            log_status("Still waiting for pool to be closed!!")

    if verify['status'] == 'True':
        await writeCommentToLogger("Signature verified")

        res = await agent.admin_GET(f"/connections",
                                    params={"their_did": their_did})
        if res != []:
            resp['status'] = "Signature verified"
            resp['connection_id'] = res[0]['connection_id']
        else:
            resp[
                'status'] = "Signature verified but not connected to the client agent"
    else:
        await writeCommentToLogger("Incorrect Signature")

        resp['status'] = "not verified"

    log_status("The status : " + verify['status'])

    return web.json_response(resp)
Beispiel #21
0
async def handle_issue_credential(request):
    global agent
    global issue_message
    global temp_conn_id

    CRED_PREVIEW_TYPE = (
        "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/issue-credential/1.0/credential-preview"
    )
    state = issue_message["state"]
    credential_exchange_id = issue_message["credential_exchange_id"]
    prev_state = agent.cred_state.get(credential_exchange_id)

    if prev_state == state:
        return  # ignore
    agent.cred_state[credential_exchange_id] = state

    if state == "request_received":
        cred_attrs = agent.cred_attrs[
            issue_message["credential_definition_id"]]
        cred_preview = {
            "@type":
            CRED_PREVIEW_TYPE,
            "attributes": [{
                "name": n,
                "value": v
            } for (n, v) in cred_attrs.items()],
        }
        res = await agent.admin_POST(
            f"/issue-credential/records/{credential_exchange_id}/issue",
            {
                "comment":
                f"Issuing credential, exchange {credential_exchange_id}",
                "credential_preview": cred_preview,
            },
        )
        log_status("Credential has been issued!!")
        log_msg(res['credential'])

        return web.json_response({"status": True})
Beispiel #22
0
async def input_invitation(agent_container):
    agent_container.agent._connection_ready = asyncio.Future()
    async for details in prompt_loop("Invite details: "):
        b64_invite = None
        try:
            url = urlparse(details)
            query = url.query
            if query and "c_i=" in query:
                pos = query.index("c_i=") + 4
                b64_invite = query[pos:]
            elif query and "oob=" in query:
                pos = query.index("oob=") + 4
                b64_invite = query[pos:]
            else:
                b64_invite = details
        except ValueError:
            b64_invite = details

        if b64_invite:
            try:
                padlen = 4 - len(b64_invite) % 4
                if padlen <= 2:
                    b64_invite += "=" * padlen
                invite_json = base64.urlsafe_b64decode(b64_invite)
                details = invite_json.decode("utf-8")
            except binascii.Error:
                pass
            except UnicodeDecodeError:
                pass

        if details:
            try:
                details = json.loads(details)
                break
            except json.JSONDecodeError as e:
                log_msg("Invalid invitation:", str(e))

    with log_timer("Connect duration:"):
        connection = await agent_container.input_invitation(details, wait=True)
Beispiel #23
0
async def handle_create_schema_credential_definition(request):
    global agent
    global credDefIdList
    data                = await request.json()
    # Check if data is empty or has the values
    if "schema_name" not in data:
        return web.json_response({"status" : "Schema name needed"})
    if "attributes" not in data:
        return web.json_response({"status" : "Attributes needed"})
    # Schema name and attributes input validation
    if data['schema_name']=='' or data['schema_name']==None:
        return web.json_response({"status" : "Enter a valid schema name"})
    if data['attributes']=='' or data['attributes']==None:
        return web.json_response({"status" : "Enter valid attibutes"})

    schema_name         = data['schema_name']
    attr_list           = [element.strip(' ') for element in data['attributes'].split(",")]

    version = format(
        "%d.%d.%d"
        % (
            random.randint(1, 101),
            random.randint(1, 101),
            random.randint(1, 101),
        )
    )
    
    (schema_id, credential_definition_id) = await agent.register_schema_and_creddef(
        schema_name, version, attr_list
    )

    log_msg("schema has been created !!")
    log_msg("Schema and Credential definition has been created !!")
    log_msg("Schema id : ", schema_id)
    log_msg("Credential definition id : ", credential_definition_id)

    credDefIdList.append({
        "schema_name" : schema_name,
        "credential_definition_id" : credential_definition_id,
        "attr_list" : attr_list,
    })

    await writeCommentToLogger("Schema and credential definition created")

    return web.json_response({
        "schema_id"                : schema_id,
        "credential_definition_id" : credential_definition_id
    })
async def input_invitation(agent):
    async for details in prompt_loop("Invite details: "):
        b64_invite = None
        try:
            url = urlparse(details)
            query = url.query
            if query and "c_i=" in query:
                pos = query.index("c_i=") + 4
                b64_invite = query[pos:]
            else:
                b64_invite = details
        except ValueError:
            b64_invite = details

        if b64_invite:
            try:
                invite_json = base64.urlsafe_b64decode(b64_invite)
                details = invite_json.decode("utf-8")
            except binascii.Error:
                pass
            except UnicodeDecodeError:
                pass

        if details:
            try:
                json.loads(details)
                break
            except json.JSONDecodeError as e:
                log_msg("Invalid invitation:", str(e))

    with log_timer("Connect duration:"):
        connection = await agent.admin_POST("/connections/receive-invitation",
                                            details)
        agent.connection_id = connection["connection_id"]
        log_json(connection, label="Invitation response:")

        await agent.detect_connection()
    async def connect():
        # Generate an invitation
        log_status(
            "#5 Create a connection to alice and print out the invite details")
        connection = await agent.admin_POST("/connections/create-invitation")

        agent.active_connection_id = connection["connection_id"]
        agent.connection_list.append(connection["connection_id"])
        log_msg("all connections :", agent.connection_list)
        log_json(connection, label="Invitation response:")
        log_msg("*****************")
        log_msg(json.dumps(connection["invitation"]),
                label="Invitation:",
                color=None)
        log_msg("*****************")
        agent._connection_ready = asyncio.Future()

        return json.dumps(connection["invitation"])
async def handle_create_invitation(request):
    with log_timer("Generate invitation duration:"):
        log_status(
            "#5 Create a connection to alice and print out the invite details"
        )
        connection = await agent.admin_POST("/connections/create-invitation")

    agent.connection_id = connection["connection_id"]
    log_json(connection, label="Invitation response:")
    log_msg("*****************")
    log_msg(json.dumps(connection["invitation"]), label="Invitation:", color=None)
    log_msg("*****************")

    return web.json_response(connection["invitation"])
Beispiel #27
0
async def handle_create_invitation(request):
    global agent
    log_status("Create invitation has been called !!")
    connection = await agent.admin_POST("/connections/create-invitation")
    agent.connection_id = connection["connection_id"]
    agent._connection_ready = asyncio.Future()
    log_json(connection, label="Invitation response:")
    log_msg("*****************")
    log_msg(json.dumps(connection["invitation"]),
            label="Invitation:",
            color=None)
    log_msg("*****************")

    await writeCommentToLogger("Invitation created")

    return web.json_response(connection["invitation"])
async def main(start_port: int, show_timing: bool = False):

    genesis = await default_genesis_txns()
    if not genesis:
        print("Error retrieving ledger genesis transactions")
        sys.exit(1)

    agent = None

    try:
        log_status(
            "#1 Provision an agent and wallet, get back configuration details")
        agent = RegulatorAgent(start_port,
                               start_port + 1,
                               genesis_data=genesis,
                               timing=show_timing)
        await agent.listen_webhooks(start_port + 2)
        await agent.register_did()

        with log_timer("Startup duration:"):
            await agent.start_process()
        log_msg("Admin url is at:", agent.admin_url)
        log_msg("Endpoint url is at:", agent.endpoint)

        # Create a schema
        with log_timer("Publish schema/cred def duration:"):
            log_status("#3/4 Create a new schema/cred def on the ledger")
            version = format("%d.%d.%d" % (
                random.randint(1, 101),
                random.randint(1, 101),
                random.randint(1, 101),
            ))
            (
                _,  # schema id
                credential_definition_id,
            ) = await agent.register_schema_and_creddef(
                "Certified Researcher schema", version,
                ["institution", "date"])

        # TODO add an additional credential for Student ID

        with log_timer("Generate invitation duration:"):
            # Generate an invitation
            log_status(
                "#5 Create a connection to Hospital and print out the invite details"
            )
            connection = await agent.admin_POST(
                "/connections/create-invitation")

        agent.active_connection_id = connection["connection_id"]
        agent.connection_list.append(connection["connection_id"])
        log_json(connection, label="Invitation response:")
        log_msg("*****************")
        log_msg(json.dumps(connection["invitation"]),
                label="Invitation:",
                color=None)
        log_msg("*****************")

        log_msg("Waiting for connection...")
        await agent.detect_connection()

        async for option in prompt_loop(
                "(1) Issue Credential, (2) Create a New Invitation, (X) Exit? [1/2/X] "
        ):
            if option is None or option in "xX":
                break

            elif option == "1":
                log_status("#13 Issue credential offer to X")

                today = date.today()
                # TODO define attributes to send for credential
                agent.cred_attrs[credential_definition_id] = {
                    # "name": str(credential_definition_id),
                    "date": str(today),
                    "institution": "Edinburgh Napier University",
                    # "age": "24",
                }

                cred_preview = {
                    "@type":
                    CRED_PREVIEW_TYPE,
                    "attributes":
                    [{
                        "name": n,
                        "value": v
                    } for (n, v) in
                     agent.cred_attrs[credential_definition_id].items()],
                }
                offer_request = {
                    "connection_id": agent.active_connection_id,
                    "credential_definition_id": credential_definition_id,
                    "comment":
                    f"Offer on cred def id {credential_definition_id}",
                    "credential_preview": cred_preview,
                }
                await agent.admin_POST("/issue-credential/send-offer",
                                       offer_request)
            elif option == "2":
                # handle new invitation
                with log_timer("Generate invitation duration:"):
                    # Generate an invitation
                    log_status(
                        "#5 Create a connection to alice and print out the invite details"
                    )
                    connection = await agent.admin_POST(
                        "/connections/create-invitation")
                agent.active_connection_id = connection["connection_id"]
                agent.connection_list.append(connection["connection_id"])
                log_msg("all connections :", agent.connection_list)
                log_json(connection, label="Invitation response:")
                log_msg("*****************")
                log_msg(json.dumps(connection["invitation"]),
                        label="Invitation:",
                        color=None)
                log_msg("*****************")
                agent._connection_ready = asyncio.Future()
                log_msg("Waiting for connection...")
                await agent.detect_connection()

        if show_timing:
            timing = await agent.fetch_timing()
            if timing:
                for line in agent.format_timing(timing):
                    log_msg(line)

    finally:
        terminated = True
        try:
            if agent:
                await agent.terminate()
        except Exception:
            LOGGER.exception("Error terminating agent:")
            terminated = False

    await asyncio.sleep(0.1)

    if not terminated:
        os._exit(1)
async def test_main(
    start_port: int,
    no_auto: bool = False,
    revocation: bool = False,
    tails_server_base_url: str = None,
    show_timing: bool = False,
    multitenant: bool = False,
    mediation: bool = False,
    use_did_exchange: bool = False,
    wallet_type: str = None,
):
    """Test to startup a couple of agents."""

    faber_container = None
    alice_container = None
    try:
        # initialize the containers
        faber_container = AgentContainer(
            genesis,
            "Faber.agent",
            start_port,
            no_auto=no_auto,
            revocation=revocation,
            tails_server_base_url=tails_server_base_url,
            show_timing=show_timing,
            multitenant=multitenant,
            mediation=mediation,
            use_did_exchange=use_did_exchange,
            wallet_type=wallet_type,
            public_did=True,
            seed="random",
        )
        alice_container = AgentContainer(
            genesis,
            "Alice.agent",
            start_port + 10,
            no_auto=no_auto,
            revocation=False,
            show_timing=show_timing,
            multitenant=multitenant,
            mediation=mediation,
            use_did_exchange=use_did_exchange,
            wallet_type=wallet_type,
            public_did=False,
            seed=None,
        )

        # start the agents - faber gets a public DID and schema/cred def
        await faber_container.initialize(
            schema_name="degree schema",
            schema_attrs=[
                "name",
                "date",
                "degree",
                "grade",
            ],
        )
        await alice_container.initialize()

        # faber create invitation
        invite = await faber_container.generate_invitation()

        # alice accept invitation
        invite_details = invite["invitation"]
        connection = await alice_container.input_invitation(invite_details)

        # wait for faber connection to activate
        await faber_container.detect_connection()
        await alice_container.detect_connection()

        # TODO faber issue credential to alice
        # TODO alice check for received credential

        log_msg("Sleeping ...")
        await asyncio.sleep(3.0)

    except Exception as e:
        LOGGER.exception("Error initializing agent:", e)
        raise (e)

    finally:
        terminated = True
        try:
            # shut down containers at the end of the test
            if alice_container:
                log_msg("Shutting down alice agent ...")
                await alice_container.terminate()
            if faber_container:
                log_msg("Shutting down faber agent ...")
                await faber_container.terminate()
        except Exception as e:
            LOGGER.exception("Error terminating agent:", e)
            terminated = False

    await asyncio.sleep(0.1)

    if not terminated:
        os._exit(1)

    await asyncio.sleep(2.0)
    os._exit(1)
    async def initialize(
        self,
        the_agent: DemoAgent = None,
        schema_name: str = None,
        schema_attrs: list = None,
    ):
        """Startup agent(s), register DID, schema, cred def as appropriate."""

        if not the_agent:
            log_status(
                "#1 Provision an agent and wallet, get back configuration details"
                + (f" (Wallet type: {self.wallet_type})" if self.
                   wallet_type else ""))
            self.agent = AriesAgent(
                self.ident,
                self.start_port,
                self.start_port + 1,
                genesis_data=self.genesis_txns,
                no_auto=self.no_auto,
                tails_server_base_url=self.tails_server_base_url,
                timing=self.show_timing,
                revocation=self.revocation,
                multitenant=self.multitenant,
                mediation=self.mediation,
                wallet_type=self.wallet_type,
                seed=self.seed,
                arg_file=self.arg_file,
            )
        else:
            self.agent = the_agent

        await self.agent.listen_webhooks(self.start_port + 2)

        if self.public_did:
            await self.agent.register_did()

        with log_timer("Startup duration:"):
            await self.agent.start_process()

        log_msg("Admin URL is at:", self.agent.admin_url)
        log_msg("Endpoint URL is at:", self.agent.endpoint)

        if self.mediation:
            self.mediator_agent = await start_mediator_agent(
                self.start_port + 4, self.genesis_txns)
            if not self.mediator_agent:
                raise Exception("Mediator agent returns None :-(")
        else:
            self.mediator_agent = None

        if self.multitenant:
            # create an initial managed sub-wallet (also mediated)
            rand_name = str(random.randint(100_000, 999_999))
            await self.agent.register_or_switch_wallet(
                self.ident + ".initial." + rand_name,
                public_did=self.public_did,
                webhook_port=None,
                mediator_agent=self.mediator_agent,
            )
        elif self.mediation:
            # we need to pre-connect the agent to its mediator
            if not await connect_wallet_to_mediator(self.agent,
                                                    self.mediator_agent):
                raise Exception("Mediation setup FAILED :-(")

        if schema_name and schema_attrs:
            # Create a schema/cred def
            self.cred_def_id = await self.create_schema_and_cred_def(
                schema_name, schema_attrs)