Skip to content

Chore: Bump middleware to v0.2.4 #46

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
859 changes: 451 additions & 408 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ include = []

[tool.poetry.dependencies]
python = ">=3.9,<3.12"
olas-operate-middleware = "0.2.2"
olas-operate-middleware = "0.2.5"
tqdm = "^4.67.1"

[tool.poetry.group.dev.dependencies]
Expand Down
66 changes: 43 additions & 23 deletions scripts/predict_trader/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
wei_to_xdai,
)
from web3 import HTTPProvider, Web3
from web3.exceptions import ContractLogicError

from operate.constants import (
OPERATE_HOME,
Expand All @@ -54,9 +55,10 @@
MECH_ACTIVITY_CHECKER_JSON_URL,
MECH_CONTRACT_JSON_URL,
)
from operate.ledger.profiles import STAKING
from operate.cli import OperateApp
from operate.ledger.profiles import get_staking_contract
from operate.operate_types import Chain
from operate.quickstart.run_service import load_local_config
from operate.quickstart.run_service import load_local_config, NO_STAKING_PROGRAM_ID
from scripts.utils import get_service_from_config

SCRIPT_PATH = Path(__file__).resolve().parent
Expand Down Expand Up @@ -228,10 +230,12 @@ def _parse_args() -> Any:
operator_wallet_data = json.load(file)

template_path = Path(SCRIPT_PATH.parents[1], "configs", "config_predict_trader.json")
config = load_local_config()
operate = OperateApp()
service = get_service_from_config(template_path)
config = load_local_config(operate=operate, service_name=service.name)
chain_config = service.chain_configs["gnosis"]
agent_address = service.keys[0].address
master_eoa = operator_wallet_data["address"]
if "safes" in operator_wallet_data and "gnosis" in operator_wallet_data["safes"]:
operator_address = operator_wallet_data["safes"]["gnosis"]
else:
Expand Down Expand Up @@ -262,26 +266,33 @@ def _parse_args() -> Any:
try:
w3 = Web3(HTTPProvider(rpc))

staking_token_address = STAKING[Chain.GNOSIS][config.staking_program_id]
staking_token_data = requests.get(STAKING_TOKEN_INSTANCE_ABI_PATH).json()

staking_token_abi = staking_token_data.get("abi", [])
staking_token_contract = w3.eth.contract(
address=staking_token_address, abi=staking_token_abi # type: ignore
staking_token_address = get_staking_contract(
chain=Chain.GNOSIS.value,
staking_program_id=config.staking_program_id,
)
if staking_token_address is None:
is_staked = False
staking_state = StakingState.UNSTAKED
else:
staking_token_data = requests.get(STAKING_TOKEN_INSTANCE_ABI_PATH).json()

staking_token_abi = staking_token_data.get("abi", [])
staking_token_contract = w3.eth.contract(
address=staking_token_address, abi=staking_token_abi # type: ignore
)

staking_state = StakingState(
staking_token_contract.functions.getStakingState(
service_id
).call()
)
staking_state = StakingState(
staking_token_contract.functions.getStakingState(
service_id
).call()
)

is_staked = (
staking_state == StakingState.STAKED
or staking_state == StakingState.EVICTED
)

is_staked = (
staking_state == StakingState.STAKED
or staking_state == StakingState.EVICTED
)
_print_status("Is service staked?", _color_bool(is_staked, "Yes", "No"))
is_mm_staking = "mech_marketplace" in config.staking_program_id
if is_staked:
_print_status("Staking program", config.staking_program_id) # type: ignore
if staking_state == StakingState.STAKED:
Expand Down Expand Up @@ -311,14 +322,14 @@ def _parse_args() -> Any:
abi=service_registry_token_utility_abi,
)

