async def handle(self, context: RequestContext, responder: BaseResponder):
        """Handle get fees."""
        ledger: BaseLedger = await context.inject(BaseLedger)
        if context.message.method != SOV_METHOD:
            report = ProblemReport(
                explain_ltxt=('Method "{}" is not supported.'.format(
                    context.message.method)),
                who_retries='none')
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        try:
            async with ledger:
                xfer_auth = await get_transfer_auth(ledger)
        except (LedgerError, PaymentError) as err:
            report = ProblemReport(explain_ltxt=(err), who_retries='none')
            await responder.send_reply(report)
            return
        except IndyError as err:
            # TODO: Remove when IndyErrorHandler bug is fixed.
            # Likely to be next ACA-Py release.
            message = 'Unexpected IndyError while retrieving transfer fee'
            if hasattr(err, 'message'):
                message += ': {}'.format(err.message)
            report = ProblemReport(explain_ltxt=(message), who_retries='none')
            await responder.send_reply(report)
            return

        fees = Fees(total=sovatoms_to_tokens(xfer_auth['price']))
        fees.assign_thread_from(context.message)
        await responder.send_reply(fees)
    async def handle(self, context: RequestContext, responder: BaseResponder):
        """Handle received get request."""
        ledger: BaseLedger = await context.inject(BaseLedger, required=False)
        if not ledger or ledger.LEDGER_TYPE != 'indy':
            report = ProblemReport(
                explain_ltxt='Invalid ledger.',
                who_retries='none'
            )
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        taa_info = await ledger.get_txn_author_agreement()
        acceptance = await ledger.get_latest_txn_author_acceptance()

        if taa_info['taa_required'] and not acceptance:
            needed = True
        elif acceptance and acceptance['digest'] != taa_info['taa_record']['digest']:
            needed = True
        else:
            needed = False

        result = Taa(
            version=taa_info['taa_record']['version'],
            text=taa_info['taa_record']['text'],
            needed=needed
        )
        result.assign_thread_from(context.message)
        await responder.send_reply(result)
    async def handle(self, context: RequestContext, responder: BaseResponder):
        """Handle delete connection request."""
        if context.message.connection_id == \
                context.connection_record.connection_id:

            report = ProblemReport(
                explain_ltxt='Current connection cannot be deleted.',
                who_retries='none')
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        try:
            connection = await ConnectionRecord.retrieve_by_id(
                context, context.message.connection_id)
        except StorageNotFoundError:
            report = ProblemReport(explain_ltxt='Connection not found.',
                                   who_retries='none')
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        await connection.delete_record(context)
        ack = ConnectionAck()
        ack.assign_thread_from(context.message)
        await responder.send_reply(ack)
Example #4
0
    async def handle(self, context: RequestContext, responder: BaseResponder):
        """Handle received send requests."""
        # pylint: disable=protected-access
        try:
            connection = await ConnectionRecord.retrieve_by_id(
                context, context.message.connection_id)
        except StorageNotFoundError:
            report = ProblemReport(explain_ltxt='Connection not found.',
                                   who_retries='none')
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        msg = BasicMessage(content=context.message.content,
                           localization=LocalizationDecorator(locale='en'))

        await responder.send(msg, connection_id=connection.connection_id)

        record = BasicMessageRecord(
            connection_id=context.message.connection_id,
            message_id=msg._id,
            sent_time=msg.sent_time,
            content=msg.content,
            state=BasicMessageRecord.STATE_SENT)
        await record.save(context, reason='Message sent.')
        sent_msg = Sent(connection_id=connection.connection_id, message=record)
        sent_msg.assign_thread_from(context.message)
        await responder.send_reply(sent_msg)
