def test_transaction_digest_encode_decode(): """Test encoding and decoding of transaction_digest.""" class TransactionDigestProtobufObject: transaction_digest_bytes = b"" ledger_id = "some_ledger" body = "digest" td = TransactionDigest(ledger_id, body) TransactionDigest.encode(TransactionDigestProtobufObject, td) recovered_td = TransactionDigest.decode(TransactionDigestProtobufObject) assert td == recovered_td
def send_signed_transaction( self, api: LedgerApi, message: LedgerApiMessage, dialogue: LedgerApiDialogue, ) -> LedgerApiMessage: """ Send the request 'send_signed_tx'. :param api: the API object. :param message: the Ledger API message :return: None """ transaction_digest = api.send_signed_transaction( message.signed_transaction.body ) if transaction_digest is None: # pragma: nocover response = self.get_error_message( ValueError("No transaction_digest returned"), api, message, dialogue ) else: response = cast( LedgerApiMessage, dialogue.reply( performative=LedgerApiMessage.Performative.TRANSACTION_DIGEST, target_message=message, transaction_digest=TransactionDigest( message.signed_transaction.ledger_id, transaction_digest ), ), ) return response
def send_signed_transaction( self, api: LedgerApi, message: LedgerApiMessage, dialogue: LedgerApiDialogue, ) -> LedgerApiMessage: """ Send the request 'send_signed_tx'. :param api: the API object. :param message: the Ledger API message :return: None """ transaction_digest = api.send_signed_transaction( message.signed_transaction.body ) if transaction_digest is None: # pragma: nocover response = self.get_error_message( ValueError("No transaction_digest returned"), api, message, dialogue ) else: response = LedgerApiMessage( performative=LedgerApiMessage.Performative.TRANSACTION_DIGEST, message_id=message.message_id + 1, target=message.message_id, dialogue_reference=dialogue.dialogue_label.dialogue_reference, transaction_digest=TransactionDigest( message.signed_transaction.ledger_id, transaction_digest ), ) response.counterparty = message.counterparty dialogue.update(response) return response
def _handle_inform(self, fipa_msg: FipaMessage, fipa_dialogue: FipaDialogue) -> 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 fipa_msg: the message :param fipa_dialogue: the dialogue object :return: None """ self.context.logger.info("received INFORM from sender={}".format( fipa_msg.sender[-5:])) strategy = cast(GenericStrategy, self.context.strategy) if strategy.is_ledger_tx and "transaction_digest" in fipa_msg.info.keys( ): self.context.logger.info( "checking whether transaction={} has been received ...".format( fipa_msg.info["transaction_digest"])) ledger_api_dialogues = cast(LedgerApiDialogues, self.context.ledger_api_dialogues) ledger_api_msg, ledger_api_dialogue = ledger_api_dialogues.create( counterparty=LEDGER_API_ADDRESS, performative=LedgerApiMessage.Performative. GET_TRANSACTION_RECEIPT, transaction_digest=TransactionDigest( fipa_dialogue.terms.ledger_id, fipa_msg.info["transaction_digest"]), ) ledger_api_dialogue = cast(LedgerApiDialogue, ledger_api_dialogue) ledger_api_dialogue.associated_fipa_dialogue = fipa_dialogue self.context.outbox.put_message(message=ledger_api_msg) elif strategy.is_ledger_tx: self.context.logger.warning( "did not receive transaction digest from sender={}.".format( fipa_msg.sender[-5:])) elif not strategy.is_ledger_tx and "Done" in fipa_msg.info.keys(): inform_msg = fipa_dialogue.reply( performative=FipaMessage.Performative.INFORM, target_message=fipa_msg, info=fipa_dialogue.data_for_sale, ) self.context.outbox.put_message(message=inform_msg) fipa_dialogues = cast(FipaDialogues, self.context.fipa_dialogues) fipa_dialogues.dialogue_stats.add_dialogue_endstate( FipaDialogue.EndState.SUCCESSFUL, fipa_dialogue.is_self_initiated) self.context.logger.info( "transaction confirmed, sending data={} to buyer={}.".format( fipa_dialogue.data_for_sale, fipa_msg.sender[-5:], )) else: self.context.logger.warning( "did not receive transaction confirmation from sender={}.". format(fipa_msg.sender[-5:]))
def test_init_transaction_digest(): """Test the transaction_digest object initialization.""" ledger_id = "some_ledger" body = "digest" td = TransactionDigest(ledger_id, body) assert td.ledger_id == ledger_id assert td.body == body assert str(td) == "TransactionDigest: ledger_id={}, body={}".format(ledger_id, body) assert td == td
def setup(cls): """Setup the test class.""" super().setup() cls.ledger_api_handler = cast( GenericLedgerApiHandler, cls._skill.skill_context.handlers.ledger_api) cls.strategy = cast(GenericStrategy, cls._skill.skill_context.strategy) cls.fipa_dialogues = cast(FipaDialogues, cls._skill.skill_context.fipa_dialogues) cls.ledger_api_dialogues = cast( LedgerApiDialogues, cls._skill.skill_context.ledger_api_dialogues) cls.terms = Terms( "some_ledger_id", cls._skill.skill_context.agent_address, "counterprty", {"currency_id": 50}, {"good_id": -10}, "some_nonce", ) cls.list_of_fipa_messages = ( DialogueMessage(FipaMessage.Performative.CFP, {"query": "some_query"}, True), DialogueMessage(FipaMessage.Performative.PROPOSE, {"proposal": "some_proposal"}), DialogueMessage(FipaMessage.Performative.ACCEPT), DialogueMessage( FipaMessage.Performative.MATCH_ACCEPT_W_INFORM, {"info": { "address": "some_term_sender_address" }}, ), DialogueMessage( FipaMessage.Performative.INFORM, { "info": { "transaction_digest": "some_transaction_digest_body" } }, ), ) cls.transaction_digest = TransactionDigest("some_ledger_id", "some_body") cls.transaction_receipt = TransactionReceipt("some_ledger_id", "some_receipt", "some_transaction") cls.list_of_ledger_api_messages = ( DialogueMessage( LedgerApiMessage.Performative.GET_TRANSACTION_RECEIPT, {"transaction_digest": cls.transaction_digest}, ), DialogueMessage( LedgerApiMessage.Performative.TRANSACTION_RECEIPT, {"transaction_receipt": cls.transaction_receipt}, ), )
def test_handle_inform_is_ledger_tx_and_with_tx_digest(self): """Test the _handle_inform method of the fipa handler where is_ledger_tx is True and info contains transaction_digest.""" # setup self.strategy._is_ledger_tx = True tx_digest = "some_transaction_digest_body" ledger_id = "some_ledger_id" fipa_dialogue = self.prepare_skill_dialogue( dialogues=self.fipa_dialogues, messages=self.list_of_messages[:4], ) fipa_dialogue.terms = Terms( ledger_id, self.skill.skill_context.agent_address, "counterprty", {"currency_id": 50}, {"good_id": -10}, "some_nonce", ) incoming_message = self.build_incoming_message_for_skill_dialogue( dialogue=fipa_dialogue, performative=FipaMessage.Performative.INFORM, info={"transaction_digest": tx_digest}, ) # operation with patch.object(self.fipa_handler.context.logger, "log") as mock_logger: self.fipa_handler.handle(incoming_message) incoming_message = cast(FipaMessage, incoming_message) # after mock_logger.assert_any_call( logging.INFO, f"received INFORM from sender={COUNTERPARTY_ADDRESS[-5:]}") mock_logger.assert_any_call( logging.INFO, f"checking whether transaction={incoming_message.info['transaction_digest']} has been received ...", ) self.assert_quantity_in_outbox(1) has_attributes, error_str = self.message_has_attributes( actual_message=self.get_message_from_outbox(), message_type=LedgerApiMessage, performative=LedgerApiMessage.Performative.GET_TRANSACTION_RECEIPT, to=LEDGER_API_ADDRESS, sender=self.skill.skill_context.agent_address, target=0, transaction_digest=TransactionDigest(ledger_id, tx_digest), ) assert has_attributes, error_str
async def test_attempts_get_transaction_receipt(): """Test retry and sleep.""" dispatcher = LedgerApiRequestDispatcher(ConnectionStatus()) dispatcher.connection_status.is_connected = True mock_api = Mock() contract_api_dialogues = ContractApiDialogues() message = LedgerApiMessage( performative=LedgerApiMessage.Performative.GET_TRANSACTION_RECEIPT, dialogue_reference=contract_api_dialogues. new_self_initiated_dialogue_reference(), transaction_digest=TransactionDigest("asdad", "sdfdsf"), ) message.counterparty = "test" dialogue = contract_api_dialogues.update(message) mock_api.get_transaction.return_value = None mock_api.is_transaction_settled.return_value = True with patch.object(dispatcher, "MAX_ATTEMPTS", 2): with patch.object(dispatcher, "TIMEOUT", 0.001): msg = dispatcher.get_transaction_receipt(mock_api, message, dialogue) assert msg.performative == LedgerApiMessage.Performative.ERROR
def setup(cls): """Setup the test class.""" super().setup() cls.ledger_api_handler = cast( LedgerApiHandler, cls._skill.skill_context.handlers.ledger_api) cls.ledger_api_dialogues = cast( LedgerApiDialogues, cls._skill.skill_context.ledger_api_dialogues) cls.signing_dialogues = cast( SigningDialogues, cls._skill.skill_context.signing_dialogues) cls.contract_api_dialogues = cast( ContractApiDialogues, cls._skill.skill_context.contract_api_dialogues) cls.parameters = cast(Parameters, cls._skill.skill_context.parameters) cls.game = cast(Game, cls._skill.skill_context.game) cls.logger = cls.ledger_api_handler.context.logger cls.ledger_id = "some_ledger_id" cls.contract_id = "some_contract_id" cls.callable = "some_callable" cls.kwargs = Kwargs({"some_key": "some_value"}) cls.body = {"some_key": "some_value"} cls.body_str = "some_body" cls.contract_address = "some_contract_address" cls.raw_transaction = RawTransaction(cls.ledger_id, cls.body) cls.signed_transaction = SignedTransaction(cls.ledger_id, cls.body) cls.transaction_digest = TransactionDigest(cls.ledger_id, cls.body_str) cls.receipt = {"contractAddress": cls.contract_address} cls.transaction_receipt = TransactionReceipt( cls.ledger_id, cls.receipt, {"transaction_key": "transaction_value"}) cls.terms = Terms( cls.ledger_id, cls._skill.skill_context.agent_address, "counterprty", {"currency_id": 50}, {"good_id": -10}, "some_nonce", ) cls.list_of_signing_messages = (DialogueMessage( SigningMessage.Performative.SIGN_TRANSACTION, { "terms": cls.terms, "raw_transaction": SigningMessage.RawTransaction(cls.ledger_id, cls.body), }, ), ) cls.list_of_contract_api_messages = (DialogueMessage( ContractApiMessage.Performative.GET_DEPLOY_TRANSACTION, { "ledger_id": cls.ledger_id, "contract_id": cls.contract_id, "callable": cls.callable, "kwargs": cls.kwargs, }, ), ) cls.list_of_ledger_api_messages = ( DialogueMessage(LedgerApiMessage.Performative.GET_RAW_TRANSACTION, {"terms": cls.terms}), DialogueMessage( LedgerApiMessage.Performative.RAW_TRANSACTION, {"raw_transaction": cls.raw_transaction}, ), DialogueMessage( LedgerApiMessage.Performative.SEND_SIGNED_TRANSACTION, {"signed_transaction": cls.signed_transaction}, ), DialogueMessage( LedgerApiMessage.Performative.TRANSACTION_DIGEST, {"transaction_digest": cls.transaction_digest}, ), DialogueMessage( LedgerApiMessage.Performative.GET_TRANSACTION_RECEIPT, {"transaction_digest": cls.transaction_digest}, ), )
def _handle_inform(self, fipa_msg: FipaMessage, fipa_dialogue: FipaDialogue) -> 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 fipa_msg: the message :param fipa_dialogue: the dialogue object :return: None """ new_message_id = fipa_msg.message_id + 1 new_target = fipa_msg.message_id self.context.logger.info("[{}]: received INFORM from sender={}".format( self.context.agent_name, fipa_msg.counterparty[-5:])) strategy = cast(GenericStrategy, self.context.strategy) if strategy.is_ledger_tx and "transaction_digest" in fipa_msg.info.keys( ): self.context.logger.info( "[{}]: checking whether transaction={} has been received ...". format(self.context.agent_name, fipa_msg.info["transaction_digest"])) ledger_api_dialogues = cast(LedgerApiDialogues, self.context.ledger_api_dialogues) ledger_api_msg = LedgerApiMessage( performative=LedgerApiMessage.Performative. GET_TRANSACTION_RECEIPT, dialogue_reference=ledger_api_dialogues. new_self_initiated_dialogue_reference(), transaction_digest=TransactionDigest( fipa_dialogue.terms.ledger_id, fipa_msg.info["transaction_digest"]), ) ledger_api_msg.counterparty = LEDGER_API_ADDRESS ledger_api_dialogue = cast( Optional[LedgerApiDialogue], ledger_api_dialogues.update(ledger_api_msg)) assert (ledger_api_dialogue is not None), "LedgerApiDialogue construction failed." ledger_api_dialogue.associated_fipa_dialogue = fipa_dialogue self.context.outbox.put_message(message=ledger_api_msg) elif strategy.is_ledger_tx: self.context.logger.warning( "[{}]: did not receive transaction digest from sender={}.". format(self.context.agent_name, fipa_msg.counterparty[-5:])) elif not strategy.is_ledger_tx and "Done" in fipa_msg.info.keys(): inform_msg = FipaMessage( message_id=new_message_id, dialogue_reference=fipa_dialogue.dialogue_label. dialogue_reference, target=new_target, performative=FipaMessage.Performative.INFORM, info=fipa_dialogue.data_for_sale, ) inform_msg.counterparty = fipa_msg.counterparty fipa_dialogue.update(inform_msg) self.context.outbox.put_message(message=inform_msg) fipa_dialogues = cast(FipaDialogues, self.context.fipa_dialogues) fipa_dialogues.dialogue_stats.add_dialogue_endstate( FipaDialogue.EndState.SUCCESSFUL, fipa_dialogue.is_self_initiated) self.context.logger.info( "[{}]: transaction confirmed, sending data={} to buyer={}.". format( self.context.agent_name, fipa_dialogue.data_for_sale, fipa_msg.counterparty[-5:], )) else: self.context.logger.warning( "[{}]: did not receive transaction confirmation from sender={}." .format(self.context.agent_name, fipa_msg.counterparty[-5:]))