diff --git a/packages/packages.json b/packages/packages.json index 154c8763..dec14849 100644 --- a/packages/packages.json +++ b/packages/packages.json @@ -16,14 +16,14 @@ "contract/valory/staking_token/0.1.0": "bafybeig4fl35dn7d5gnprux2nwsqbirm7zkiujz3xvrwcjuktz6hkq4as4", "contract/valory/relayer/0.1.0": "bafybeihzgjyvhtorugjw3yldznqsbwo3aqpxowm7k2nrvj6qtwpsc7jl7u", "skill/valory/market_manager_abci/0.1.0": "bafybeig44vtxcq7aarqkg2mskly3zwwnyfc45rtdvorwz6ywspwg3obqn4", - "skill/valory/decision_maker_abci/0.1.0": "bafybeiejbfkl4im6srigta53ysan3tu5hlbb44cbd2mgryp2hsanyxpdge", - "skill/valory/trader_abci/0.1.0": "bafybeigfccxw5v76pectrmh2a3ibd4gt2hhtskkqay6an3g7lgdyotuz34", - "skill/valory/tx_settlement_multiplexer_abci/0.1.0": "bafybeiaiek6b3p7dro45qjoecmgseznhixhrgqgxfiap7lqw4rbi5fyhvy", + "skill/valory/decision_maker_abci/0.1.0": "bafybeiapszwgdpq6ipu5ffjgzi3r7ylyuaju6n26xalclnnixnzprnynuu", + "skill/valory/trader_abci/0.1.0": "bafybeidvlov6ktapczwfeipyaalakbvb4eqcw6brctxzp6hqplf2pfpr7a", + "skill/valory/tx_settlement_multiplexer_abci/0.1.0": "bafybeiggsvl7zxifj3haydd4njb3griljqpr4wledvqi3gh2lvcbbphxdq", "skill/valory/staking_abci/0.1.0": "bafybeidubhfvlf6x627t4wetc6ran5sb4pttjphyhv6vefp2a4kcuca2be", "skill/valory/check_stop_trading_abci/0.1.0": "bafybeiboctfgetji6xlzw2buts5zsejnlrrhqkppme2p6fwzu26zznb324", - "agent/valory/trader/0.1.0": "bafybeiaxm4ts4odvhmbltyaa7rngm6jio7b4fdwvwszahw2ndfjdpd547a", - "service/valory/trader/0.1.0": "bafybeig3dk2wuzspnu7aeop2wbxd7sfe5yjlsj3yreen6v6vrtqwj4htyq", - "service/valory/trader_pearl/0.1.0": "bafybeicnm3uxoo7xfotbuhiafqalhfai2etkj5pqha6v4gejy4ilg5lcom" + "agent/valory/trader/0.1.0": "bafybeicpf66igauitqbhnt24scqrmlxfu6ervkfyq2tucejxxz33f2rbtu", + "service/valory/trader/0.1.0": "bafybeifkkqoxce4gjueffcuhmwpu76r7oynfxzonphy4dr5euk6r6fkwhe", + "service/valory/trader_pearl/0.1.0": "bafybeibf6w4xnjii2nbzvsykmes3rreedogvmiggl2ih7djis4fzkhaodu" }, "third_party": { "protocol/open_aea/signing/1.0.0": "bafybeihv62fim3wl2bayavfcg3u5e5cxu3b7brtu4cn5xoxd6lqwachasi", diff --git a/packages/valory/agents/trader/aea-config.yaml b/packages/valory/agents/trader/aea-config.yaml index 6ce00db8..b184b170 100644 --- a/packages/valory/agents/trader/aea-config.yaml +++ b/packages/valory/agents/trader/aea-config.yaml @@ -47,10 +47,10 @@ skills: - valory/reset_pause_abci:0.1.0:bafybeiameewywqigpupy3u2iwnkfczeiiucue74x2l5lbge74rmw6bgaie - valory/termination_abci:0.1.0:bafybeif2zim2de356eo3sipkmoev5emwadpqqzk3huwqarywh4tmqt3vzq - valory/transaction_settlement_abci:0.1.0:bafybeic3tccdjypuge2lewtlgprwkbb53lhgsgn7oiwzyrcrrptrbeyote -- valory/tx_settlement_multiplexer_abci:0.1.0:bafybeiaiek6b3p7dro45qjoecmgseznhixhrgqgxfiap7lqw4rbi5fyhvy +- valory/tx_settlement_multiplexer_abci:0.1.0:bafybeiggsvl7zxifj3haydd4njb3griljqpr4wledvqi3gh2lvcbbphxdq - valory/market_manager_abci:0.1.0:bafybeig44vtxcq7aarqkg2mskly3zwwnyfc45rtdvorwz6ywspwg3obqn4 -- valory/decision_maker_abci:0.1.0:bafybeiejbfkl4im6srigta53ysan3tu5hlbb44cbd2mgryp2hsanyxpdge -- valory/trader_abci:0.1.0:bafybeigfccxw5v76pectrmh2a3ibd4gt2hhtskkqay6an3g7lgdyotuz34 +- valory/decision_maker_abci:0.1.0:bafybeiapszwgdpq6ipu5ffjgzi3r7ylyuaju6n26xalclnnixnzprnynuu +- valory/trader_abci:0.1.0:bafybeidvlov6ktapczwfeipyaalakbvb4eqcw6brctxzp6hqplf2pfpr7a - valory/staking_abci:0.1.0:bafybeidubhfvlf6x627t4wetc6ran5sb4pttjphyhv6vefp2a4kcuca2be - valory/check_stop_trading_abci:0.1.0:bafybeiboctfgetji6xlzw2buts5zsejnlrrhqkppme2p6fwzu26zznb324 - valory/mech_interact_abci:0.1.0:bafybeih2cck5xu6yaibomwtm5zbcp6llghr3ighdnk56fzwu3ihu5xx35e @@ -192,7 +192,6 @@ models: bet_threshold: ${int:100000000000000000} blacklisting_duration: ${int:3600} ipfs_address: ${str:https://gateway.autonolas.tech/ipfs/} - tools_accuracy_hash: ${str:QmR8etyW3TPFadNtNrW54vfnFqmh8vBrMARWV76EmxCZyk} prompt_template: ${str:With the given question "@{question}" and the `yes` option represented by `@{yes}` and the `no` option represented by `@{no}`, what are the respective probabilities of `p_yes` and `p_no` occurring?} @@ -258,12 +257,6 @@ models: bet_amount_field: ${str:collateral_amount} results_filename: ${str:benchmarking_results.csv} randomness: ${str:benchmarking_randomness} - acc_info_fields: - args: - tool: ${str:tool} - requests: ${str:total_requests} - accuracy: ${str:tool_accuracy} - sep: ${str:,} network_subgraph: args: headers: diff --git a/packages/valory/services/trader/service.yaml b/packages/valory/services/trader/service.yaml index 0673410e..29e41069 100644 --- a/packages/valory/services/trader/service.yaml +++ b/packages/valory/services/trader/service.yaml @@ -7,7 +7,7 @@ license: Apache-2.0 fingerprint: README.md: bafybeigtuothskwyvrhfosps2bu6suauycolj67dpuxqvnicdrdu7yhtvq fingerprint_ignore_patterns: [] -agent: valory/trader:0.1.0:bafybeiaxm4ts4odvhmbltyaa7rngm6jio7b4fdwvwszahw2ndfjdpd547a +agent: valory/trader:0.1.0:bafybeicpf66igauitqbhnt24scqrmlxfu6ervkfyq2tucejxxz33f2rbtu number_of_agents: 4 deployment: agent: @@ -97,7 +97,6 @@ type: skill bet_threshold: ${BET_THRESHOLD:int:100000000000000000} blacklisting_duration: ${BLACKLISTING_DURATION:int:3600} ipfs_address: ${IPFS_ADDRESS:str:https://gateway.autonolas.tech/ipfs/} - tools_accuracy_hash: ${TOOLS_ACCURACY_HASH:str:QmR8etyW3TPFadNtNrW54vfnFqmh8vBrMARWV76EmxCZyk} prompt_template: ${PROMPT_TEMPLATE:str:With the given question "@{question}" and the `yes` option represented by `@{yes}` and the `no` option represented by `@{no}`, what are the respective probabilities of `p_yes` and `p_no` @@ -167,13 +166,7 @@ type: skill bet_amount_field: ${BENCHMARKING_MODE_BET_AMOUNT_FIELD:str:collateral_amount} results_filename: ${BENCHMARKING_MODE_RESULTS_FILENAME:str:benchmarking_results.csv} randomness: ${BENCHMARKING_MODE_RANDOMNESS:str:benchmarking_randomness} - acc_info_fields: &id005 - args: - tool: ${ACC_INFO_FIELDS_TOOL:str:tool} - requests: ${ACC_INFO_FIELDS_REQUESTS:str:total_requests} - accuracy: ${ACC_INFO_FIELDS_ACCURACY:str:tool_accuracy} - sep: ${ACC_INFO_FIELDS_SEP:str:,} - network_subgraph: &id006 + network_subgraph: &id005 args: headers: Content-Type: ${NETWORK_SUBGRAPH_CONTENT_TYPE:str:application/json} @@ -186,7 +179,7 @@ type: skill error_type: ${NETWORK_SUBGRAPH_ERROR_TYPE:str:dict} retries: ${NETWORK_SUBGRAPH_RETRIES:int:5} url: ${NETWORK_SUBGRAPH_URL:str:https://api.thegraph.com/subgraphs/name/stakewise/ethereum-gnosis} - omen_subgraph: &id007 + omen_subgraph: &id006 args: headers: Content-Type: ${OMEN_SUBGRAPH_CONTENT_TYPE:str:application/json} @@ -198,14 +191,14 @@ type: skill error_type: ${NETWORK_SUBGRAPH_ERROR_TYPE:str:dict} retries: ${OMEN_SUBGRAPH_RETRIES:int:5} url: ${OMEN_SUBGRAPH_URL:str:https://api.thegraph.com/subgraphs/name/protofire/omen-xdai} - randomness_api: &id008 + randomness_api: &id007 args: method: ${RANDOMNESS_API_METHOD:str:GET} response_key: ${RANDOMNESS_API_RESPONSE_KEY:str:null} response_type: ${RANDOMNESS_API_RESPONSE_TYPE:str:dict} retries: ${RANDOMNESS_API_RETRIES:int:5} url: ${RANDOMNESS_API_URL:str:https://drand.cloudflare.com/public/latest} - mech_response: &id009 + mech_response: &id008 args: headers: Content-Type: ${MECH_RESPONSE_API_CONTENT_TYPE:str:application/json} @@ -214,7 +207,7 @@ type: skill response_type: ${MECH_RESPONSE_API_RESPONSE_TYPE:str:str} retries: ${MECH_RESPONSE_API_RETRIES:int:5} url: ${MECH_RESPONSE_API_URL:str:''} - agent_tools: &id010 + agent_tools: &id009 args: headers: Content-Type: ${AGENT_TOOLS_API_CONTENT_TYPE:str:application/json} @@ -223,7 +216,7 @@ type: skill response_type: ${AGENT_TOOLS_API_RESPONSE_TYPE:str:list} retries: ${AGENT_TOOLS_API_RETRIES:int:5} url: ${AGENT_TOOLS_API_URL:str:''} - trades_subgraph: &id011 + trades_subgraph: &id010 args: headers: Content-Type: ${TRADES_SUBGRAPH_CONTENT_TYPE:str:application/json} @@ -235,7 +228,7 @@ type: skill error_type: ${NETWORK_SUBGRAPH_ERROR_TYPE:str:dict} retries: ${TRADES_SUBGRAPH_RETRIES:int:5} url: ${TRADES_SUBGRAPH_URL:str:https://api.thegraph.com/subgraphs/name/protofire/omen-xdai} - conditional_tokens_subgraph: &id012 + conditional_tokens_subgraph: &id011 args: headers: Content-Type: ${CONDITIONAL_TOKENS_SUBGRAPH_CONTENT_TYPE:str:application/json} @@ -247,7 +240,7 @@ type: skill error_type: ${NETWORK_SUBGRAPH_ERROR_TYPE:str:dict} retries: ${CONDITIONAL_TOKENS_SUBGRAPH_RETRIES:int:5} url: ${CONDITIONAL_TOKENS_SUBGRAPH_URL:str:https://api.thegraph.com/subgraphs/name/gnosis/conditional-tokens-gc} - realitio_subgraph: &id013 + realitio_subgraph: &id012 args: headers: Content-Type: ${REALITIO_SUBGRAPH_CONTENT_TYPE:str:application/json} @@ -365,15 +358,14 @@ type: skill rpc_sleep_time: ${RPC_SLEEP_TIME:int:10} mech_interaction_sleep_time: ${MECH_INTERACTION_SLEEP_TIME:int:10} benchmark_tool: *id004 - acc_info_fields: *id005 - network_subgraph: *id006 - omen_subgraph: *id007 - randomness_api: *id008 - mech_response: *id009 - agent_tools: *id010 - trades_subgraph: *id011 - conditional_tokens_subgraph: *id012 - realitio_subgraph: *id013 + network_subgraph: *id005 + omen_subgraph: *id006 + randomness_api: *id007 + mech_response: *id008 + agent_tools: *id009 + trades_subgraph: *id010 + conditional_tokens_subgraph: *id011 + realitio_subgraph: *id012 2: models: params: @@ -480,15 +472,14 @@ type: skill rpc_sleep_time: ${RPC_SLEEP_TIME:int:10} mech_interaction_sleep_time: ${MECH_INTERACTION_SLEEP_TIME:int:10} benchmark_tool: *id004 - acc_info_fields: *id005 - network_subgraph: *id006 - omen_subgraph: *id007 - randomness_api: *id008 - mech_response: *id009 - agent_tools: *id010 - trades_subgraph: *id011 - conditional_tokens_subgraph: *id012 - realitio_subgraph: *id013 + network_subgraph: *id005 + omen_subgraph: *id006 + randomness_api: *id007 + mech_response: *id008 + agent_tools: *id009 + trades_subgraph: *id010 + conditional_tokens_subgraph: *id011 + realitio_subgraph: *id012 3: models: params: @@ -595,15 +586,14 @@ type: skill rpc_sleep_time: ${RPC_SLEEP_TIME:int:10} mech_interaction_sleep_time: ${MECH_INTERACTION_SLEEP_TIME:int:10} benchmark_tool: *id004 - acc_info_fields: *id005 - network_subgraph: *id006 - omen_subgraph: *id007 - randomness_api: *id008 - mech_response: *id009 - agent_tools: *id010 - trades_subgraph: *id011 - conditional_tokens_subgraph: *id012 - realitio_subgraph: *id013 + network_subgraph: *id005 + omen_subgraph: *id006 + randomness_api: *id007 + mech_response: *id008 + agent_tools: *id009 + trades_subgraph: *id010 + conditional_tokens_subgraph: *id011 + realitio_subgraph: *id012 --- public_id: valory/ledger:0.19.0 type: connection diff --git a/packages/valory/services/trader_pearl/service.yaml b/packages/valory/services/trader_pearl/service.yaml index aabd9ccf..3992c94c 100644 --- a/packages/valory/services/trader_pearl/service.yaml +++ b/packages/valory/services/trader_pearl/service.yaml @@ -8,7 +8,7 @@ license: Apache-2.0 fingerprint: README.md: bafybeibg7bdqpioh4lmvknw3ygnllfku32oca4eq5pqtvdrdsgw6buko7e fingerprint_ignore_patterns: [] -agent: valory/trader:0.1.0:bafybeiaxm4ts4odvhmbltyaa7rngm6jio7b4fdwvwszahw2ndfjdpd547a +agent: valory/trader:0.1.0:bafybeicpf66igauitqbhnt24scqrmlxfu6ervkfyq2tucejxxz33f2rbtu number_of_agents: 1 deployment: agent: diff --git a/packages/valory/skills/decision_maker_abci/behaviours/base.py b/packages/valory/skills/decision_maker_abci/behaviours/base.py index c3f843cc..2c6b1151 100644 --- a/packages/valory/skills/decision_maker_abci/behaviours/base.py +++ b/packages/valory/skills/decision_maker_abci/behaviours/base.py @@ -46,8 +46,6 @@ from packages.valory.skills.abstract_round_abci.behaviour_utils import TimeoutException from packages.valory.skills.decision_maker_abci.io_.loader import ComponentPackageLoader from packages.valory.skills.decision_maker_abci.models import ( - AccuracyInfoFields, - BenchmarkingMockData, BenchmarkingMode, CONFIDENCE_FIELD, DecisionMakerParams, @@ -173,19 +171,6 @@ def benchmarking_mode(self) -> BenchmarkingMode: """Return the benchmarking mode configurations.""" return cast(BenchmarkingMode, self.context.benchmarking_mode) - @property - def mock_data(self) -> BenchmarkingMockData: - """Return the mock data for the benchmarking mode.""" - mock_data = self.shared_state.mock_data - if mock_data is None: - raise ValueError("Attempted to access the mock data while being empty!") - return mock_data - - @property - def acc_info_fields(self) -> AccuracyInfoFields: - """Return the accuracy information fieldnames.""" - return cast(AccuracyInfoFields, self.context.acc_info_fields) - @property def shared_state(self) -> SharedState: """Get the shared state.""" @@ -256,11 +241,7 @@ def policy(self) -> EGreedyPolicy: @property def is_first_period(self) -> bool: """Return whether it is the first period of the service.""" - return ( - self.synchronized_data.period_count == 0 - and not self.benchmarking_mode.enabled - or self.shared_state.mock_data is None - ) + return self.synchronized_data.period_count == 0 @property def sampled_bet(self) -> Bet: @@ -599,7 +580,6 @@ def wait_for_condition_with_sleep( self, condition_gen: Callable[[], WaitableConditionType], timeout: Optional[float] = None, - sleep_time_override: Optional[int] = None, ) -> Generator[None, None, None]: """Wait for a condition to happen and sleep in-between checks. @@ -609,8 +589,6 @@ def wait_for_condition_with_sleep( :param condition_gen: a generator of the condition to wait for :param timeout: the maximum amount of time to wait - :param sleep_time_override: override for the sleep time. - If None is given, the default value is used, which is the RPC timeout set in the configuration. :yield: None """ @@ -620,15 +598,16 @@ def wait_for_condition_with_sleep( else datetime.max ) - sleep_time = sleep_time_override or self.params.rpc_sleep_time while True: condition_satisfied = yield from condition_gen() if condition_satisfied: break if timeout is not None and datetime.now() > deadline: raise TimeoutException() - self.context.logger.info(f"Retrying in {sleep_time} seconds.") - yield from self.sleep(sleep_time) + self.context.logger.info( + f"Retrying in {self.params.rpc_sleep_time} seconds." + ) + yield from self.sleep(self.params.rpc_sleep_time) def _write_benchmark_results( self, @@ -639,6 +618,13 @@ def _write_benchmark_results( liquidity_info: LiquidityInfo = INIT_LIQUIDITY_INFO, ) -> None: """Write the results to the benchmarking file.""" + mock_data = self.shared_state.mock_data + if mock_data is None: + self.context.logger.error( + "The mock data are empty! Cannot write the benchmark result." + ) + return + add_headers = False results_path = self.params.store_path / self.benchmarking_mode.results_filename if not os.path.isfile(results_path): @@ -663,11 +649,11 @@ def _write_benchmark_results( results_file.write(row) results = ( - self.mock_data.id, + mock_data.id, # reintroduce duplicate quotes and quote the question # as it may contain commas which are also used as separators - QUOTE + self.mock_data.question.replace(QUOTE, TWO_QUOTES) + QUOTE, - self.mock_data.answer, + QUOTE + mock_data.question.replace(QUOTE, TWO_QUOTES) + QUOTE, + mock_data.answer, p_yes, p_no, confidence, diff --git a/packages/valory/skills/decision_maker_abci/behaviours/bet_placement.py b/packages/valory/skills/decision_maker_abci/behaviours/bet_placement.py index efcd346a..aefaba91 100644 --- a/packages/valory/skills/decision_maker_abci/behaviours/bet_placement.py +++ b/packages/valory/skills/decision_maker_abci/behaviours/bet_placement.py @@ -195,7 +195,7 @@ def _prepare_safe_tx(self) -> Generator[None, None, Optional[str]]: outcome = self.sampled_bet.get_outcome(self.outcome_index) investment = self._collateral_amount_info(self.investment_amount) self.context.logger.info( - f"Preparing a multisig transaction to place a bet for {outcome!r}, with confidence " + f"Preparing a mutlisig transaction to place a bet for {outcome!r}, with confidence " f"{self.synchronized_data.confidence!r}, for the amount of {investment}, which is equal to the amount of " f"{self.buy_amount!r} WEI of the conditional token corresponding to {outcome!r}." ) diff --git a/packages/valory/skills/decision_maker_abci/behaviours/blacklisting.py b/packages/valory/skills/decision_maker_abci/behaviours/blacklisting.py index a8bf1e0e..a9666348 100644 --- a/packages/valory/skills/decision_maker_abci/behaviours/blacklisting.py +++ b/packages/valory/skills/decision_maker_abci/behaviours/blacklisting.py @@ -46,7 +46,30 @@ def synced_time(self) -> float: return synced_time.timestamp() def _blacklist(self) -> None: - """Blacklist the sampled bet.""" + """Update the policy and blacklist the sampled bet.""" + # calculate the penalty + if self.synchronized_data.is_mech_price_set: + # impose a penalty equivalent to the mech's price on the tool responsible for blacklisting the market + penalty_wei = self.synchronized_data.mech_price + elif self.benchmarking_mode.enabled: + # penalize using the simulated mech's cost + penalty_wei = self.benchmarking_mode.mech_cost + else: + # if the price has not been set or a nevermined subscription is used, penalize using a small amount, + # approximating the cost of a transaction + penalty_wei = -TX_COST_APPROX + + # update the policy to penalize the most recently utilized mech tool + tool_idx = self.synchronized_data.mech_tool_idx + penalty = -self.wei_to_native(penalty_wei) + penalty *= self.params.tool_punishment_multiplier + self.policy.add_reward(tool_idx, penalty) + + if self.benchmarking_mode.enabled: + # skip blacklisting the market as we should be based solely on the input data of the simulation + return + + # blacklist the sampled bet sampled_bet_index = self.synchronized_data.sampled_bet_index sampled_bet = self.bets[sampled_bet_index] sampled_bet.status = BetStatus.BLACKLISTED @@ -67,9 +90,7 @@ def async_act(self) -> Generator: with self.context.benchmark_tool.measure(self.behaviour_id).local(): self.read_bets() - # skip blacklisting when benchmarking as we should be based solely on the input data of the simulation - if not self.benchmarking_mode.enabled: - self._blacklist() + self._blacklist() self.store_bets() bets_hash = ( None if self.benchmarking_mode.enabled else self.hash_stored_bets() diff --git a/packages/valory/skills/decision_maker_abci/behaviours/decision_receive.py b/packages/valory/skills/decision_maker_abci/behaviours/decision_receive.py index 34612264..9688d47a 100644 --- a/packages/valory/skills/decision_maker_abci/behaviours/decision_receive.py +++ b/packages/valory/skills/decision_maker_abci/behaviours/decision_receive.py @@ -118,6 +118,11 @@ def _next_dataset_row(self) -> Optional[Dict[str, str]]: def _parse_dataset_row(self, row: Dict[str, str]) -> str: """Parse a dataset's row to store the mock market data and to mock a prediction response.""" mode = self.benchmarking_mode + self.shared_state.mock_data = BenchmarkingMockData( + row[mode.question_id_field], + row[mode.question_field], + row[mode.answer_field], + ) mech_tool = self.synchronized_data.mech_tool fields = {} @@ -131,14 +136,6 @@ def _parse_dataset_row(self, row: Dict[str, str]) -> str: else: fields[prediction_attribute] = row[mech_tool + field_part] - # set the benchmarking mock data - self.shared_state.mock_data = BenchmarkingMockData( - row[mode.question_id_field], - row[mode.question_field], - row[mode.answer_field], - float(fields[P_YES_FIELD]), - ) - # set the info utility to zero as it does not matter for the benchmark fields[INFO_UTILITY_FIELD] = "0" return json.dumps(fields) diff --git a/packages/valory/skills/decision_maker_abci/behaviours/reedem.py b/packages/valory/skills/decision_maker_abci/behaviours/reedem.py index fcc79321..4bafe466 100644 --- a/packages/valory/skills/decision_maker_abci/behaviours/reedem.py +++ b/packages/valory/skills/decision_maker_abci/behaviours/reedem.py @@ -76,7 +76,7 @@ class RedeemInfoBehaviour(StorageManagerBehaviour, QueryingBehaviour, ABC): def __init__(self, **kwargs: Any) -> None: """Initialize a `RedeemInfo` object.""" super().__init__(**kwargs) - self.utilized_tools: Dict[str, str] = {} + self.utilized_tools: Dict[str, int] = {} self.redeemed_condition_ids: Set[str] = set() self.payout_so_far: int = 0 self.trades: Set[Trade] = set() @@ -114,29 +114,37 @@ def _set_block_number(self, trade: Trade) -> Generator: f"Chose block number {self.earliest_block_number!r} as closest to timestamp {timestamp!r}" ) - def _try_update_policy(self, tool: str) -> None: - """Try to update the policy.""" - try: - self.policy.update_accuracy_store(tool) - except KeyError: - self.context.logger.warning( - f"The stored utilized tools seem to be outdated as no {tool=} was found. " - "The policy will not be updated. " - "No action is required as this will be automatically resolved." - ) - def _update_policy(self, update: Trade) -> None: """Update the policy.""" # the mapping might not contain a tool for a bet placement because it might have happened on a previous run - tool = self.utilized_tools.get(update.transactionHash, None) - if tool is None: - return + tool_index = self.utilized_tools.get(update.transactionHash, None) + if tool_index is not None: + # we try to avoid an ever-increasing dictionary of utilized tools by removing a tool when not needed anymore + del self.utilized_tools[update.transactionHash] + claimable_xdai = self.wei_to_native(update.claimable_amount) + mech_price = self.wei_to_native(self.synchronized_data.mech_price) + reward = claimable_xdai - mech_price + try: + self.policy.add_reward(tool_index, reward) + except IndexError: + self.context.logger.warning( + f"The stored utilized tools seem to be outdated as no tool with an index {tool_index!r} was found. " + "The policy will not be updated. " + "No action is required as this will be automatically resolved." + ) - # we try to avoid an ever-increasing dictionary of utilized tools by removing a tool when not needed anymore - del self.utilized_tools[update.transactionHash] - if not update.is_winning: - return - self._try_update_policy(tool) + def _stats_report(self) -> None: + """Report policy statistics.""" + stats_report = "Policy statistics so far (only for resolved markets):\n" + for i, tool in enumerate(self.mech_tools): + stats_report += ( + f"{tool} tool:\n" + f"\tTimes used: {self.policy.counts[i]}\n" + f"\tReward rate: {self.policy.reward_rates[i]}\n" + ) + best_tool = self.mech_tools[self.policy.best_tool] + stats_report += f"Best tool so far is {best_tool!r}." + self.context.logger.info(stats_report) def update_redeem_info(self, chunk: list) -> Generator: """Update the redeeming information using the given chunk.""" @@ -171,7 +179,8 @@ def update_redeem_info(self, chunk: list) -> Generator: if update == unique_obj: self.claimable_amounts[condition_id] += update.claimable_amount - self.context.logger.info(self.policy.stats_report()) + if self.policy.has_updated: + self._stats_report() class RedeemBehaviour(RedeemInfoBehaviour): @@ -910,69 +919,45 @@ def _setup_policy_and_tools(self) -> Generator[None, None, bool]: status = yield from super()._setup_policy_and_tools() return status - def _build_payload(self, redeem_tx_hex: Optional[str] = None) -> RedeemPayload: - """Build the redeeming round's payload.""" - agent = self.context.agent_address - tx_submitter = self.matching_round.auto_round_id() - benchmarking_enabled = self.benchmarking_mode.enabled - policy = self.policy.serialize() - utilized_tools = json.dumps(self.utilized_tools) - condition_ids = json.dumps(list(self.redeemed_condition_ids)) - payout = self.payout_so_far - return RedeemPayload( - agent, - tx_submitter, - redeem_tx_hex, - benchmarking_enabled, - policy, - utilized_tools, - condition_ids, - payout, - ) - - def _benchmarking_act(self) -> RedeemPayload: - """The act of the agent while running in benchmarking mode.""" - if self.mock_data.is_winning: - tool = self.synchronized_data.mech_tool - self._try_update_policy(tool) - return self._build_payload() - - def _normal_act(self) -> Generator[None, None, Optional[RedeemPayload]]: - """The act of the agent while running in normal mode.""" - if not self.redeeming_progress.check_started: - yield from self._get_redeem_info() - self._store_progress() - else: - msg = "Picking up progress from where it was left off before the timeout occurred." - self.context.logger.info(msg) - self._load_progress() - - if not self.redeeming_progress.check_finished: - self.redeeming_progress.cleaned = yield from self._clean_redeem_info() - - payload = RedeemPayload(self.context.agent_address) - if self.redeeming_progress.cleaned: - redeem_tx_hex = yield from self._prepare_safe_tx() - if redeem_tx_hex is not None: - payload = self._build_payload(redeem_tx_hex) - - return payload - def async_act(self) -> Generator: """Do the action.""" with self.context.benchmark_tool.measure(self.behaviour_id).local(): success = yield from self._setup_policy_and_tools() if not success: - return None + return - payload: Optional[RedeemPayload] - if self.benchmarking_mode.enabled: - payload = self._benchmarking_act() + if not self.redeeming_progress.check_started: + yield from self._get_redeem_info() + self._store_progress() else: - payload = yield from self._normal_act() - if payload is None: - return - - self._store_all() + msg = "Picking up progress from where it was left off before the timeout occurred." + self.context.logger.info(msg) + self._load_progress() + + if not self.redeeming_progress.check_finished: + self.redeeming_progress.cleaned = yield from self._clean_redeem_info() + + agent = self.context.agent_address + payload = RedeemPayload(agent) + + if self.redeeming_progress.cleaned: + redeem_tx_hex = yield from self._prepare_safe_tx() + if redeem_tx_hex is not None: + tx_submitter = self.matching_round.auto_round_id() + policy = self.policy.serialize() + utilized_tools = json.dumps(self.utilized_tools) + condition_ids = json.dumps(list(self.redeemed_condition_ids)) + payout = self.payout_so_far + self._store_all() + payload = RedeemPayload( + agent, + tx_submitter, + redeem_tx_hex, + None, + policy, + utilized_tools, + condition_ids, + payout, + ) yield from self.finish_behaviour(payload) diff --git a/packages/valory/skills/decision_maker_abci/behaviours/storage_manager.py b/packages/valory/skills/decision_maker_abci/behaviours/storage_manager.py index 78496ae2..a860ca04 100644 --- a/packages/valory/skills/decision_maker_abci/behaviours/storage_manager.py +++ b/packages/valory/skills/decision_maker_abci/behaviours/storage_manager.py @@ -19,10 +19,8 @@ """This module contains a behaviour for managing the storage of the agent.""" -import csv import json from abc import ABC -from io import StringIO from typing import Any, Dict, Generator, List, Optional from packages.valory.contracts.agent_registry.contract import AgentRegistryContract @@ -34,17 +32,12 @@ WaitableConditionType, ) from packages.valory.skills.decision_maker_abci.models import AgentToolsSpecs -from packages.valory.skills.decision_maker_abci.policy import ( - AccuracyInfo, - EGreedyPolicy, -) +from packages.valory.skills.decision_maker_abci.policy import EGreedyPolicy POLICY_STORE = "policy_store.json" AVAILABLE_TOOLS_STORE = "available_tools_store.json" UTILIZED_TOOLS_STORE = "utilized_tools.json" -GET = "GET" -OK_CODE = 200 class StorageManagerBehaviour(DecisionMakerBaseBehaviour, ABC): @@ -55,9 +48,8 @@ def __init__(self, **kwargs: Any) -> None: super().__init__(**kwargs) self._mech_id: int = 0 self._mech_hash: str = "" - self._utilized_tools: Dict[str, str] = {} + self._utilized_tools: Dict[str, int] = {} self._mech_tools: Optional[List[str]] = None - self._accuracy_information: StringIO = StringIO() @property def mech_tools(self) -> List[str]: @@ -71,16 +63,6 @@ def mech_tools(self, mech_tools: List[str]) -> None: """Set the mech agent's tools.""" self._mech_tools = mech_tools - @property - def accuracy_information(self) -> StringIO: - """Get the accuracy information.""" - return self._accuracy_information - - @accuracy_information.setter - def accuracy_information(self, accuracy_information: StringIO) -> None: - """Set the accuracy information.""" - self._accuracy_information = accuracy_information - @property def mech_id(self) -> int: """Get the mech's id.""" @@ -102,12 +84,12 @@ def mech_hash(self, mech_hash: str) -> None: self._mech_hash = mech_hash @property - def utilized_tools(self) -> Dict[str, str]: + def utilized_tools(self) -> Dict[str, int]: """Get the utilized tools.""" return self._utilized_tools @utilized_tools.setter - def utilized_tools(self, utilized_tools: Dict[str, str]) -> None: + def utilized_tools(self, utilized_tools: Dict[str, int]) -> None: """Get the utilized tools.""" self._utilized_tools = utilized_tools @@ -226,6 +208,55 @@ def _get_tools( ): yield from self.wait_for_condition_with_sleep(step) + def _update_utilized_tools( + self, indexes: List[int], remove_mode: bool = False + ) -> None: + """Update the utilized tools' indexes to match the fact that the given ones have been removed or added.""" + if len(indexes) == 0: + return + + updated_tools = {} + for tx_hash, tool_idx in self.utilized_tools.items(): + removed = False + updated_idx = tool_idx + + for idx in indexes: + if removed: + continue + + if tool_idx == idx and remove_mode: + removed = True + continue + + if tool_idx == idx: + updated_idx += 1 + if tool_idx > idx: + updated_idx += -1 if remove_mode else 1 + + if not removed: + updated_tools[tx_hash] = updated_idx + + self.context.logger.info( + f"Updated the utilized tools' indexes: {self.utilized_tools} -> {updated_tools}." + ) + self.utilized_tools = updated_tools + + def _adjust_policy_tools(self, local: List[str]) -> None: + """Add or remove tools from the policy to match the remote tools.""" + # remove tools if they are not available anymore + # process the indices in reverse order to avoid index shifting when removing the unavailable tools later + reversed_idx = range(len(local) - 1, -1, -1) + removed_idx = [idx for idx in reversed_idx if local[idx] not in self.mech_tools] + self.policy.remove_tools(removed_idx) + self._update_utilized_tools(sorted(removed_idx), remove_mode=True) + + # add tools if there are new ones available + # process the indices in reverse order to avoid index shifting when adding the new tools later + reversed_idx = range(len(self.mech_tools) - 1, -1, -1) + new_idx = [idx for idx in reversed_idx if self.mech_tools[idx] not in local] + self.policy.add_new_tools(new_idx) + self._update_utilized_tools(new_idx) + def _try_recover_policy(self) -> Optional[EGreedyPolicy]: """Try to recover the policy from the policy store.""" try: @@ -238,62 +269,19 @@ def _try_recover_policy(self) -> Optional[EGreedyPolicy]: return None def _get_init_policy(self) -> EGreedyPolicy: - """Get the initial policy.""" - # try to read the policy from the policy store, and if we cannot recover the policy, we create a new one - return self._try_recover_policy() or EGreedyPolicy(self.params.epsilon) - - def _fetch_accuracy_info(self) -> Generator[None, None, bool]: - """Fetch the latest accuracy information available.""" - # get the CSV file from IPFS - self.context.logger.info("Reading accuracy information from IPFS...") - accuracy_link = self.params.ipfs_address + self.params.tools_accuracy_hash - response = yield from self.get_http_response(method=GET, url=accuracy_link) - if response.status_code != OK_CODE: - self.context.logger.error( - f"Could not retrieve data from the url {accuracy_link}. " - f"Received status code {response.status_code}." - ) - return False - - self.context.logger.info("Parsing accuracy information of the tools...") - try: - self.accuracy_information = StringIO(response.body.decode()) - except (ValueError, TypeError) as e: - self.context.logger.error( - f"Could not parse response from ipfs server, " - f"the following error was encountered {type(e).__name__}: {e}" - ) - return False - - return True - - def _update_accuracy_store(self, local_tools: List[str]) -> None: - """Update the accuracy store file with the latest information available""" - self.context.logger.info("Updating accuracy information of the policy...") - sep = self.acc_info_fields.sep - reader: csv.DictReader = csv.DictReader( - self.accuracy_information, delimiter=sep - ) - accuracy_store = self.policy.accuracy_store - - # update the accuracy store using the latest accuracy information (only entered during the first period) - for row in reader: - tool = row[self.acc_info_fields.tool] - # overwrite local with global information (naturally, no global information is available for pending) - accuracy_store[tool] = AccuracyInfo( - int(row[self.acc_info_fields.requests]), - # set the pending using the local policy if this information exists - accuracy_store.get(tool, AccuracyInfo()).pending, - float(row[self.acc_info_fields.accuracy]), - ) - - # update the accuracy store by adding tools which we do not have any global information about yet - for tool in local_tools: - accuracy_store.setdefault(tool, AccuracyInfo()) - - self.policy.update_weighted_accuracy() - - def _set_policy(self) -> Generator: + """Get the initial policy""" + # try to read the policy from the policy store + policy = self._try_recover_policy() + if policy is not None: + # we successfully recovered the policy, so we return it + return policy + + # we could not recover the policy, so we create a new one + n_relevant = len(self.mech_tools) + policy = EGreedyPolicy.initial_state(self.params.epsilon, n_relevant) + return policy + + def _set_policy(self) -> None: """Set the E Greedy Policy.""" if self.is_first_period or not self.synchronized_data.is_policy_set: self._policy = self._get_init_policy() @@ -304,14 +292,10 @@ def _set_policy(self) -> Generator: self._policy = self.synchronized_data.policy local_tools = self.synchronized_data.available_mech_tools - if self.is_first_period: - yield from self.wait_for_condition_with_sleep( - self._fetch_accuracy_info, sleep_time_override=self.params.sleep_time - ) - self._update_accuracy_store(local_tools) + self._adjust_policy_tools(local_tools) - def _try_recover_utilized_tools(self) -> Dict[str, str]: - """Try to recover the utilized tools from the tools store.""" + def _try_recover_utilized_tools(self) -> Dict[str, int]: + """Try to recover the available tools from the tools store.""" tools_path = self.params.store_path / UTILIZED_TOOLS_STORE try: with open(tools_path, "r") as tools_file: @@ -341,7 +325,7 @@ def _setup_policy_and_tools(self) -> Generator[None, None, bool]: if self._mech_tools is None: return False - yield from self._set_policy() + self._set_policy() return True def _store_policy(self) -> None: diff --git a/packages/valory/skills/decision_maker_abci/behaviours/tool_selection.py b/packages/valory/skills/decision_maker_abci/behaviours/tool_selection.py index 17816bec..89765259 100644 --- a/packages/valory/skills/decision_maker_abci/behaviours/tool_selection.py +++ b/packages/valory/skills/decision_maker_abci/behaviours/tool_selection.py @@ -36,7 +36,7 @@ class ToolSelectionBehaviour(StorageManagerBehaviour): matching_round = ToolSelectionRound - def _select_tool(self) -> Generator[None, None, Optional[str]]: + def _select_tool(self) -> Generator[None, None, Optional[int]]: """Select a Mech tool based on an e-greedy policy and return its index.""" success = yield from self._setup_policy_and_tools() if not success: @@ -47,9 +47,10 @@ def _select_tool(self) -> Generator[None, None, Optional[str]]: if self.benchmarking_mode.enabled else self.synchronized_data.most_voted_randomness ) - selected_tool = self.policy.select_tool(randomness) - self.context.logger.info(f"Selected the mech tool {selected_tool!r}.") - return selected_tool + selected_idx = self.policy.select_tool(randomness) + selected = self.mech_tools[selected_idx] if selected_idx is not None else "NaN" + self.context.logger.info(f"Selected the mech tool {selected!r}.") + return selected_idx def async_act(self) -> Generator: """Do the action.""" @@ -57,10 +58,6 @@ def async_act(self) -> Generator: mech_tools = policy = utilized_tools = None selected_tool = yield from self._select_tool() if selected_tool is not None: - # the period will increment when the benchmarking finishes - benchmarking_running = self.synchronized_data.period_count == 0 - if self.benchmarking_mode.enabled and benchmarking_running: - self.policy.tool_used(selected_tool) mech_tools = json.dumps(self.mech_tools) policy = self.policy.serialize() utilized_tools = json.dumps(self.utilized_tools, sort_keys=True) diff --git a/packages/valory/skills/decision_maker_abci/fsm_specification.yaml b/packages/valory/skills/decision_maker_abci/fsm_specification.yaml index 62c7dd9f..70813bd9 100644 --- a/packages/valory/skills/decision_maker_abci/fsm_specification.yaml +++ b/packages/valory/skills/decision_maker_abci/fsm_specification.yaml @@ -64,7 +64,7 @@ states: transition_func: (BetPlacementRound, DONE): FinishedDecisionMakerRound (BetPlacementRound, INSUFFICIENT_BALANCE): RefillRequiredRound - (BetPlacementRound, MOCK_TX): RedeemRound + (BetPlacementRound, MOCK_TX): RandomnessRound (BetPlacementRound, NONE): ImpossibleRound (BetPlacementRound, NO_MAJORITY): BetPlacementRound (BetPlacementRound, ROUND_TIMEOUT): BetPlacementRound diff --git a/packages/valory/skills/decision_maker_abci/models.py b/packages/valory/skills/decision_maker_abci/models.py index ab96cbd1..379f8b2f 100644 --- a/packages/valory/skills/decision_maker_abci/models.py +++ b/packages/valory/skills/decision_maker_abci/models.py @@ -83,8 +83,6 @@ L0_END_FIELD = "l0_end" L1_END_FIELD = "l1_end" INFO_UTILITY_FIELD = "info_utility" -YES = "yes" -NO = "no" class PromptTemplate(Template): @@ -135,24 +133,24 @@ def get_end_liquidity(self) -> List[int]: class RedeemingProgress: """A structure to keep track of the redeeming check progress.""" - trades: Set[Trade] = field(default_factory=set) - utilized_tools: Dict[str, str] = field(default_factory=dict) + trades: Set[Trade] = field(default_factory=lambda: set()) + utilized_tools: Dict[str, int] = field(default_factory=lambda: {}) policy: Optional[EGreedyPolicy] = None - claimable_amounts: Dict[HexBytes, int] = field(default_factory=dict) + claimable_amounts: Dict[HexBytes, int] = field(default_factory=lambda: {}) earliest_block_number: int = 0 event_filtering_batch_size: int = 0 check_started: bool = False check_from_block: BlockIdentifier = "earliest" check_to_block: BlockIdentifier = "latest" cleaned: bool = False - payouts: Dict[str, int] = field(default_factory=dict) - unredeemed_trades: Dict[str, int] = field(default_factory=dict) + payouts: Dict[str, int] = field(default_factory=lambda: {}) + unredeemed_trades: Dict[str, int] = field(default_factory=lambda: {}) claim_started: bool = False claim_from_block: BlockIdentifier = "earliest" claim_to_block: BlockIdentifier = "latest" - answered: list = field(default_factory=list) - claiming_condition_ids: List[str] = field(default_factory=list) - claimed_condition_ids: List[str] = field(default_factory=list) + answered: list = field(default_factory=lambda: []) + claiming_condition_ids: List[str] = field(default_factory=lambda: []) + claimed_condition_ids: List[str] = field(default_factory=lambda: []) @property def check_finished(self) -> bool: @@ -206,7 +204,7 @@ def __init__(self, *args: Any, skill_context: SkillContext, **kwargs: Any) -> No self.in_flight_req: bool = False self.req_to_callback: Dict[str, Callable] = {} self.mock_data: Optional[BenchmarkingMockData] = None - # latest liquidity information (only relevant to the benchmarking mode) + # latest liquidity information self.liquidity_amounts: Dict[str, List[int]] = {} self.liquidity_prices: Dict[str, List[float]] = {} @@ -336,7 +334,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.use_fallback_strategy: bool = self._ensure( "use_fallback_strategy", kwargs, bool ) - self.tools_accuracy_hash: str = self._ensure("tools_accuracy_hash", kwargs, str) # the threshold amount in WEI starting from which we are willing to place a bet self.bet_threshold: int = self._ensure("bet_threshold", kwargs, int) # the duration, in seconds, of blacklisting a bet before retrying to make an estimate for it @@ -489,18 +486,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class AccuracyInfoFields(Model, TypeCheckMixin): - """Configuration which holds the accuracy information file's fieldnames.""" - - def __init__(self, *args: Any, **kwargs: Any) -> None: - """Initialize the `AccuracyInfoFields` object.""" - self.tool: str = self._ensure("tool", kwargs, str) - self.requests: str = self._ensure("requests", kwargs, str) - self.accuracy: str = self._ensure("accuracy", kwargs, str) - self.sep: str = self._ensure("sep", kwargs, str) - super().__init__(*args, **kwargs) - - class AgentToolsSpecs(ApiSpecs): """A model that wraps ApiSpecs for the Mech agent's tools specifications.""" @@ -559,17 +544,6 @@ class BenchmarkingMockData: id: str question: str answer: str - p_yes: float - - @property - def is_winning(self) -> bool: - """Whether the current position is winning.""" - return ( - self.answer == YES - and self.p_yes > 0.5 - or self.answer == NO - and self.p_yes < 0.5 - ) class TradesSubgraph(Subgraph): diff --git a/packages/valory/skills/decision_maker_abci/payloads.py b/packages/valory/skills/decision_maker_abci/payloads.py index 2168f690..1c8b0996 100644 --- a/packages/valory/skills/decision_maker_abci/payloads.py +++ b/packages/valory/skills/decision_maker_abci/payloads.py @@ -106,4 +106,4 @@ class ToolSelectionPayload(BaseTxPayload): mech_tools: Optional[str] policy: Optional[str] utilized_tools: Optional[str] - selected_tool: Optional[str] + index: Optional[int] diff --git a/packages/valory/skills/decision_maker_abci/policy.py b/packages/valory/skills/decision_maker_abci/policy.py index b85e71ac..d04d4d65 100644 --- a/packages/valory/skills/decision_maker_abci/policy.py +++ b/packages/valory/skills/decision_maker_abci/policy.py @@ -21,8 +21,8 @@ import json import random -from dataclasses import asdict, dataclass, field, is_dataclass -from typing import Any, Dict, List, Optional, Union +from dataclasses import asdict, dataclass, is_dataclass +from typing import Any, List, Optional, Union RandomnessType = Union[int, float, str, bytes, bytearray, None] @@ -43,140 +43,102 @@ def argmax(li: List) -> int: return li.index((max(li))) -@dataclass -class AccuracyInfo: - """The accuracy information of a tool.""" - - # the number of requests that this tool has responded to - requests: int = 0 - # the number of pending evaluations, i.e., responses for which we have not redeemed yet - pending: int = 0 - # the accuracy of the tool - accuracy: float = 0.0 - - -class EGreedyPolicyDecoder(json.JSONDecoder): - """A custom JSON decoder for the e greedy policy.""" - - def __init__(self, *args: Any, **kwargs: Any) -> None: - """Initialize the custom JSON decoder.""" - super().__init__(object_hook=self.hook, *args, **kwargs) - - @staticmethod - def hook( - data: Dict[str, Any] - ) -> Union["EGreedyPolicy", AccuracyInfo, Dict[str, "EGreedyPolicy"]]: - """Perform the custom decoding.""" - for cls_ in (AccuracyInfo, EGreedyPolicy): - cls_attributes = cls_.__annotations__.keys() # pylint: disable=no-member - if sorted(cls_attributes) == sorted(data.keys()): - # if the attributes match the ones of the current class, use it to perform the deserialization - return cls_(**data) - - return data - - @dataclass class EGreedyPolicy: - """An e-Greedy policy for the tool selection based on tool accuracy.""" + """An e-Greedy policy for the tool selection.""" eps: float - accuracy_store: Dict[str, AccuracyInfo] = field(default_factory=dict) - weighted_accuracy: Dict[str, float] = field(default_factory=dict) + counts: List[int] + rewards: List[float] + initial_value = 0 - def __post_init__(self) -> None: - """Perform post-initialization checks.""" - if not (0 <= self.eps <= 1): - error = f"Cannot initialize the policy with an epsilon value of {self.eps}. Must be between 0 and 1." + @classmethod + def initial_state(cls, eps: float, n_tools: int) -> "EGreedyPolicy": + """Return an instance on its initial state.""" + if n_tools <= 0 or eps > 1 or eps < 0: + error = f"Cannot initialize an e Greedy Policy with {eps=} and {n_tools=}" raise ValueError(error) - self.update_weighted_accuracy() + + return EGreedyPolicy( + eps, + [cls.initial_value] * n_tools, + [float(cls.initial_value)] * n_tools, + ) @classmethod def deserialize(cls, policy: str) -> "EGreedyPolicy": """Deserialize a string to an `EGreedyPolicy` object.""" - return json.loads(policy, cls=EGreedyPolicyDecoder) - - @property - def tools(self) -> List[str]: - """Get the number of the policy's tools.""" - return list(self.accuracy_store.keys()) + return EGreedyPolicy(**json.loads(policy)) @property def n_tools(self) -> int: """Get the number of the policy's tools.""" - return len(self.accuracy_store) + return len(self.counts) @property - def n_requests(self) -> int: - """Get the total number of requests.""" - return sum(acc_info.requests for acc_info in self.accuracy_store.values()) + def random_tool(self) -> int: + """Get the index of a tool randomly.""" + return random.randrange(self.n_tools) # nosec @property def has_updated(self) -> bool: """Whether the policy has ever been updated since its genesis or not.""" - return self.n_requests > 0 + return sum(self.counts) > 0 @property - def random_tool(self) -> str: - """Get the name of a tool randomly.""" - return random.choice(list(self.accuracy_store.keys())) # nosec + def reward_rates(self) -> List[float]: + """Get the reward rates.""" + return [ + reward / count if count > 0 else 0 + for reward, count in zip(self.rewards, self.counts) + ] @property - def best_tool(self) -> str: + def best_tool(self) -> int: """Get the best tool.""" - weighted_accuracy = list(self.weighted_accuracy.values()) - best = argmax(weighted_accuracy) - return self.tools[best] - - def update_weighted_accuracy(self) -> None: - """Update the weighted accuracy for each tool.""" - self.weighted_accuracy = { - tool: (acc_info.accuracy / 100) - * (acc_info.requests - acc_info.pending) - / self.n_requests - for tool, acc_info in self.accuracy_store.items() - } - - def select_tool(self, randomness: RandomnessType = None) -> Optional[str]: + return argmax(self.reward_rates) + + def add_new_tools(self, indexes: List[int], avoid_shift: bool = False) -> None: + """Add new tools to the current policy.""" + if avoid_shift: + indexes = sorted(indexes, reverse=True) + + for i in indexes: + self.counts.insert(i, self.initial_value) + self.rewards.insert(i, float(self.initial_value)) + + def remove_tools(self, indexes: List[int], avoid_shift: bool = False) -> None: + """Remove the knowledge for the tools corresponding to the given indexes.""" + if avoid_shift: + indexes = sorted(indexes, reverse=True) + + for i in indexes: + try: + del self.counts[i] + del self.rewards[i] + except IndexError as exc: + error = "Attempted to remove tools using incorrect indexes!" + raise ValueError(error) from exc + + def select_tool(self, randomness: RandomnessType) -> Optional[int]: """Select a Mech tool and return its index.""" if self.n_tools == 0: return None - if randomness is not None: - random.seed(randomness) - - if not self.has_updated or random.random() < self.eps: # nosec + random.seed(randomness) + if sum(self.reward_rates) == 0 or random.random() < self.eps: # nosec return self.random_tool return self.best_tool - def tool_used(self, tool: str) -> None: - """Increase the times used for the given tool.""" - self.accuracy_store[tool].pending += 1 - self.update_weighted_accuracy() + def tool_used(self, index: int) -> None: + """Increase the times used for the tool corresponding to the given index.""" + self.counts[index] += 1 - def update_accuracy_store(self, tool: str) -> None: - """Update the accuracy store for the given tool.""" - self.accuracy_store[tool].requests += 1 - self.accuracy_store[tool].pending -= 1 - self.update_weighted_accuracy() + def add_reward(self, index: int, reward: float = 0) -> None: + """Add a reward for the tool corresponding to the given index.""" + self.rewards[index] += reward def serialize(self) -> str: - """Return the accuracy policy serialized.""" + """Return the policy serialized.""" return json.dumps(self, cls=DataclassEncoder, sort_keys=True) - - def stats_report(self) -> str: - """Report policy statistics.""" - if not self.has_updated: - return "No policy statistics available." - - report = "Policy statistics so far (only for resolved markets):\n" - stats = ( - f"{tool} tool:\n" - f"\tTimes used: {self.accuracy_store[tool].requests}\n" - f"\tWeighted Accuracy: {self.weighted_accuracy[tool]}" - for tool in self.tools - ) - report += "\n".join(stats) - report += f"Best tool so far is {self.best_tool!r}." - return report diff --git a/packages/valory/skills/decision_maker_abci/rounds.py b/packages/valory/skills/decision_maker_abci/rounds.py index 41c78d48..c5b1da78 100644 --- a/packages/valory/skills/decision_maker_abci/rounds.py +++ b/packages/valory/skills/decision_maker_abci/rounds.py @@ -143,7 +143,7 @@ class DecisionMakerAbciApp(AbciApp[Event]): - fetch error: 19. 9. BetPlacementRound - done: 12. - - mock tx: 10. + - mock tx: 4. - insufficient balance: 18. - no majority: 9. - round timeout: 9. @@ -258,8 +258,8 @@ class DecisionMakerAbciApp(AbciApp[Event]): }, BetPlacementRound: { Event.DONE: FinishedDecisionMakerRound, - # skip the bet placement tx - Event.MOCK_TX: RedeemRound, + # skip the bet placement tx and the redeeming + Event.MOCK_TX: RandomnessRound, Event.INSUFFICIENT_BALANCE: RefillRequiredRound, # degenerate round on purpose, owner must refill the safe Event.NO_MAJORITY: BetPlacementRound, Event.ROUND_TIMEOUT: BetPlacementRound, diff --git a/packages/valory/skills/decision_maker_abci/skill.yaml b/packages/valory/skills/decision_maker_abci/skill.yaml index 9e5d1385..65088295 100644 --- a/packages/valory/skills/decision_maker_abci/skill.yaml +++ b/packages/valory/skills/decision_maker_abci/skill.yaml @@ -12,33 +12,33 @@ fingerprint: README.md: bafybeia367zzdwndvlhw27rvnwodytjo3ms7gbc3q7mhrrjqjgfasnk47i __init__.py: bafybeih563ujnigeci2ldzh7hakbau6a222vsed7leg3b7lq32vcn3nm4a behaviours/__init__.py: bafybeih6ddz2ocvm6x6ytvlbcz6oi4snb5ee5xh5h65nq4w2qf7fd7zfky - behaviours/base.py: bafybeidpo2jaunr2odotiapfkc7v6pxq6nzqckjjge6vavbsh3ejc54pti - behaviours/bet_placement.py: bafybeihmia64t2payxfqcnfdqg675ui2yp3hnyfwb2xhj2hn7wl237b4re - behaviours/blacklisting.py: bafybeibofq3emoxxcndkozupsyo2xrigewy6ojvzfdvzwruvsvgyilokbu + behaviours/base.py: bafybeihkdoii3gjnmwknqa4lzqb3whjh7o75lvirzvkmnzq3kiavhewtge + behaviours/bet_placement.py: bafybeia62an6dpkf6b46fzc4epcyh3zuvpvoge3ewmussclxbldjf3bdue + behaviours/blacklisting.py: bafybeiascy4axrqofvv3yivpxxdhkkoe2loyidl46el35wqfjbb6lm6hha behaviours/check_benchmarking.py: bafybeiao2lyj7apezkqrpgsyzb3dwvrdgsrgtprf6iuhsmlsufvxfl5bci behaviours/claim_subscription.py: bafybeihv5dg74deifzk46ppdwcvz6lgamgl6m7qr6sgqv2zie35j2576ca - behaviours/decision_receive.py: bafybeib465wlp74vq2jdaed53irnuqq22vdjj6punkjg4kyh6dovxf764u + behaviours/decision_receive.py: bafybeihigsoxbvchkt64sw52p4s2mu5l5jh5ncuhao5e24bke2nhv5qrmi behaviours/decision_request.py: bafybeiabjzzcwcfbfmtoftjhewmkgbhxfnigbc5cwmmxl6cob5gv64jwwa behaviours/handle_failed_tx.py: bafybeidxpc6u575ymct5tdwutvzov6zqfdoio5irgldn3fw7q3lg36mmxm behaviours/order_subscription.py: bafybeibl5ktq5lcwzr3komg77o67yebiokqyii7r3fsshatpww5tr5r3ke behaviours/randomness.py: bafybeidmr33teizrs4uxlo5tdz766ds6os4pe5lttstm7jpmhgmjz5ti3q - behaviours/reedem.py: bafybeigddys4zqpztjma3rakgcmkrk55hiskgivhq2cgxsqnhl5wikmrym + behaviours/reedem.py: bafybeiglaxc37hotppmgoznwjr2kchd3lyt6kmfqbljjnwue67ca4xcc2m behaviours/round_behaviour.py: bafybeibvhobpvzzd37ecleuyp2jrbed6nontcw7urtsilbbzvqsmmupx64 behaviours/sampling.py: bafybeibtkli72qsvotkrsepkgpiumtr5sershtkpb427oygnszs3dpgxry - behaviours/storage_manager.py: bafybeifelwjwstg5dwrnzeav5mumz47kqrlmv4crfn27a3vliomychd2x4 - behaviours/tool_selection.py: bafybeiat3mqtki55dnjmrrzpahjv3n26y5b45iehqx6tycqra76wtp7gxq + behaviours/storage_manager.py: bafybeigthyyyof7jvusz4mqtzgh5ptkqitnv2e6aetfjghhlhiebcavmpy + behaviours/tool_selection.py: bafybeiadjzh6yg4lamamfnqrdrcnczrxjibhrmbsiynlba6shfpzfuc7bm dialogues.py: bafybeigpwuzku3we7axmxeamg7vn656maww6emuztau5pg3ebsoquyfdqm - fsm_specification.yaml: bafybeicvrvzcjt4hg5jyr2eleoajpbb7q2fbq2bopmbnwy33fsjdblzygu + fsm_specification.yaml: bafybeif2kas4eho4aielucf3ihjzjsog32icccbxrvje6kkw7aw4m4zg6q handlers.py: bafybeigod6gbjrxy4mbmulbzsbokeaoycoqys64vqtxnumishfukzf73za io_/__init__.py: bafybeifxgmmwjqzezzn3e6keh2bfo4cyo7y5dq2ept3stfmgglbrzfl5rq io_/loader.py: bafybeih3sdsx5dhe4kzhtoafexjgkutsujwqy3zcdrlrkhtdks45bc7exa - models.py: bafybeif76bwktyx6i4h7gqunn33q2s4fjlstm4xb5hhsj3zmq4jsofmq4i - payloads.py: bafybeia32ds4ks5g3rhd43w6siy74vi5inaheuxhswiy5ndykxtgncoeu4 - policy.py: bafybeihp4lzv4ejyu6k5reukbpa6kamglicpymxfx6obm5pgugik4vc63y + models.py: bafybeib26hiscz7i44mc2nvydrhn6cfiep3z76alozmzokxvtz2sk6b5jy + payloads.py: bafybeiheazhwvvg4e5p6g32vlawc7imswjznku2i47u5nsruk4agaxtf7m + policy.py: bafybeidbsu5zn456jpku65jajwlxyg5kn2ltlkctkculkj2i2tfmmwm4jq redeem_info.py: bafybeifiiix4gihfo4avraxt34sfw35v6dqq45do2drrssei2shbps63mm - rounds.py: bafybeieffmnu3sivnagmhrhcufnh5zun6pxligc6wp26me43u6cjy2y3xi + rounds.py: bafybeihzr4tovdz2dzgzm4elwifejrtkto6mcdb5zwfk5lyzp63nmuzepa states/__init__.py: bafybeid23llnyp6j257dluxmrnztugo5llsrog7kua53hllyktz4dqhqoy - states/base.py: bafybeiayitlxvdnl3pcm54l3zt5z5bcexbxixchrwtrmbhwoimm4555p7m + states/base.py: bafybeiglhscyt3dmht2s5adeqmwo5buvpezhw3pkgarm7jslazkil3lsse states/bet_placement.py: bafybeibalhxhp2c4oljmiwqi6ds3g36fgtabmf42mb5sgq6z22znrcbhda states/blacklisting.py: bafybeiapelgjhbjjn4uq4z5gspyirqzwzgccg5anktrp5kxdwamfnfw5mi states/check_benchmarking.py: bafybeiabv6pq7q45jd3nkor5afmlycqgec5ctuwcfbdukkjjm4imesv4ni @@ -51,7 +51,7 @@ fingerprint: states/randomness.py: bafybeifgsyipvvu2e6caggyoo5vsmd64uexuho5ybyf3ry424r7kldcfre states/redeem.py: bafybeiblidmpt73ocac73wmakusrnf5267vs7s2foc5pqkrz4vuqgy3b4u states/sampling.py: bafybeihriyyskmlupjiwytx2pdpftms7plkjku5bip64c3ztx7oi3n43ci - states/tool_selection.py: bafybeiak5ihuie4nxh3sguiea6pcdgyxr4k4xyzvq6o2uj5xpf7urocawy + states/tool_selection.py: bafybeihjaixmgipyggpxolub633msg2vwv4ub7kam5jkov4drtf4er5qci tests/__init__.py: bafybeiakpi3k3kc7wrjj7hrluvjcj36lu2gezpmrctwiz5yg2fe7ggnf3i tests/behaviours/__init__.py: bafybeic7icz7lfhfepdkqkase7y7zn3a6pwdw6fx4ah2hajmgejawpolc4 tests/behaviours/data/.gitkeep: bafybeiekl43sjsyqfgl6y27ve5ydo4svcngrptgtffblokmspfezroxvvi @@ -210,7 +210,6 @@ models: bet_threshold: 100000000000000000 blacklisting_duration: 3600 ipfs_address: https://gateway.autonolas.tech/ipfs/ - tools_accuracy_hash: QmR8etyW3TPFadNtNrW54vfnFqmh8vBrMARWV76EmxCZyk prompt_template: With the given question "@{question}" and the `yes` option represented by `@{yes}` and the `no` option represented by `@{no}`, what are the respective probabilities of `p_yes` and `p_no` occurring? @@ -312,13 +311,6 @@ models: results_filename: benchmarking_results.csv randomness: benchmarking_randomness class_name: BenchmarkingMode - acc_info_fields: - args: - tool: tool - requests: total_requests - accuracy: tool_accuracy - sep: ',' - class_name: AccuracyInfoFields trades_subgraph: args: api_id: trades diff --git a/packages/valory/skills/decision_maker_abci/states/base.py b/packages/valory/skills/decision_maker_abci/states/base.py index 01e7cf9a..4c18c273 100644 --- a/packages/valory/skills/decision_maker_abci/states/base.py +++ b/packages/valory/skills/decision_maker_abci/states/base.py @@ -104,16 +104,25 @@ def policy(self) -> EGreedyPolicy: @property def has_tool_selection_run(self) -> bool: """Get whether the tool selection has run.""" - mech_tool = self.db.get("mech_tool", None) - return mech_tool is not None + mech_tool_idx = self.db.get("mech_tool_idx", None) + return mech_tool_idx is not None + + @property + def mech_tool_idx(self) -> int: + """Get the mech tool's index.""" + return int(self.db.get_strict("mech_tool_idx")) @property def mech_tool(self) -> str: """Get the selected mech tool.""" - return str(self.db.get_strict("mech_tool")) + try: + return self.available_mech_tools[self.mech_tool_idx] + except IndexError as exc: + error = f"{self.mech_tool_idx=} is not available in {self.available_mech_tools=}." + raise IndexError(error) from exc @property - def utilized_tools(self) -> Dict[str, str]: + def utilized_tools(self) -> Dict[str, int]: """Get a mapping of the utilized tools' indexes for each transaction.""" tools = str(self.db.get_strict("utilized_tools")) return json.loads(tools) diff --git a/packages/valory/skills/decision_maker_abci/states/tool_selection.py b/packages/valory/skills/decision_maker_abci/states/tool_selection.py index 9b6ce631..6ab871a4 100644 --- a/packages/valory/skills/decision_maker_abci/states/tool_selection.py +++ b/packages/valory/skills/decision_maker_abci/states/tool_selection.py @@ -42,6 +42,6 @@ class ToolSelectionRound(CollectSameUntilThresholdRound): get_name(SynchronizedData.available_mech_tools), get_name(SynchronizedData.policy), get_name(SynchronizedData.utilized_tools), - get_name(SynchronizedData.mech_tool), + get_name(SynchronizedData.mech_tool_idx), ) collection_key = get_name(SynchronizedData.participant_to_selection) diff --git a/packages/valory/skills/trader_abci/fsm_specification.yaml b/packages/valory/skills/trader_abci/fsm_specification.yaml index 2882d4fe..da5a7c8b 100644 --- a/packages/valory/skills/trader_abci/fsm_specification.yaml +++ b/packages/valory/skills/trader_abci/fsm_specification.yaml @@ -94,7 +94,7 @@ states: transition_func: (BetPlacementRound, DONE): PreTxSettlementRound (BetPlacementRound, INSUFFICIENT_BALANCE): ResetAndPauseRound - (BetPlacementRound, MOCK_TX): RedeemRound + (BetPlacementRound, MOCK_TX): RandomnessRound (BetPlacementRound, NONE): ImpossibleRound (BetPlacementRound, NO_MAJORITY): BetPlacementRound (BetPlacementRound, ROUND_TIMEOUT): BetPlacementRound diff --git a/packages/valory/skills/trader_abci/models.py b/packages/valory/skills/trader_abci/models.py index 9462cd6c..51062d75 100644 --- a/packages/valory/skills/trader_abci/models.py +++ b/packages/valory/skills/trader_abci/models.py @@ -27,9 +27,6 @@ ) from packages.valory.skills.abstract_round_abci.models import Requests as BaseRequests from packages.valory.skills.check_stop_trading_abci.models import CheckStopTradingParams -from packages.valory.skills.decision_maker_abci.models import ( - AccuracyInfoFields as BaseAccuracyInfoFields, -) from packages.valory.skills.decision_maker_abci.models import ( AgentToolsSpecs as DecisionMakerAgentToolsSpecs, ) @@ -95,7 +92,6 @@ ConditionalTokensSubgraph = DecisionMakerConditionalTokensSubgraph RealitioSubgraph = DecisionMakerRealitioSubgraph BenchmarkingMode = BaseBenchmarkingMode -AccuracyInfoFields = BaseAccuracyInfoFields MARGIN = 5 diff --git a/packages/valory/skills/trader_abci/skill.yaml b/packages/valory/skills/trader_abci/skill.yaml index 243cb4dd..4c62dacc 100644 --- a/packages/valory/skills/trader_abci/skill.yaml +++ b/packages/valory/skills/trader_abci/skill.yaml @@ -11,9 +11,9 @@ fingerprint: behaviours.py: bafybeigc6hszbu66ccajny5eh7thfgsrlr36je4mzziwp4mupgvtaeu6aa composition.py: bafybeidp3sl5uomb5stgk6y7nifxv7zomfe3emqstbuw32urorpimq7lgi dialogues.py: bafybeiebofyykseqp3fmif36cqmmyf3k7d2zbocpl6t6wnlpv4szghrxbm - fsm_specification.yaml: bafybeig72lgkum7aeieb52jch6qkfdtarzdc2w64562hutck4rowzo3dcy + fsm_specification.yaml: bafybeif7fxldzdglalwgmo3u44jkjdox2tdgf6zbq7epw6ju4kyl5b7tze handlers.py: bafybeibbxybbi66em63ad33cllymypr3za3f5xvor3m2krhuxoyxnqjnxu - models.py: bafybeidrtcycxhuig776kjhnuonwlvjmn4kb2n3uvxdrpmc3hwn65qsolm + models.py: bafybeicovhcparwbvqdbrofv4kxiyznuezpqxsdxqx3wkkvht7patop4e4 fingerprint_ignore_patterns: [] connections: [] contracts: [] @@ -25,8 +25,8 @@ skills: - valory/transaction_settlement_abci:0.1.0:bafybeic3tccdjypuge2lewtlgprwkbb53lhgsgn7oiwzyrcrrptrbeyote - valory/termination_abci:0.1.0:bafybeif2zim2de356eo3sipkmoev5emwadpqqzk3huwqarywh4tmqt3vzq - valory/market_manager_abci:0.1.0:bafybeig44vtxcq7aarqkg2mskly3zwwnyfc45rtdvorwz6ywspwg3obqn4 -- valory/decision_maker_abci:0.1.0:bafybeiejbfkl4im6srigta53ysan3tu5hlbb44cbd2mgryp2hsanyxpdge -- valory/tx_settlement_multiplexer_abci:0.1.0:bafybeiaiek6b3p7dro45qjoecmgseznhixhrgqgxfiap7lqw4rbi5fyhvy +- valory/decision_maker_abci:0.1.0:bafybeiapszwgdpq6ipu5ffjgzi3r7ylyuaju6n26xalclnnixnzprnynuu +- valory/tx_settlement_multiplexer_abci:0.1.0:bafybeiggsvl7zxifj3haydd4njb3griljqpr4wledvqi3gh2lvcbbphxdq - valory/staking_abci:0.1.0:bafybeidubhfvlf6x627t4wetc6ran5sb4pttjphyhv6vefp2a4kcuca2be - valory/check_stop_trading_abci:0.1.0:bafybeiboctfgetji6xlzw2buts5zsejnlrrhqkppme2p6fwzu26zznb324 - valory/mech_interact_abci:0.1.0:bafybeih2cck5xu6yaibomwtm5zbcp6llghr3ighdnk56fzwu3ihu5xx35e @@ -161,7 +161,6 @@ models: bet_threshold: 100000000000000000 blacklisting_duration: 3600 ipfs_address: https://gateway.autonolas.tech/ipfs/ - tools_accuracy_hash: QmR8etyW3TPFadNtNrW54vfnFqmh8vBrMARWV76EmxCZyk prompt_template: With the given question "@{question}" and the `yes` option represented by `@{yes}` and the `no` option represented by `@{no}`, what are the respective probabilities of `p_yes` and `p_no` occurring? @@ -271,13 +270,6 @@ models: results_filename: benchmarking_results.csv randomness: benchmarking_randomness class_name: BenchmarkingMode - acc_info_fields: - args: - tool: tool - requests: total_requests - accuracy: tool_accuracy - sep: ',' - class_name: AccuracyInfoFields network_subgraph: args: api_id: network diff --git a/packages/valory/skills/tx_settlement_multiplexer_abci/rounds.py b/packages/valory/skills/tx_settlement_multiplexer_abci/rounds.py index cee81700..06dff3b7 100644 --- a/packages/valory/skills/tx_settlement_multiplexer_abci/rounds.py +++ b/packages/valory/skills/tx_settlement_multiplexer_abci/rounds.py @@ -103,14 +103,14 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Enum]]: # if a mech request was just performed, increase the utilized tool's counter if event == Event.MECH_REQUESTING_DONE: policy = synced_data.policy - policy.tool_used(synced_data.mech_tool) + policy.tool_used(synced_data.mech_tool_idx) policy_update = policy.serialize() self.synchronized_data.update(policy=policy_update) # if a bet was just placed, edit the utilized tools mapping if event == Event.BET_PLACEMENT_DONE: utilized_tools = synced_data.utilized_tools - utilized_tools[synced_data.final_tx_hash] = synced_data.mech_tool + utilized_tools[synced_data.final_tx_hash] = synced_data.mech_tool_idx tools_update = json.dumps(utilized_tools, sort_keys=True) self.synchronized_data.update(utilized_tools=tools_update) diff --git a/packages/valory/skills/tx_settlement_multiplexer_abci/skill.yaml b/packages/valory/skills/tx_settlement_multiplexer_abci/skill.yaml index d6b4c623..f2d4676c 100644 --- a/packages/valory/skills/tx_settlement_multiplexer_abci/skill.yaml +++ b/packages/valory/skills/tx_settlement_multiplexer_abci/skill.yaml @@ -13,7 +13,7 @@ fingerprint: fsm_specification.yaml: bafybeicd7us5ffvsrxm7ybaanyzojbhmo7xtsfd3swtdem4dfsxkidxw7a handlers.py: bafybeiafbqr7ojfcbwohvee7x4zzswad3ymfrrbjlfz7uuuttmn3qdfs6q models.py: bafybeigtmxoecoow663hgqnyinxarlrttyyt5ghpbdamdv4tc4kikcfx3a - rounds.py: bafybeig3dhhrf5tkj63b3bk2mqfprcwzk3galz2ukzvdenz4g2femaixku + rounds.py: bafybeig77b7m5fyhy4bsdnmveszagq27v2ck7627tyhw6zzn7spmz5qalu fingerprint_ignore_patterns: [] connections: [] contracts: [] @@ -21,7 +21,7 @@ protocols: - valory/ledger_api:1.0.0:bafybeihdk6psr4guxmbcrc26jr2cbgzpd5aljkqvpwo64bvaz7tdti2oni skills: - valory/abstract_round_abci:0.1.0:bafybeiar2yhzxacfe3qqamqhaihtlcimquwedffctw55sowx6rac3cm3ui -- valory/decision_maker_abci:0.1.0:bafybeiejbfkl4im6srigta53ysan3tu5hlbb44cbd2mgryp2hsanyxpdge +- valory/decision_maker_abci:0.1.0:bafybeiapszwgdpq6ipu5ffjgzi3r7ylyuaju6n26xalclnnixnzprnynuu - valory/staking_abci:0.1.0:bafybeidubhfvlf6x627t4wetc6ran5sb4pttjphyhv6vefp2a4kcuca2be - valory/mech_interact_abci:0.1.0:bafybeih2cck5xu6yaibomwtm5zbcp6llghr3ighdnk56fzwu3ihu5xx35e behaviours: diff --git a/poetry.lock b/poetry.lock index 41825794..dc030271 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,9 +1,10 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand. [[package]] name = "aiohttp" version = "3.9.5" description = "Async http client/server framework (asyncio)" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -100,6 +101,7 @@ speedups = ["Brotli", "aiodns", "brotlicffi"] name = "aiosignal" version = "1.3.1" description = "aiosignal: a list of registered asynchronous callbacks" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -114,6 +116,7 @@ frozenlist = ">=1.1.0" name = "altgraph" version = "0.17.4" description = "Python graph (network) package" +category = "main" optional = false python-versions = "*" files = [ @@ -125,6 +128,7 @@ files = [ name = "anyio" version = "4.4.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -147,6 +151,7 @@ trio = ["trio (>=0.23)"] name = "asn1crypto" version = "1.4.0" description = "Fast ASN.1 parser and serializer with definitions for private keys, public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, PKCS#12, PKCS#5, X.509 and TSP" +category = "main" optional = false python-versions = "*" files = [ @@ -158,6 +163,7 @@ files = [ name = "async-timeout" version = "4.0.3" description = "Timeout context manager for asyncio programs" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -169,6 +175,7 @@ files = [ name = "attrs" version = "23.2.0" description = "Classes Without Boilerplate" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -188,6 +195,7 @@ tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "p name = "backoff" version = "2.2.1" description = "Function decoration for backoff and retry" +category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -199,6 +207,7 @@ files = [ name = "base58" version = "2.1.1" description = "Base58 and Base58Check implementation." +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -213,6 +222,7 @@ tests = ["PyHamcrest (>=2.0.2)", "mypy", "pytest (>=4.6)", "pytest-benchmark", " name = "bcrypt" version = "4.1.3" description = "Modern password hashing for your software and your servers" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -253,6 +263,7 @@ typecheck = ["mypy"] name = "bech32" version = "1.2.0" description = "Reference implementation for Bech32 and segwit addresses." +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -264,6 +275,7 @@ files = [ name = "bitarray" version = "2.9.2" description = "efficient arrays of booleans -- C extension" +category = "main" optional = false python-versions = "*" files = [ @@ -395,6 +407,7 @@ files = [ name = "cached-property" version = "1.5.2" description = "A decorator for caching properties in classes." +category = "main" optional = false python-versions = "*" files = [ @@ -406,6 +419,7 @@ files = [ name = "certifi" version = "2021.10.8" description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false python-versions = "*" files = [ @@ -417,6 +431,7 @@ files = [ name = "cffi" version = "1.16.0" description = "Foreign Function Interface for Python calling C code." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -481,6 +496,7 @@ pycparser = "*" name = "charset-normalizer" version = "2.1.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" optional = false python-versions = ">=3.6.0" files = [ @@ -495,6 +511,7 @@ unicode-backport = ["unicodedata2"] name = "click" version = "8.1.7" description = "Composable command line interface toolkit" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -509,6 +526,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -520,6 +538,7 @@ files = [ name = "cosmpy" version = "0.9.2" description = "A library for interacting with the cosmos networks" +category = "main" optional = false python-versions = ">=3.8,<4.0" files = [ @@ -542,6 +561,7 @@ requests = "*" name = "coverage" version = "7.6.0" description = "Code coverage measurement for Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -609,6 +629,7 @@ toml = ["tomli"] name = "cryptography" version = "42.0.8" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -663,6 +684,7 @@ test-randomorder = ["pytest-randomly"] name = "cytoolz" version = "0.12.3" description = "Cython implementation of Toolz: High performance functional utilities" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -782,6 +804,7 @@ cython = ["cython"] name = "distlib" version = "0.3.8" description = "Distribution utilities" +category = "main" optional = false python-versions = "*" files = [ @@ -793,6 +816,7 @@ files = [ name = "distro" version = "1.9.0" description = "Distro - an OS platform information API" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -804,6 +828,7 @@ files = [ name = "docker" version = "6.1.2" description = "A Python library for the Docker Engine API." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -826,6 +851,7 @@ ssh = ["paramiko (>=2.4.3)"] name = "dockerpty" version = "0.4.1" description = "Python library to use the pseudo-tty of a docker container" +category = "main" optional = false python-versions = "*" files = [ @@ -839,6 +865,7 @@ six = ">=1.3.0" name = "docopt" version = "0.6.2" description = "Pythonic argument parser, that will make you smile" +category = "main" optional = false python-versions = "*" files = [ @@ -849,6 +876,7 @@ files = [ name = "ecdsa" version = "0.16.1" description = "ECDSA cryptographic signature library (pure python)" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -867,6 +895,7 @@ gmpy2 = ["gmpy2"] name = "eth-abi" version = "4.0.0" description = "eth_abi: Python utilities for working with Ethereum ABI definitions, especially encoding and decoding" +category = "main" optional = false python-versions = ">=3.7, <4" files = [ @@ -890,6 +919,7 @@ tools = ["hypothesis (>=4.18.2,<5.0.0)"] name = "eth-account" version = "0.8.0" description = "eth-account: Sign Ethereum transactions and messages with local private keys" +category = "main" optional = false python-versions = ">=3.6, <4" files = [ @@ -917,6 +947,7 @@ test = ["coverage", "hypothesis (>=4.18.0,<5)", "pytest (>=6.2.5,<7)", "pytest-x name = "eth-hash" version = "0.7.0" description = "eth-hash: The Ethereum hashing function, keccak256, sometimes (erroneously) called sha3" +category = "main" optional = false python-versions = ">=3.8, <4" files = [ @@ -938,6 +969,7 @@ test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] name = "eth-keyfile" version = "0.6.1" description = "A library for handling the encrypted keyfiles used to store ethereum private keys." +category = "main" optional = false python-versions = "*" files = [ @@ -960,6 +992,7 @@ test = ["pytest (>=6.2.5,<7)"] name = "eth-keys" version = "0.4.0" description = "Common API for Ethereum key operations." +category = "main" optional = false python-versions = "*" files = [ @@ -982,6 +1015,7 @@ test = ["asn1tools (>=0.146.2,<0.147)", "eth-hash[pycryptodome]", "eth-hash[pysh name = "eth-rlp" version = "0.3.0" description = "eth-rlp: RLP definitions for common Ethereum objects in Python" +category = "main" optional = false python-versions = ">=3.7, <4" files = [ @@ -1004,6 +1038,7 @@ test = ["eth-hash[pycryptodome]", "pytest (>=6.2.5,<7)", "pytest-xdist", "tox (= name = "eth-typing" version = "3.5.2" description = "eth-typing: Common type annotations for ethereum python packages" +category = "main" optional = false python-versions = ">=3.7.2, <4" files = [ @@ -1024,6 +1059,7 @@ test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] name = "eth-utils" version = "2.2.0" description = "eth-utils: Common utility functions for python code that interacts with Ethereum" +category = "main" optional = false python-versions = ">=3.7,<4" files = [ @@ -1045,13 +1081,14 @@ test = ["hypothesis (>=4.43.0)", "mypy (==0.971)", "pytest (>=7.0.0)", "pytest-x [[package]] name = "exceptiongroup" -version = "1.2.1" +version = "1.2.2" description = "Backport of PEP 654 (exception groups)" +category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, - {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, ] [package.extras] @@ -1061,6 +1098,7 @@ test = ["pytest (>=6)"] name = "filelock" version = "3.15.4" description = "A platform independent file lock." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1077,6 +1115,7 @@ typing = ["typing-extensions (>=4.8)"] name = "flask" version = "2.1.3" description = "A simple framework for building complex web applications." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1099,6 +1138,7 @@ dotenv = ["python-dotenv"] name = "frozenlist" version = "1.4.1" description = "A list-like structure which implements collections.abc.MutableSequence" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1185,6 +1225,7 @@ files = [ name = "googleapis-common-protos" version = "1.63.2" description = "Common protobufs used in Google APIs" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1202,6 +1243,7 @@ grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] name = "gql" version = "3.5.0" description = "GraphQL client for Python" +category = "main" optional = false python-versions = "*" files = [ @@ -1230,6 +1272,7 @@ websockets = ["websockets (>=10,<12)"] name = "graphql-core" version = "3.2.3" description = "GraphQL implementation for Python, a port of GraphQL.js, the JavaScript reference implementation for GraphQL." +category = "main" optional = false python-versions = ">=3.6,<4" files = [ @@ -1241,6 +1284,7 @@ files = [ name = "grpcio" version = "1.53.0" description = "HTTP/2-based RPC framework" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1298,6 +1342,7 @@ protobuf = ["grpcio-tools (>=1.53.0)"] name = "hexbytes" version = "0.3.1" description = "hexbytes: Python `bytes` subclass that decodes hex, with a readable console output" +category = "main" optional = false python-versions = ">=3.7, <4" files = [ @@ -1315,6 +1360,7 @@ test = ["eth-utils (>=1.0.1,<3)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>= name = "hypothesis" version = "6.21.6" description = "A library for property-based testing" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1346,6 +1392,7 @@ zoneinfo = ["backports.zoneinfo (>=0.2.1)", "importlib-resources (>=3.3.0)", "tz name = "idna" version = "3.7" description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1357,6 +1404,7 @@ files = [ name = "importlib-metadata" version = "8.0.0" description = "Read metadata from Python packages" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1376,6 +1424,7 @@ test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "p name = "importlib-resources" version = "6.4.0" description = "Read resources from Python packages" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1394,6 +1443,7 @@ testing = ["jaraco.test (>=5.4)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "p name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1405,6 +1455,7 @@ files = [ name = "ipfshttpclient" version = "0.8.0a2" description = "Python IPFS HTTP CLIENT library" +category = "main" optional = false python-versions = ">=3.6.2,!=3.7.0,!=3.7.1" files = [ @@ -1420,6 +1471,7 @@ requests = ">=2.11" name = "isodate" version = "0.6.1" description = "An ISO 8601 date/time/duration parser and formatter" +category = "main" optional = false python-versions = "*" files = [ @@ -1434,6 +1486,7 @@ six = "*" name = "itsdangerous" version = "2.2.0" description = "Safely pass data to untrusted environments and back." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1445,6 +1498,7 @@ files = [ name = "jinja2" version = "3.1.4" description = "A very fast and expressive template engine." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1462,6 +1516,7 @@ i18n = ["Babel (>=2.7)"] name = "jsonschema" version = "4.3.3" description = "An implementation of JSON Schema validation for Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1482,6 +1537,7 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- name = "lru-dict" version = "1.2.0" description = "An Dict like LRU container." +category = "main" optional = false python-versions = "*" files = [ @@ -1576,6 +1632,7 @@ test = ["pytest"] name = "macholib" version = "1.16.3" description = "Mach-O header analysis and editing" +category = "main" optional = false python-versions = "*" files = [ @@ -1590,6 +1647,7 @@ altgraph = ">=0.17" name = "markupsafe" version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1659,6 +1717,7 @@ files = [ name = "more-itertools" version = "10.3.0" description = "More routines for operating on iterables, beyond itertools" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1670,6 +1729,7 @@ files = [ name = "morphys" version = "1.0" description = "Smart conversions between unicode and bytes types for common cases" +category = "main" optional = false python-versions = "*" files = [ @@ -1680,6 +1740,7 @@ files = [ name = "multiaddr" version = "0.0.9" description = "Python implementation of jbenet's multiaddr" +category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" files = [ @@ -1697,6 +1758,7 @@ varint = "*" name = "multidict" version = "6.0.5" description = "multidict implementation" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1796,6 +1858,7 @@ files = [ name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1807,6 +1870,7 @@ files = [ name = "netaddr" version = "1.3.0" description = "A network address manipulation library for Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1821,6 +1885,7 @@ nicer-shell = ["ipython"] name = "open-aea" version = "1.52.0" description = "Open Autonomous Economic Agent framework (without vendor lock-in)" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1847,7 +1912,10 @@ py-multicodec = ">=0.2.0" pymultihash = "0.8.2" pytest = {version = ">=7.0.0,<7.3.0", optional = true, markers = "extra == \"all\""} python-dotenv = ">=0.14.0,<0.22.0" -pyyaml = {version = ">=6.0.1,<7", optional = true, markers = "extra == \"all\""} +pyyaml = [ + {version = ">=6.0.1,<7"}, + {version = ">=6.0.1,<9", optional = true, markers = "extra == \"all\""}, +] requests = ">=2.28.1,<3" semver = ">=2.9.1,<3.0.0" @@ -1860,6 +1928,7 @@ test-tools = ["click (>=8.1.0,<9)", "coverage (>=6.4.4,<8.0.0)", "jsonschema (>= name = "open-aea-cli-ipfs" version = "1.52.0" description = "CLI extension for open AEA framework wrapping IPFS functionality." +category = "main" optional = false python-versions = "*" files = [ @@ -1876,6 +1945,7 @@ pytest = ">=7.0.0,<7.3.0" name = "open-aea-ledger-cosmos" version = "1.52.0" description = "Python package wrapping the public and private key cryptography and ledger api of Cosmos." +category = "main" optional = false python-versions = "*" files = [ @@ -1894,6 +1964,7 @@ pycryptodome = ">=3.10.1,<4.0.0" name = "open-aea-ledger-ethereum" version = "1.52.0" description = "Python package wrapping the public and private key cryptography and ledger api of Ethereum." +category = "main" optional = false python-versions = "*" files = [ @@ -1911,6 +1982,7 @@ web3 = ">=6.0.0,<7" name = "open-aea-test-autonomy" version = "0.14.12" description = "Plugin containing test tools for open-autonomy packages." +category = "main" optional = false python-versions = "*" files = [ @@ -1928,6 +2000,7 @@ pytest = "7.2.1" name = "open-autonomy" version = "0.14.12" description = "A framework for the creation of autonomous agent services." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1964,6 +2037,7 @@ cli = ["click (>=8.1.0,<9)", "coverage (>=6.4.4,<8.0.0)", "open-aea-cli-ipfs (== name = "openapi-core" version = "0.15.0" description = "client-side and server-side support for the OpenAPI Specification v3" +category = "main" optional = false python-versions = ">=3.7.0,<4.0.0" files = [ @@ -1991,6 +2065,7 @@ requests = ["requests"] name = "openapi-schema-validator" version = "0.2.3" description = "OpenAPI schema validation for Python" +category = "main" optional = false python-versions = ">=3.7.0,<4.0.0" files = [ @@ -2010,6 +2085,7 @@ strict-rfc3339 = ["strict-rfc3339"] name = "openapi-spec-validator" version = "0.4.0" description = "OpenAPI 2.0 (aka Swagger) and OpenAPI 3.0 spec validator" +category = "main" optional = false python-versions = ">=3.7.0,<4.0.0" files = [ @@ -2030,6 +2106,7 @@ requests = ["requests"] name = "packaging" version = "23.2" description = "Core utilities for Python packages" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2041,6 +2118,7 @@ files = [ name = "paramiko" version = "3.4.0" description = "SSH2 protocol library" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2062,6 +2140,7 @@ invoke = ["invoke (>=2.0)"] name = "parse" version = "1.20.2" description = "parse() is the opposite of format()" +category = "main" optional = false python-versions = "*" files = [ @@ -2073,6 +2152,7 @@ files = [ name = "parsimonious" version = "0.9.0" description = "(Soon to be) the fastest pure-Python PEG parser I could muster" +category = "main" optional = false python-versions = "*" files = [ @@ -2086,6 +2166,7 @@ regex = ">=2022.3.15" name = "pathable" version = "0.4.3" description = "Object-oriented paths" +category = "main" optional = false python-versions = ">=3.7.0,<4.0.0" files = [ @@ -2097,6 +2178,7 @@ files = [ name = "pefile" version = "2023.2.7" description = "Python PE parsing module" +category = "main" optional = false python-versions = ">=3.6.0" files = [ @@ -2108,6 +2190,7 @@ files = [ name = "platformdirs" version = "4.2.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2124,6 +2207,7 @@ type = ["mypy (>=1.8)"] name = "pluggy" version = "1.5.0" description = "plugin and hook calling mechanisms for python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2139,6 +2223,7 @@ testing = ["pytest", "pytest-benchmark"] name = "protobuf" version = "4.24.4" description = "" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2161,6 +2246,7 @@ files = [ name = "py" version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -2172,6 +2258,7 @@ files = [ name = "py-ecc" version = "6.0.0" description = "Elliptic curve crypto in python including secp256k1 and alt_bn128" +category = "main" optional = false python-versions = ">=3.6, <4" files = [ @@ -2194,6 +2281,7 @@ test = ["pytest (==6.2.5)", "pytest-xdist (==1.26.0)"] name = "py-eth-sig-utils" version = "0.4.0" description = "Python Ethereum Signing Utils" +category = "main" optional = false python-versions = "*" files = [ @@ -2211,6 +2299,7 @@ rlp = ">=1.1.0" name = "py-multibase" version = "1.0.3" description = "Multibase implementation for Python" +category = "main" optional = false python-versions = "*" files = [ @@ -2227,6 +2316,7 @@ six = ">=1.10.0,<2.0" name = "py-multicodec" version = "0.2.1" description = "Multicodec implementation in Python" +category = "main" optional = false python-versions = "*" files = [ @@ -2243,6 +2333,7 @@ varint = ">=1.0.2,<2.0.0" name = "pycparser" version = "2.22" description = "C parser in Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2254,6 +2345,7 @@ files = [ name = "pycryptodome" version = "3.18.0" description = "Cryptographic library for Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -2295,6 +2387,7 @@ files = [ name = "pyinstaller" version = "6.8.0" description = "PyInstaller bundles a Python application and all its dependencies into a single package." +category = "main" optional = false python-versions = "<3.13,>=3.8" files = [ @@ -2330,6 +2423,7 @@ hook-testing = ["execnet (>=1.5.0)", "psutil", "pytest (>=2.7.3)"] name = "pyinstaller-hooks-contrib" version = "2024.7" description = "Community maintained hooks for PyInstaller" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2346,6 +2440,7 @@ setuptools = ">=42.0.0" name = "pymultihash" version = "0.8.2" description = "Python implementation of the multihash specification" +category = "main" optional = false python-versions = "*" files = [ @@ -2361,6 +2456,7 @@ sha3 = ["pysha3"] name = "pynacl" version = "1.5.0" description = "Python binding to the Networking and Cryptography (NaCl) library" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2387,6 +2483,7 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] name = "pyrsistent" version = "0.20.0" description = "Persistent/Functional/Immutable data structures" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2428,6 +2525,7 @@ files = [ name = "pytest" version = "7.2.1" description = "pytest: simple powerful testing with Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2451,6 +2549,7 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2. name = "pytest-asyncio" version = "0.21.2" description = "Pytest support for asyncio" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2469,6 +2568,7 @@ testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy name = "pytest-cov" version = "4.0.0" description = "Pytest plugin for measuring coverage." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2487,6 +2587,7 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale name = "pytest-randomly" version = "3.12.0" description = "Pytest plugin to randomly order tests and control random.seed." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2502,6 +2603,7 @@ pytest = "*" name = "pytest-rerunfailures" version = "11.0" description = "pytest plugin to re-run tests to eliminate flaky failures" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2517,6 +2619,7 @@ pytest = ">=5.3" name = "python-baseconv" version = "1.2.2" description = "Convert numbers from base 10 integers to base X strings and back again." +category = "main" optional = false python-versions = "*" files = [ @@ -2527,6 +2630,7 @@ files = [ name = "python-dateutil" version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -2541,6 +2645,7 @@ six = ">=1.5" name = "python-dotenv" version = "0.21.1" description = "Read key-value pairs from a .env file and set them as environment variables" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2555,6 +2660,7 @@ cli = ["click (>=5.0)"] name = "pytz" version = "2022.2.1" description = "World timezone definitions, modern and historical" +category = "main" optional = false python-versions = "*" files = [ @@ -2566,6 +2672,7 @@ files = [ name = "pyunormalize" version = "15.1.0" description = "Unicode normalization forms (NFC, NFKC, NFD, NFKD). A library independent from the Python core Unicode database." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2576,6 +2683,7 @@ files = [ name = "pywin32" version = "306" description = "Python for Window Extensions" +category = "main" optional = false python-versions = "*" files = [ @@ -2599,6 +2707,7 @@ files = [ name = "pywin32-ctypes" version = "0.2.2" description = "A (partial) reimplementation of pywin32 using ctypes/cffi" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2610,6 +2719,7 @@ files = [ name = "pyyaml" version = "6.0.1" description = "YAML parser and emitter for Python" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2618,7 +2728,6 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -2626,16 +2735,8 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -2652,7 +2753,6 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -2660,7 +2760,6 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -2670,6 +2769,7 @@ files = [ name = "regex" version = "2024.5.15" description = "Alternative regular expression module, to replace re." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2758,6 +2858,7 @@ files = [ name = "requests" version = "2.28.1" description = "Python HTTP for Humans." +category = "main" optional = false python-versions = ">=3.7, <4" files = [ @@ -2779,6 +2880,7 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "requests-toolbelt" version = "1.0.0" description = "A utility belt for advanced users of python-requests" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -2793,6 +2895,7 @@ requests = ">=2.0.1,<3.0.0" name = "rlp" version = "3.0.0" description = "A package for Recursive Length Prefix encoding and decoding" +category = "main" optional = false python-versions = "*" files = [ @@ -2814,6 +2917,7 @@ test = ["hypothesis (==5.19.0)", "pytest (>=6.2.5,<7)", "tox (>=2.9.1,<3)"] name = "semver" version = "2.13.0" description = "Python helper for Semantic Versioning (http://semver.org/)" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -2823,23 +2927,26 @@ files = [ [[package]] name = "setuptools" -version = "70.3.0" +version = "71.0.3" description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-70.3.0-py3-none-any.whl", hash = "sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc"}, - {file = "setuptools-70.3.0.tar.gz", hash = "sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5"}, + {file = "setuptools-71.0.3-py3-none-any.whl", hash = "sha256:f501b6e6db709818dc76882582d9c516bf3b67b948864c5fa1d1624c09a49207"}, + {file = "setuptools-71.0.3.tar.gz", hash = "sha256:3d8531791a27056f4a38cd3e54084d8b1c4228ff9cf3f2d7dd075ec99f9fd70d"}, ] [package.extras] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (<7.4)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -2851,6 +2958,7 @@ files = [ name = "sniffio" version = "1.3.1" description = "Sniff out which async library your code is running under" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2862,6 +2970,7 @@ files = [ name = "sortedcontainers" version = "2.4.0" description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +category = "main" optional = false python-versions = "*" files = [ @@ -2873,6 +2982,7 @@ files = [ name = "texttable" version = "1.6.7" description = "module to create simple ASCII tables" +category = "main" optional = false python-versions = "*" files = [ @@ -2884,6 +2994,7 @@ files = [ name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -2895,6 +3006,7 @@ files = [ name = "tomli" version = "2.0.1" description = "A lil' TOML parser" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2906,6 +3018,7 @@ files = [ name = "tomte" version = "0.2.17" description = "A library that wraps many useful tools (linters, analysers, etc) to keep Python code clean, secure, well-documented and optimised." +category = "main" optional = false python-versions = "<4,>=3.8" files = [ @@ -2943,6 +3056,7 @@ vulture = ["vulture (==2.7)"] name = "toolz" version = "0.12.1" description = "List processing tools and functional utilities" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2954,6 +3068,7 @@ files = [ name = "tox" version = "3.28.0" description = "tox is a generic virtualenv management and test command line tool" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ @@ -2979,6 +3094,7 @@ testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pathlib2 (>=2.3.3)", "psu name = "typing-extensions" version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2990,6 +3106,7 @@ files = [ name = "urllib3" version = "1.26.16" description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -3006,6 +3123,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] name = "valory-docker-compose" version = "1.29.3" description = "Multi-container orchestration for Docker" +category = "main" optional = false python-versions = ">=3.4" files = [ @@ -3034,6 +3152,7 @@ tests = ["ddt (>=1.2.2,<2)", "pytest (<6)"] name = "varint" version = "1.0.2" description = "Simple python varint implementation" +category = "main" optional = false python-versions = "*" files = [ @@ -3044,6 +3163,7 @@ files = [ name = "virtualenv" version = "20.26.3" description = "Virtual Python Environment builder" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3064,6 +3184,7 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess name = "watchdog" version = "4.0.1" description = "Filesystem events monitoring" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3108,6 +3229,7 @@ watchmedo = ["PyYAML (>=3.10)"] name = "web3" version = "6.20.0" description = "web3.py" +category = "main" optional = false python-versions = ">=3.7.2" files = [ @@ -3142,6 +3264,7 @@ tester = ["eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1)", "eth-tester[py-evm] (>=0. name = "websocket-client" version = "0.59.0" description = "WebSocket client for Python with low level API options" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -3156,6 +3279,7 @@ six = "*" name = "websockets" version = "12.0" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3237,6 +3361,7 @@ files = [ name = "werkzeug" version = "2.0.3" description = "The comprehensive WSGI web application library." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -3251,6 +3376,7 @@ watchdog = ["watchdog"] name = "yarl" version = "1.9.4" description = "Yet another URL library" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3354,6 +3480,7 @@ multidict = ">=4.0" name = "zipp" version = "3.19.2" description = "Backport of pathlib-compatible object wrapper for zip files" +category = "main" optional = false python-versions = ">=3.8" files = [