Example #5
0
    async def handle(self, context: RequestContext, responder: BaseResponder):
        """Handle static connection get list request."""
        connection_mgr = ConnectionManager(context)
        wallet: BaseWallet = await context.inject(BaseWallet)
        try:
            tag_filter = dict(
                filter(lambda item: item[1] is not None, {
                    'initiator': context.message.initiator,
                    'invitation_key': context.message.invitation_key,
                    'my_did': context.message.my_did,
                    'invitation_mode': ConnectionRecord.INVITATION_MODE_STATIC,
                    'their_did': context.message.their_did,
                    'their_role': context.message.their_role
                }.items())
            )
            records = await ConnectionRecord.query(context, tag_filter)
        except StorageNotFoundError:
            report = ProblemReport(
                explain_ltxt='Connection not found.',
                who_retries='none'
            )
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        def flatten_target(connection, target, my_info):
            """Map for flattening results."""
            return {
                'connection_id': connection.connection_id,
                'their_info': {
                    'label': target.label,
                    'did': target.did,
                    'vk': target.recipient_keys[0],
                    'endpoint': target.endpoint
                },
                'my_info': {
                    'did': my_info.did,
                    'vk': my_info.verkey,
                    'endpoint': context.settings.get("default_endpoint")
                }
            }

        targets = []
        my_info = []
        for record in records:
            targets.append(
                await connection_mgr.get_connection_target(record)
            )
            my_info.append(await wallet.get_local_did(record.my_did))

        results = list(map(
            flatten_target,
            records,
            targets,
            my_info
        ))

        static_connections = StaticConnectionList(results=results)
        static_connections.assign_thread_from(context.message)
        await responder.send_reply(static_connections)
    async def handle(self, context: RequestContext, responder: BaseResponder):
        """Handle received address list requests."""
        if context.message.method and context.message.method != SOV_METHOD:
            report = ProblemReport(
                explain_ltxt=('Method "{}" is not supported.'.format(
                    context.message.method)),
                who_retries='none')
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        ledger: BaseLedger = await context.inject(BaseLedger)
        try:
            addresses = json.loads(await payment.list_payment_addresses(
                ledger.wallet.handle))

            async with ledger:
                address_results = []
                for address in addresses:
                    balance = 0
                    sources = []
                    async for source in get_sources(ledger, address):
                        balance += source['amount']
                        sources.append(source)
                    address_results.append({
                        'address':
                        address,
                        'method':
                        SOV_METHOD,
                        'balance':
                        sovatoms_to_tokens(balance),
                        'raw_repr': {
                            'sources': sources
                        }
                    })
        except (LedgerError, PaymentError) as err:
            report = ProblemReport(explain_ltxt=(err), who_retries='none')
            await responder.send_reply(report)
            return
        except IndyError as err:
            # TODO: Remove when IndyErrorHandler bug is fixed.
            # Likely to be next ACA-Py release.
            message = 'Unexpected IndyError while retrieving addresses'
            if hasattr(err, 'message'):
                message += ': {}'.format(err.message)
            report = ProblemReport(explain_ltxt=(message), who_retries='none')
            await responder.send_reply(report)
            return

        result = AddressList(addresses=address_results)
        result.assign_thread_from(context.message)
        await responder.send_reply(result)
Example #7
0
    async def handle(self, context: RequestContext, responder: BaseResponder):
        """Handle received send presentation proposal request."""

        connection_id = str(context.message.connection_id)
        try:
            connection_record = await ConnectionRecord.retrieve_by_id(
                context,
                connection_id
            )
        except StorageNotFoundError:
            report = ProblemReport(
                explain_ltxt='Connection not found.',
                who_retries='none'
            )
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        if not connection_record.is_ready:
            report = ProblemReport(
                explain_ltxt='Connection invalid.',
                who_retries='none'
            )
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        comment = context.message.comment
        # Aries#0037 calls it a proposal in the proposal struct but it's of type preview
        presentation_proposal = PresentationProposal(
            comment=comment,
            presentation_proposal=context.message.presentation_proposal
        )
        auto_present = (
            context.message.auto_present or
            context.settings.get("debug.auto_respond_presentation_request")
        )

        presentation_manager = PresentationManager(context)

        presentation_exchange_record = (
            await presentation_manager.create_exchange_for_proposal(
                connection_id=connection_id,
                presentation_proposal_message=presentation_proposal,
                auto_present=auto_present
            )
        )
        await responder.send(presentation_proposal, connection_id=connection_id)

        pres_exchange = PresExchange(**presentation_exchange_record.serialize())
        pres_exchange.assign_thread_from(context.message)
        await responder.send_reply(pres_exchange)
Example #8
0
        async def _wrapped(handler, context: RequestContext,
                           responder: BaseResponder):

            if not context.connection_record \
                    or context.connection_record.their_role != role:
                report = ProblemReport(
                    explain_ltxt='This connection is not authorized to perform'
                    ' the requested action.',
                    who_retries='none')
                report.assign_thread_from(context.message)
                await responder.send_reply(report)
                return

            return await func(handler, context, responder)