if is_mm_staking:
try:
activity_checker_data = requests.get(MECH_CONTRACT_JSON_URL).json()
activity_checker_abi = activity_checker_data.get("abi", [])
mm_activity_checker_contract = w3.eth.contract(
address=activity_checker_address, abi=activity_checker_abi # type: ignore
)
mech_contract_address = mm_activity_checker_contract.functions.mechMarketplace().call()
else:
except ContractLogicError:
mech_contract_address = activity_checker_contract.functions.agentMech().call()

mech_contract_data = requests.get(MECH_CONTRACT_JSON_URL).json()
Expand Down Expand Up @@ -437,12 +448,21 @@ def _parse_args() -> Any:
_print_status("xDAI Balance", wei_to_xdai(safe_xdai))
_print_status("WxDAI Balance", wei_to_wxdai(safe_wxdai))

# Owner/Operator
# Master Safe - Agent Owner/Operator
operator_xdai = get_balance(operator_address, rpc)
_print_subsection_header("Owner/Operator")
_print_subsection_header("Master Safe - Agent Owner/Operator")
_print_status("Address", operator_address)
_print_status(
"xDAI Balance",
f"{wei_to_xdai(operator_xdai)} {_warning_message(operator_xdai, OPERATOR_XDAI_BALANCE_THRESHOLD)}",
)

# Master EOA - Master Safe Owner
master_eoa_xdai = get_balance(master_eoa, rpc)
_print_subsection_header("Master EOA - Master Safe Owner")
_print_status("Address", master_eoa)
_print_status(
"xDAI Balance",
f"{wei_to_xdai(master_eoa_xdai)} {_warning_message(master_eoa_xdai, OPERATOR_XDAI_BALANCE_THRESHOLD)}",
)
print("")
6 changes: 5 additions & 1 deletion scripts/predict_trader/trades.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from string import Template
from typing import Any, Dict, Optional

