def get_raw_transaction( self, api: LedgerApi, message: LedgerApiMessage, dialogue: LedgerApiDialogue, ) -> LedgerApiMessage: """ Send the request 'get_raw_transaction'. :param api: the API object. :param message: the Ledger API message :return: None """ raw_transaction = api.get_transfer_transaction( sender_address=message.terms.sender_address, destination_address=message.terms.counterparty_address, amount=message.terms.sender_payable_amount, tx_fee=message.terms.fee, tx_nonce=message.terms.nonce, **message.terms.kwargs, ) if raw_transaction is None: response = self.get_error_message( ValueError("No raw transaction returned"), api, message, dialogue ) else: response = LedgerApiMessage( performative=LedgerApiMessage.Performative.RAW_TRANSACTION, message_id=message.message_id + 1, target=message.message_id, dialogue_reference=dialogue.dialogue_label.dialogue_reference, raw_transaction=RawTransaction( message.terms.ledger_id, raw_transaction ), ) response.counterparty = message.counterparty dialogue.update(response) 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_signed_transaction(self, signing_msg: SigningMessage, signing_dialogue: SigningDialogue) -> None: """ Handle an oef search message. :param signing_msg: the signing message :param signing_dialogue: the dialogue :return: None """ self.context.logger.info( "[{}]: transaction signing was successful.".format( self.context.agent_name)) ledger_api_dialogues = cast(LedgerApiDialogues, self.context.ledger_api_dialogues) ledger_api_msg = LedgerApiMessage( performative=LedgerApiMessage.Performative.SEND_SIGNED_TRANSACTION, dialogue_reference=ledger_api_dialogues. new_self_initiated_dialogue_reference(), signed_transaction=signing_msg.signed_transaction, ) 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, "Error when creating signing dialogue." ledger_api_dialogue.associated_signing_dialogue = signing_dialogue self.context.outbox.put_message(message=ledger_api_msg) self.context.logger.info("[{}]: sending transaction to ledger.".format( self.context.agent_name))
def _handle_signed_transaction(self, signing_msg: SigningMessage, signing_dialogue: SigningDialogue) -> None: """ Handle an oef search message. :param signing_msg: the signing message :param signing_dialogue: the dialogue :return: None """ self.context.logger.info("transaction signing was successful.") fipa_dialogue = signing_dialogue.associated_fipa_dialogue ledger_api_dialogue = fipa_dialogue.associated_ledger_api_dialogue last_ledger_api_msg = ledger_api_dialogue.last_incoming_message assert (last_ledger_api_msg is not None ), "Could not retrieve last message in ledger api dialogue" ledger_api_msg = LedgerApiMessage( performative=LedgerApiMessage.Performative.SEND_SIGNED_TRANSACTION, dialogue_reference=ledger_api_dialogue.dialogue_label. dialogue_reference, target=last_ledger_api_msg.message_id, message_id=last_ledger_api_msg.message_id + 1, signed_transaction=signing_msg.signed_transaction, ) ledger_api_msg.counterparty = LEDGER_API_ADDRESS ledger_api_dialogue.update(ledger_api_msg) self.context.outbox.put_message(message=ledger_api_msg) self.context.logger.info("sending transaction to ledger.")
async def test_no_raw_tx(): """Test no raw tx returned.""" dispatcher = LedgerApiRequestDispatcher(ConnectionStatus()) mock_api = Mock() contract_api_dialogues = ContractApiDialogues() message = LedgerApiMessage( performative=LedgerApiMessage.Performative.GET_RAW_TRANSACTION, dialogue_reference=contract_api_dialogues. new_self_initiated_dialogue_reference(), terms=Terms( ledger_id=EthereumCrypto.identifier, sender_address="1111", counterparty_address="22222", amount_by_currency_id={"ETH": -1}, quantities_by_good_id={"some_service_id": 1}, is_sender_payable_tx_fee=True, nonce="", fee_by_currency_id={"ETH": 10}, chain_id=3, ), ) message.counterparty = "test" dialogue = contract_api_dialogues.update(message) mock_api.get_transfer_transaction.return_value = None msg = dispatcher.get_raw_transaction(mock_api, message, dialogue) assert msg.performative == LedgerApiMessage.Performative.ERROR
def _handle_transaction_digest( self, ledger_api_msg: LedgerApiMessage, ledger_api_dialogue: LedgerApiDialogue) -> None: """ Handle a message of transaction_digest performative. :param ledger_api_message: the ledger api message :param ledger_api_dialogue: the ledger api dialogue """ self.context.logger.info( "[{}]: transaction was successfully submitted. Transaction digest={}" .format(self.context.agent_name, ledger_api_msg.transaction_digest)) msg = LedgerApiMessage( performative=LedgerApiMessage.Performative.GET_TRANSACTION_RECEIPT, message_id=ledger_api_msg.message_id + 1, dialogue_reference=ledger_api_dialogue.dialogue_label. dialogue_reference, target=ledger_api_msg.message_id, transaction_digest=ledger_api_msg.transaction_digest, ) msg.counterparty = ledger_api_msg.counterparty ledger_api_dialogue.update(msg) self.context.outbox.put_message(message=msg) self.context.logger.info( "[{}]: requesting transaction receipt.".format( self.context.agent_name))
def get_error_message( self, e: Exception, api: LedgerApi, message: Message, dialogue: BaseDialogue, ) -> LedgerApiMessage: """ Build an error message. :param e: the exception. :param api: the Ledger API. :param message: the request message. :return: an error message response. """ message = cast(LedgerApiMessage, message) dialogue = cast(LedgerApiDialogue, dialogue) response = LedgerApiMessage( performative=LedgerApiMessage.Performative.ERROR, message_id=message.message_id + 1, target=message.message_id, dialogue_reference=dialogue.dialogue_label.dialogue_reference, code=500, message=str(e), data=b"", ) response.counterparty = message.counterparty dialogue.update(response) return response
def get_balance( self, api: LedgerApi, message: LedgerApiMessage, dialogue: LedgerApiDialogue, ) -> LedgerApiMessage: """ Send the request 'get_balance'. :param api: the API object. :param message: the Ledger API message :return: None """ balance = api.get_balance(message.address) if balance is None: response = self.get_error_message( ValueError("No balance returned"), api, message, dialogue ) else: response = LedgerApiMessage( performative=LedgerApiMessage.Performative.BALANCE, message_id=message.message_id + 1, target=message.message_id, dialogue_reference=dialogue.dialogue_label.dialogue_reference, balance=balance, ledger_id=message.ledger_id, ) response.counterparty = message.counterparty dialogue.update(response) return response
def get_transaction_receipt( self, api: LedgerApi, message: LedgerApiMessage, dialogue: LedgerApiDialogue, ) -> LedgerApiMessage: """ Send the request 'get_transaction_receipt'. :param api: the API object. :param message: the Ledger API message :return: None """ is_settled = False attempts = 0 while (not is_settled and attempts < self.MAX_ATTEMPTS and self.connection_state.get() == ConnectionStates.connected): time.sleep(self.TIMEOUT) transaction_receipt = api.get_transaction_receipt( message.transaction_digest.body) is_settled = api.is_transaction_settled(transaction_receipt) attempts += 1 attempts = 0 transaction = api.get_transaction(message.transaction_digest.body) while (transaction is None and attempts < self.MAX_ATTEMPTS and self.connection_state.get() == ConnectionStates.connected): time.sleep(self.TIMEOUT) transaction = api.get_transaction(message.transaction_digest.body) attempts += 1 if not is_settled: # pragma: nocover response = self.get_error_message( ValueError("Transaction not settled within timeout"), api, message, dialogue, ) elif transaction_receipt is None: # pragma: nocover response = self.get_error_message( ValueError("No transaction_receipt returned"), api, message, dialogue) elif transaction is None: # pragma: nocover response = self.get_error_message(ValueError("No tx returned"), api, message, dialogue) else: response = LedgerApiMessage( performative=LedgerApiMessage.Performative.TRANSACTION_RECEIPT, message_id=message.message_id + 1, target=message.message_id, dialogue_reference=dialogue.dialogue_label.dialogue_reference, transaction_receipt=TransactionReceipt( message.transaction_digest.ledger_id, transaction_receipt, transaction, ), ) response.counterparty = message.counterparty dialogue.update(response) return response
def _handle_match_accept( self, fipa_msg: FipaMessage, fipa_dialogue: FipaDialogue ) -> None: """ Handle the match accept. :param fipa_msg: the message :param fipa_dialogue: the dialogue object :return: None """ self.context.logger.info( "received MATCH_ACCEPT_W_INFORM from sender={} with info={}".format( fipa_msg.counterparty[-5:], fipa_msg.info ) ) strategy = cast(GenericStrategy, self.context.strategy) if strategy.is_ledger_tx: transfer_address = fipa_msg.info.get("address", None) if transfer_address is not None and isinstance(transfer_address, str): fipa_dialogue.terms.counterparty_address = transfer_address ledger_api_dialogues = cast( LedgerApiDialogues, self.context.ledger_api_dialogues ) ledger_api_msg = LedgerApiMessage( performative=LedgerApiMessage.Performative.GET_RAW_TRANSACTION, dialogue_reference=ledger_api_dialogues.new_self_initiated_dialogue_reference(), terms=fipa_dialogue.terms, ) 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 ), "Error when creating ledger api dialogue." ledger_api_dialogue.associated_fipa_dialogue = fipa_dialogue fipa_dialogue.associated_ledger_api_dialogue = ledger_api_dialogue self.context.outbox.put_message(message=ledger_api_msg) self.context.logger.info( "requesting transfer transaction from ledger api..." ) else: inform_msg = FipaMessage( message_id=fipa_msg.message_id + 1, dialogue_reference=fipa_dialogue.dialogue_label.dialogue_reference, target=fipa_msg.message_id, performative=FipaMessage.Performative.INFORM, info={"Done": "Sending payment via bank transfer"}, ) inform_msg.counterparty = fipa_msg.counterparty fipa_dialogue.update(inform_msg) self.context.outbox.put_message(message=inform_msg) self.context.logger.info( "informing counterparty={} of payment.".format( fipa_msg.counterparty[-5:] ) )
def setup(self) -> None: """Implement the setup for the behaviour.""" strategy = cast(Strategy, self.context.strategy) ledger_api_dialogues = cast( LedgerApiDialogues, self.context.ledger_api_dialogues ) ledger_api_msg = LedgerApiMessage( performative=LedgerApiMessage.Performative.GET_BALANCE, dialogue_reference=ledger_api_dialogues.new_self_initiated_dialogue_reference(), ledger_id=strategy.ledger_id, address=cast(str, self.context.agent_addresses.get(strategy.ledger_id)), ) ledger_api_msg.counterparty = LEDGER_API_ADDRESS ledger_api_dialogues.update(ledger_api_msg) self.context.outbox.put_message(message=ledger_api_msg)
async def test_no_balance(): """Test no balance.""" dispatcher = LedgerApiRequestDispatcher(AsyncState()) mock_api = Mock() message = LedgerApiMessage( performative=LedgerApiMessage.Performative.GET_BALANCE, dialogue_reference=dispatcher.dialogues. new_self_initiated_dialogue_reference(), ledger_id=ETHEREUM, address="test", ) message.counterparty = "test" dialogue = dispatcher.dialogues.update(message) mock_api.get_balance.return_value = None msg = dispatcher.get_balance(mock_api, message, dialogue) assert msg.performative == LedgerApiMessage.Performative.ERROR
async def test_no_balance(): """Test no balance.""" dispatcher = LedgerApiRequestDispatcher(ConnectionStatus()) mock_api = Mock() contract_api_dialogues = ContractApiDialogues() message = LedgerApiMessage( performative=LedgerApiMessage.Performative.GET_BALANCE, dialogue_reference=contract_api_dialogues. new_self_initiated_dialogue_reference(), ledger_id=EthereumCrypto.identifier, address="test", ) message.counterparty = "test" dialogue = contract_api_dialogues.update(message) mock_api.get_balance.return_value = None msg = dispatcher.get_balance(mock_api, message, dialogue) assert msg.performative == LedgerApiMessage.Performative.ERROR
def _request_balance(self) -> None: """ Request ledger balance. :return: None """ strategy = cast(Strategy, self.context.strategy) ledger_api_dialogues = cast( LedgerApiDialogues, self.context.ledger_api_dialogues ) ledger_api_msg = LedgerApiMessage( performative=LedgerApiMessage.Performative.GET_BALANCE, dialogue_reference=ledger_api_dialogues.new_self_initiated_dialogue_reference(), ledger_id=strategy.ledger_id, address=cast(str, self.context.agent_addresses.get(strategy.ledger_id)), ) ledger_api_msg.counterparty = LEDGER_API_ADDRESS ledger_api_dialogues.update(ledger_api_msg) self.context.outbox.put_message(message=ledger_api_msg)
async def test_get_balance(ledger_id, address, config, ledger_apis_connection: Connection): """Test get balance.""" import aea # noqa # to load registries ledger_api_dialogues = LedgerApiDialogues(address) request = LedgerApiMessage( performative=LedgerApiMessage.Performative.GET_BALANCE, dialogue_reference=ledger_api_dialogues. new_self_initiated_dialogue_reference(), ledger_id=ledger_id, address=address, ) request.counterparty = str(ledger_apis_connection.connection_id) ledger_api_dialogue = ledger_api_dialogues.update(request) assert ledger_api_dialogue is not None envelope = Envelope( to=str(ledger_apis_connection.connection_id), sender=address, protocol_id=request.protocol_id, message=request, ) await ledger_apis_connection.send(envelope) await asyncio.sleep(0.01) response = await ledger_apis_connection.receive() assert response is not None assert type(response.message) == LedgerApiMessage response_msg_orig = cast(LedgerApiMessage, response.message) response_msg = copy.copy(response_msg_orig) response_msg.is_incoming = True response_msg.counterparty = response_msg_orig.sender response_dialogue = ledger_api_dialogues.update(response_msg) assert response_dialogue == ledger_api_dialogue assert response_msg.performative == LedgerApiMessage.Performative.BALANCE actual_balance_amount = response_msg.balance expected_balance_amount = make_ledger_api(ledger_id, **config).get_balance(address) assert actual_balance_amount == expected_balance_amount
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(self) -> None: """ Implement the setup. :return: None """ strategy = cast(GenericStrategy, self.context.strategy) if strategy.is_ledger_tx: ledger_api_dialogues = cast(LedgerApiDialogues, self.context.ledger_api_dialogues) ledger_api_msg = LedgerApiMessage( performative=LedgerApiMessage.Performative.GET_BALANCE, dialogue_reference=ledger_api_dialogues. new_self_initiated_dialogue_reference(), ledger_id=strategy.ledger_id, address=cast( str, self.context.agent_addresses.get(strategy.ledger_id)), ) ledger_api_msg.counterparty = LEDGER_API_ADDRESS ledger_api_dialogues.update(ledger_api_msg) self.context.outbox.put_message(message=ledger_api_msg) self._register_agent() self._register_service()
def _handle_terms(self, ml_trade_msg: MlTradeMessage, ml_trade_dialogue: MlTradeDialogue) -> None: """ Handle the terms of the request. :param ml_trade_msg: the ml trade message :param ml_trade_dialogue: the dialogue object :return: None """ terms = ml_trade_msg.terms self.context.logger.info( "received terms message from {}: terms={}".format( ml_trade_msg.counterparty[-5:], terms.values)) strategy = cast(Strategy, self.context.strategy) acceptable = strategy.is_acceptable_terms(terms) affordable = strategy.is_affordable_terms(terms) if not acceptable and affordable: self.context.logger.info( "rejecting, terms are not acceptable and/or affordable") return if strategy.is_ledger_tx: # construct a tx for settlement on the ledger ledger_api_dialogues = cast(LedgerApiDialogues, self.context.ledger_api_dialogues) ledger_api_msg = LedgerApiMessage( performative=LedgerApiMessage.Performative.GET_RAW_TRANSACTION, dialogue_reference=ledger_api_dialogues. new_self_initiated_dialogue_reference(), terms=Terms( ledger_id=terms.values["ledger_id"], sender_address=self.context.agent_addresses[ terms.values["ledger_id"]], counterparty_address=terms.values["address"], amount_by_currency_id={ terms.values["currency_id"]: -terms.values["price"] }, is_sender_payable_tx_fee=True, quantities_by_good_id={"ml_training_data": 1}, nonce=uuid.uuid4().hex, fee_by_currency_id={terms.values["currency_id"]: 1}, ), ) 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), "Error when creating ledger api dialogue." ledger_api_dialogue.associated_ml_trade_dialogue = ml_trade_dialogue self.context.outbox.put_message(message=ledger_api_msg) self.context.logger.info( "requesting transfer transaction from ledger api...") else: # accept directly with a dummy transaction digest, no settlement ml_accept = MlTradeMessage( performative=MlTradeMessage.Performative.ACCEPT, dialogue_reference=ml_trade_dialogue.dialogue_label. dialogue_reference, message_id=ml_trade_msg.message_id + 1, target=ml_trade_msg.message_id, tx_digest=DUMMY_DIGEST, terms=terms, ) ml_accept.counterparty = ml_trade_msg.counterparty ml_trade_dialogue.update(ml_accept) self.context.outbox.put_message(message=ml_accept) self.context.logger.info("sending dummy transaction digest ...")
async def test_send_signed_transaction_ethereum( ledger_apis_connection: Connection): """Test send signed transaction with Ethereum APIs.""" import aea # noqa # to load registries crypto1 = EthereumCrypto(private_key_path=ETHEREUM_PRIVATE_KEY_PATH) crypto2 = EthereumCrypto() api = aea.crypto.registries.make_ledger_api(EthereumCrypto.identifier, **ETHEREUM_TESTNET_CONFIG) api = cast(EthereumApi, api) ledger_api_dialogues = LedgerApiDialogues() amount = 40000 fee = 30000 request = LedgerApiMessage( performative=LedgerApiMessage.Performative.GET_RAW_TRANSACTION, dialogue_reference=ledger_api_dialogues. new_self_initiated_dialogue_reference(), terms=Terms( ledger_id=EthereumCrypto.identifier, sender_address=crypto1.address, counterparty_address=crypto2.address, amount_by_currency_id={"ETH": -amount}, quantities_by_good_id={"some_service_id": 1}, is_sender_payable_tx_fee=True, nonce="", fee_by_currency_id={"ETH": fee}, chain_id=3, ), ) request.counterparty = str(ledger_apis_connection.connection_id) ledger_api_dialogue = ledger_api_dialogues.update(request) assert ledger_api_dialogue is not None envelope = Envelope( to=str(ledger_apis_connection.connection_id), sender=crypto1.address, protocol_id=request.protocol_id, message=request, ) await ledger_apis_connection.send(envelope) await asyncio.sleep(0.01) response = await ledger_apis_connection.receive() assert response is not None assert type(response.message) == LedgerApiMessage response_message = cast(LedgerApiMessage, response.message) assert (response_message.performative == LedgerApiMessage.Performative.RAW_TRANSACTION) response_dialogue = ledger_api_dialogues.update(response_message) assert response_dialogue == ledger_api_dialogue assert type(response_message.raw_transaction) == RawTransaction assert response_message.raw_transaction.ledger_id == request.terms.ledger_id # raw_tx = api.get_transfer_transaction( # sender_address=crypto1.address, # destination_address=crypto2.address, # amount=amount, # tx_fee=fee, # tx_nonce="", # chain_id=3, # ) signed_transaction = crypto1.sign_transaction( response_message.raw_transaction.body) request = LedgerApiMessage( performative=LedgerApiMessage.Performative.SEND_SIGNED_TRANSACTION, dialogue_reference=ledger_api_dialogue.dialogue_label. dialogue_reference, signed_transaction=SignedTransaction(EthereumCrypto.identifier, signed_transaction), ) request.counterparty = str(ledger_apis_connection.connection_id) ledger_api_dialogue.update(request) envelope = Envelope( to=str(ledger_apis_connection.connection_id), sender=crypto1.address, protocol_id=request.protocol_id, message=request, ) await ledger_apis_connection.send(envelope) await asyncio.sleep(0.01) response = await ledger_apis_connection.receive() assert response is not None assert type(response.message) == LedgerApiMessage response_message = cast(LedgerApiMessage, response.message) assert (response_message.performative != LedgerApiMessage.Performative.ERROR ), f"Received error: {response_message.message}" assert (response_message.performative == LedgerApiMessage.Performative.TRANSACTION_DIGEST) response_dialogue = ledger_api_dialogues.update(response_message) assert response_dialogue == ledger_api_dialogue assert type(response_message.transaction_digest) == TransactionDigest assert type(response_message.transaction_digest.body) == str assert (response_message.transaction_digest.ledger_id == request.signed_transaction.ledger_id) assert type(response_message.transaction_digest.body.startswith("0x")) request = LedgerApiMessage( performative=LedgerApiMessage.Performative.GET_TRANSACTION_RECEIPT, dialogue_reference=ledger_api_dialogue.dialogue_label. dialogue_reference, transaction_digest=response_message.transaction_digest, ) request.counterparty = str(ledger_apis_connection.connection_id) ledger_api_dialogue.update(request) envelope = Envelope( to=str(ledger_apis_connection.connection_id), sender=crypto1.address, protocol_id=request.protocol_id, message=request, ) await ledger_apis_connection.send(envelope) await asyncio.sleep(0.01) response = await ledger_apis_connection.receive() assert response is not None assert type(response.message) == LedgerApiMessage response_message = cast(LedgerApiMessage, response.message) assert (response_message.performative == LedgerApiMessage.Performative.TRANSACTION_RECEIPT) response_dialogue = ledger_api_dialogues.update(response_message) assert response_dialogue == ledger_api_dialogue assert type(response_message.transaction_receipt) == TransactionReceipt assert response_message.transaction_receipt.receipt is not None assert response_message.transaction_receipt.transaction is not None assert (response_message.transaction_receipt.ledger_id == request.transaction_digest.ledger_id)
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:]))