Example #9
0
    async def handle(self, context: RequestContext, responder: BaseResponder):
        """Handle received send proposal request."""
        connection_id = str(context.message.connection_id)
        credential_definition_id = context.message.credential_definition_id
        comment = context.message.comment

        credential_manager = CredentialManager(context)

        try:
            connection_record = await ConnectionRecord.retrieve_by_id(
                context,
                connection_id
            )
        except StorageNotFoundError:
            report = ProblemReport(
                explain_ltxt='Connection not found.',
                who_retries='none'
            )
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        if not connection_record.is_ready:
            report = ProblemReport(
                explain_ltxt='Connection invalid.',
                who_retries='none'
            )
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        credential_exchange_record = await credential_manager.create_proposal(
            connection_id,
            comment=comment,
            credential_preview=context.message.credential_proposal,
            credential_definition_id=credential_definition_id
        )

        await responder.send(
            CredentialProposal(
                comment=context.message.comment,
                credential_proposal=context.message.credential_proposal,
                cred_def_id=context.message.credential_definition_id
            ),
            connection_id=connection_id
        )
        cred_exchange = CredExchange(**credential_exchange_record.serialize())
        cred_exchange.assign_thread_from(context.message)
        await responder.send_reply(cred_exchange)
Example #10
0
    async def handle(self, context: RequestContext, responder: BaseResponder):
        """Handle received presentation request request."""

        connection_id = str(context.message.connection_id)
        try:
            connection_record = await ConnectionRecord.retrieve_by_id(
                context, connection_id)
        except StorageNotFoundError:
            report = ProblemReport(explain_ltxt='Connection not found.',
                                   who_retries='none')
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        if not connection_record.is_ready:
            report = ProblemReport(explain_ltxt='Connection invalid.',
                                   who_retries='none')
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        comment = context.message.comment

        indy_proof_request = context.message.proof_request
        if not indy_proof_request.get('nonce'):
            indy_proof_request['nonce'] = str(uuid4().int)

        presentation_request_message = PresentationRequest(
            comment=comment,
            request_presentations_attach=[
                AttachDecorator.from_indy_dict(indy_proof_request)
            ])

        presentation_manager = PresentationManager(context)

        presentation_exchange_record = (
            await presentation_manager.create_exchange_for_request(
                connection_id=connection_id,
                presentation_request_message=presentation_request_message))

        await responder.send(presentation_request_message,
                             connection_id=connection_id)

        pres_exchange = IssuerPresExchange(
            **presentation_exchange_record.serialize())
        pres_exchange.assign_thread_from(context.message)
        await responder.send_reply(pres_exchange)