from operate.cli import OperateApp
from operate.operate_types import Chain
from operate.quickstart.run_service import load_local_config
from scripts.predict_trader.mech_events import get_mech_requests
Expand Down Expand Up @@ -850,7 +851,10 @@ def get_mech_statistics(mech_requests: Dict[str, Any]) -> Dict[str, Dict[str, in
if __name__ == "__main__":
user_args = _parse_args()

config = load_local_config()
template_path = Path(SCRIPT_PATH.parents[1], "configs", "config_predict_trader.json")
operate = OperateApp()
service = get_service_from_config(template_path)
config = load_local_config(operate, service.name)
rpc = config.rpc[Chain.GNOSIS.value]

mech_requests = get_mech_requests(
Expand Down
2 changes: 1 addition & 1 deletion scripts/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@ def get_service_from_config(config_path: Path) -> Service:

operate = OperateApp()
manager = operate.service_manager()
configure_local_config(template)
configure_local_config(template, operate)
return get_service(manager, template)
74 changes: 17 additions & 57 deletions tests/test_run_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,7 @@ def get_base_config(config_path: str = "") -> dict:
base_prompts = {
r"Please input your password \(or press enter\)\:": base_config["TEST_PASSWORD"],
r"Please confirm your password\:": base_config["TEST_PASSWORD"],
r"Enter local user account password \[hidden input\]\:": base_config["TEST_PASSWORD"],
r"Enter your choice": base_config["STAKING_CHOICE"],
r"Please input your backup owner \(leave empty to skip\)\:": base_config["BACKUP_WALLET"],
r"Press enter to continue": "\n",
Expand Down Expand Up @@ -773,7 +774,7 @@ class BaseTestService:
config_settings = None
logger = None
child = None
temp_dir = None
temp_dir = Path
original_cwd = None
temp_env = None
_setup_complete = False
Expand All @@ -785,38 +786,7 @@ def setup_class(cls):
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
cls.log_file = Path(f'test_run_service_{timestamp}.log')
cls.logger = setup_logging(cls.log_file)

# Create temporary directory and store original path
cls.original_cwd = os.getcwd()
cls.temp_dir = tempfile.TemporaryDirectory(prefix='operate_test_')
cls.logger.info(f"Created temporary directory: {cls.temp_dir.name}")

# Define exclusion patterns
exclude_patterns = [
'.git', # Git directory
'.pytest_cache', # Pytest cache
'__pycache__', # Python cache
'*.pyc', # Python compiled files
'logs', # Log files
'*.log', # Log files
'.env' # Environment files
]

def ignore_patterns(path, names):
return set(n for n in names if any(p in n or any(p.endswith(n) for p in exclude_patterns) for p in exclude_patterns))

# Copy project files to temp directory
shutil.copytree(cls.original_cwd, cls.temp_dir.name, dirs_exist_ok=True, ignore=ignore_patterns)

# Copy .git directory if it exists
git_dir = Path(cls.original_cwd) / '.git'
if git_dir.exists():
shutil.copytree(git_dir, Path(cls.temp_dir.name) / '.git', symlinks=True)

# Switch to temporary directory
os.chdir(cls.temp_dir.name)
cls.logger.info(f"Changed working directory to: {cls.temp_dir.name}")

# Handle memeooorr config modifications if needed
if "memeooorr" in cls.config_path.lower():
temp_config_path = os.path.join(cls.temp_dir.name, 'configs', os.path.basename(cls.config_path))
Expand Down Expand Up @@ -915,12 +885,6 @@ def teardown_class(cls):
except Exception as e:
cls.logger.error(f"Error stopping service: {str(e)}")

# Clean up resources
os.chdir(cls.original_cwd)
if cls.temp_dir:
temp_dir_path = cls.temp_dir.name
cleanup_directory(temp_dir_path, cls.logger)
cls.logger.info("Cleanup completed")
cls._setup_complete = False

except Exception as e:
Expand Down Expand Up @@ -1003,7 +967,6 @@ def stop_service(cls):
cwd=stop_dir # Explicitly set working directory for stop_service
)
process.expect(pexpect.EOF)
time.sleep(0)

def test_health_check(self):
"""Test service health endpoint"""
Expand Down Expand Up @@ -1049,36 +1012,21 @@ def setup_class(self):
def setup(self, request):
"""Setup for each test case."""
config_path = request.param
temp_dir = None

try:
# Create a temporary directory for stop_service
temp_dir = tempfile.TemporaryDirectory(prefix='operate_test_')

# Copy necessary files to temp directory
shutil.copytree('.', temp_dir.name, dirs_exist_ok=True,
ignore=shutil.ignore_patterns('.git', '.pytest_cache', '__pycache__',
'*.pyc', 'logs', '*.log', '.env'))

# First ensure any existing service is stopped
if not ensure_service_stopped(config_path, temp_dir.name, self.logger):
if not ensure_service_stopped(config_path, self.temp_dir.name, self.logger):
raise RuntimeError("Failed to stop existing service")

self.test_class = self.get_test_class(config_path, self.temp_dir)
self.test_class.setup_class()

yield
if self.test_class._setup_complete:
self.test_class.teardown_class()

finally:
# Clean up the temporary directory
if temp_dir:
temp_dir_path = temp_dir.name
try:
temp_dir.cleanup()
except Exception:
self.logger.warning("Built-in cleanup failed, trying custom cleanup...")
cleanup_directory(temp_dir_path, self.logger)
pass

def teardown_class(self):
# Clean up the temporary directory
Expand Down Expand Up @@ -1112,5 +1060,17 @@ def test_agent_full_suite(self, setup):
# Run shutdown logs test
test_instance.test_shutdown_logs()

def teardown_class(self):
# Clean up the temporary directory
if self.temp_dir:
temp_dir_path = self.temp_dir.name
try:
self.logger.info("Cleaning up temporary directory...")
cleanup_directory(temp_dir_path, self.logger)
except Exception:
self.logger.warning("Built-in cleanup failed, trying custom cleanup...")
cleanup_directory(temp_dir_path, self.logger)


if __name__ == "__main__":
pytest.main(["-v", __file__, "-s", "--log-cli-level=INFO"])