def test_kwargs(): """Test the kwargs custom type.""" body = {"key_1": 1, "key_2": 2} kwargs = ContractApiMessage.Kwargs(body) assert str(kwargs) == "Kwargs: body={}".format(body) with pytest.raises(ValueError, match="body must not be None"): ContractApiMessage.Kwargs(None)
async def test_callable_wrong_number_of_arguments_apis_method_call( erc1155_contract, ledger_apis_connection, caplog): """ Test a contract callable with wrong number of arguments. Test the case of either GET_DEPLOY_TRANSACTION. """ address = ETHEREUM_ADDRESS_ONE contract_api_dialogues = ContractApiDialogues(address) request, _ = contract_api_dialogues.create( counterparty=str(ledger_apis_connection.connection_id), performative=ContractApiMessage.Performative.GET_DEPLOY_TRANSACTION, ledger_id=ETHEREUM, contract_id=str(ERC1155_PUBLIC_ID), callable="get_deploy_transaction", kwargs=ContractApiMessage.Kwargs({}), ) envelope = Envelope( to=request.to, sender=request.sender, protocol_id=request.protocol_id, message=request, ) with unittest.mock.patch.object( ledger_apis_connection._contract_dispatcher, "_call_stub", return_value=None): with caplog.at_level(logging.DEBUG, "aea.packages.fetchai.connections.ledger"): await ledger_apis_connection.send(envelope) await asyncio.sleep(0.01) assert ( "An error occurred while processing the contract api request: 'get_deploy_transaction() missing 1 required positional argument: 'deployer_address''." in caplog.text)
def _option_interaction(self, option_type: str, act: str, params: Dict[str, Any]) -> None: if option_type not in ["btc", "eth"]: raise ValueError("Missing option types!") if act not in ["create_option", "exercise", "estimate"]: raise ValueError("Missing act types!") strategy = cast(Strategy, self.context.strategy) strategy.deployment_status["status"] = "deploying" strategy.is_behaviour_active = False contract_api_dialogues = cast(ContractApiDialogues, self.context.contract_api_dialogues) params.update({"deployer_address": self.context.agent_address}) contract_api_msg, contract_api_dialogue = contract_api_dialogues.create( counterparty=LEDGER_API_ADDRESS, performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION, ledger_id=strategy.ledger_id, contract_id=f"eightballer/{option_type}options:0.1.0", contract_address=strategy. deployment_status[f"{option_type}options"][1], callable=f"{act}", kwargs=ContractApiMessage.Kwargs(params), ) strategy.deployment_status[f"{option_type}options_{act}"] = ( "pending", contract_api_dialogue.dialogue_label.dialogue_reference[0], ) contract_api_dialogue = cast( ContractApiDialogue, contract_api_dialogue, ) contract_api_dialogue.terms = strategy.get_deploy_terms() self.context.outbox.put_message(message=contract_api_msg) self.context.logger.info( f"contract deployer requesting {act} {option_type} transaction...")
async def test_run_async(): """Test run async error handled.""" # for pydocstyle def _raise(): raise Exception("Expected") contract_api_dialogues = ContractApiDialogues("address") request, dialogue = contract_api_dialogues.create( counterparty="str(ledger_apis_connection.connection_id)", performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION, ledger_id=ETHEREUM, contract_id=str(ERC1155_PUBLIC_ID), contract_address="test addr", callable="get_create_batch_transaction", kwargs=ContractApiMessage.Kwargs({ "deployer_address": "test_addr", "token_ids": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], }), ) api = None msg = await ContractApiRequestDispatcher(MultiplexerStatus()).run_async( _raise, api, request, dialogue) assert msg.performative == ContractApiMessage.Performative.ERROR
def _request_contract_state(self, contract_name: str, callable: str, parameters: dict) -> None: """ Request contract deploy transaction :return: None """ params = {"deployer_address": self.context.agent_address} params.update(parameters) strategy = cast(Strategy, self.context.strategy) strategy.is_behaviour_active = False contract_api_dialogues = cast(ContractApiDialogues, self.context.contract_api_dialogues) contract_api_msg, contract_api_dialogue = contract_api_dialogues.create( counterparty=LEDGER_API_ADDRESS, performative=ContractApiMessage.Performative.GET_STATE, ledger_id=strategy.ledger_id, contract_id=f"eightballer/{contract_name}:0.1.0", contract_address=strategy.deployment_status[contract_name][1], callable=callable, kwargs=ContractApiMessage.Kwargs(params), ) contract_api_dialogue = cast( ContractApiDialogue, contract_api_dialogue, ) contract_api_dialogue.terms = strategy.get_deploy_terms() self.context.outbox.put_message(message=contract_api_msg) strategy.deployment_status[f"{contract_name}_{callable}"] = ( "pending", contract_api_dialogue.dialogue_label.dialogue_reference[0], ) strategy.deployment_status["status"] = "deploying" self.context.logger.info( f"requesting contract {contract_name} state transaction...")
def test_get_raw_transaction_serialization(): """Test the serialization for 'get_raw_transaction' speech-act works.""" kwargs_arg = ContractApiMessage.Kwargs({"key_1": 1, "key_2": 2}) msg = ContractApiMessage( message_id=1, dialogue_reference=(str(0), ""), target=0, performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION, ledger_id="some_ledger_id", contract_id="some_contract_id", contract_address="some_contract_address", callable="some_callable", kwargs=kwargs_arg, ) msg.to = "receiver" envelope = Envelope( to=msg.to, sender="sender", message=msg, ) envelope_bytes = envelope.encode() actual_envelope = Envelope.decode(envelope_bytes) expected_envelope = envelope assert expected_envelope.to == actual_envelope.to assert expected_envelope.sender == actual_envelope.sender assert (expected_envelope.protocol_specification_id == actual_envelope.protocol_specification_id) assert expected_envelope.message != actual_envelope.message actual_msg = ContractApiMessage.serializer.decode(actual_envelope.message) actual_msg.to = actual_envelope.to actual_msg.sender = actual_envelope.sender expected_msg = msg assert expected_msg == actual_msg
def _request_query_transaction(self) -> None: """ Request transaction that requests value from Fetch oracle contract :return: None """ strategy = cast(Strategy, self.context.strategy) strategy.is_behaviour_active = False contract_api_dialogues = cast(ContractApiDialogues, self.context.contract_api_dialogues) contract_api_msg, contract_api_dialogue = contract_api_dialogues.create( counterparty=str(LEDGER_API_ADDRESS), performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION, ledger_id=strategy.ledger_id, contract_id=str(CLIENT_CONTRACT_PUBLIC_ID), contract_address=strategy.client_contract_address, callable="get_query_transaction", kwargs=ContractApiMessage.Kwargs({ "from_address": self.context.agent_address, "query_function": strategy.query_function, "gas": strategy.default_gas_query, }), ) contract_api_dialogue = cast(ContractApiDialogue, contract_api_dialogue) contract_api_dialogue.terms = strategy.get_query_terms() self.context.outbox.put_message(message=contract_api_msg) self.context.logger.info("requesting query transaction...")
def _request_grant_role_transaction(self) -> None: """ Request transaction that grants oracle role in a Fetch oracle contract :return: None """ strategy = cast(Strategy, self.context.strategy) strategy.is_behaviour_active = False contract_api_dialogues = cast(ContractApiDialogues, self.context.contract_api_dialogues) contract_api_msg, contract_api_dialogue = contract_api_dialogues.create( counterparty=str(LEDGER_API_ADDRESS), performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION, ledger_id=strategy.ledger_id, contract_id=str(CONTRACT_PUBLIC_ID), contract_address=strategy.contract_address, callable="get_grant_role_transaction", kwargs=ContractApiMessage.Kwargs({ "oracle_address": self.context.agent_address, "gas": strategy.default_gas_grant_role, }), ) contract_api_dialogue = cast(ContractApiDialogue, contract_api_dialogue) contract_api_dialogue.terms = strategy.get_grant_role_terms() envelope_context = EnvelopeContext(skill_id=self.context.skill_id, connection_id=LEDGER_API_ADDRESS) self.context.outbox.put_message(message=contract_api_msg, context=envelope_context) self.context.logger.info("requesting grant role transaction...")
def _request_token_mint_transaction(self) -> None: """ Request token mint transaction :return: None """ strategy = cast(Strategy, self.context.strategy) strategy.is_behaviour_active = False contract_api_dialogues = cast(ContractApiDialogues, self.context.contract_api_dialogues) contract_api_msg, contract_api_dialogue = contract_api_dialogues.create( counterparty=LEDGER_API_ADDRESS, performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION, ledger_id=strategy.ledger_id, contract_id=strategy.contract_id, contract_address=strategy.contract_address, callable="get_mint_batch_transaction", kwargs=ContractApiMessage.Kwargs({ "deployer_address": self.context.agent_address, "recipient_address": self.context.agent_address, "token_ids": strategy.token_ids, "mint_quantities": strategy.mint_quantities, "gas": strategy.gas, }), ) contract_api_dialogue = cast(ContractApiDialogue, contract_api_dialogue) contract_api_dialogue.terms = strategy.get_mint_token_terms() self.context.outbox.put_message(message=contract_api_msg) self.context.logger.info("requesting mint batch transaction...")
def _request_contract_state(self, contract_name: str, callable_: str, parameters: dict) -> None: """ Request contract deploy transaction :return: None """ params = {"deployer_address": self.context.agent_address} params.update(parameters) strategy = cast(Strategy, self.context.strategy) strategy.is_price_behaviour_active = False contract_api_dialogues = cast(ContractApiDialogues, self.context.contract_api_dialogues) contract_api_msg, contract_api_dialogue = contract_api_dialogues.create( counterparty=LEDGER_API_ADDRESS, performative=ContractApiMessage.Performative.GET_STATE, ledger_id=strategy.ledger_id, contract_id=f"eightballer/{contract_name}:0.1.0", contract_address=strategy.get_contract_address(contract_name), callable=callable_, kwargs=ContractApiMessage.Kwargs(params), ) contract_api_dialogue = cast(ContractApiDialogue, contract_api_dialogue) contract_api_dialogue.terms = strategy.get_deploy_terms() strategy.set_status( contract_name, callable_, contract_api_dialogue.dialogue_label.dialogue_reference[0], ) self.context.outbox.put_message(message=contract_api_msg)
def _request_contract_deploy_transaction(self) -> None: """ Request contract deploy transaction :return: None """ parameters = cast(Parameters, self.context.parameters) contract_api_dialogues = cast( ContractApiDialogues, self.context.contract_api_dialogues ) contract_api_msg, contract_api_dialogue = contract_api_dialogues.create( counterparty=LEDGER_API_ADDRESS, performative=ContractApiMessage.Performative.GET_DEPLOY_TRANSACTION, ledger_id=parameters.ledger_id, contract_id=parameters.contract_id, callable=ContractApiDialogue.Callable.GET_DEPLOY_TRANSACTION.value, kwargs=ContractApiMessage.Kwargs( {"deployer_address": self.context.agent_address, "gas": parameters.gas} ), ) contract_api_dialogue = cast(ContractApiDialogue, contract_api_dialogue,) contract_api_dialogue.terms = parameters.get_deploy_terms() contract_api_dialogue.callable = ( ContractApiDialogue.Callable.GET_DEPLOY_TRANSACTION ) self.context.outbox.put_message(message=contract_api_msg) self.context.logger.info("requesting contract deployment transaction...")
def _request_token_create_transaction(self) -> None: """ Request token create transaction :return: None """ strategy = cast(Strategy, self.context.strategy) strategy.is_behaviour_active = False contract_api_dialogues = cast(ContractApiDialogues, self.context.contract_api_dialogues) contract_api_msg = ContractApiMessage( performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION, dialogue_reference=contract_api_dialogues. new_self_initiated_dialogue_reference(), ledger_id=strategy.ledger_id, contract_id="fetchai/erc1155:0.6.0", contract_address=strategy.contract_address, callable="get_create_batch_transaction", kwargs=ContractApiMessage.Kwargs({ "deployer_address": self.context.agent_address, "token_ids": strategy.token_ids, }), ) contract_api_msg.counterparty = LEDGER_API_ADDRESS contract_api_dialogue = cast( Optional[ContractApiDialogue], contract_api_dialogues.update(contract_api_msg), ) assert contract_api_dialogue is not None, "ContractApiDialogue not generated" contract_api_dialogue.terms = strategy.get_create_token_terms() self.context.outbox.put_message(message=contract_api_msg) self.context.logger.info( "[{}]: Requesting create batch transaction...".format( self.context.agent_name))
async def test_erc1155_get_deploy_transaction(erc1155_contract, ledger_apis_connection): """Test get state with contract erc1155.""" address = ETHEREUM_ADDRESS_ONE contract_api_dialogues = ContractApiDialogues(address) request, contract_api_dialogue = contract_api_dialogues.create( counterparty=str(ledger_apis_connection.connection_id), performative=ContractApiMessage.Performative.GET_DEPLOY_TRANSACTION, ledger_id=ETHEREUM, contract_id=str(ERC1155_PUBLIC_ID), callable="get_deploy_transaction", kwargs=ContractApiMessage.Kwargs({"deployer_address": address}), ) envelope = Envelope(to=request.to, sender=request.sender, 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) == ContractApiMessage response_message = cast(ContractApiMessage, response.message) assert ( response_message.performative == ContractApiMessage.Performative.RAW_TRANSACTION ), "Error: {}".format(response_message.message) response_dialogue = contract_api_dialogues.update(response_message) assert response_dialogue == contract_api_dialogue assert type(response_message.raw_transaction) == RawTransaction assert response_message.raw_transaction.ledger_id == ETHEREUM assert len(response.message.raw_transaction.body) == 6 assert len(response.message.raw_transaction.body["data"]) > 0
async def test_callable_generic_error(erc1155_contract, ledger_apis_connection): """Test error messages when an exception is raised while processing the request.""" contract, contract_address = erc1155_contract address = ETHEREUM_ADDRESS_ONE contract_api_dialogues = ContractApiDialogues(address) token_id = 1 request, _ = contract_api_dialogues.create( counterparty=str(ledger_apis_connection.connection_id), performative=ContractApiMessage.Performative.GET_STATE, ledger_id=ETHEREUM, contract_id=str(ERC1155_PUBLIC_ID), contract_address=contract_address, callable="get_balance", kwargs=ContractApiMessage.Kwargs( {"agent_address": address, "token_id": token_id} ), ) envelope = Envelope(to=request.to, sender=request.sender, message=request,) with unittest.mock.patch( "inspect.getfullargspec", side_effect=Exception("Generic error") ): with unittest.mock.patch.object( ledger_apis_connection._logger, "error" ) as mock_logger: await ledger_apis_connection.send(envelope) await asyncio.sleep(0.01) response = await ledger_apis_connection.receive() mock_logger.assert_any_call( "An error occurred while processing the contract api request: 'Generic error'." ) assert ( response.message.performative == ContractApiMessage.Performative.ERROR ) assert response.message.message == "Generic error"
def _request_contract_deploy_transaction(self) -> None: """ Request contract deployment transaction :return: None """ strategy = cast(Strategy, self.context.strategy) strategy.is_behaviour_active = False contract_api_dialogues = cast(ContractApiDialogues, self.context.contract_api_dialogues) contract_api_msg, contract_api_dialogue = contract_api_dialogues.create( counterparty=str(LEDGER_API_ADDRESS), performative=ContractApiMessage.Performative. GET_DEPLOY_TRANSACTION, ledger_id=strategy.ledger_id, contract_id=str(CLIENT_CONTRACT_PUBLIC_ID), callable="get_deploy_transaction", kwargs=ContractApiMessage.Kwargs({ "deployer_address": self.context.agent_address, "fetchOracleContractAddress": strategy.oracle_contract_address, "gas": strategy.default_gas_deploy, }), ) contract_api_dialogue = cast( ContractApiDialogue, contract_api_dialogue, ) contract_api_dialogue.terms = strategy.get_deploy_terms() self.context.outbox.put_message(message=contract_api_msg) self.context.logger.info( "requesting contract deployment transaction...")
def _request_update_transaction(self, update_args: Dict[str, Any]) -> None: """ Request transaction that updates value in Fetch oracle contract :return: None """ strategy = cast(Strategy, self.context.strategy) strategy.is_behaviour_active = False contract_api_dialogues = cast(ContractApiDialogues, self.context.contract_api_dialogues) contract_api_msg, contract_api_dialogue = contract_api_dialogues.create( counterparty=str(LEDGER_API_ADDRESS), performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION, ledger_id=strategy.ledger_id, contract_id=str(CONTRACT_PUBLIC_ID), contract_address=strategy.contract_address, callable="get_update_transaction", kwargs=ContractApiMessage.Kwargs({ "oracle_address": self.context.agent_address, "update_function": strategy.update_function, "update_args": list(update_args.values()), "gas": strategy.default_gas_update, }), ) contract_api_dialogue = cast(ContractApiDialogue, contract_api_dialogue) contract_api_dialogue.terms = strategy.get_update_terms() self.context.outbox.put_message(message=contract_api_msg) self.context.logger.info("requesting update transaction...")
def _request_create_items_transaction(self, game: Game) -> None: """ Request token create transaction :return: None """ parameters = cast(Parameters, self.context.parameters) contract_api_dialogues = cast( ContractApiDialogues, self.context.contract_api_dialogues ) token_ids = [int(good_id) for good_id in game.conf.good_id_to_name.keys()] + [ int(currency_id) for currency_id in game.conf.currency_id_to_name.keys() ] contract_api_msg, contract_api_dialogue = contract_api_dialogues.create( counterparty=LEDGER_API_ADDRESS, performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION, ledger_id=parameters.ledger_id, contract_id=parameters.contract_id, contract_address=parameters.contract_address, callable=ContractApiDialogue.Callable.GET_CREATE_BATCH_TRANSACTION.value, kwargs=ContractApiMessage.Kwargs( { "deployer_address": self.context.agent_address, "token_ids": token_ids, "gas": parameters.gas, } ), ) contract_api_dialogue = cast(ContractApiDialogue, contract_api_dialogue) contract_api_dialogue.terms = parameters.get_create_token_terms() contract_api_dialogue.callable = ( ContractApiDialogue.Callable.GET_CREATE_BATCH_TRANSACTION ) self.context.outbox.put_message(message=contract_api_msg) self.context.logger.info("requesting create items transaction...")
def _request_approve_transaction(self) -> None: """ Request transaction that approves client contract to spend tokens on behalf of sender :return: None """ strategy = cast(Strategy, self.context.strategy) strategy.is_behaviour_active = False contract_api_dialogues = cast(ContractApiDialogues, self.context.contract_api_dialogues) contract_api_msg, contract_api_dialogue = contract_api_dialogues.create( counterparty=str(LEDGER_API_ADDRESS), performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION, ledger_id=strategy.ledger_id, contract_id=str(FET_ERC20_PUBLIC_ID), contract_address=strategy.erc20_address, callable="get_approve_transaction", kwargs=ContractApiMessage.Kwargs({ "from_address": self.context.agent_address, "spender": strategy.client_contract_address, "amount": strategy.approve_amount, "gas": strategy.default_gas_approve, }), ) contract_api_dialogue = cast(ContractApiDialogue, contract_api_dialogue) contract_api_dialogue.terms = strategy.get_approve_terms() self.context.outbox.put_message(message=contract_api_msg) self.context.logger.info("requesting query transaction...")
async def test_callable_cannot_find(erc1155_contract, ledger_apis_connection, caplog): """Test error messages when an exception is raised while processing the request.""" address = ETHEREUM_ADDRESS_ONE contract_api_dialogues = ContractApiDialogues(address) token_id = 1 contract_address = "0x250A2aeb3eB84782e83365b4c42dbE3CDA9920e4" request, _ = contract_api_dialogues.create( counterparty=str(ledger_apis_connection.connection_id), performative=ContractApiMessage.Performative.GET_STATE, ledger_id=ETHEREUM, contract_id=str(ERC1155_PUBLIC_ID), contract_address=contract_address, callable="unknown_callable", kwargs=ContractApiMessage.Kwargs({ "agent_address": address, "token_id": token_id }), ) envelope = Envelope( to=request.to, sender=request.sender, protocol_id=request.protocol_id, message=request, ) with caplog.at_level(logging.DEBUG, "aea.packages.fetchai.connections.ledger"): await ledger_apis_connection.send(envelope) await asyncio.sleep(0.01) assert f"Cannot find {request.callable} in contract" in caplog.text
def _handle_accept_w_inform( self, fipa_msg: FipaMessage, fipa_dialogue: FipaDialogue ) -> None: """ Handle the ACCEPT_W_INFORM. If the ACCEPT_W_INFORM message contains the signed transaction, sign it too, otherwise do nothing. :param fipa_msg: the message :param fipa_dialogue: the dialogue object :return: None """ tx_signature = fipa_msg.info.get("tx_signature", None) if tx_signature is not None: self.context.logger.info( "received ACCEPT_W_INFORM from sender={}: tx_signature={}".format( fipa_msg.sender[-5:], tx_signature ) ) strategy = cast(Strategy, self.context.strategy) contract_api_dialogues = cast( ContractApiDialogues, self.context.contract_api_dialogues ) contract_api_msg, contract_api_dialogue = contract_api_dialogues.create( counterparty=LEDGER_API_ADDRESS, performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION, ledger_id=strategy.ledger_id, contract_id=strategy.contract_id, contract_address=strategy.contract_address, callable="get_atomic_swap_single_transaction", kwargs=ContractApiMessage.Kwargs( { "from_address": self.context.agent_address, "to_address": fipa_msg.sender, "token_id": int(fipa_dialogue.proposal.values["token_id"]), "from_supply": int( fipa_dialogue.proposal.values["from_supply"] ), "to_supply": int(fipa_dialogue.proposal.values["to_supply"]), "value": int(fipa_dialogue.proposal.values["value"]), "trade_nonce": int( fipa_dialogue.proposal.values["trade_nonce"] ), "signature": tx_signature, } ), ) contract_api_dialogue = cast(ContractApiDialogue, contract_api_dialogue) contract_api_dialogue.terms = strategy.get_single_swap_terms( fipa_dialogue.proposal, fipa_msg.sender ) self.context.outbox.put_message(message=contract_api_msg) self.context.logger.info("requesting single atomic swap transaction...") else: self.context.logger.info( "received ACCEPT_W_INFORM from sender={} with no signature.".format( fipa_msg.sender[-5:] ) )
def _handle_register( self, register_msg: RegisterMessage, register_dialogue: RegisterDialogue ) -> None: """ Handle an register message. :param register_msg: the register message :param register_dialogue: the dialogue :return: None """ self.context.logger.info( f"received register_msg register message={register_msg} in dialogue={register_dialogue}." ) strategy = cast(Strategy, self.context.strategy) is_valid, error_code, error_msg = strategy.valid_registration( register_msg.info, register_msg.sender ) if is_valid: strategy.lock_registration_temporarily( register_msg.sender, register_msg.info ) self.context.logger.info( f"valid registration={register_msg.info}. Verifying if tokens staked." ) contract_api_dialogues = cast( ContractApiDialogues, self.context.contract_api_dialogues ) kwargs = strategy.get_kwargs(register_msg.info) terms = strategy.get_terms(register_msg.sender) contract_api_msg, contract_api_dialogue = contract_api_dialogues.create( counterparty=LEDGER_API_ADDRESS, performative=ContractApiMessage.Performative.GET_STATE, ledger_id=strategy.contract_ledger_id, contract_id=strategy.contract_id, contract_address=strategy.contract_address, callable=strategy.contract_callable, kwargs=ContractApiMessage.Kwargs(kwargs), ) contract_api_dialogue = cast(ContractApiDialogue, contract_api_dialogue) contract_api_dialogue.terms = terms contract_api_dialogue.associated_register_dialogue = register_dialogue self.context.outbox.put_message(contract_api_msg) else: self.context.logger.info( f"invalid registration={register_msg.info}. Rejecting." ) reply = register_dialogue.reply( performative=RegisterMessage.Performative.ERROR, error_code=error_code, error_msg=error_msg, info={}, ) self.context.outbox.put_message(reply)
def _request_mint_items_transaction(self, game: Game) -> None: """ Request token mint transaction :return: None """ if not game.is_allowed_to_mint: return game.is_allowed_to_mint = False agent_state = game.get_next_agent_state_for_minting() if agent_state is None: return name = game.registration.agent_addr_to_name[agent_state.agent_address] self.context.logger.info( f"requesting mint_items transactions for agent={name}." ) parameters = cast(Parameters, self.context.parameters) token_ids = [] # type: List[int] mint_quantities = [] # type: List[int] for good_id, quantity in agent_state.quantities_by_good_id.items(): token_ids.append(int(good_id)) mint_quantities.append(quantity) for currency_id, amount in agent_state.amount_by_currency_id.items(): token_ids.append(int(currency_id)) mint_quantities.append(amount) contract_api_dialogues = cast( ContractApiDialogues, self.context.contract_api_dialogues ) contract_api_msg, contract_api_dialogue = contract_api_dialogues.create( counterparty=LEDGER_API_ADDRESS, performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION, ledger_id=parameters.ledger_id, contract_id=parameters.contract_id, contract_address=parameters.contract_address, callable=ContractApiDialogue.Callable.GET_MINT_BATCH_TRANSACTION.value, kwargs=ContractApiMessage.Kwargs( { "deployer_address": self.context.agent_address, "recipient_address": self.context.agent_address, "token_ids": token_ids, "mint_quantities": mint_quantities, "gas": parameters.gas, } ), ) contract_api_dialogue = cast(ContractApiDialogue, contract_api_dialogue) contract_api_dialogue.terms = parameters.get_mint_token_terms() contract_api_dialogue.callable = ( ContractApiDialogue.Callable.GET_MINT_BATCH_TRANSACTION ) self.context.outbox.put_message(message=contract_api_msg)
def test_setup(self): """Test the setup method of the tac behaviour.""" # operation with patch.object(self.logger, "log") as mock_logger: self.tac_behaviour.setup() # after assert self.game.phase == Phase.CONTRACT_DEPLOYMENT_PROPOSAL self.assert_quantity_in_outbox(2) # first message is produced in superclass (from tac_control skill) which has its own unit tests self.drop_messages_from_outbox(1) # _request_contract_deploy_transaction message = self.get_message_from_outbox() has_attributes, error_str = self.message_has_attributes( actual_message=message, message_type=ContractApiMessage, performative=ContractApiMessage.Performative.GET_DEPLOY_TRANSACTION, to=LEDGER_API_ADDRESS, sender=self.skill.skill_context.agent_address, ledger_id=self.parameters.ledger_id, contract_id=self.parameters.contract_id, callable=ContractApiDialogue.Callable.GET_DEPLOY_TRANSACTION.value, kwargs=ContractApiMessage.Kwargs( {"deployer_address": self.skill.skill_context.agent_address} ), ) assert has_attributes, error_str assert ( cast( ContractApiDialogue, self.contract_api_dialogues.get_dialogue(message) ).terms == self.parameters.get_deploy_terms() ) assert ( cast( ContractApiDialogue, self.contract_api_dialogues.get_dialogue(message) ).callable == ContractApiDialogue.Callable.GET_DEPLOY_TRANSACTION ) mock_logger.assert_any_call( logging.INFO, "requesting contract deployment transaction..." )
async def test_erc1155_get_raw_message(erc1155_contract, ledger_apis_connection): """Test get state with contract erc1155.""" address = ETHEREUM_ADDRESS_ONE contract_address = "0x250A2aeb3eB84782e83365b4c42dbE3CDA9920e4" contract_api_dialogues = ContractApiDialogues(address) request, contract_api_dialogue = contract_api_dialogues.create( counterparty=str(ledger_apis_connection.connection_id), performative=ContractApiMessage.Performative.GET_RAW_MESSAGE, ledger_id=ETHEREUM, contract_id=str(ERC1155_PUBLIC_ID), contract_address=contract_address, callable="get_hash_single", kwargs=ContractApiMessage.Kwargs({ "from_address": address, "to_address": address, "token_id": 1, "from_supply": 10, "to_supply": 0, "value": 0, "trade_nonce": 1, }), ) envelope = Envelope( to=request.to, sender=request.sender, 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) == ContractApiMessage response_message = cast(ContractApiMessage, response.message) assert (response_message.performative == ContractApiMessage.Performative.RAW_MESSAGE), "Error: {}".format( response_message.message) response_dialogue = contract_api_dialogues.update(response_message) assert response_dialogue == contract_api_dialogue assert type(response_message.raw_message) == RawMessage assert response_message.raw_message.ledger_id == ETHEREUM assert type(response.message.raw_message.body) == bytes
async def test_callable_wrong_number_of_arguments_api_and_contract_address( erc1155_contract, ledger_apis_connection): """ Test a contract callable with wrong number of arguments. Test the case of either GET_STATE, GET_RAW_MESSAGE or GET_RAW_TRANSACTION. """ address = ETHEREUM_ADDRESS_ONE contract_api_dialogues = ContractApiDialogues(address) token_id = 1 contract_address = "0x250A2aeb3eB84782e83365b4c42dbE3CDA9920e4" request, _ = contract_api_dialogues.create( counterparty=str(ledger_apis_connection.connection_id), performative=ContractApiMessage.Performative.GET_STATE, ledger_id=ETHEREUM, contract_id=str(ERC1155_PUBLIC_ID), contract_address=contract_address, callable="get_balance", kwargs=ContractApiMessage.Kwargs({ "agent_address": address, "token_id": token_id }), ) envelope = Envelope( to=request.to, sender=request.sender, protocol_id=request.protocol_id, message=request, ) with unittest.mock.patch( "inspect.getfullargspec", return_value=unittest.mock.MagicMock(args=[None])): with unittest.mock.patch.object(ledger_apis_connection._logger, "error") as mock_logger: await ledger_apis_connection.send(envelope) await asyncio.sleep(0.01) response = await ledger_apis_connection.receive() mock_logger.assert_any_call( "Expected two or more positional arguments, got 1") assert (response.message.performative == ContractApiMessage.Performative.ERROR) assert (response.message.message == "Expected two or more positional arguments, got 1")
async def test_callable_wrong_number_of_arguments_apis( erc1155_contract, ledger_apis_connection ): """ Test a contract callable with wrong number of arguments. Test the case of either GET_DEPLOY_TRANSACTION. """ contract, contract_address = erc1155_contract address = ETHEREUM_ADDRESS_ONE contract_api_dialogues = ContractApiDialogues(address) request, _ = contract_api_dialogues.create( counterparty=str(ledger_apis_connection.connection_id), performative=ContractApiMessage.Performative.GET_DEPLOY_TRANSACTION, ledger_id=ETHEREUM, contract_id=str(ERC1155_PUBLIC_ID), callable="get_deploy_transaction", kwargs=ContractApiMessage.Kwargs({}), ) envelope = Envelope(to=request.to, sender=request.sender, message=request,) with unittest.mock.patch( "inspect.getfullargspec", return_value=unittest.mock.MagicMock(args=[]) ): with unittest.mock.patch.object( ledger_apis_connection._contract_dispatcher, "_call_stub", return_value=None ): with unittest.mock.patch.object( ledger_apis_connection._contract_dispatcher.logger, "error" ) as mock_logger: await ledger_apis_connection.send(envelope) await asyncio.sleep(0.01) response = await ledger_apis_connection.receive() mock_logger.assert_any_call( "Exception during contract request: Expected one or more positional arguments, got 0" ) assert ( response.message.performative == ContractApiMessage.Performative.ERROR ) assert ( response.message.message == "Expected one or more positional arguments, got 0" )
async def test_erc1155_get_raw_transaction(erc1155_contract, ledger_apis_connection): """Test get state with contract erc1155.""" address = ETHEREUM_ADDRESS_ONE contract_address = "0x250A2aeb3eB84782e83365b4c42dbE3CDA9920e4" contract_api_dialogues = ContractApiDialogues(address) request, contract_api_dialogue = contract_api_dialogues.create( counterparty=str(ledger_apis_connection.connection_id), performative=ContractApiMessage.Performative.GET_RAW_TRANSACTION, ledger_id=ETHEREUM, contract_id=str(ERC1155_PUBLIC_ID), contract_address=contract_address, callable="get_create_batch_transaction", kwargs=ContractApiMessage.Kwargs({ "deployer_address": address, "token_ids": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }), ) envelope = Envelope( to=request.to, sender=request.sender, 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) == ContractApiMessage response_message = cast(ContractApiMessage, response.message) assert (response_message.performative == ContractApiMessage.Performative. RAW_TRANSACTION), "Error: {}".format(response_message.message) response_dialogue = contract_api_dialogues.update(response_message) assert response_dialogue == contract_api_dialogue assert type(response_message.raw_transaction) == RawTransaction assert response_message.raw_transaction.ledger_id == ETHEREUM assert len(response.message.raw_transaction.body) == 7 assert len(response.message.raw_transaction.body["data"]) > 0
async def test_erc1155_get_state(erc1155_contract, ledger_apis_connection): """Test get state with contract erc1155.""" address = ETHEREUM_ADDRESS_ONE contract_address = "0x250A2aeb3eB84782e83365b4c42dbE3CDA9920e4" contract_api_dialogues = ContractApiDialogues(address) token_id = 1 request, contract_api_dialogue = contract_api_dialogues.create( counterparty=str(ledger_apis_connection.connection_id), performative=ContractApiMessage.Performative.GET_STATE, ledger_id=ETHEREUM, contract_id=str(ERC1155_PUBLIC_ID), contract_address=contract_address, callable="get_balance", kwargs=ContractApiMessage.Kwargs({ "agent_address": address, "token_id": token_id }), ) envelope = Envelope( to=request.to, sender=request.sender, 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) == ContractApiMessage response_message = cast(ContractApiMessage, response.message) assert (response_message.performative == ContractApiMessage.Performative.STATE), "Error: {}".format( response_message.message) response_dialogue = contract_api_dialogues.update(response_message) assert response_dialogue == contract_api_dialogue assert type(response_message.state) == State assert response_message.state.ledger_id == ETHEREUM result = response_message.state.body.get("balance", None) expected_result = {token_id: 0} assert result is not None and result == expected_result
def _handle_propose(self, fipa_msg: FipaMessage, fipa_dialogue: FipaDialogue) -> None: """ Handle the CFP. If the CFP matches the supplied services then send a PROPOSE, otherwise send a DECLINE. :param fipa_msg: the message :param fipa_dialogue: the dialogue object :return: None """ if all(key in [ "contract_address", "from_supply", "to_supply", "value", "trade_nonce", "token_id", ] for key in fipa_msg.proposal.values.keys()): # accept any proposal with the correct keys self.context.logger.info( "[{}]: received valid PROPOSE from sender={}: proposal={}". format( self.context.agent_name, fipa_msg.counterparty[-5:], fipa_msg.proposal.values, )) strategy = cast(Strategy, self.context.strategy) contract_api_dialogues = cast(ContractApiDialogues, self.context.contract_api_dialogues) contract_api_msg = ContractApiMessage( performative=ContractApiMessage.Performative.GET_RAW_MESSAGE, dialogue_reference=contract_api_dialogues. new_self_initiated_dialogue_reference(), ledger_id=strategy.ledger_id, contract_id="fetchai/erc1155:0.6.0", contract_address=fipa_msg.proposal.values["contract_address"], callable="get_hash_single", kwargs=ContractApiMessage.Kwargs({ "from_address": fipa_msg.counterparty, "to_address": self.context.agent_address, "token_id": int(fipa_msg.proposal.values["token_id"]), "from_supply": int(fipa_msg.proposal.values["from_supply"]), "to_supply": int(fipa_msg.proposal.values["to_supply"]), "value": int(fipa_msg.proposal.values["value"]), "trade_nonce": int(fipa_msg.proposal.values["trade_nonce"]), }), ) terms = Terms( ledger_id=strategy.ledger_id, sender_address=self.context.agent_address, counterparty_address=fipa_msg.counterparty, amount_by_currency_id={}, quantities_by_good_id={ str(fipa_msg.proposal.values["token_id"]): int(fipa_msg.proposal.values["from_supply"]) - int(fipa_msg.proposal.values["to_supply"]) }, is_sender_payable_tx_fee=False, nonce=str(fipa_msg.proposal.values["trade_nonce"]), ) contract_api_msg.counterparty = LEDGER_API_ADDRESS contract_api_dialogue = cast( Optional[ContractApiDialogue], contract_api_dialogues.update(contract_api_msg), ) assert (contract_api_dialogue is not None), "Error when creating contract api dialogue." contract_api_dialogue.terms = terms contract_api_dialogue.associated_fipa_dialogue = fipa_dialogue self.context.outbox.put_message(message=contract_api_msg) self.context.logger.info( "[{}]: requesting single hash message from contract api...". format(self.context.agent_name)) else: self.context.logger.info( "[{}]: received invalid PROPOSE from sender={}: proposal={}". format( self.context.agent_name, fipa_msg.counterparty[-5:], fipa_msg.proposal.values, ))
def test_kwargs(): """Test the kwargs custom type.""" body = {"key_1": 1, "key_2": 2} kwargs = ContractApiMessage.Kwargs(body) assert str(kwargs) == "Kwargs: body={}".format(body)