def _handle_accept(self, msg: FIPAMessage, dialogue: Dialogue) -> None: """ Handle the ACCEPT. Respond with a MATCH_ACCEPT_W_INFORM which contains the address to send the funds to. :param msg: the message :param dialogue: the dialogue object :return: None """ new_message_id = msg.message_id + 1 new_target = msg.message_id self.context.logger.info("[{}]: received ACCEPT from sender={}".format( self.context.agent_name, msg.counterparty[-5:])) self.context.logger.info( "[{}]: sending MATCH_ACCEPT_W_INFORM to sender={}".format( self.context.agent_name, msg.counterparty[-5:])) proposal = cast(Description, dialogue.proposal) identifier = cast(str, proposal.values.get("ledger_id")) match_accept_msg = FIPAMessage( message_id=new_message_id, dialogue_reference=dialogue.dialogue_label.dialogue_reference, target=new_target, performative=FIPAMessage.Performative.MATCH_ACCEPT_W_INFORM, info={"address": self.context.agent_addresses[identifier]}, ) dialogue.outgoing_extend(match_accept_msg) self.context.outbox.put_message( to=msg.counterparty, sender=self.context.agent_address, protocol_id=FIPAMessage.protocol_id, message=FIPASerializer().encode(match_accept_msg), )
def _handle_cfp(self, msg: FipaMessage, dialogue: Dialogue) -> None: """ Handle the CFP. If the CFP matches the supplied services then send a PROPOSE, otherwise send a DECLINE. :param msg: the message :param dialogue: the dialogue object :return: None """ new_message_id = msg.message_id + 1 new_target = msg.message_id self.context.logger.info("[{}]: received CFP from sender={}".format( self.context.agent_name, msg.counterparty[-5:])) query = cast(Query, msg.query) strategy = cast(Strategy, self.context.strategy) if strategy.is_matching_supply(query): proposal, data_for_sale = strategy.generate_proposal_and_data( query, msg.counterparty) dialogue.data_for_sale = data_for_sale dialogue.proposal = proposal self.context.logger.info( "[{}]: sending a PROPOSE with proposal={} to sender={}".format( self.context.agent_name, proposal.values, msg.counterparty[-5:])) proposal_msg = FipaMessage( message_id=new_message_id, dialogue_reference=dialogue.dialogue_label.dialogue_reference, target=new_target, performative=FipaMessage.Performative.PROPOSE, proposal=proposal, ) proposal_msg.counterparty = msg.counterparty dialogue.update(proposal_msg) self.context.outbox.put_message( to=msg.counterparty, sender=self.context.agent_address, protocol_id=FipaMessage.protocol_id, message=FipaSerializer().encode(proposal_msg), ) else: self.context.logger.info( "[{}]: declined the CFP from sender={}".format( self.context.agent_name, msg.counterparty[-5:])) decline_msg = FipaMessage( message_id=new_message_id, dialogue_reference=dialogue.dialogue_label.dialogue_reference, target=new_target, performative=FipaMessage.Performative.DECLINE, ) decline_msg.counterparty = msg.counterparty dialogue.update(decline_msg) self.context.outbox.put_message( to=msg.counterparty, sender=self.context.agent_address, protocol_id=FipaMessage.protocol_id, message=FipaSerializer().encode(decline_msg), )
def _handle_inform(self, msg: FIPAMessage, dialogue: Dialogue) -> None: """ Handle the INFORM. If the INFORM message contains the transaction_digest then verify that it is settled, otherwise do nothing. If the transaction is settled, send the data, otherwise do nothing. :param msg: the message :param dialogue: the dialogue object :return: None """ new_message_id = msg.message_id + 1 new_target = msg.message_id self.context.logger.info("[{}]: received INFORM from sender={}".format( self.context.agent_name, msg.counterparty[-5:])) strategy = cast(Strategy, self.context.strategy) if strategy.is_ledger_tx and ("transaction_digest" in msg.info.keys()): tx_digest = msg.info["transaction_digest"] self.context.logger.info( "[{}]: checking whether transaction={} has been received ...". format(self.context.agent_name, tx_digest)) proposal = cast(Description, dialogue.proposal) ledger_id = cast(str, proposal.values.get("ledger_id")) is_valid = self.context.ledger_apis.is_tx_valid( ledger_id, tx_digest, self.context.agent_addresses[ledger_id], msg.counterparty, cast(str, proposal.values.get("tx_nonce")), cast(int, proposal.values.get("price")), ) # TODO: check the tx_digest references a transaction with the correct terms if is_valid: token_balance = self.context.ledger_apis.token_balance( ledger_id, cast(str, self.context.agent_addresses.get(ledger_id))) self.context.logger.info( "[{}]: transaction={} settled, new balance={}. Sending data to sender={}" .format( self.context.agent_name, tx_digest, token_balance, msg.counterparty[-5:], )) inform_msg = FIPAMessage( message_id=new_message_id, dialogue_reference=dialogue.dialogue_label. dialogue_reference, target=new_target, performative=FIPAMessage.Performative.INFORM, info=dialogue.data_for_sale, ) dialogue.outgoing_extend(inform_msg) self.context.outbox.put_message( to=msg.counterparty, sender=self.context.agent_address, protocol_id=FIPAMessage.protocol_id, message=FIPASerializer().encode(inform_msg), ) dialogues = cast(Dialogues, self.context.dialogues) dialogues.dialogue_stats.add_dialogue_endstate( Dialogue.EndState.SUCCESSFUL, dialogue.is_self_initiated) else: self.context.logger.info( "[{}]: transaction={} not settled, aborting".format( self.context.agent_name, tx_digest)) elif "Done" in msg.info.keys(): inform_msg = FIPAMessage( message_id=new_message_id, dialogue_reference=dialogue.dialogue_label.dialogue_reference, target=new_target, performative=FIPAMessage.Performative.INFORM, info=dialogue.data_for_sale, ) dialogue.outgoing_extend(inform_msg) self.context.outbox.put_message( to=msg.counterparty, sender=self.context.agent_address, protocol_id=FIPAMessage.protocol_id, message=FIPASerializer().encode(inform_msg), ) dialogues = cast(Dialogues, self.context.dialogues) dialogues.dialogue_stats.add_dialogue_endstate( Dialogue.EndState.SUCCESSFUL, dialogue.is_self_initiated) else: self.context.logger.warning( "[{}]: did not receive transaction digest from sender={}.". format(self.context.agent_name, msg.counterparty[-5:]))