Skip to content
This repository was archived by the owner on May 29, 2025. It is now read-only.

Commit e92d136

Browse files
authored
Merge pull request #392 from valory-xyz/feat/remove_blockscout_dep
Remove blockscout dependency
2 parents c44f726 + e4b6d0e commit e92d136

File tree

2 files changed

+208
-53
lines changed

2 files changed

+208
-53
lines changed

scripts/choose_staking.py

Lines changed: 151 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,48 @@
1818
#
1919
# ------------------------------------------------------------------------------
2020

21+
"""Choose staking program."""
22+
2123
import argparse
24+
import json
2225
import os
23-
import requests
2426
import sys
2527
import textwrap
26-
import json
27-
from dotenv import dotenv_values, set_key, unset_key
2828
from 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
3033
from web3 import Web3
3134

35+
3236
SCRIPT_PATH = Path(__file__).resolve().parent
3337
STORE_PATH = Path(SCRIPT_PATH, "..", ".trader_runner")
3438
DOTENV_PATH = Path(STORE_PATH, ".env")
3539
RPC_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

3764
IPFS_ADDRESS = "https://gateway.autonolas.tech/ipfs/f01701220{hash}"
3865
NEVERMINED_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

126157
def _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+
143191
contracts_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]:
231303
def _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

265351
def 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+
304413
if __name__ == "__main__":
305414
main()

0 commit comments

Comments
 (0)