Example #11
0
    async def handle(self, context: RequestContext, responder: BaseResponder):
        """Handle received send request."""
        comment = context.message.comment
        connection_id = str(context.message.connection_id)
        preview_spec = context.message.credential_proposal

        try:
            connection_record = await ConnectionRecord.retrieve_by_id(
                context, connection_id)
        except StorageNotFoundError:
            report = ProblemReport(explain_ltxt='Connection not found.',
                                   who_retries='none')
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        if not connection_record.is_ready:
            report = ProblemReport(explain_ltxt='Connection invalid.',
                                   who_retries='none')
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        credential_proposal = CredentialProposal(
            comment=comment,
            credential_proposal=preview_spec,
            **{
                t: getattr(context.message, t)
                for t in CRED_DEF_TAGS if hasattr(context.message, t)
            },
        )

        credential_manager = CredentialManager(context)


        cred_exchange_record, cred_offer_message = \
            await credential_manager.prepare_send(
                connection_id,
                credential_proposal=credential_proposal
            )

        await responder.send(cred_offer_message,
                             connection_id=cred_exchange_record.connection_id)
        cred_exchange = IssuerCredExchange(**cred_exchange_record.serialize())
        cred_exchange.assign_thread_from(context.message)
        await responder.send_reply(cred_exchange)
    async def handle(self, context: RequestContext, responder: BaseResponder):
        """Handle payment"""
        ledger: BaseLedger = await context.inject(BaseLedger)
        if context.message.method != SOV_METHOD:
            report = ProblemReport(
                explain_ltxt=('Method "{}" is not supported.'.format(
                    context.message.method)),
                who_retries='none')
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        async with ledger:
            try:
                fee = (await get_transfer_auth(ledger))['price']
                inputs, outputs = await prepare_payment(
                    ledger, context.message.from_address,
                    context.message.to_address,
                    tokens_to_sovatoms(context.message.amount), fee)
                receipts = await make_payment(ledger, inputs, outputs)
            except (LedgerError, PaymentError) as err:
                report = ProblemReport(explain_ltxt=(err), who_retries='none')
                await responder.send_reply(report)
                return
            except IndyError as err:
                # TODO: Remove when IndyErrorHandler bug is fixed.
                # Likely to be next ACA-Py release.
                message = 'Unexpected IndyError while making payment'
                if hasattr(err, 'message'):
                    message += ': {}'.format(err.message)
                report = ProblemReport(explain_ltxt=(message),
                                       who_retries='none')
                await responder.send_reply(report)
                return

        completed = TransferComplete(from_address=context.message.from_address,
                                     to_address=context.message.to_address,
                                     amount=context.message.amount,
                                     fees=sovatoms_to_tokens(fee),
                                     method=SOV_METHOD,
                                     raw_repr=receipts)
        completed.assign_thread_from(context.message)
        await responder.send_reply(completed)
    async def handle(self, context: RequestContext, responder: BaseResponder):
        """Handle update connection request."""
        try:
            connection = await ConnectionRecord.retrieve_by_id(
                context, context.message.connection_id)
        except StorageNotFoundError:
            report = ProblemReport(explain_ltxt='Connection not found.',
                                   who_retries='none')
            report.assign_thread_from(context.message)
            await responder.send_reply(report)

        new_label = context.message.label or connection.their_label
        connection.their_label = new_label
        new_role = context.message.role or connection.their_role
        connection.their_role = new_role
        await connection.save(context, reason="Update request received.")
        conn_response = Connection(connection=connection)
        conn_response.assign_thread_from(context.message)
        await responder.send_reply(conn_response)
    async def handle(self, context: RequestContext, responder: BaseResponder):
        """Handle taa acceptance messages."""
        ledger: BaseLedger = await context.inject(BaseLedger, required=False)
        if not ledger or ledger.LEDGER_TYPE != 'indy':
            report = ProblemReport(
                explain_ltxt='Invalid ledger.',
                who_retries='none'
            )
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        taa_record = {
            'version': context.message.version,
            'text': context.message.text,
            'digest': ledger.taa_digest(
                context.message.version, context.message.text
            )
        }
        try:
            await ledger.accept_txn_author_agreement(
                taa_record,
                context.message.mechanism
            )
        except Exception as err:
            report = ProblemReport(
                explain_ltxt='An error occured while attempting to accept'
                ' the Transaction Author Agreement: {}'.format(
                    err
                ),
                who_retries='none'
            )
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        result = Accepted()
        result.assign_thread_from(context.message)
        await responder.send_reply(result)
    async def handle(self, context: RequestContext, responder: BaseResponder):
        """Handle received create address requests."""
        wallet: BaseWallet = await context.inject(BaseWallet)
        ledger: BaseLedger = await context.inject(BaseLedger)
        if context.message.method != SOV_METHOD:
            report = ProblemReport(
                explain_ltxt=('Method "{}" is not supported.'.format(
                    context.message.method)),
                who_retries='none')
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        if context.message.seed and len(context.message.seed) < 32:
            report = ProblemReport(
                explain_ltxt=('Seed must be 32 characters in length'),
                who_retries='none')
            report.assign_thread_from(context.message)
            await responder.send_reply(report)
            return

        try:
            address_str = await payment.create_payment_address(
                wallet.handle, SOV_METHOD,
                json.dumps({'seed': context.message.seed}))
        except IndyError as err:
            message = 'Failed to create payment address'
            if hasattr(err, 'message'):
                message += ': {}'.format(err.message)
            report = ProblemReport(explain_ltxt=(message), who_retries='none')
            await responder.send_reply(report)
            return

        try:
            async with ledger:
                balance = 0
                sources = []
                async for source in get_sources(ledger, address_str):
                    balance += source['amount']
                    sources.append(source)
        except (LedgerError, PaymentError) as err:
            report = ProblemReport(explain_ltxt=(err), who_retries='none')
            await responder.send_reply(report)
            return
        except IndyError as err:
            # TODO: Remove when IndyErrorHandler bug is fixed.
            # Likely to be next ACA-Py release.
            message = 'Unexpected IndyError while retrieving address balances'
            if hasattr(err, 'message'):
                message += ': {}'.format(err.message)
            report = ProblemReport(explain_ltxt=(message), who_retries='none')
            await responder.send_reply(report)
            return

        address = Address(
            address=address_str,
            method=SOV_METHOD,
            balance=sovatoms_to_tokens(balance),
        )
        address.assign_thread_from(context.message)
        await responder.send_reply(address)
        return