From 1bdc652499382b4188197ff57f14fb4c4465a271 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Thu, 28 Mar 2024 13:27:40 +0100 Subject: [PATCH 01/15] feat: support different networks --- mech_client/cli.py | 17 ++- mech_client/configs/mechs.json | 32 ++++++ mech_client/interact.py | 187 ++++++++++++++++++++++++++------- mech_client/subgraph.py | 25 +++-- 4 files changed, 207 insertions(+), 54 deletions(-) create mode 100644 mech_client/configs/mechs.json diff --git a/mech_client/cli.py b/mech_client/cli.py index e6ef373..60d21fc 100644 --- a/mech_client/cli.py +++ b/mech_client/cli.py @@ -40,6 +40,11 @@ def cli() -> None: @click.command() @click.argument("prompt") @click.argument("agent_id", type=int) +@click.option( + "--key", + type=click.Path(exists=True, file_okay=True, dir_okay=False), + help="Path to private key to use for request minting", +) @click.option( "--tool", type=str, @@ -52,11 +57,6 @@ def cli() -> None: help="Extra attribute (key=value) to be included in the request metadata", metavar="KEY=VALUE", ) -@click.option( - "--key", - type=click.Path(exists=True, file_okay=True, dir_okay=False), - help="Path to private key to use for request minting", -) @click.option( "--confirm", type=click.Choice( @@ -79,6 +79,11 @@ def cli() -> None: type=float, help="Amount of sleep before retrying the transaction", ) +@click.option( + "--chain-id", + type=str, + help="Id of the mech's chain configuration (stored configs/mechs.json)", +) def interact( # pylint: disable=too-many-arguments prompt: str, agent_id: int, @@ -89,6 +94,7 @@ def interact( # pylint: disable=too-many-arguments retries: Optional[int] = None, timeout: Optional[float] = None, sleep: Optional[float] = None, + chain_id: Optional[str] = None, ) -> None: """Interact with a mech specifying a prompt and tool.""" try: @@ -112,6 +118,7 @@ def interact( # pylint: disable=too-many-arguments retries=retries, timeout=timeout, sleep=sleep, + chain_id=chain_id, ) except (ValueError, FileNotFoundError) as e: raise click.ClickException(str(e)) from e diff --git a/mech_client/configs/mechs.json b/mech_client/configs/mechs.json new file mode 100644 index 0000000..cf018e4 --- /dev/null +++ b/mech_client/configs/mechs.json @@ -0,0 +1,32 @@ +{ + "gnosis": { + "agent_registry_contract": "0xE49CB081e8d96920C38aA7AB90cb0294ab4Bc8EA", + "rpc_url": "https://rpc.eu-central-2.gateway.fm/v4/gnosis/non-archival/mainnet", + "wss_endpoint": "wss://rpc.eu-central-2.gateway.fm/ws/v4/gnosis/non-archival/mainnet", + "ledger_config": { + "address": "https://rpc.eu-central-2.gateway.fm/v4/gnosis/non-archival/mainnet", + "chain_id": 100, + "poa_chain": false, + "default_gas_price_strategy": "eip1559", + "is_gas_estimation_enabled": false + }, + "manual_gas_limit": 100000, + "block_explorer_url": "https://gnosis.blockscout.com/api/v2/smart-contracts/{contract_address}", + "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" + }, + "polygon": { + "agent_registry_contract": "0xE49CB081e8d96920C38aA7AB90cb0294ab4Bc8EA", + "rpc_url": "https://rpc.eu-central-2.gateway.fm/v4/gnosis/non-archival/mainnet", + "wss_endpoint": "wss://rpc.eu-central-2.gateway.fm/ws/v4/gnosis/non-archival/mainnet", + "ledger_config": { + "address": "https://rpc.eu-central-2.gateway.fm/v4/gnosis/non-archival/mainnet", + "chain_id": 100, + "poa_chain": false, + "default_gas_price_strategy": "eip1559", + "is_gas_estimation_enabled": false + }, + "manual_gas_limit": 100000, + "block_explorer_url": "https://gnosis.blockscout.com/api/v2/smart-contracts/{contract_address}", + "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" + } +} \ No newline at end of file diff --git a/mech_client/interact.py b/mech_client/interact.py index 40d80fe..01562b1 100644 --- a/mech_client/interact.py +++ b/mech_client/interact.py @@ -26,9 +26,11 @@ """ import asyncio +import json import os import time import warnings +from dataclasses import asdict, dataclass from datetime import datetime from enum import Enum from pathlib import Path @@ -51,33 +53,8 @@ ) -AGENT_REGISTRY_CONTRACT = "0xE49CB081e8d96920C38aA7AB90cb0294ab4Bc8EA" -MECHX_CHAIN_RPC = os.environ.get( - "MECHX_CHAIN_RPC", - "https://rpc.eu-central-2.gateway.fm/v4/gnosis/non-archival/mainnet", -) -LEDGER_CONFIG = { - "address": MECHX_CHAIN_RPC, - "chain_id": 100, - "poa_chain": False, - "default_gas_price_strategy": "eip1559", - "is_gas_estimation_enabled": False, -} PRIVATE_KEY_FILE_PATH = "ethereum_private_key.txt" - -WSS_ENDPOINT = os.getenv( - "WEBSOCKET_ENDPOINT", - "wss://rpc.eu-central-2.gateway.fm/ws/v4/gnosis/non-archival/mainnet", -) -MANUAL_GAS_LIMIT = int( - os.getenv( - "MANUAL_GAS_LIMIT", - "100_000", - ) -) -BLOCKSCOUT_API_URL = ( - "https://gnosis.blockscout.com/api/v2/smart-contracts/{contract_address}" -) +MECH_CONFIGS = Path(__file__).parent / "configs" / "mechs.json" MAX_RETRIES = 3 WAIT_SLEEP = 3.0 @@ -87,6 +64,80 @@ warnings.filterwarnings("ignore", "The log with transaction hash.*") +@dataclass +class LedgerConfig: + """Ledger configuration""" + + address: str + chain_id: int + poa_chain: bool + default_gas_price_strategy: str + is_gas_estimation_enabled: bool + + def __post_init__(self) -> None: + """Post initialization to override with environment variables.""" + address = os.getenv("MECHX_LEDGER_ADDRESS") + if address: + self.address = address + + chain_id = os.getenv("MECHX_LEDGER_CHAIN_ID") + if chain_id: + self.chain_id = int(chain_id) + + poa_chain = os.getenv("MECHX_LEDGER_POA_CHAIN") + if poa_chain: + self.poa_chain = bool(poa_chain) + + default_gas_price_strategy = os.getenv( + "MECHX_LEDGER_DEFAULT_GAS_PRICE_STRATEGY" + ) + if default_gas_price_strategy: + self.default_gas_price_strategy = default_gas_price_strategy + + is_gas_estimation_enabled = os.getenv("MECHX_LEDGER_IS_GAS_ESTIMATION_ENABLED") + if is_gas_estimation_enabled: + self.is_gas_estimation_enabled = bool(is_gas_estimation_enabled) + + +@dataclass +class MechConfig: + """Mech configuration""" + + agent_registry_contract: str + rpc_url: str + wss_endpoint: str + ledger_config: LedgerConfig + manual_gas_limit: int + block_explorer_url: str + subgraph_url: str + + def __post_init__(self) -> None: + """Post initialization to override with environment variables.""" + agent_registry_contract = os.getenv("MECHX_AGENT_REGISTRY_CONTRACT") + if agent_registry_contract: + self.agent_registry_contract = agent_registry_contract + + rpc_url = os.getenv("MECHX_CHAIN_RPC") + if rpc_url: + self.rpc_url = rpc_url + + wss_endpoint = os.getenv("MECHX_WSS_ENDPOINT") + if wss_endpoint: + self.wss_endpoint = wss_endpoint + + manual_gas_limit = os.getenv("MECHX_MANUAL_GAS_LIMIT") + if manual_gas_limit: + self.manual_gas_limit = int(manual_gas_limit) + + block_explorer_url = os.getenv("MECHX_BLOCK_EXPLORER_URL") + if block_explorer_url: + self.block_explorer_url = block_explorer_url + + subgraph_url = os.getenv("MECHX_SUBGRAPH_URL") + if subgraph_url: + self.subgraph_url = subgraph_url + + class ConfirmationType(Enum): """Verification type.""" @@ -95,6 +146,20 @@ class ConfirmationType(Enum): WAIT_FOR_BOTH = "wait-for-both" +def get_mech_config(chain_id: Optional[str] = None) -> MechConfig: + """Get `MechConfig` configuration""" + with open(MECH_CONFIGS, "r", encoding="UTF-8") as file: + data = json.load(file) + + if chain_id is None: + chain_id = next(iter(data)) + + entry = data[chain_id].copy() + ledger_config = LedgerConfig(**entry.pop("ledger_config")) + mech_config = MechConfig(**entry, ledger_config=ledger_config) + return mech_config + + def calculate_topic_id(event: Dict) -> str: """Caclulate topic ID""" text = event["name"] @@ -120,9 +185,9 @@ def get_event_signatures(abi: List) -> Tuple[str, str]: return request, deliver -def get_abi(contract_address: str) -> List: +def get_abi(contract_address: str, block_explorer_url: str) -> List: """Get contract abi""" - abi_request_url = BLOCKSCOUT_API_URL.format(contract_address=contract_address) + abi_request_url = block_explorer_url.format(contract_address=contract_address) response = requests.get(abi_request_url).json() return response["abi"] @@ -190,7 +255,11 @@ def format_row(row: Tuple[Any, Any]) -> str: def verify_or_retrieve_tool( - agent_id: int, ledger_api: EthereumApi, tool: Optional[str] = None + agent_id: int, + ledger_api: EthereumApi, + agent_registry_contract: str, + block_explorer_url: str, + tool: Optional[str] = None, ) -> str: """ Checks if the tool is valid and for what agent. @@ -199,12 +268,21 @@ def verify_or_retrieve_tool( :type agent_id: int :param ledger_api: The Ethereum API used for interacting with the ledger. :type ledger_api: EthereumApi + :param agent_registry_contract: Agent registry contract address. + :type agent_registry_contract: str + :param block_explorer_url: Block explorer URL. + :type block_explorer_url: str :param tool: The tool to verify or retrieve (optional). :type tool: Optional[str] :return: The result of the verification or retrieval. :rtype: str """ - available_tools = fetch_tools(agent_id=agent_id, ledger_api=ledger_api) + available_tools = fetch_tools( + agent_id=agent_id, + ledger_api=ledger_api, + agent_registry_contract=agent_registry_contract, + block_explorer_url=block_explorer_url, + ) if tool is not None and tool not in available_tools: raise ValueError( f"Provided tool `{tool}` not in the list of available tools; Available tools={available_tools}" @@ -214,11 +292,16 @@ def verify_or_retrieve_tool( return _tool_selector_prompt(available_tools=available_tools) -def fetch_tools(agent_id: int, ledger_api: EthereumApi) -> List[str]: +def fetch_tools( + agent_id: int, + ledger_api: EthereumApi, + agent_registry_contract: str, + block_explorer_url: str, +) -> List[str]: """Fetch tools for specified agent ID.""" mech_registry = get_contract( - contract_address=AGENT_REGISTRY_CONTRACT, - abi=get_abi(AGENT_REGISTRY_CONTRACT), + contract_address=agent_registry_contract, + abi=get_abi(agent_registry_contract, block_explorer_url), ledger_api=ledger_api, ) token_uri = mech_registry.functions.tokenURI(agent_id).call() @@ -230,6 +313,7 @@ def send_request( # pylint: disable=too-many-arguments,too-many-locals crypto: EthereumCrypto, ledger_api: EthereumApi, mech_contract: Web3Contract, + gas_limit: int, prompt: str, tool: str, extra_attributes: Optional[Dict[str, Any]] = None, @@ -247,6 +331,8 @@ def send_request( # pylint: disable=too-many-arguments,too-many-locals :type ledger_api: EthereumApi :param mech_contract: The mech contract instance. :type mech_contract: Web3Contract + :param gas_limit: Gas limit. + :type gas_limit: int :param prompt: The request prompt. :type prompt: str :param tool: The requested tool. @@ -271,7 +357,7 @@ def send_request( # pylint: disable=too-many-arguments,too-many-locals tx_args = { "sender_address": crypto.address, "value": price, - "gas": MANUAL_GAS_LIMIT, + "gas": gas_limit, } tries = 0 @@ -308,6 +394,7 @@ def wait_for_data_url( # pylint: disable=too-many-arguments request_id: str, wss: websocket.WebSocket, mech_contract: Web3Contract, + subgraph_url: str, deliver_signature: str, ledger_api: EthereumApi, crypto: Crypto, @@ -322,6 +409,8 @@ def wait_for_data_url( # pylint: disable=too-many-arguments :type wss: websocket.WebSocket :param mech_contract: The mech contract instance. :type mech_contract: Web3Contract + :param subgraph_url: Subgraph URL. + :type subgraph_url: str :param deliver_signature: Topic signature for Deliver event :type deliver_signature: str :param ledger_api: The Ethereum API used for interacting with the ledger. @@ -358,7 +447,7 @@ def wait_for_data_url( # pylint: disable=too-many-arguments ) ) mech_task = loop.create_task( - watch_for_data_url_from_subgraph(request_id=request_id) + watch_for_data_url_from_subgraph(request_id=request_id, url=subgraph_url) ) tasks.append(mech_task) tasks.append(on_chain_task) @@ -388,6 +477,7 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals retries: Optional[int] = None, timeout: Optional[float] = None, sleep: Optional[float] = None, + chain_id: Optional[str] = None, ) -> Any: """ Interact with agent mech contract. @@ -411,9 +501,15 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals :type timeout: float :param sleep: Amount of sleep before retrying the transaction :type sleep: float + :param chain_id: Id of the mech's chain configuration (stored configs/mechs.json) + :type chain_id: str: :rtype: Any """ - contract_address = query_agent_address(agent_id=agent_id, timeout=timeout) + mech_config = get_mech_config(chain_id) + ledger_config = mech_config.ledger_config + contract_address = query_agent_address( + agent_id=agent_id, timeout=timeout, url=mech_config.subgraph_url + ) if contract_address is None: raise ValueError(f"Agent with ID {agent_id} does not exist!") @@ -423,12 +519,21 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals f"Private key file `{private_key_path}` does not exist!" ) - wss = websocket.create_connection(WSS_ENDPOINT) + wss = websocket.create_connection(mech_config.wss_endpoint) crypto = EthereumCrypto(private_key_path=private_key_path) - ledger_api = EthereumApi(**LEDGER_CONFIG) + ledger_api = EthereumApi(**asdict(ledger_config)) - tool = verify_or_retrieve_tool(agent_id=agent_id, ledger_api=ledger_api, tool=tool) - abi = get_abi(contract_address=contract_address) + tool = verify_or_retrieve_tool( + agent_id=agent_id, + ledger_api=ledger_api, + tool=tool, + agent_registry_contract=mech_config.agent_registry_contract, + block_explorer_url=mech_config.block_explorer_url, + ) + abi = get_abi( + contract_address=contract_address, + block_explorer_url=mech_config.block_explorer_url, + ) mech_contract = get_contract( contract_address=contract_address, abi=abi, ledger_api=ledger_api ) @@ -444,6 +549,7 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals crypto=crypto, ledger_api=ledger_api, mech_contract=mech_contract, + gas_limit=mech_config.manual_gas_limit, prompt=prompt, tool=tool, extra_attributes=extra_attributes, @@ -462,6 +568,7 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals request_id=request_id, wss=wss, mech_contract=mech_contract, + subgraph_url=mech_config.subgraph_url, deliver_signature=deliver_event_signature, ledger_api=ledger_api, crypto=crypto, diff --git a/mech_client/subgraph.py b/mech_client/subgraph.py index 5882db8..3d7e509 100644 --- a/mech_client/subgraph.py +++ b/mech_client/subgraph.py @@ -27,7 +27,6 @@ from gql.transport.aiohttp import AIOHTTPTransport -MECH_SUBGRAPH_URL = "https://api.studio.thegraph.com/query/57238/mech/version/latest" AGENT_QUERY_TEMPLATE = Template( """{ createMeches(where:{agentId:$agent_id}) { @@ -52,19 +51,22 @@ def query_agent_address( - agent_id: int, timeout: Optional[float] = None + agent_id: int, url: str, timeout: Optional[float] = None ) -> Optional[str]: """ Query agent address from subgraph. :param agent_id: The ID of the agent. - :param timeout: Timeout for the request. :type agent_id: int + :param url: Subgraph URL. + :type url: str + :param timeout: Timeout for the request. + :type timeout: Optional[float] :return: The agent address if found, None otherwise. :rtype: Optional[str] """ client = Client( - transport=AIOHTTPTransport(url=MECH_SUBGRAPH_URL), + transport=AIOHTTPTransport(url=url), execute_timeout=timeout or 30.0, ) response = client.execute( @@ -81,19 +83,22 @@ def query_agent_address( async def query_deliver_hash( - request_id: str, timeout: Optional[float] = None + request_id: str, url: str, timeout: Optional[float] = None ) -> Optional[str]: """ Query deliver IPFS hash from subgraph. :param request_id: The ID of the mech request. - :param timeout: Timeout for the request. :type request_id: str + :param url: Subgraph URL. + :type url: str + :param timeout: Timeout for the request. + :type timeout: Optional[float] :return: The deliver IPFS hash if found, None otherwise. :rtype: Optional[str] """ client = Client( - transport=AIOHTTPTransport(url=MECH_SUBGRAPH_URL), + transport=AIOHTTPTransport(url=url), execute_timeout=timeout or 30.0, ) response = await client.execute_async( @@ -110,13 +115,15 @@ async def query_deliver_hash( async def watch_for_data_url_from_subgraph( - request_id: str, timeout: Optional[float] = None + request_id: str, url: str, timeout: Optional[float] = None ) -> Optional[str]: """ Continuously query for data URL until it's available or timeout is reached. :param request_id: The ID of the mech request. :type request_id: str + :param url: Subgraph URL. + :type url: str :param timeout: Maximum time to wait for the data URL in seconds. Defaults to DEFAULT_TIMEOUT. :type timeout: Optional[float] :return: Data URL if available within timeout, otherwise None. @@ -125,7 +132,7 @@ async def watch_for_data_url_from_subgraph( timeout = timeout or DEFAULT_TIMEOUT start_time = asyncio.get_event_loop().time() while True: - response = await query_deliver_hash(request_id=request_id) + response = await query_deliver_hash(request_id=request_id, url=url) if response is not None: return f"https://gateway.autonolas.tech/ipfs/{response}" From 80466698a07afbee98da874c5b76841454f25c01 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Thu, 28 Mar 2024 14:22:53 +0100 Subject: [PATCH 02/15] chore: add placeholders --- README.md | 36 ++++++++++++---- mech_client/cli.py | 6 +-- mech_client/configs/mechs.json | 76 ++++++++++++++++++++++++++++++---- mech_client/interact.py | 27 ++++++------ 4 files changed, 113 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 7334459..f3fc133 100644 --- a/README.md +++ b/README.md @@ -10,16 +10,10 @@ Basic client to interact with a mech pip install mech-client ``` -Then, set a websocket endpoint for Gnosis RPC like so: - -```bash -export WEBSOCKET_ENDPOINT= -``` - Note: If you encounter an "Out of gas" error when executing the tool, you will need to increase the gas limit by setting, e.g., ```bash -export MANUAL_GAS_LIMIT=200000 +export MECHX_GAS_LIMIT=200000 ``` ## CLI: @@ -88,6 +82,7 @@ mechx interact --key Example output: ```bash mechx interact "write a short poem" 3 --key ~/gnosis_key --tool openai-text-davinci-003 +Using gnosis chain configuration. Prompt uploaded: https://gateway.autonolas.tech/ipfs/f01701220ad773628911d12e28f005e3f249e990d684e5dba07542259195602f9afed30bf Transaction sent: https://gnosisscan.io/tx/0x0d9209e32e965a820b9e80accfcd71ea3b1174b9758dd251c2e627a60ec426a5 Created on-chain request with ID 111240237160304797537720810617416341148235899500021985333360197012735240803849 @@ -95,10 +90,11 @@ Data arrived: https://gateway.autonolas.tech/ipfs/bafybeifk2h35ncszlze7t64rpblfo Data from agent: {'requestId': 111240237160304797537720810617416341148235899500021985333360197012735240803849, 'result': "\n\nI am brave and I'm strong\nI don't hide away my song\nI am here and I'm proud\nMy voice will be heard loud!"} ``` -By default the client will wait for data to arrive from on-chain using the websocket subscription and off-chain using the ACN and show you the result which arrives first. You can specify the type of confirmation you want using `--confirm` flag like this +By default the client will wait for data to arrive from on-chain using the websocket subscription and subgraph, and off-chain using the ACN and show you the result which arrives first. You can specify the type of confirmation you want using `--confirm` flag like this ```bash mechx interact "write a short poem" 3 --key ~/gnosis_key --tool openai-text-davinci-003 --confirm on-chain +Using gnosis chain configuration. Prompt uploaded: https://gateway.autonolas.tech/ipfs/f017012205e37f761221a8ba4005e91c36b94153e9432b8888ff2acae6b101dd5a5de6768 Transaction sent: https://gnosisscan.io/tx/0xf1ef63f617717bbb8deb09699af99aa39f10155d33796de2fd7eb61c9c1458b6 Created on-chain request with ID 81653153529124597849081567361606842861262371002932574194580478443414142139857 @@ -106,6 +102,30 @@ Data arrived: https://gateway.autonolas.tech/ipfs/f0170122069b55e077430a00f3cbc3 Data from agent: {'requestId': 81653153529124597849081567361606842861262371002932574194580478443414142139857, 'result': "\n\nA summer breeze, so sweet,\nA gentle reminder of summer's heat.\nThe sky so blue, no cloud in sight,\nA perfect day, a wondrous sight."} ``` +### Chain configuration + +Configurations for different chains are stored in the file `configs/mechs.json`. By default, `mech interact` will choose the first configuration on the JSON. You can specify which config you want to use using the `--chain-config` flag, for example, + +```bash +mechx interact --chain-config gnosis +``` + +Additionally, you can override any configuration parameter by exporting any of the following environment variables: + +```bash +MECHX_CHAIN_RPC +MECHX_WSS_ENDPOINT +MECHX_GAS_LIMIT +MECHX_BLOCK_EXPLORER_URL +MECHX_SUBGRAPH_URL + +MECHX_LEDGER_ADDRESS +MECHX_LEDGER_CHAIN_ID +MECHX_LEDGER_POA_CHAIN +MECHX_LEDGER_DEFAULT_GAS_PRICE_STRATEGY +MECHX_LEDGER_IS_GAS_ESTIMATION_ENABLED +``` + ## Programmatic Usage: ```python diff --git a/mech_client/cli.py b/mech_client/cli.py index 60d21fc..fc81fc6 100644 --- a/mech_client/cli.py +++ b/mech_client/cli.py @@ -80,7 +80,7 @@ def cli() -> None: help="Amount of sleep before retrying the transaction", ) @click.option( - "--chain-id", + "--chain-config", type=str, help="Id of the mech's chain configuration (stored configs/mechs.json)", ) @@ -94,7 +94,7 @@ def interact( # pylint: disable=too-many-arguments retries: Optional[int] = None, timeout: Optional[float] = None, sleep: Optional[float] = None, - chain_id: Optional[str] = None, + chain_config: Optional[str] = None, ) -> None: """Interact with a mech specifying a prompt and tool.""" try: @@ -118,7 +118,7 @@ def interact( # pylint: disable=too-many-arguments retries=retries, timeout=timeout, sleep=sleep, - chain_id=chain_id, + chain_config=chain_config, ) except (ValueError, FileNotFoundError) as e: raise click.ClickException(str(e)) from e diff --git a/mech_client/configs/mechs.json b/mech_client/configs/mechs.json index cf018e4..7813024 100644 --- a/mech_client/configs/mechs.json +++ b/mech_client/configs/mechs.json @@ -10,23 +10,83 @@ "default_gas_price_strategy": "eip1559", "is_gas_estimation_enabled": false }, - "manual_gas_limit": 100000, + "gas_limit": 100000, "block_explorer_url": "https://gnosis.blockscout.com/api/v2/smart-contracts/{contract_address}", "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" }, + "arbitrum": { + "agent_registry_contract": "", + "rpc_url": "", + "wss_endpoint": "t", + "ledger_config": { + "address": "", + "chain_id": 100, + "poa_chain": false, + "default_gas_price_strategy": "eip1559", + "is_gas_estimation_enabled": false + }, + "gas_limit": 100000, + "block_explorer_url": "", + "subgraph_url": "" + }, "polygon": { - "agent_registry_contract": "0xE49CB081e8d96920C38aA7AB90cb0294ab4Bc8EA", - "rpc_url": "https://rpc.eu-central-2.gateway.fm/v4/gnosis/non-archival/mainnet", - "wss_endpoint": "wss://rpc.eu-central-2.gateway.fm/ws/v4/gnosis/non-archival/mainnet", + "agent_registry_contract": "", + "rpc_url": "", + "wss_endpoint": "t", "ledger_config": { - "address": "https://rpc.eu-central-2.gateway.fm/v4/gnosis/non-archival/mainnet", + "address": "", "chain_id": 100, "poa_chain": false, "default_gas_price_strategy": "eip1559", "is_gas_estimation_enabled": false }, - "manual_gas_limit": 100000, - "block_explorer_url": "https://gnosis.blockscout.com/api/v2/smart-contracts/{contract_address}", - "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" + "gas_limit": 100000, + "block_explorer_url": "", + "subgraph_url": "" + }, + "base": { + "agent_registry_contract": "", + "rpc_url": "", + "wss_endpoint": "t", + "ledger_config": { + "address": "", + "chain_id": 100, + "poa_chain": false, + "default_gas_price_strategy": "eip1559", + "is_gas_estimation_enabled": false + }, + "gas_limit": 100000, + "block_explorer_url": "", + "subgraph_url": "" + }, + "celo": { + "agent_registry_contract": "", + "rpc_url": "", + "wss_endpoint": "t", + "ledger_config": { + "address": "", + "chain_id": 100, + "poa_chain": false, + "default_gas_price_strategy": "eip1559", + "is_gas_estimation_enabled": false + }, + "gas_limit": 100000, + "block_explorer_url": "", + "subgraph_url": "" + }, + "optimism": { + "agent_registry_contract": "", + "rpc_url": "", + "wss_endpoint": "t", + "ledger_config": { + "address": "", + "chain_id": 100, + "poa_chain": false, + "default_gas_price_strategy": "eip1559", + "is_gas_estimation_enabled": false + }, + "gas_limit": 100000, + "block_explorer_url": "", + "subgraph_url": "" } } \ No newline at end of file diff --git a/mech_client/interact.py b/mech_client/interact.py index 01562b1..d602c89 100644 --- a/mech_client/interact.py +++ b/mech_client/interact.py @@ -107,7 +107,7 @@ class MechConfig: rpc_url: str wss_endpoint: str ledger_config: LedgerConfig - manual_gas_limit: int + gas_limit: int block_explorer_url: str subgraph_url: str @@ -125,9 +125,9 @@ def __post_init__(self) -> None: if wss_endpoint: self.wss_endpoint = wss_endpoint - manual_gas_limit = os.getenv("MECHX_MANUAL_GAS_LIMIT") - if manual_gas_limit: - self.manual_gas_limit = int(manual_gas_limit) + gas_limit = os.getenv("MECHX_GAS_LIMIT") + if gas_limit: + self.gas_limit = int(gas_limit) block_explorer_url = os.getenv("MECHX_BLOCK_EXPLORER_URL") if block_explorer_url: @@ -146,15 +146,16 @@ class ConfirmationType(Enum): WAIT_FOR_BOTH = "wait-for-both" -def get_mech_config(chain_id: Optional[str] = None) -> MechConfig: +def get_mech_config(chain_config: Optional[str] = None) -> MechConfig: """Get `MechConfig` configuration""" with open(MECH_CONFIGS, "r", encoding="UTF-8") as file: data = json.load(file) - if chain_id is None: - chain_id = next(iter(data)) + if chain_config is None: + chain_config = next(iter(data)) - entry = data[chain_id].copy() + print(f"Chain configuration: {chain_config}") + entry = data[chain_config].copy() ledger_config = LedgerConfig(**entry.pop("ledger_config")) mech_config = MechConfig(**entry, ledger_config=ledger_config) return mech_config @@ -477,7 +478,7 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals retries: Optional[int] = None, timeout: Optional[float] = None, sleep: Optional[float] = None, - chain_id: Optional[str] = None, + chain_config: Optional[str] = None, ) -> Any: """ Interact with agent mech contract. @@ -501,11 +502,11 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals :type timeout: float :param sleep: Amount of sleep before retrying the transaction :type sleep: float - :param chain_id: Id of the mech's chain configuration (stored configs/mechs.json) - :type chain_id: str: + :param chain_config: Id of the mech's chain configuration (stored configs/mechs.json) + :type chain_config: str: :rtype: Any """ - mech_config = get_mech_config(chain_id) + mech_config = get_mech_config(chain_config) ledger_config = mech_config.ledger_config contract_address = query_agent_address( agent_id=agent_id, timeout=timeout, url=mech_config.subgraph_url @@ -549,7 +550,7 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals crypto=crypto, ledger_api=ledger_api, mech_contract=mech_contract, - gas_limit=mech_config.manual_gas_limit, + gas_limit=mech_config.gas_limit, prompt=prompt, tool=tool, extra_attributes=extra_attributes, From 076a080dca837ea207c5fc88d9339c3ec596c031 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Thu, 28 Mar 2024 14:23:29 +0100 Subject: [PATCH 03/15] chore: minor update --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f3fc133..06e3062 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ mechx interact --key Example output: ```bash mechx interact "write a short poem" 3 --key ~/gnosis_key --tool openai-text-davinci-003 -Using gnosis chain configuration. +Chain configuration: gnosis Prompt uploaded: https://gateway.autonolas.tech/ipfs/f01701220ad773628911d12e28f005e3f249e990d684e5dba07542259195602f9afed30bf Transaction sent: https://gnosisscan.io/tx/0x0d9209e32e965a820b9e80accfcd71ea3b1174b9758dd251c2e627a60ec426a5 Created on-chain request with ID 111240237160304797537720810617416341148235899500021985333360197012735240803849 @@ -94,7 +94,7 @@ By default the client will wait for data to arrive from on-chain using the webso ```bash mechx interact "write a short poem" 3 --key ~/gnosis_key --tool openai-text-davinci-003 --confirm on-chain -Using gnosis chain configuration. +Chain configuration: gnosis Prompt uploaded: https://gateway.autonolas.tech/ipfs/f017012205e37f761221a8ba4005e91c36b94153e9432b8888ff2acae6b101dd5a5de6768 Transaction sent: https://gnosisscan.io/tx/0xf1ef63f617717bbb8deb09699af99aa39f10155d33796de2fd7eb61c9c1458b6 Created on-chain request with ID 81653153529124597849081567361606842861262371002932574194580478443414142139857 From 4d24e1ec366631ca154d2b29c2c37306c79a4aff Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Thu, 28 Mar 2024 16:35:45 +0100 Subject: [PATCH 04/15] chore: added missing configs --- README.md | 2 +- mech_client/configs/mechs.json | 72 +++++++++++++++++----------------- mech_client/interact.py | 41 ++++++++++++------- 3 files changed, 63 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 06e3062..44ea34d 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ Additionally, you can override any configuration parameter by exporting any of t MECHX_CHAIN_RPC MECHX_WSS_ENDPOINT MECHX_GAS_LIMIT -MECHX_BLOCK_EXPLORER_URL +MECHX_CONTRACT_ABI_URL MECHX_SUBGRAPH_URL MECHX_LEDGER_ADDRESS diff --git a/mech_client/configs/mechs.json b/mech_client/configs/mechs.json index 7813024..6dd9be9 100644 --- a/mech_client/configs/mechs.json +++ b/mech_client/configs/mechs.json @@ -11,82 +11,82 @@ "is_gas_estimation_enabled": false }, "gas_limit": 100000, - "block_explorer_url": "https://gnosis.blockscout.com/api/v2/smart-contracts/{contract_address}", + "contract_abi_url": "https://gnosis.blockscout.com/api/v2/smart-contracts/{contract_address}", "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" }, "arbitrum": { - "agent_registry_contract": "", - "rpc_url": "", - "wss_endpoint": "t", + "agent_registry_contract": "0xa4799B083E0068732456EF45ff9fe5c683658327", + "rpc_url": "https://arbitrum.llamarpc.com", + "wss_endpoint": "wss://arbitrum-one-rpc.publicnode.com", "ledger_config": { - "address": "", - "chain_id": 100, + "address": "https://arbitrum.llamarpc.com", + "chain_id": 42161, "poa_chain": false, "default_gas_price_strategy": "eip1559", "is_gas_estimation_enabled": false }, "gas_limit": 100000, - "block_explorer_url": "", - "subgraph_url": "" + "contract_abi_url": "https://api.arbiscan.io/api?module=contract&action=getabi&address={contract_address}", + "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" }, "polygon": { - "agent_registry_contract": "", - "rpc_url": "", - "wss_endpoint": "t", + "agent_registry_contract": "0x984cf72FDe8B5aA910e9e508aC5e007ae5BDcC9C", + "rpc_url": "https://polygon-bor-rpc.publicnode.com", + "wss_endpoint": "wss://polygon-bor-rpc.publicnode.com", "ledger_config": { - "address": "", - "chain_id": 100, + "address": "https://polygon-bor-rpc.publicnode.com", + "chain_id": 137, "poa_chain": false, "default_gas_price_strategy": "eip1559", "is_gas_estimation_enabled": false }, "gas_limit": 100000, - "block_explorer_url": "", - "subgraph_url": "" + "contract_abi_url": "", + "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" }, "base": { - "agent_registry_contract": "", - "rpc_url": "", - "wss_endpoint": "t", + "agent_registry_contract": "0x88DE734655184a09B70700aE4F72364d1ad23728", + "rpc_url": "https://base.llamarpc.com", + "wss_endpoint": "wss://base-rpc.publicnode.com", "ledger_config": { - "address": "", - "chain_id": 100, + "address": "https://base.llamarpc.com", + "chain_id": 8453, "poa_chain": false, "default_gas_price_strategy": "eip1559", "is_gas_estimation_enabled": false }, "gas_limit": 100000, - "block_explorer_url": "", - "subgraph_url": "" + "contract_abi_url": "https://base.blockscout.com/api/v2/smart-contracts/{contract_address}", + "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" }, "celo": { - "agent_registry_contract": "", - "rpc_url": "", - "wss_endpoint": "t", + "agent_registry_contract": "0xE49CB081e8d96920C38aA7AB90cb0294ab4Bc8EA", + "rpc_url": "https://forno.celo.org", + "wss_endpoint": "wss://forno.celo.org/ws", "ledger_config": { - "address": "", - "chain_id": 100, + "address": "https://forno.celo.org", + "chain_id": 42220, "poa_chain": false, "default_gas_price_strategy": "eip1559", "is_gas_estimation_enabled": false }, "gas_limit": 100000, - "block_explorer_url": "", - "subgraph_url": "" + "contract_abi_url": "https://explorer.celo.org/mainnet/api?module=contract&action=getabi&address={contract_address}", + "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" }, "optimism": { - "agent_registry_contract": "", - "rpc_url": "", - "wss_endpoint": "t", + "agent_registry_contract": "0x75D529FAe220bC8db714F0202193726b46881B76", + "rpc_url": "https://mainnet.optimism.io", + "wss_endpoint": "wss://optimism-rpc.publicnode.com", "ledger_config": { - "address": "", - "chain_id": 100, + "address": "https://mainnet.optimism.io", + "chain_id": 10, "poa_chain": false, "default_gas_price_strategy": "eip1559", "is_gas_estimation_enabled": false }, "gas_limit": 100000, - "block_explorer_url": "", - "subgraph_url": "" + "contract_abi_url": "", + "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" } } \ No newline at end of file diff --git a/mech_client/interact.py b/mech_client/interact.py index d602c89..a234d83 100644 --- a/mech_client/interact.py +++ b/mech_client/interact.py @@ -108,7 +108,7 @@ class MechConfig: wss_endpoint: str ledger_config: LedgerConfig gas_limit: int - block_explorer_url: str + contract_abi_url: str subgraph_url: str def __post_init__(self) -> None: @@ -129,9 +129,9 @@ def __post_init__(self) -> None: if gas_limit: self.gas_limit = int(gas_limit) - block_explorer_url = os.getenv("MECHX_BLOCK_EXPLORER_URL") - if block_explorer_url: - self.block_explorer_url = block_explorer_url + contract_abi_url = os.getenv("MECHX_CONTRACT_ABI_URL") + if contract_abi_url: + self.contract_abi_url = contract_abi_url subgraph_url = os.getenv("MECHX_SUBGRAPH_URL") if subgraph_url: @@ -186,11 +186,22 @@ def get_event_signatures(abi: List) -> Tuple[str, str]: return request, deliver -def get_abi(contract_address: str, block_explorer_url: str) -> List: +def get_abi(contract_address: str, contract_abi_url: str) -> List: """Get contract abi""" - abi_request_url = block_explorer_url.format(contract_address=contract_address) + abi_request_url = contract_abi_url.format(contract_address=contract_address) response = requests.get(abi_request_url).json() - return response["abi"] + + if "result" in response: + result = response["result"] + try: + abi = json.loads(result) + except json.JSONDecodeError: + print("Error: Failed to parse 'result' field as JSON") + exit(1) + else: + abi = response.get("abi") + + return abi if abi else [] def get_contract( @@ -259,7 +270,7 @@ def verify_or_retrieve_tool( agent_id: int, ledger_api: EthereumApi, agent_registry_contract: str, - block_explorer_url: str, + contract_abi_url: str, tool: Optional[str] = None, ) -> str: """ @@ -271,8 +282,8 @@ def verify_or_retrieve_tool( :type ledger_api: EthereumApi :param agent_registry_contract: Agent registry contract address. :type agent_registry_contract: str - :param block_explorer_url: Block explorer URL. - :type block_explorer_url: str + :param contract_abi_url: Block explorer URL. + :type contract_abi_url: str :param tool: The tool to verify or retrieve (optional). :type tool: Optional[str] :return: The result of the verification or retrieval. @@ -282,7 +293,7 @@ def verify_or_retrieve_tool( agent_id=agent_id, ledger_api=ledger_api, agent_registry_contract=agent_registry_contract, - block_explorer_url=block_explorer_url, + contract_abi_url=contract_abi_url, ) if tool is not None and tool not in available_tools: raise ValueError( @@ -297,12 +308,12 @@ def fetch_tools( agent_id: int, ledger_api: EthereumApi, agent_registry_contract: str, - block_explorer_url: str, + contract_abi_url: str, ) -> List[str]: """Fetch tools for specified agent ID.""" mech_registry = get_contract( contract_address=agent_registry_contract, - abi=get_abi(agent_registry_contract, block_explorer_url), + abi=get_abi(agent_registry_contract, contract_abi_url), ledger_api=ledger_api, ) token_uri = mech_registry.functions.tokenURI(agent_id).call() @@ -529,11 +540,11 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals ledger_api=ledger_api, tool=tool, agent_registry_contract=mech_config.agent_registry_contract, - block_explorer_url=mech_config.block_explorer_url, + contract_abi_url=mech_config.contract_abi_url, ) abi = get_abi( contract_address=contract_address, - block_explorer_url=mech_config.block_explorer_url, + contract_abi_url=mech_config.contract_abi_url, ) mech_contract = get_contract( contract_address=contract_address, abi=abi, ledger_api=ledger_api From 79c736b4acfabf4746af3e9f771b43326b79b1f8 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Thu, 28 Mar 2024 16:43:52 +0100 Subject: [PATCH 05/15] chore: add message --- mech_client/interact.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mech_client/interact.py b/mech_client/interact.py index a234d83..9124459 100644 --- a/mech_client/interact.py +++ b/mech_client/interact.py @@ -569,6 +569,7 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals timeout=timeout, sleep=sleep, ) + print("Waiting for transaction receipt...") request_id = watch_for_request_id( wss=wss, mech_contract=mech_contract, From 15973e41de1c67299ef93b86b82c90b91bb42cc7 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Thu, 28 Mar 2024 17:31:20 +0100 Subject: [PATCH 06/15] chore: add return --- mech_client/interact.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mech_client/interact.py b/mech_client/interact.py index 9124459..21f4b77 100644 --- a/mech_client/interact.py +++ b/mech_client/interact.py @@ -333,7 +333,7 @@ def send_request( # pylint: disable=too-many-arguments,too-many-locals retries: Optional[int] = None, timeout: Optional[float] = None, sleep: Optional[float] = None, -) -> None: +) -> Optional[str]: """ Sends a request to the mech. @@ -394,12 +394,13 @@ def send_request( # pylint: disable=too-many-arguments,too-many-locals raise_on_try=True, ) print(f"Transaction sent: https://gnosisscan.io/tx/{transaction_digest}") - return + return transaction_digest except Exception as e: # pylint: disable=broad-except print( f"Error occured while sending the transaction: {e}; Retrying in {sleep}" ) time.sleep(sleep) + return None def wait_for_data_url( # pylint: disable=too-many-arguments From 28a3379609d0f2309d69dcec75ae08313502db1b Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Thu, 28 Mar 2024 17:47:08 +0100 Subject: [PATCH 07/15] fix: doc --- mech_client/interact.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mech_client/interact.py b/mech_client/interact.py index 21f4b77..d99be48 100644 --- a/mech_client/interact.py +++ b/mech_client/interact.py @@ -359,6 +359,8 @@ def send_request( # pylint: disable=too-many-arguments,too-many-locals :type timeout: float :param sleep: Amount of sleep before retrying the transaction :type sleep: float + :return: The transaction hash. + :rtype: Optional[str] """ v1_file_hash_hex_truncated, v1_file_hash_hex = push_metadata_to_ipfs( prompt, tool, extra_attributes From b0a6dd19a7948ad33c040e6ce4a1bbdc60d8d670 Mon Sep 17 00:00:00 2001 From: David Minarsch Date: Thu, 28 Mar 2024 22:03:44 +0000 Subject: [PATCH 08/15] Apply suggestions from code review --- mech_client/configs/mechs.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mech_client/configs/mechs.json b/mech_client/configs/mechs.json index 6dd9be9..f0964cd 100644 --- a/mech_client/configs/mechs.json +++ b/mech_client/configs/mechs.json @@ -41,7 +41,7 @@ "is_gas_estimation_enabled": false }, "gas_limit": 100000, - "contract_abi_url": "", + "contract_abi_url": "https://api.polygonscan.com/api?module=contract&action=getabi&address={contract_address}", "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" }, "base": { @@ -86,7 +86,7 @@ "is_gas_estimation_enabled": false }, "gas_limit": 100000, - "contract_abi_url": "", + "contract_abi_url": "https://api-optimistic.etherscan.io/api?module=contract&action=getabi&address={contract_address}", "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" } } \ No newline at end of file From 5fe3c1826ee6300441364dad0b21d853015ed099 Mon Sep 17 00:00:00 2001 From: David Minarsch Date: Thu, 28 Mar 2024 23:25:00 +0000 Subject: [PATCH 09/15] chore: partial fix to multi-network support --- mech_client/configs/mechs.json | 14 +++++++------- mech_client/interact.py | 2 +- mech_client/subgraph.py | 14 +++++++++++++- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/mech_client/configs/mechs.json b/mech_client/configs/mechs.json index f0964cd..b08da22 100644 --- a/mech_client/configs/mechs.json +++ b/mech_client/configs/mechs.json @@ -27,7 +27,7 @@ }, "gas_limit": 100000, "contract_abi_url": "https://api.arbiscan.io/api?module=contract&action=getabi&address={contract_address}", - "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" + "subgraph_url": "" }, "polygon": { "agent_registry_contract": "0x984cf72FDe8B5aA910e9e508aC5e007ae5BDcC9C", @@ -42,12 +42,12 @@ }, "gas_limit": 100000, "contract_abi_url": "https://api.polygonscan.com/api?module=contract&action=getabi&address={contract_address}", - "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" + "subgraph_url": "" }, "base": { "agent_registry_contract": "0x88DE734655184a09B70700aE4F72364d1ad23728", "rpc_url": "https://base.llamarpc.com", - "wss_endpoint": "wss://base-rpc.publicnode.com", + "wss_endpoint": "wss://base.gateway.tenderly.co", "ledger_config": { "address": "https://base.llamarpc.com", "chain_id": 8453, @@ -56,8 +56,8 @@ "is_gas_estimation_enabled": false }, "gas_limit": 100000, - "contract_abi_url": "https://base.blockscout.com/api/v2/smart-contracts/{contract_address}", - "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" + "contract_abi_url": "https://api.basescan.org/api?module=contract&action=getabi&address={contract_address}", + "subgraph_url": "" }, "celo": { "agent_registry_contract": "0xE49CB081e8d96920C38aA7AB90cb0294ab4Bc8EA", @@ -72,7 +72,7 @@ }, "gas_limit": 100000, "contract_abi_url": "https://explorer.celo.org/mainnet/api?module=contract&action=getabi&address={contract_address}", - "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" + "subgraph_url": "" }, "optimism": { "agent_registry_contract": "0x75D529FAe220bC8db714F0202193726b46881B76", @@ -87,6 +87,6 @@ }, "gas_limit": 100000, "contract_abi_url": "https://api-optimistic.etherscan.io/api?module=contract&action=getabi&address={contract_address}", - "subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest" + "subgraph_url": "" } } \ No newline at end of file diff --git a/mech_client/interact.py b/mech_client/interact.py index d99be48..04f97e6 100644 --- a/mech_client/interact.py +++ b/mech_client/interact.py @@ -523,7 +523,7 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals mech_config = get_mech_config(chain_config) ledger_config = mech_config.ledger_config contract_address = query_agent_address( - agent_id=agent_id, timeout=timeout, url=mech_config.subgraph_url + agent_id=agent_id, timeout=timeout, url=mech_config.subgraph_url, chain_config=chain_config ) if contract_address is None: raise ValueError(f"Agent with ID {agent_id} does not exist!") diff --git a/mech_client/subgraph.py b/mech_client/subgraph.py index 3d7e509..b389fce 100644 --- a/mech_client/subgraph.py +++ b/mech_client/subgraph.py @@ -51,7 +51,7 @@ def query_agent_address( - agent_id: int, url: str, timeout: Optional[float] = None + agent_id: int, url: str, timeout: Optional[float] = None, chain_config: Optional[str] = None, ) -> Optional[str]: """ Query agent address from subgraph. @@ -62,9 +62,21 @@ def query_agent_address( :type url: str :param timeout: Timeout for the request. :type timeout: Optional[float] + :type chain_config: Optional[str]: :return: The agent address if found, None otherwise. :rtype: Optional[str] """ + # temporary hard coded until subgraph present + if chain_config == "base" and agent_id == 2: + return "0x111D7DB1B752AB4D2cC0286983D9bd73a49bac6c" + if chain_config == "arbitrum" and agent_id == 2: + return "0x1FDAD3a5af5E96e5a64Fc0662B1814458F114597" + if chain_config == "polygon" and agent_id == 2: + return "0xbF92568718982bf65ee4af4F7020205dE2331a8a" + if chain_config == "celo" and agent_id == 2: + return "0xbF92568718982bf65ee4af4F7020205dE2331a8a" + if chain_config == "optimism" and agent_id == 2: + return "0xbF92568718982bf65ee4af4F7020205dE2331a8a" client = Client( transport=AIOHTTPTransport(url=url), execute_timeout=timeout or 30.0, From f4c5283c69cd712c0f6645f0d31f5c87f9b68db9 Mon Sep 17 00:00:00 2001 From: David Minarsch Date: Fri, 29 Mar 2024 09:40:18 +0000 Subject: [PATCH 10/15] chore: add missing mechs --- mech_client/subgraph.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mech_client/subgraph.py b/mech_client/subgraph.py index b389fce..9fdfbe8 100644 --- a/mech_client/subgraph.py +++ b/mech_client/subgraph.py @@ -74,9 +74,9 @@ def query_agent_address( if chain_config == "polygon" and agent_id == 2: return "0xbF92568718982bf65ee4af4F7020205dE2331a8a" if chain_config == "celo" and agent_id == 2: - return "0xbF92568718982bf65ee4af4F7020205dE2331a8a" + return "0x230eD015735c0D01EA0AaD2786Ed6Bd3C6e75912" if chain_config == "optimism" and agent_id == 2: - return "0xbF92568718982bf65ee4af4F7020205dE2331a8a" + return "0xDd40E7D93c37eFD860Bd53Ab90b2b0a8D05cf71a" client = Client( transport=AIOHTTPTransport(url=url), execute_timeout=timeout or 30.0, From 4c5d8079a3ad09090ff1cf0a7a1e87eb3bb5654a Mon Sep 17 00:00:00 2001 From: David Minarsch Date: Fri, 29 Mar 2024 10:45:32 +0000 Subject: [PATCH 11/15] chore: fix config arbitrum --- mech_client/configs/mechs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mech_client/configs/mechs.json b/mech_client/configs/mechs.json index b08da22..a935d79 100644 --- a/mech_client/configs/mechs.json +++ b/mech_client/configs/mechs.json @@ -17,7 +17,7 @@ "arbitrum": { "agent_registry_contract": "0xa4799B083E0068732456EF45ff9fe5c683658327", "rpc_url": "https://arbitrum.llamarpc.com", - "wss_endpoint": "wss://arbitrum-one-rpc.publicnode.com", + "wss_endpoint": "wss://arbitrum.gateway.tenderly.co", "ledger_config": { "address": "https://arbitrum.llamarpc.com", "chain_id": 42161, From 48f30ed061fbbe1840c601c73ee42eb2b19139e9 Mon Sep 17 00:00:00 2001 From: David Minarsch Date: Fri, 29 Mar 2024 10:48:23 +0000 Subject: [PATCH 12/15] chore: fix config polygon --- mech_client/configs/mechs.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mech_client/configs/mechs.json b/mech_client/configs/mechs.json index a935d79..d86e6e2 100644 --- a/mech_client/configs/mechs.json +++ b/mech_client/configs/mechs.json @@ -32,11 +32,11 @@ "polygon": { "agent_registry_contract": "0x984cf72FDe8B5aA910e9e508aC5e007ae5BDcC9C", "rpc_url": "https://polygon-bor-rpc.publicnode.com", - "wss_endpoint": "wss://polygon-bor-rpc.publicnode.com", + "wss_endpoint": "wss://polygon.gateway.tenderly.co", "ledger_config": { "address": "https://polygon-bor-rpc.publicnode.com", "chain_id": 137, - "poa_chain": false, + "poa_chain": true, "default_gas_price_strategy": "eip1559", "is_gas_estimation_enabled": false }, From db584de301864dcf65d8faec709bcae535df5747 Mon Sep 17 00:00:00 2001 From: David Minarsch Date: Fri, 29 Mar 2024 10:56:34 +0000 Subject: [PATCH 13/15] chore: config optimism --- mech_client/configs/mechs.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mech_client/configs/mechs.json b/mech_client/configs/mechs.json index d86e6e2..07901dc 100644 --- a/mech_client/configs/mechs.json +++ b/mech_client/configs/mechs.json @@ -71,13 +71,13 @@ "is_gas_estimation_enabled": false }, "gas_limit": 100000, - "contract_abi_url": "https://explorer.celo.org/mainnet/api?module=contract&action=getabi&address={contract_address}", + "contract_abi_url": "https://api.celoscan.io/api?module=contract&action=getabi&address={contract_address}", "subgraph_url": "" }, "optimism": { "agent_registry_contract": "0x75D529FAe220bC8db714F0202193726b46881B76", "rpc_url": "https://mainnet.optimism.io", - "wss_endpoint": "wss://optimism-rpc.publicnode.com", + "wss_endpoint": "wss://optimism.gateway.tenderly.co", "ledger_config": { "address": "https://mainnet.optimism.io", "chain_id": 10, From 211245ba381556947de3d64f94dff9d90c069d82 Mon Sep 17 00:00:00 2001 From: David Minarsch Date: Fri, 29 Mar 2024 10:58:59 +0000 Subject: [PATCH 14/15] chore: fix black linting --- mech_client/interact.py | 5 ++++- mech_client/subgraph.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/mech_client/interact.py b/mech_client/interact.py index 04f97e6..b315619 100644 --- a/mech_client/interact.py +++ b/mech_client/interact.py @@ -523,7 +523,10 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals mech_config = get_mech_config(chain_config) ledger_config = mech_config.ledger_config contract_address = query_agent_address( - agent_id=agent_id, timeout=timeout, url=mech_config.subgraph_url, chain_config=chain_config + agent_id=agent_id, + timeout=timeout, + url=mech_config.subgraph_url, + chain_config=chain_config, ) if contract_address is None: raise ValueError(f"Agent with ID {agent_id} does not exist!") diff --git a/mech_client/subgraph.py b/mech_client/subgraph.py index 9fdfbe8..52a502f 100644 --- a/mech_client/subgraph.py +++ b/mech_client/subgraph.py @@ -51,7 +51,10 @@ def query_agent_address( - agent_id: int, url: str, timeout: Optional[float] = None, chain_config: Optional[str] = None, + agent_id: int, + url: str, + timeout: Optional[float] = None, + chain_config: Optional[str] = None, ) -> Optional[str]: """ Query agent address from subgraph. From 0f1bb3f8d21844a24b9759be09df59983dee6073 Mon Sep 17 00:00:00 2001 From: David Minarsch Date: Fri, 29 Mar 2024 11:12:57 +0000 Subject: [PATCH 15/15] chore: fix pylint --- mech_client/interact.py | 3 ++- mech_client/subgraph.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mech_client/interact.py b/mech_client/interact.py index b315619..100dcf0 100644 --- a/mech_client/interact.py +++ b/mech_client/interact.py @@ -28,6 +28,7 @@ import asyncio import json import os +import sys import time import warnings from dataclasses import asdict, dataclass @@ -197,7 +198,7 @@ def get_abi(contract_address: str, contract_abi_url: str) -> List: abi = json.loads(result) except json.JSONDecodeError: print("Error: Failed to parse 'result' field as JSON") - exit(1) + sys.exit(1) else: abi = response.get("abi") diff --git a/mech_client/subgraph.py b/mech_client/subgraph.py index 52a502f..ff963bd 100644 --- a/mech_client/subgraph.py +++ b/mech_client/subgraph.py @@ -50,7 +50,7 @@ DEFAULT_TIMEOUT = 600.0 -def query_agent_address( +def query_agent_address( # pylint: disable=too-many-return-statements agent_id: int, url: str, timeout: Optional[float] = None,