1818#
1919# ------------------------------------------------------------------------------
2020
21+ """Choose staking program."""
22+
2123import argparse
24+ import json
2225import os
23- import requests
2426import sys
2527import textwrap
26- import json
27- from dotenv import dotenv_values , set_key , unset_key
2828from pathlib import Path
29- from typing import Any , Dict , List , Tuple
29+ from typing import Any , Dict , List
30+
31+ import requests
32+ from dotenv import dotenv_values , set_key , unset_key
3033from web3 import Web3
3134
35+
3236SCRIPT_PATH = Path (__file__ ).resolve ().parent
3337STORE_PATH = Path (SCRIPT_PATH , ".." , ".trader_runner" )
3438DOTENV_PATH = Path (STORE_PATH , ".env" )
3539RPC_PATH = Path (STORE_PATH , "rpc.txt" )
40+ STAKING_TOKEN_INSTANCE_ABI_PATH = Path (
41+ SCRIPT_PATH ,
42+ ".." ,
43+ "trader" ,
44+ "packages" ,
45+ "valory" ,
46+ "contracts" ,
47+ "staking_token" ,
48+ "build" ,
49+ "StakingToken.json" ,
50+ )
51+ STAKING_TOKEN_IMPLEMENTATION_ABI_PATH = STAKING_TOKEN_INSTANCE_ABI_PATH
52+ ACTIVITY_CHECKER_ABI_PATH = Path (
53+ SCRIPT_PATH ,
54+ ".." ,
55+ "trader" ,
56+ "packages" ,
57+ "valory" ,
58+ "contracts" ,
59+ "mech_activity" ,
60+ "build" ,
61+ "MechActivity.json" ,
62+ )
3663
3764IPFS_ADDRESS = "https://gateway.autonolas.tech/ipfs/f01701220{hash}"
3865NEVERMINED_MECH_CONTRACT_ADDRESS = "0x327E26bDF1CfEa50BFAe35643B23D5268E41F7F9"
@@ -84,18 +111,20 @@ def _prompt_select_staking_program() -> str:
84111 env_file_vars = dotenv_values (DOTENV_PATH )
85112
86113 program_id = None
87- if ' STAKING_PROGRAM' in env_file_vars :
114+ if " STAKING_PROGRAM" in env_file_vars :
88115 print ("The staking program is already selected." )
89116
90- program_id = env_file_vars .get (' STAKING_PROGRAM' )
117+ program_id = env_file_vars .get (" STAKING_PROGRAM" )
91118 if program_id not in STAKING_PROGRAMS :
92119 print (f"WARNING: Selected staking program { program_id } is unknown." )
93120 print ("" )
94121 program_id = None
95122
96123 if not program_id :
97124 if os .environ .get ("ATTENDED" ) == "false" :
98- print ("No staking program set in environment variable STAKING_PROGRAM. Defaulting to 'no_staking'." )
125+ print (
126+ "No staking program set in environment variable STAKING_PROGRAM. Defaulting to 'no_staking'."
127+ )
99128 return NO_STAKING_PROGRAM_ID
100129
101130 print ("Please, select your staking program preference" )
@@ -105,7 +134,9 @@ def _prompt_select_staking_program() -> str:
105134 metadata = _get_staking_contract_metadata (program_id = key )
106135 name = metadata ["name" ]
107136 description = metadata ["description" ]
108- wrapped_description = textwrap .fill (description , width = 80 , initial_indent = ' ' , subsequent_indent = ' ' )
137+ wrapped_description = textwrap .fill (
138+ description , width = 80 , initial_indent = " " , subsequent_indent = " "
139+ )
109140 print (f"{ index + 1 } ) { name } \n { wrapped_description } \n " )
110141
111142 while True :
@@ -124,8 +155,12 @@ def _prompt_select_staking_program() -> str:
124155
125156
126157def _get_abi (contract_address : str ) -> List :
127- contract_abi_url = "https://gnosis.blockscout.com/api/v2/smart-contracts/{contract_address}"
128- response = requests .get (contract_abi_url .format (contract_address = contract_address )).json ()
158+ contract_abi_url = (
159+ "https://gnosis.blockscout.com/api/v2/smart-contracts/{contract_address}"
160+ )
161+ response = requests .get (
162+ contract_abi_url .format (contract_address = contract_address )
163+ ).json ()
129164
130165 if "result" in response :
131166 result = response ["result" ]
@@ -140,70 +175,107 @@ def _get_abi(contract_address: str) -> List:
140175 return abi if abi else []
141176
142177
178+ def _load_abi_from_file (path : Path ) -> Dict [str , Any ]:
179+ if not os .path .exists (path ):
180+ print (
181+ "Error: Contract airtfacts not found. Please execute 'run_service.sh' before executing this script."
182+ )
183+ sys .exit (1 )
184+
185+ with open (path , "r" , encoding = "utf-8" ) as f :
186+ data = json .load (f )
187+
188+ return data .get ("abi" )
189+
190+
143191contracts_cache : Dict [str , Any ] = {}
144192
145193
146- def _get_staking_token_contract (program_id : str ) -> Any :
194+ def _get_staking_token_contract (program_id : str , use_blockscout : bool = False ) -> Any :
147195 if program_id in contracts_cache :
148196 return contracts_cache [program_id ]
149197
150- with open (RPC_PATH , 'r' , encoding = "utf-8" ) as file :
198+ with open (RPC_PATH , "r" , encoding = "utf-8" ) as file :
151199 rpc = file .read ().strip ()
152200
153201 w3 = Web3 (Web3 .HTTPProvider (rpc ))
154202 staking_token_instance_address = STAKING_PROGRAMS .get (program_id )
155- abi = _get_abi (staking_token_instance_address )
203+ if use_blockscout :
204+ abi = _get_abi (staking_token_instance_address )
205+ else :
206+ abi = _load_abi_from_file (STAKING_TOKEN_INSTANCE_ABI_PATH )
156207 contract = w3 .eth .contract (address = staking_token_instance_address , abi = abi )
157208
158- if ' getImplementation' in [func .fn_name for func in contract .all_functions ()]:
209+ if " getImplementation" in [func .fn_name for func in contract .all_functions ()]:
159210 # It is a proxy contract
160211 implementation_address = contract .functions .getImplementation ().call ()
161- abi = _get_abi (implementation_address )
212+ if use_blockscout :
213+ abi = _get_abi (implementation_address )
214+ else :
215+ abi = _load_abi_from_file (STAKING_TOKEN_IMPLEMENTATION_ABI_PATH )
162216 contract = w3 .eth .contract (address = staking_token_instance_address , abi = abi )
163217
164218 contracts_cache [program_id ] = contract
165219 return contract
166220
167221
168- def _get_staking_contract_metadata (program_id : str ) -> Dict [str , str ]:
222+ def _get_staking_contract_metadata (
223+ program_id : str , use_blockscout : bool = False
224+ ) -> Dict [str , str ]:
169225 try :
170226 if program_id == NO_STAKING_PROGRAM_ID :
171227 return NO_STAKING_PROGRAM_METADATA
172228
173- staking_token_contract = _get_staking_token_contract (program_id = program_id )
229+ staking_token_contract = _get_staking_token_contract (
230+ program_id = program_id , use_blockscout = use_blockscout
231+ )
174232 metadata_hash = staking_token_contract .functions .metadataHash ().call ()
175233 ipfs_address = IPFS_ADDRESS .format (hash = metadata_hash .hex ())
176234 response = requests .get (ipfs_address )
177235
178236 if response .status_code == 200 :
179237 return response .json ()
180238
181- raise Exception (f"Failed to fetch data from { ipfs_address } : { response .status_code } " )
182- except Exception :
239+ raise Exception ( # pylint: disable=broad-except
240+ f"Failed to fetch data from { ipfs_address } : { response .status_code } "
241+ )
242+ except Exception : # pylint: disable=broad-except
183243 return {
184244 "name" : program_id ,
185245 "description" : program_id ,
186246 }
187247
188248
189- def _get_staking_env_variables (program_id : str ) -> Dict [str , str ]:
249+ def _get_staking_env_variables ( # pylint: disable=too-many-locals
250+ program_id : str , use_blockscout : bool = False
251+ ) -> Dict [str , str ]:
190252 if program_id == NO_STAKING_PROGRAM_ID :
191253 return NO_STAKING_PROGRAM_ENV_VARIABLES
192254
193255 staking_token_instance_address = STAKING_PROGRAMS .get (program_id )
194- staking_token_contract = _get_staking_token_contract (program_id = program_id )
256+ staking_token_contract = _get_staking_token_contract (
257+ program_id = program_id , use_blockscout = use_blockscout
258+ )
195259 agent_id = staking_token_contract .functions .agentIds (0 ).call ()
196260 service_registry = staking_token_contract .functions .serviceRegistry ().call ()
197261 staking_token = staking_token_contract .functions .stakingToken ().call ()
198- service_registry_token_utility = staking_token_contract .functions .serviceRegistryTokenUtility ().call ()
262+ service_registry_token_utility = (
263+ staking_token_contract .functions .serviceRegistryTokenUtility ().call ()
264+ )
199265 min_staking_deposit = staking_token_contract .functions .minStakingDeposit ().call ()
200266 min_staking_bond = min_staking_deposit
201267
202- if 'activityChecker' in [func .fn_name for func in staking_token_contract .all_functions ()]:
268+ if "activityChecker" in [
269+ func .fn_name for func in staking_token_contract .all_functions ()
270+ ]:
203271 activity_checker = staking_token_contract .functions .activityChecker ().call ()
204- abi = _get_abi (activity_checker )
205272
206- with open (RPC_PATH , 'r' , encoding = "utf-8" ) as file :
273+ if use_blockscout :
274+ abi = _get_abi (activity_checker )
275+ else :
276+ abi = _load_abi_from_file (ACTIVITY_CHECKER_ABI_PATH )
277+
278+ with open (RPC_PATH , "r" , encoding = "utf-8" ) as file :
207279 rpc = file .read ().strip ()
208280
209281 w3 = Web3 (Web3 .HTTPProvider (rpc ))
@@ -231,7 +303,12 @@ def _get_staking_env_variables(program_id: str) -> Dict[str, str]:
231303def _set_dotenv_file_variables (env_vars : Dict [str , str ]) -> None :
232304 for key , value in env_vars .items ():
233305 if value :
234- set_key (dotenv_path = DOTENV_PATH , key_to_set = key , value_to_set = value , quote_mode = "never" )
306+ set_key (
307+ dotenv_path = DOTENV_PATH ,
308+ key_to_set = key ,
309+ value_to_set = value ,
310+ quote_mode = "never" ,
311+ )
235312 else :
236313 unset_key (dotenv_path = DOTENV_PATH , key_to_unset = key )
237314
@@ -240,31 +317,50 @@ def _get_nevermined_env_variables() -> Dict[str, str]:
240317 env_file_vars = dotenv_values (DOTENV_PATH )
241318 use_nevermined = False
242319
243- if 'USE_NEVERMINED' not in env_file_vars :
244- set_key (dotenv_path = DOTENV_PATH , key_to_set = "USE_NEVERMINED" , value_to_set = "false" , quote_mode = "never" )
245- elif env_file_vars .get ('USE_NEVERMINED' ).strip () not in ("True" , "true" ):
246- set_key (dotenv_path = DOTENV_PATH , key_to_set = "USE_NEVERMINED" , value_to_set = "false" , quote_mode = "never" )
320+ if "USE_NEVERMINED" not in env_file_vars :
321+ set_key (
322+ dotenv_path = DOTENV_PATH ,
323+ key_to_set = "USE_NEVERMINED" ,
324+ value_to_set = "false" ,
325+ quote_mode = "never" ,
326+ )
327+ elif env_file_vars .get ("USE_NEVERMINED" ).strip () not in ("True" , "true" ):
328+ set_key (
329+ dotenv_path = DOTENV_PATH ,
330+ key_to_set = "USE_NEVERMINED" ,
331+ value_to_set = "false" ,
332+ quote_mode = "never" ,
333+ )
247334 else :
248335 use_nevermined = True
249336
250337 if use_nevermined :
251- print (" - A Nevermined subscription will be used to pay for the mech requests." )
338+ print (
339+ " - A Nevermined subscription will be used to pay for the mech requests."
340+ )
252341 return {
253342 "MECH_CONTRACT_ADDRESS" : NEVERMINED_MECH_CONTRACT_ADDRESS ,
254343 "AGENT_REGISTRY_ADDRESS" : NEVERMINED_AGENT_REGISTRY_ADDRESS ,
255- "MECH_REQUEST_PRICE" : NEVERMINED_MECH_REQUEST_PRICE
344+ "MECH_REQUEST_PRICE" : NEVERMINED_MECH_REQUEST_PRICE ,
256345 }
257346 else :
258347 print (" - No Nevermined subscription set." )
259- return {
260- "AGENT_REGISTRY_ADDRESS" : "" ,
261- "MECH_REQUEST_PRICE" : ""
262- }
348+ return {"AGENT_REGISTRY_ADDRESS" : "" , "MECH_REQUEST_PRICE" : "" }
263349
264350
265351def main () -> None :
352+ """Main method"""
266353 parser = argparse .ArgumentParser (description = "Set up staking configuration." )
267- parser .add_argument ("--reset" , action = "store_true" , help = "Reset USE_STAKING and STAKING_PROGRAM in .env file" )
354+ parser .add_argument (
355+ "--reset" ,
356+ action = "store_true" ,
357+ help = "Reset USE_STAKING and STAKING_PROGRAM in .env file" ,
358+ )
359+ parser .add_argument (
360+ "--use_blockscout" ,
361+ action = "store_true" ,
362+ help = "Use Blockscout to retrieve contract data." ,
363+ )
268364 args = parser .parse_args ()
269365
270366 if args .reset :
@@ -275,23 +371,35 @@ def main() -> None:
275371 print ("=====================================" )
276372 print ("" )
277373 print (f"Your current staking program preference is set to '{ staking_program } '." )
278- print ("You can reset your preference. However, your trader might not be able to switch between staking contracts until it has been staked for a minimum staking period in the current program." )
374+ print (
375+ "You can reset your preference. However, your trader might not be able to switch between staking contracts until it has been staked for a minimum staking period in the current program."
376+ )
279377 print ("" )
280378 if os .environ .get ("ATTENDED" ) == "true" :
281- response = input ("Do you want to reset your staking program preference? (yes/no): " ).strip ().lower ()
282- if response not in ['yes' , 'y' ]:
379+ response = (
380+ input (
381+ "Do you want to reset your staking program preference? (yes/no): "
382+ )
383+ .strip ()
384+ .lower ()
385+ )
386+ if response not in ["yes" , "y" ]:
283387 return
284388
285389 print ("" )
286390 unset_key (dotenv_path = DOTENV_PATH , key_to_unset = "USE_STAKING" )
287391 unset_key (dotenv_path = DOTENV_PATH , key_to_unset = "STAKING_PROGRAM" )
288- print (f"Environment variables USE_STAKING and STAKING_PROGRAM have been reset in '{ DOTENV_PATH } '." )
392+ print (
393+ f"Environment variables USE_STAKING and STAKING_PROGRAM have been reset in '{ DOTENV_PATH } '."
394+ )
289395 print ("" )
290396
291397 program_id = _prompt_select_staking_program ()
292398
293399 print (" - Populating staking program variables in the .env file" )
294- staking_env_variables = _get_staking_env_variables (program_id )
400+ staking_env_variables = _get_staking_env_variables (
401+ program_id , use_blockscout = args .use_blockscout
402+ )
295403 _set_dotenv_file_variables (staking_env_variables )
296404
297405 print (" - Populating Nevermined variables in the .env file" )
@@ -301,5 +409,6 @@ def main() -> None:
301409 print ("" )
302410 print ("Finished populating the .env file." )
303411
412+
304413if __name__ == "__main__" :
305414 main ()
0 commit comments