diff --git a/rank_traders.py b/rank_traders.py index 699b8f07..d9f087a8 100644 --- a/rank_traders.py +++ b/rank_traders.py @@ -21,9 +21,12 @@ """This script queries the OMEN subgraph to obtain the trades of a given address.""" import datetime +import os import sys from argparse import ArgumentParser from collections import defaultdict +from dotenv import load_dotenv +from pathlib import Path from string import Template from typing import Any @@ -38,6 +41,11 @@ FPMM_CREATOR = "0x89c5cc945dd550bcffb72fe42bff002429f46fec" DEFAULT_FROM_DATE = "1970-01-01T00:00:00" DEFAULT_TO_DATE = "2038-01-19T03:14:07" +SCRIPT_PATH = Path(__file__).resolve().parent +STORE_PATH = Path(SCRIPT_PATH, ".trader_runner") +ENV_FILE = Path(STORE_PATH, ".env") + +load_dotenv(ENV_FILE) headers = { @@ -167,7 +175,8 @@ def _query_omen_xdai_subgraph( fpmm_to_timestamp: float, ) -> dict[str, Any]: """Query the subgraph.""" - url = "https://api.thegraph.com/subgraphs/name/protofire/omen-xdai" + subgraph_api_key = os.getenv('SUBGRAPH_API_KEY') + url = f"https://gateway-arbitrum.network.thegraph.com/api/{subgraph_api_key}/subgraphs/id/9fUVQpFwzpdWS9bq5WkAnmKbNNcoBwatMR4yZq81pbbz" grouped_results = defaultdict(list) id_gt = "" diff --git a/run_service.sh b/run_service.sh index 363dbc54..cb91cfa6 100755 --- a/run_service.sh +++ b/run_service.sh @@ -400,15 +400,17 @@ prompt_use_staking() { # Prompt user for subgraph API key prompt_subgraph_api_key() { - echo "Please provide a Subgraph API key" - echo "---------------------------------" + echo "Provide a Subgraph API key" + echo "--------------------------" echo "Since June 12, 2024, you need a Subgraph API key that can be obtained at The Graph https://thegraph.com/studio/apikeys/" echo "" - echo "If you set your Subgraph API key to blank, the script will use the deprecated Subgraph endpoints (hosted services)." - echo "These deprecated endpoints might stop working, and you will need to manually edit the .trader_runner/.env file to provide your API key." - echo "" - read -rsp "Enter a Subgraph API key [hidden input]: " SUBGRAPH_API_KEY + read -rsp "Please, enter a Subgraph API key [hidden input]: " SUBGRAPH_API_KEY echo "" + while [ -z "${SUBGRAPH_API_KEY}" ]; do + echo "You cannot enter a blank API key." + read -rsp "Please, enter a Subgraph API key [hidden input]: " SUBGRAPH_API_KEY + echo "" + done } # Verify if there are enough slots for staking this service @@ -574,7 +576,7 @@ try_read_storage() { fi # INFO: This is a fix to avoid corrupting already-created stores - if [ -z "${SUBGRAPH_API_KEY+x}" ]; then + if [ -z "${SUBGRAPH_API_KEY}" ]; then prompt_subgraph_api_key dotenv_set_key "$env_file_path" "SUBGRAPH_API_KEY" "$SUBGRAPH_API_KEY" true fi @@ -611,7 +613,7 @@ directory="trader" service_repo=https://github.com/$org_name/$directory.git # This is a tested version that works well. # Feel free to replace this with a different version of the repo, but be careful as there might be breaking changes -service_version="v0.16.1" +service_version="v0.16.2" # Define constants for on-chain interaction gnosis_chain_id=100 @@ -1055,6 +1057,17 @@ if [ "${USE_STAKING}" = true ]; then perform_staking_ops fi + +# ensure Safe owner is agent +# (This may occur if update flow was interrupted) +service_safe_address=$(<"../$service_safe_address_path") +current_safe_owners=$(poetry run python "../scripts/get_safe_owners.py" "$service_safe_address" "../$agent_pkey_path" "$rpc" $password_argument | awk '{gsub(/"/, "\047", $0); print $0}') +if [[ "$current_safe_owners" == "['$operator_address']" ]]; then + echo "[Operator] Swapping Safe owner..." + poetry run python "../scripts/swap_safe_owner.py" "$service_safe_address" "../$operator_pkey_path" "$agent_address" "$rpc" $password_argument +fi + + echo "" echo "Finished checking Autonolas Protocol service $service_id state." @@ -1102,7 +1115,7 @@ if [ -n "$SUBGRAPH_API_KEY" ]; then export CONDITIONAL_TOKENS_SUBGRAPH_URL="https://gateway-arbitrum.network.thegraph.com/api/$SUBGRAPH_API_KEY/subgraphs/id/7s9rGBffUTL8kDZuxvvpuc46v44iuDarbrADBFw5uVp2" export NETWORK_SUBGRAPH_URL="https://gateway-arbitrum.network.thegraph.com/api/$SUBGRAPH_API_KEY/subgraphs/id/FxV6YUix58SpYmLBwc9gEHkwjfkqwe1X5FJQjn8nKPyA" export OMEN_SUBGRAPH_URL="https://gateway-arbitrum.network.thegraph.com/api/$SUBGRAPH_API_KEY/subgraphs/id/9fUVQpFwzpdWS9bq5WkAnmKbNNcoBwatMR4yZq81pbbz" - export REALITIO_SUBGRAPH_URL="https://gateway-arbitrum.network.thegraph.com/api/$SUBGRAPH_API_KEY/subgraphs/id/E7ymrCnNcQdAAgLbdFWzGE5mvr5" + export REALITIO_SUBGRAPH_URL="https://gateway-arbitrum.network.thegraph.com/api/$SUBGRAPH_API_KEY/subgraphs/id/E7ymrCnNcQdAAgLbdFWzGE5mvr5Mb5T9VfT43FqA7bNh" export TRADES_SUBGRAPH_URL="https://gateway-arbitrum.network.thegraph.com/api/$SUBGRAPH_API_KEY/subgraphs/id/9fUVQpFwzpdWS9bq5WkAnmKbNNcoBwatMR4yZq81pbbz" fi diff --git a/scripts/staking.py b/scripts/staking.py index e86ab0d1..55f95589 100644 --- a/scripts/staking.py +++ b/scripts/staking.py @@ -353,7 +353,7 @@ def main() -> None: sys.exit(0) print( - f"Service {args.service_id} is already staked on {staking_program}." + f"Service {args.service_id} is already staked on {staking_program}. " f"Checking if the staking contract has any rewards..." ) available_rewards = get_available_rewards( diff --git a/scripts/utils.py b/scripts/utils.py index b3589844..90f7d89e 100644 --- a/scripts/utils.py +++ b/scripts/utils.py @@ -179,6 +179,10 @@ def is_service_staked( service_staking_state = staking_contract.get_service_staking_state( ledger_api, staking_contract_address, service_id ).pop("data") + + if isinstance(service_staking_state, int): + service_staking_state = StakingState(service_staking_state) + is_staked = service_staking_state == StakingState.STAKED or service_staking_state == StakingState.EVICTED return is_staked @@ -191,6 +195,9 @@ def is_service_evicted( ledger_api, staking_contract_address, service_id ).pop("data") + if isinstance(service_staking_state, int): + service_staking_state = StakingState(service_staking_state) + is_evicted = service_staking_state == StakingState.EVICTED return is_evicted diff --git a/trades.py b/trades.py index 80585a72..b99feae9 100644 --- a/trades.py +++ b/trades.py @@ -21,9 +21,11 @@ """This script queries the OMEN subgraph to obtain the trades of a given address.""" import datetime +import os import re from argparse import Action, ArgumentError, ArgumentParser, Namespace from collections import defaultdict +from dotenv import load_dotenv from enum import Enum from pathlib import Path from string import Template @@ -57,12 +59,16 @@ SCRIPT_PATH = Path(__file__).resolve().parent STORE_PATH = Path(SCRIPT_PATH, ".trader_runner") RPC_PATH = Path(STORE_PATH, "rpc.txt") +ENV_FILE = Path(STORE_PATH, ".env") WXDAI_CONTRACT_ADDRESS = "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d" SCRIPT_PATH = Path(__file__).resolve().parent STORE_PATH = Path(SCRIPT_PATH, ".trader_runner") SAFE_ADDRESS_PATH = Path(STORE_PATH, "service_safe_address.txt") +load_dotenv(ENV_FILE) + + headers = { "Accept": "application/json, multipart/mixed", "Content-Type": "application/json", @@ -171,6 +177,7 @@ class MarketAttribute(Enum): NUM_TRADES = "Num_trades" WINNER_TRADES = "Winner_trades" NUM_REDEEMED = "Num_redeemed" + NUM_INVALID_MARKET = "Num_invalid_market" INVESTMENT = "Investment" FEES = "Fees" MECH_CALLS = "Mech_calls" @@ -322,7 +329,8 @@ def _query_omen_xdai_subgraph( # pylint: disable=too-many-locals fpmm_to_timestamp: float = DEFAULT_TO_TIMESTAMP, ) -> Dict[str, Any]: """Query the subgraph.""" - url = "https://api.thegraph.com/subgraphs/name/protofire/omen-xdai" + subgraph_api_key = os.getenv('SUBGRAPH_API_KEY') + url = f"https://gateway-arbitrum.network.thegraph.com/api/{subgraph_api_key}/subgraphs/id/9fUVQpFwzpdWS9bq5WkAnmKbNNcoBwatMR4yZq81pbbz" grouped_results = defaultdict(list) creationTimestamp_gt = "0" @@ -367,7 +375,8 @@ def _query_omen_xdai_subgraph( # pylint: disable=too-many-locals def _query_conditional_tokens_gc_subgraph(creator: str) -> Dict[str, Any]: """Query the subgraph.""" - url = "https://api.thegraph.com/subgraphs/name/gnosis/conditional-tokens-gc" + subgraph_api_key = os.getenv('SUBGRAPH_API_KEY') + url = f"https://gateway-arbitrum.network.thegraph.com/api/{subgraph_api_key}/subgraphs/id/7s9rGBffUTL8kDZuxvvpuc46v44iuDarbrADBFw5uVp2" all_results: Dict[str, Any] = {"data": {"user": {"userPositions": []}}} userPositions_id_gt = "" @@ -515,7 +524,7 @@ def _get_market_state(market: Dict[str, Any]) -> MarketState: def _format_table(table: Dict[Any, Dict[Any, Any]]) -> str: - column_width = 14 + column_width = 18 table_str = " " * column_width @@ -555,6 +564,16 @@ def _format_table(table: Dict[Any, Dict[Any, Any]]) -> str: ) + "\n" ) + table_str += ( + f"{MarketAttribute.NUM_INVALID_MARKET:<{column_width}}" + + "".join( + [ + f"{table[MarketAttribute.NUM_INVALID_MARKET][c]:>{column_width}}" + for c in STATS_TABLE_COLS + ] + ) + + "\n" + ) table_str += ( f"{MarketAttribute.MECH_CALLS:<{column_width}}" + "".join( @@ -720,6 +739,15 @@ def parse_user( # pylint: disable=too-many-locals,too-many-statements earnings = collateral_amount output += " Final answer: Market has been declared invalid.\n" output += f" Earnings: {wei_to_xdai(earnings)}\n" + redeemed = _is_redeemed(user_json, fpmmTrade) + if redeemed: + statistics_table[MarketAttribute.NUM_INVALID_MARKET][ + market_status + ] += 1 + statistics_table[MarketAttribute.REDEMPTIONS][ + market_status + ] += earnings + elif outcome_index == current_answer: earnings = outcomes_tokens_traded output += f" Final answer: {fpmm['outcomes'][current_answer]!r} - Congrats! The trade was for the winner answer.\n" @@ -739,7 +767,10 @@ def parse_user( # pylint: disable=too-many-locals,too-many-statements earnings = 0 output += f" Final answer: {fpmm['outcomes'][current_answer]!r} - The trade was for the loser answer.\n" - statistics_table[MarketAttribute.EARNINGS][market_status] += earnings + if not is_invalid: + statistics_table[MarketAttribute.EARNINGS][ + market_status + ] += earnings if 0 < earnings < DUST_THRESHOLD: output += "Earnings are dust.\n"