diff --git a/docs/index.md b/docs/index.md index 5d20afea..4246b1f7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -31,7 +31,7 @@ In order to run a local demo service based on the IEKit: 2. Fetch the IEKit. ```bash - autonomy fetch valory/impact_evaluator:0.1.0:bafybeihig5bdamlnm5m6nbyeunku3bmugzn2r5xkemsqwgvh7fiq6sguqm --service + autonomy fetch valory/impact_evaluator:0.1.0:bafybeiazidghbbfiuxzqpuy3rlpqthejwpyl57tkqshaba7oshordufsym --service ``` 3. Build the Docker image of the service agents diff --git a/packages/packages.json b/packages/packages.json index 25552ddc..f301dccc 100644 --- a/packages/packages.json +++ b/packages/packages.json @@ -13,22 +13,22 @@ "connection/valory/openai/0.1.0": "bafybeigyehjbahya5mp7vyp5tjvn36rey4btvzskp3ql3mgxp3zu6gwq5a", "connection/valory/farcaster/0.1.0": "bafybeibbdas7lxbipksodaphjms3uop7vnzjqkroktjq2g6wbvgtlldaxi", "skill/valory/dynamic_nft_abci/0.1.0": "bafybeietq6nqkeze6esw5dwa4cjajluzd2tvg24hlg2pihxz2v67vxorpu", - "skill/valory/twitter_scoring_abci/0.1.0": "bafybeiedultjq4wokxuchbr4nv7m3y3mqq6qwtir6m5epggnbgew6yb24i", + "skill/valory/twitter_scoring_abci/0.1.0": "bafybeibviksrbdkg5ewyhy7iz7ob5eqks3dxethmrhbff264mtul5um7am", "skill/valory/ceramic_read_abci/0.1.0": "bafybeiede3ehp4bfpbk23gncj52goq62rd3rm5wwlbyaexxrfohucdcpia", "skill/valory/ceramic_write_abci/0.1.0": "bafybeiemid3ipekyqupbqpfw55g7b2wwx56g2ita73rjalk6fyqgneroam", - "skill/valory/impact_evaluator_abci/0.1.0": "bafybeifbgoisaa553l6oi5odt5d24hqwdz3ev6eqffh4tqkfzd73l3f6uu", + "skill/valory/impact_evaluator_abci/0.1.0": "bafybeiebnecjdt46qfwhtk5ok5l3fu2y3vka76k2ickazkmkktjkt2wihi", "skill/valory/generic_scoring_abci/0.1.0": "bafybeidxytbreu7sudoggnfjxpbfxsxwbis6dipokkq6uo23xaautnwca4", "skill/valory/twitter_write_abci/0.1.0": "bafybeid377kr5f3dmb5nyhvucglyaaqkuhthxkfosgl54zskwmsuwz56ie", "skill/valory/llm_abci/0.1.0": "bafybeibmckwphs5zqdfnutktwgq7bxfw2auhsxezoopkep5dadkuwqvwgy", "skill/valory/decision_making_abci/0.1.0": "bafybeigsywkfb4lujy4y2c5tsmr2iulq7s6uad7uv2fbiwv7awxz5wfbi4", "skill/valory/olas_week_abci/0.1.0": "bafybeifvhx6issf3xzesjihtbl63ymfrdvzfp4lqrg7liesyes4aiaydfm", - "skill/valory/mech_interact_abci/0.1.0": "bafybeigto5ssrbrbqmeoc6wijcly2klmrhfcnaioa5u3wsofdm7bccowcq", + "skill/valory/mech_interact_abci/0.1.0": "bafybeiesl4k7lkvubzf42hduoxrmruwlmimscxltw6l5nq57shfb3l632y", "skill/valory/farcaster_write_abci/0.1.0": "bafybeihiayft7ovmijrstdo6m7fd5pqnqi7z2mximljpeskambbgo6476q", "skill/valory/farcaster_test_abci/0.1.0": "bafybeidkrbog6z54364dor5irf5tlebhaxy4btnmb2cgobpswqfh6cfk5i", - "agent/valory/impact_evaluator/0.1.0": "bafybeifhygewmf2pdq4vyeiwucoutziaw6nral34pxjtwjgybjp5rfu4aq", + "agent/valory/impact_evaluator/0.1.0": "bafybeia7bsxknskfv623j2jdqdrarenim3kuffnlyle72r7fipdtf2p4x4", "agent/valory/farcaster_test/0.1.0": "bafybeihelkwq4ocgpdkiglclwhigklp67clhjkaabg7dkiduw5apb6zwbe", - "service/valory/impact_evaluator/0.1.0": "bafybeihig5bdamlnm5m6nbyeunku3bmugzn2r5xkemsqwgvh7fiq6sguqm", - "service/valory/impact_evaluator_local/0.1.0": "bafybeiflg7sn26pqmvkvm7feohjolorwtutqqwc3kk7d4uqamr3qzi5xpq" + "service/valory/impact_evaluator/0.1.0": "bafybeiazidghbbfiuxzqpuy3rlpqthejwpyl57tkqshaba7oshordufsym", + "service/valory/impact_evaluator_local/0.1.0": "bafybeiflgpcafwijrrvsokzx32gbn2tkajgfrpprdkzcogcbsyw426offe" }, "third_party": { "protocol/open_aea/signing/1.0.0": "bafybeihv62fim3wl2bayavfcg3u5e5cxu3b7brtu4cn5xoxd6lqwachasi", diff --git a/packages/valory/agents/impact_evaluator/aea-config.yaml b/packages/valory/agents/impact_evaluator/aea-config.yaml index 6e206c9a..19ae6b7b 100644 --- a/packages/valory/agents/impact_evaluator/aea-config.yaml +++ b/packages/valory/agents/impact_evaluator/aea-config.yaml @@ -43,9 +43,9 @@ protocols: skills: - valory/abstract_abci:0.1.0:bafybeieeaseuy5rbbw465knz27vccvpkfge43q7isl7fkdlfapwd7bpi24 - valory/abstract_round_abci:0.1.0:bafybeib733xfbndtpvkf44mtk7oyodnficgloo6xhn7xmqxxeos33es65u -- valory/impact_evaluator_abci:0.1.0:bafybeifbgoisaa553l6oi5odt5d24hqwdz3ev6eqffh4tqkfzd73l3f6uu +- valory/impact_evaluator_abci:0.1.0:bafybeiebnecjdt46qfwhtk5ok5l3fu2y3vka76k2ickazkmkktjkt2wihi - valory/generic_scoring_abci:0.1.0:bafybeidxytbreu7sudoggnfjxpbfxsxwbis6dipokkq6uo23xaautnwca4 -- valory/twitter_scoring_abci:0.1.0:bafybeiedultjq4wokxuchbr4nv7m3y3mqq6qwtir6m5epggnbgew6yb24i +- valory/twitter_scoring_abci:0.1.0:bafybeibviksrbdkg5ewyhy7iz7ob5eqks3dxethmrhbff264mtul5um7am - valory/ceramic_read_abci:0.1.0:bafybeiede3ehp4bfpbk23gncj52goq62rd3rm5wwlbyaexxrfohucdcpia - valory/ceramic_write_abci:0.1.0:bafybeiemid3ipekyqupbqpfw55g7b2wwx56g2ita73rjalk6fyqgneroam - valory/dynamic_nft_abci:0.1.0:bafybeietq6nqkeze6esw5dwa4cjajluzd2tvg24hlg2pihxz2v67vxorpu @@ -57,7 +57,7 @@ skills: - valory/decision_making_abci:0.1.0:bafybeigsywkfb4lujy4y2c5tsmr2iulq7s6uad7uv2fbiwv7awxz5wfbi4 - valory/llm_abci:0.1.0:bafybeibmckwphs5zqdfnutktwgq7bxfw2auhsxezoopkep5dadkuwqvwgy - valory/olas_week_abci:0.1.0:bafybeifvhx6issf3xzesjihtbl63ymfrdvzfp4lqrg7liesyes4aiaydfm -- valory/mech_interact_abci:0.1.0:bafybeigto5ssrbrbqmeoc6wijcly2klmrhfcnaioa5u3wsofdm7bccowcq +- valory/mech_interact_abci:0.1.0:bafybeiesl4k7lkvubzf42hduoxrmruwlmimscxltw6l5nq57shfb3l632y default_ledger: ethereum required_ledgers: - ethereum diff --git a/packages/valory/services/impact_evaluator/service.yaml b/packages/valory/services/impact_evaluator/service.yaml index 426bb934..526ddaf2 100644 --- a/packages/valory/services/impact_evaluator/service.yaml +++ b/packages/valory/services/impact_evaluator/service.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 fingerprint: README.md: bafybeign56hilwuoa6bgos3uqabss4gew4vadkik7vhj3ucpqw6nxtqtpe fingerprint_ignore_patterns: [] -agent: valory/impact_evaluator:0.1.0:bafybeifhygewmf2pdq4vyeiwucoutziaw6nral34pxjtwjgybjp5rfu4aq +agent: valory/impact_evaluator:0.1.0:bafybeia7bsxknskfv623j2jdqdrarenim3kuffnlyle72r7fipdtf2p4x4 number_of_agents: 4 deployment: agent: diff --git a/packages/valory/services/impact_evaluator_local/service.yaml b/packages/valory/services/impact_evaluator_local/service.yaml index 6bbe6fa1..c6e7e6df 100644 --- a/packages/valory/services/impact_evaluator_local/service.yaml +++ b/packages/valory/services/impact_evaluator_local/service.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 fingerprint: README.md: bafybeign56hilwuoa6bgos3uqabss4gew4vadkik7vhj3ucpqw6nxtqtpe fingerprint_ignore_patterns: [] -agent: valory/impact_evaluator:0.1.0:bafybeifhygewmf2pdq4vyeiwucoutziaw6nral34pxjtwjgybjp5rfu4aq +agent: valory/impact_evaluator:0.1.0:bafybeia7bsxknskfv623j2jdqdrarenim3kuffnlyle72r7fipdtf2p4x4 number_of_agents: 1 deployment: agent: diff --git a/packages/valory/skills/impact_evaluator_abci/skill.yaml b/packages/valory/skills/impact_evaluator_abci/skill.yaml index 1e7b1b2e..2b64388c 100644 --- a/packages/valory/skills/impact_evaluator_abci/skill.yaml +++ b/packages/valory/skills/impact_evaluator_abci/skill.yaml @@ -26,7 +26,7 @@ skills: - valory/abstract_round_abci:0.1.0:bafybeib733xfbndtpvkf44mtk7oyodnficgloo6xhn7xmqxxeos33es65u - valory/ceramic_read_abci:0.1.0:bafybeiede3ehp4bfpbk23gncj52goq62rd3rm5wwlbyaexxrfohucdcpia - valory/generic_scoring_abci:0.1.0:bafybeidxytbreu7sudoggnfjxpbfxsxwbis6dipokkq6uo23xaautnwca4 -- valory/twitter_scoring_abci:0.1.0:bafybeiedultjq4wokxuchbr4nv7m3y3mqq6qwtir6m5epggnbgew6yb24i +- valory/twitter_scoring_abci:0.1.0:bafybeibviksrbdkg5ewyhy7iz7ob5eqks3dxethmrhbff264mtul5um7am - valory/ceramic_write_abci:0.1.0:bafybeiemid3ipekyqupbqpfw55g7b2wwx56g2ita73rjalk6fyqgneroam - valory/dynamic_nft_abci:0.1.0:bafybeietq6nqkeze6esw5dwa4cjajluzd2tvg24hlg2pihxz2v67vxorpu - valory/registration_abci:0.1.0:bafybeibc7duasoaw5b4ene5oxfba2dmdzstsrws6ipi57ymgdtoxjadn54 @@ -37,7 +37,7 @@ skills: - valory/llm_abci:0.1.0:bafybeibmckwphs5zqdfnutktwgq7bxfw2auhsxezoopkep5dadkuwqvwgy - valory/twitter_write_abci:0.1.0:bafybeid377kr5f3dmb5nyhvucglyaaqkuhthxkfosgl54zskwmsuwz56ie - valory/olas_week_abci:0.1.0:bafybeifvhx6issf3xzesjihtbl63ymfrdvzfp4lqrg7liesyes4aiaydfm -- valory/mech_interact_abci:0.1.0:bafybeigto5ssrbrbqmeoc6wijcly2klmrhfcnaioa5u3wsofdm7bccowcq +- valory/mech_interact_abci:0.1.0:bafybeiesl4k7lkvubzf42hduoxrmruwlmimscxltw6l5nq57shfb3l632y behaviours: main: args: {} diff --git a/packages/valory/skills/mech_interact_abci/skill.yaml b/packages/valory/skills/mech_interact_abci/skill.yaml index 75a92b9d..b4c00945 100644 --- a/packages/valory/skills/mech_interact_abci/skill.yaml +++ b/packages/valory/skills/mech_interact_abci/skill.yaml @@ -25,12 +25,13 @@ fingerprint: states/request.py: bafybeifdkqn4o2tx57yflnxfhy6eoy42z7bdpadcevre64aw7l2hh2kpjy states/response.py: bafybeibaxnp2oxwjptoq7qzm6o7ww2qrdj2vnxzg2qt523vz2ftqzx5hyi tests/__init__.py: bafybeifojfnffwlsv6aiku25nwyjwm7h4m45yci3fgmaawpeoyoogzonum - tests/test_behaviours.py: bafybeidj7git7zaego7k75eejtxlr3usj6wnnqisu7urqwvalpwh5w7nyq + tests/test_behaviours.py: bafybeid34kv6ho6xzynppy3olrsuoau5ia6gpxy5ii4wkog2piqn2rmfre tests/test_dialogues.py: bafybeig6uzk7fklieyxapemiobdvv5tyx7hgdkdpl4vnacohgw2ecphdpq tests/test_handlers.py: bafybeidwrmekr5tydmehvkolyksw37sah5js7buy3ca5fxkpgkppmgb3wi - tests/test_models.py: bafybeid3cvcttdxlklwvr6tqmiurb2qywvmgr5bnsn62pb5gl5p552eagy + tests/test_models.py: bafybeifakxkpvq6p6nkva3kpy7odnefvjnjurcva5anwlxv6qlo6agxtyu tests/test_payloads.py: bafybeiakqhgochfu4ra4hp65hi7jvxtjd7fdub5wqmhlccrc4va26hb7da tests/test_rounds.py: bafybeiauu5adaoxu7yvtrfa6uwdw4sxr5gn2pj7qjh6vowd556iji6vtca + tests/test_states_base.py: bafybeigognrbwfajutxxzssprfnwu3s67zfuhckerwhzdf6d2wbgt7zg24 fingerprint_ignore_patterns: [] connections: [] contracts: diff --git a/packages/valory/skills/mech_interact_abci/tests/test_behaviours.py b/packages/valory/skills/mech_interact_abci/tests/test_behaviours.py index 2905d0b7..79425314 100644 --- a/packages/valory/skills/mech_interact_abci/tests/test_behaviours.py +++ b/packages/valory/skills/mech_interact_abci/tests/test_behaviours.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # -# Copyright 2023 Valory AG +# Copyright 2023-2024 Valory AG # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -21,15 +21,22 @@ from dataclasses import dataclass, field from pathlib import Path -from typing import Any, Dict, Hashable, Optional, Type +from typing import Any, Dict, Hashable, Optional, Type, cast +from unittest import mock +from unittest.mock import MagicMock import pytest +from packages.valory.protocols.contract_api import ContractApiMessage from packages.valory.skills.abstract_round_abci.base import AbciAppDB +from packages.valory.skills.abstract_round_abci.behaviour_utils import ( + make_degenerate_behaviour, +) from packages.valory.skills.abstract_round_abci.behaviours import BaseBehaviour from packages.valory.skills.abstract_round_abci.test_tools.base import ( FSMBehaviourBaseCase, ) +from packages.valory.skills.abstract_round_abci.tests.test_common import dummy_generator from packages.valory.skills.mech_interact_abci.behaviours.base import ( MechInteractBaseBehaviour, ) @@ -42,10 +49,14 @@ from packages.valory.skills.mech_interact_abci.behaviours.round_behaviour import ( MechInteractRoundBehaviour, ) +from packages.valory.skills.mech_interact_abci.models import SharedState from packages.valory.skills.mech_interact_abci.states.base import ( Event, SynchronizedData, ) +from packages.valory.skills.mech_interact_abci.states.final_states import ( + FinishedMechRequestRound, +) @dataclass @@ -55,6 +66,7 @@ class BehaviourTestCase: name: str initial_data: Dict[str, Hashable] event: Event + return_value: Any kwargs: Dict[str, Any] = field(default_factory=dict) @@ -80,11 +92,14 @@ def fast_forward(self, data: Optional[Dict[str, Any]] = None) -> None: data = data if data is not None else {} self.fast_forward_to_behaviour( - self.behaviour, - self.behaviour_class.behaviour_id, + self.behaviour, # type: ignore + self.behaviour_class.auto_behaviour_id(), SynchronizedData(AbciAppDB(setup_data=AbciAppDB.data_to_lists(data))), ) - assert self.current_behaviour_id == self.behaviour_class.behaviour_id + assert ( + self.behaviour.current_behaviour.auto_behaviour_id() # type: ignore + == self.behaviour_class.auto_behaviour_id() + ) def complete(self, event: Event) -> None: """Complete test""" @@ -93,25 +108,110 @@ def complete(self, event: Event) -> None: self.mock_a2a_transaction() self._test_done_flag_set() self.end_round(done_event=event) - assert self.current_behaviour_id == self.next_behaviour_class.behaviour_id + assert ( + self.behaviour.current_behaviour.auto_behaviour_id() # type: ignore + == self.next_behaviour_class.auto_behaviour_id() + ) class TestMechRequestBehaviour(BaseMechInteractTest): """Tests MechRequestBehaviour""" - # TODO: set next_behaviour_class behaviour_class: Type[BaseBehaviour] = MechRequestBehaviour - next_behaviour_class: Type[BaseBehaviour] = ... - - # TODO: provide test cases - @pytest.mark.parametrize("test_case", []) - def test_run(self, test_case: BehaviourTestCase) -> None: + next_behaviour_class: Type[BaseBehaviour] = make_degenerate_behaviour( + FinishedMechRequestRound + ) + + @pytest.mark.parametrize( + "test_case, kwargs", + [ + ( + BehaviourTestCase( + "Happy path - no mech request", + initial_data=dict(mech_requests=[]), + event=Event.DONE, + return_value={ + "ledger": None, + "contract": None, + "metadata_hash": None, + "multisend_safe_tx_hash": None, + }, + ), + {}, + ), + ( + BehaviourTestCase( + "Happy path", + initial_data=dict( + mech_requests='[{"prompt": "dummy_prompt_1", "tool": "dummy_tool_1", "nonce": "dummy_nonce_1"}, {"prompt": "dummy_prompt_2", "tool": "dummy_tool_2", "nonce": "dummy_nonce_2"}]', + safe_contract_address="mock_safe_contract_address", + ), + event=Event.DONE, + return_value={ + "ledger": MagicMock( + state=MagicMock(body={"get_balance_result": "10"}) + ), + "contract": MagicMock( + performative=ContractApiMessage.Performative.RAW_TRANSACTION, + raw_transaction=MagicMock( + body={ + "token": 10, + "wallet": "mock_safe_contract_address", + "data": "0x0000deadbeef0000", + "request_data": "dummy_request_data", + } + ), + ), + "metadata_hash": "QmTzQ1iVRmDDeh8aW5HX99o9dsPwzUo9tb5w1DLT8PaJfM", + "multisend_safe_tx_hash": MagicMock( + performative=ContractApiMessage.Performative.STATE, + state=MagicMock( + body={ + "tx_hash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ), + ), + }, + ), + {}, + ), + ], + ) + def test_run(self, test_case: BehaviourTestCase, kwargs) -> None: """Run tests.""" - - self.fast_forward(test_case.initial_data) - # TODO: mock the necessary calls - # self.mock_ ... - self.complete(test_case.event) + with mock.patch.object( + MechRequestBehaviour, + "get_ledger_api_response", + dummy_generator(test_case.return_value["ledger"]), + ), mock.patch.object( + MechRequestBehaviour, + "get_contract_api_response", + dummy_generator(test_case.return_value["contract"]), + ), mock.patch.object( + MechRequestBehaviour, + "send_to_ipfs", + dummy_generator(test_case.return_value["metadata_hash"]), + ): + params = cast(SharedState, self._skill.skill_context.params) + params.__dict__["_frozen"] = False + params.mech_request_price = 1 + params.mech_contract_address = "dummy_mech_contract_address" + self.fast_forward(test_case.initial_data) + self.behaviour.act_wrapper() + self.behaviour.act_wrapper() + self.behaviour.act_wrapper() + self.behaviour.act_wrapper() + self.behaviour.act_wrapper() + self.behaviour.act_wrapper() + self.behaviour.act_wrapper() + + with mock.patch.object( + MechRequestBehaviour, + "get_contract_api_response", + dummy_generator(test_case.return_value["multisend_safe_tx_hash"]), + ): + self.behaviour.act_wrapper() + self.complete(test_case.event) class TestMechResponseBehaviour(BaseMechInteractTest): diff --git a/packages/valory/skills/mech_interact_abci/tests/test_models.py b/packages/valory/skills/mech_interact_abci/tests/test_models.py index 1b18face..f4355076 100644 --- a/packages/valory/skills/mech_interact_abci/tests/test_models.py +++ b/packages/valory/skills/mech_interact_abci/tests/test_models.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # -# Copyright 2023 Valory AG +# Copyright 2023-2024 Valory AG # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,9 +18,37 @@ # ------------------------------------------------------------------------------ """Test the models.py module of the MechInteract.""" +import pytest +from hexbytes import HexBytes from packages.valory.skills.abstract_round_abci.test_tools.base import DummyContext -from packages.valory.skills.mech_interact_abci.models import SharedState +from packages.valory.skills.abstract_round_abci.tests.test_models import ( + BASE_DUMMY_PARAMS, + BASE_DUMMY_SPECS_CONFIG, +) +from packages.valory.skills.mech_interact_abci.models import ( + MechParams, + MechResponseSpecs, + MultisendBatch, + SharedState, +) + + +class TestMechResponseSpecs: + """Test MechResponseSpecs of MechInteract models.""" + + def test_initialization(self) -> None: + """Test initialization.""" + MechResponseSpecs( + **BASE_DUMMY_SPECS_CONFIG, + response_key="value", + response_index=0, + response_type="float", + error_key="error", + error_index=None, + error_type="str", + error_data="error text", + ) class TestSharedState: @@ -29,3 +57,44 @@ class TestSharedState: def test_initialization(self) -> None: """Test initialization.""" SharedState(name="", skill_context=DummyContext()) + + +class TestMechParams: + """Test MechParams of MechInteract models.""" + + def setup(self) -> None: + """Set up the tests.""" + self.mech_params = MechParams( + **BASE_DUMMY_PARAMS, + multisend_address="dummy_multisend_address", + multisend_batch_size=1, + mech_contract_address="dummy_mech_contract_address", + ipfs_address="dummy_ipfs_address", + mech_interaction_sleep_time=1, + ) + + def test_initialization(self) -> None: + """Test initialization""" + assert isinstance(self.mech_params, MechParams) + + @pytest.mark.parametrize( + "dummy_ipfs_address", ["dummy_ipfs_address", "dummy_ipfs_address/"] + ) + def test_ipfs_address(self, dummy_ipfs_address) -> None: + """Test ipfs address.""" + print(self.mech_params.ipfs_address) + self.mech_params.__dict__["_frozen"] = False + self.mech_params._ipfs_address = dummy_ipfs_address + ipfs_address = self.mech_params.ipfs_address + assert ipfs_address == "dummy_ipfs_address/" + + +class TestMultisendBatch: + """Test MultisendBatch of MechInteract models.""" + + def test_initialization(self) -> None: + """Test initialization.""" + MultisendBatch( + to="", + data=HexBytes("0xabcdef1234567890"), + ) diff --git a/packages/valory/skills/mech_interact_abci/tests/test_states_base.py b/packages/valory/skills/mech_interact_abci/tests/test_states_base.py new file mode 100644 index 00000000..87a14cfb --- /dev/null +++ b/packages/valory/skills/mech_interact_abci/tests/test_states_base.py @@ -0,0 +1,210 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2023-2024 Valory AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ +"""This module contains the tests for the state/base of the mech interact abci app.""" + +from typing import Mapping +from unittest.mock import MagicMock + +from packages.valory.skills.abstract_round_abci.base import AbciAppDB +from packages.valory.skills.mech_interact_abci.payloads import ( + MechRequestPayload, + MechResponsePayload, +) +from packages.valory.skills.mech_interact_abci.states.base import ( + Event, + MechInteractionResponse, + MechInteractionRound, + MechMetadata, + MechRequest, + SynchronizedData, +) + + +class TestEvent: + """Test the Event class of MechInteract.""" + + def test_import(self) -> None: + """Test import.""" + assert Event.DONE.value == "done" + assert Event.NO_MAJORITY.value == "no_majority" + assert Event.ROUND_TIMEOUT.value == "round_timeout" + assert Event.SKIP_REQUEST.value == "skip_request" + + +class TestMechMetaData: + """Test the MechMetaData of MechInteract.""" + + def test_initialization(self) -> None: + """Test initialization.""" + MechMetadata(prompt="dummy_prompt", tool="dummy_tool", nonce="dummy_nonce") + + +class TestMechRequest: + """Test MechRequest of MechInteract.""" + + def test_initialization(self) -> None: + """Test Initialization.""" + MechRequest() + + +class TestMechInteractionResponse: + """Test MechInteractionResponse of MechInteract.""" + + def test_initialization(self) -> None: + """Test initialization.""" + MechInteractionResponse() + + def test_retries_exceeded(self) -> None: + """Test retries exceeded.""" + mech_interact_response = MechInteractionResponse() + mech_interact_response.retries_exceeded() + assert ( + mech_interact_response.error + == "Retries were exceeded while trying to get the mech's response." + ) + + def test_incorrect_format(self) -> None: + """Test incorrect format.""" + mech_interact_response = MechInteractionResponse() + mech_interact_response.incorrect_format("dummy_res") + print(mech_interact_response.error) + assert ( + mech_interact_response.error + == "The response's format was unexpected: dummy_res" + ) + + +class TestSynchronizedData: + """Test SynchronizedData of Base States of MechInteract.""" + + def setup(self) -> None: + """Set up the tests.""" + self.synchronized_data = SynchronizedData( + db=AbciAppDB(setup_data=dict(participants=[])) + ) + self.synchronized_data.update(**dict(mech_price=1)) + self.synchronized_data.update( + **dict( + mech_requests='[{"prompt": "dummy_prompt_1", "tool": "dummy_tool_1", "nonce": "dummy_nonce_1"}, {"prompt": "dummy_prompt_2", "tool": "dummy_tool_2", "nonce": "dummy_nonce_2"}]' + ) + ) + self.synchronized_data.update( + **dict( + mech_responses=[{"nonce": "dummy_nonce_1", "result": "dummy_result_1"}] + ) + ) + self.synchronized_data.update( + **dict( + participant_to_requests={ + "dummy_sender": { + "round_count": -1, + "id_": "dummy_id", + "tx_submitter": "dummy_tx_submitter", + "tx_hash": "dummy_tx_hash", + "price": 1, + "mech_requests": "dummy_mech_requests", + "mech_responses": "dummy_mech_responses", + "sender": "dummy_sender", + "chain_id": 1, + "_metaclass_registry_key": "packages.valory.skills.mech_interact_abci.payloads.MechRequestPayload", + } + } + ) + ) + self.synchronized_data.update( + **dict( + participant_to_responses={ + "dummy_sender": { + "round_count": -1, + "id_": "dummy_id", + "sender": "dummy_sender", + "mech_responses": "dummy_mech_responses", + "_metaclass_registry_key": "packages.valory.skills.mech_interact_abci.payloads.MechResponsePayload", + } + } + ) + ) + self.synchronized_data.update(**dict(final_tx_hash="dummy_tx_hash")) + self.synchronized_data.update(**dict(chain_id="dummy_chain_id")) + self.synchronized_data.update(**dict(tx_submitter=1)) + + def test_initialization(self) -> None: + """Test initialization.""" + assert isinstance(self.synchronized_data, SynchronizedData) + + def test_mech_price(self) -> None: + """Test mech price.""" + assert self.synchronized_data.mech_price == 1 + + def test_mech_requests(self) -> None: + """Test mech requests.""" + assert self.synchronized_data.mech_requests == [ + MechMetadata( + prompt="dummy_prompt_1", tool="dummy_tool_1", nonce="dummy_nonce_1" + ), + MechMetadata( + prompt="dummy_prompt_2", tool="dummy_tool_2", nonce="dummy_nonce_2" + ), + ] + + def test_mech_responses(self) -> None: + """Test mech responses.""" + assert self.synchronized_data.mech_responses == [ + MechInteractionResponse( + data="", + requestId=0, + nonce="dummy_nonce_1", + result="dummy_result_1", + error="Unknown", + ) + ] + + def test_participant_to_requests(self) -> None: + """Test participant to requests.""" + assert isinstance(self.synchronized_data.participant_to_requests, Mapping) + for key, value in self.synchronized_data.participant_to_requests.items(): + assert isinstance(key, str) + assert isinstance(value, MechRequestPayload) + + def test_participant_to_responses(self) -> None: + """Test participant to responses.""" + assert isinstance(self.synchronized_data.participant_to_responses, Mapping) + for key, value in self.synchronized_data.participant_to_responses.items(): + assert isinstance(key, str) + assert isinstance(value, MechResponsePayload) + + def test_final_tx_hash(self) -> None: + """Test final tx hash.""" + assert self.synchronized_data.final_tx_hash == "dummy_tx_hash" + + def test_chain_id(self) -> None: + """Test chain id.""" + assert self.synchronized_data.chain_id == "dummy_chain_id" + + def test_tx_submitter(self) -> None: + """Test tx submitter.""" + assert self.synchronized_data.tx_submitter == "1" + + +class TestMechInteractionRound: + """Test MechInteractionRound of MechInteract.""" + + def test_initialization(self) -> None: + """Test initialization.""" + MechInteractionRound(synchronized_data=MagicMock(), context=MagicMock()) diff --git a/packages/valory/skills/twitter_scoring_abci/skill.yaml b/packages/valory/skills/twitter_scoring_abci/skill.yaml index 8155e05d..b2198e1f 100644 --- a/packages/valory/skills/twitter_scoring_abci/skill.yaml +++ b/packages/valory/skills/twitter_scoring_abci/skill.yaml @@ -31,7 +31,7 @@ protocols: skills: - valory/abstract_round_abci:0.1.0:bafybeib733xfbndtpvkf44mtk7oyodnficgloo6xhn7xmqxxeos33es65u - valory/decision_making_abci:0.1.0:bafybeigsywkfb4lujy4y2c5tsmr2iulq7s6uad7uv2fbiwv7awxz5wfbi4 -- valory/mech_interact_abci:0.1.0:bafybeigto5ssrbrbqmeoc6wijcly2klmrhfcnaioa5u3wsofdm7bccowcq +- valory/mech_interact_abci:0.1.0:bafybeiesl4k7lkvubzf42hduoxrmruwlmimscxltw6l5nq57shfb3l632y behaviours: main: args: {}