Skip to content

Commit

Permalink
Merge pull request #36 from valory-xyz/fix/celo
Browse files Browse the repository at this point in the history
Fix Celo configs
  • Loading branch information
dvilelaf authored Apr 9, 2024
2 parents e89f480 + 8f53d26 commit 238a714
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 39 deletions.
27 changes: 18 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ A basic client to interact with an AI Mech. [AI Mechs](https://github.com/valory
> **:warning: Warning** <br />
> **This is a *hacky* alpha version of the client. Don't rely on it as production software.**
## Requirements

- Python >=3.10

## Installation

Find the latest available release on [PyPi](https://pypi.org/project/mech-client/#description).
Expand Down Expand Up @@ -54,26 +58,26 @@ Commands:
To use the Mech Client you need an EOA account and its associated private key stored in a text file `ethereum_private_key.txt`. You can set it up in two ways:
- Use the Open AEA command `generate-key`:
- Use any software of your choice (e.g., [Metamask](https://metamask.io/)) and copy the private key:
```bash
aea generate-key ethereum
echo -n YOUR_PRIVATE_KEY > ethereum_private_key.txt
```
and display the corresponding EOA:
Do not include any leading or trailing spaces, tabs or newlines, or any other character in the file `ethereum_private_key.txt`.
- Alternatively, use the Open AEA command `generate-key` (you'll need to install [Open AEA](https://pypi.org/project/open-aea/) and its [Ethereum ledger plugin](https://pypi.org/project/open-aea-ledger-ethereum/)):

```bash
python -c "from web3 import Web3; print(Web3().eth.account.from_key(open('ethereum_private_key.txt').read()).address)"
aea generate-key ethereum
```

- Alternatively, use any software of your choice (e.g., [Metamask](https://metamask.io/)) and copy the private key:
and display the corresponding EOA:

```bash
echo -n YOUR_PRIVATE_KEY > ethereum_private_key.txt
python -c "from web3 import Web3; print(Web3().eth.account.from_key(open('ethereum_private_key.txt').read()).address)"
```

Do not include any leading or trailing spaces, tabs or newlines, or any other character in the file `ethereum_private_key.txt`.
The EOA you use must have enough funds to pay for the Mech requests, or alternatively, use a Nevermined subscription.

> **:warning: Warning** <br />
Expand All @@ -85,6 +89,10 @@ The EOA you use must have enough funds to pay for the Mech requests, or alternat
> echo ethereum_private_key.txt >> .gitignore
> ```

### Select the mech you are going to send requests to

Mechs are deployed to several networks. Find the list of supported networks and corresponging mech addresses [here](https://github.com/valory-xyz/mech?tab=readme-ov-file#examples-of-deployed-mechs).

### Generate Mech requests

The basic usage of the Mech Client is as follows:
Expand All @@ -108,7 +116,7 @@ Some useful options:
| 0 | openai-text-davinci-002 |
| ...| ... |
|--------------------------------------------------|
Tool ID >
Tool ID >
```

- `--chain-config <name>`: Use default chain configuration parameters (RPC, WSS, ...). [See below](#chain-configuration) for more details. Available values are
Expand Down Expand Up @@ -162,6 +170,7 @@ MECHX_CHAIN_RPC
MECHX_WSS_ENDPOINT
MECHX_GAS_LIMIT
MECHX_CONTRACT_ABI_URL
MECHX_TRANSACTION_URL
MECHX_SUBGRAPH_URL
MECHX_LEDGER_ADDRESS
Expand Down
10 changes: 8 additions & 2 deletions mech_client/configs/mechs.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
},
"gas_limit": 100000,
"contract_abi_url": "https://gnosis.blockscout.com/api/v2/smart-contracts/{contract_address}",
"transaction_url": "https://gnosisscan.io/tx/{transaction_digest}",
"subgraph_url": "https://api.studio.thegraph.com/query/57238/mech/version/latest"
},
"arbitrum": {
Expand All @@ -27,6 +28,7 @@
},
"gas_limit": 100000,
"contract_abi_url": "https://api.arbiscan.io/api?module=contract&action=getabi&address={contract_address}",
"transaction_url": "",
"subgraph_url": ""
},
"polygon": {
Expand All @@ -42,6 +44,7 @@
},
"gas_limit": 100000,
"contract_abi_url": "https://api.polygonscan.com/api?module=contract&action=getabi&address={contract_address}",
"transaction_url": "",
"subgraph_url": ""
},
"base": {
Expand All @@ -57,6 +60,7 @@
},
"gas_limit": 100000,
"contract_abi_url": "https://api.basescan.org/api?module=contract&action=getabi&address={contract_address}",
"transaction_url": "",
"subgraph_url": ""
},
"celo": {
Expand All @@ -66,12 +70,13 @@
"ledger_config": {
"address": "https://forno.celo.org",
"chain_id": 42220,
"poa_chain": false,
"poa_chain": true,
"default_gas_price_strategy": "eip1559",
"is_gas_estimation_enabled": false
},
"gas_limit": 100000,
"gas_limit": 250000,
"contract_abi_url": "https://api.celoscan.io/api?module=contract&action=getabi&address={contract_address}",
"transaction_url": "https://celoscan.io/tx/{transaction_digest}",
"subgraph_url": ""
},
"optimism": {
Expand All @@ -87,6 +92,7 @@
},
"gas_limit": 100000,
"contract_abi_url": "https://api-optimistic.etherscan.io/api?module=contract&action=getabi&address={contract_address}",
"transaction_url": "",
"subgraph_url": ""
}
}
42 changes: 29 additions & 13 deletions mech_client/interact.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def __post_init__(self) -> None:


@dataclass
class MechConfig:
class MechConfig: # pylint: disable=too-many-instance-attributes
"""Mech configuration"""

agent_registry_contract: str
Expand All @@ -110,6 +110,7 @@ class MechConfig:
ledger_config: LedgerConfig
gas_limit: int
contract_abi_url: str
transaction_url: str
subgraph_url: str

def __post_init__(self) -> None:
Expand All @@ -134,6 +135,10 @@ def __post_init__(self) -> None:
if contract_abi_url:
self.contract_abi_url = contract_abi_url

transaction_url = os.getenv("MECHX_TRANSACTION_URL")
if transaction_url:
self.transaction_url = transaction_url

subgraph_url = os.getenv("MECHX_SUBGRAPH_URL")
if subgraph_url:
self.subgraph_url = subgraph_url
Expand Down Expand Up @@ -396,7 +401,6 @@ def send_request( # pylint: disable=too-many-arguments,too-many-locals
signed_transaction,
raise_on_try=True,
)
print(f"Transaction sent: https://gnosisscan.io/tx/{transaction_digest}")
return transaction_digest
except Exception as e: # pylint: disable=broad-except
print(
Expand Down Expand Up @@ -462,12 +466,16 @@ def wait_for_data_url( # pylint: disable=too-many-arguments
loop=loop,
)
)
mech_task = loop.create_task(
watch_for_data_url_from_subgraph(request_id=request_id, url=subgraph_url)
)
tasks.append(mech_task)
tasks.append(on_chain_task)

if subgraph_url:
mech_task = loop.create_task(
watch_for_data_url_from_subgraph(
request_id=request_id, url=subgraph_url
)
)
tasks.append(mech_task)

async def _wait_for_tasks() -> Any: # type: ignore
"""Wait for tasks to finish."""
(finished, *_), unfinished = await asyncio.wait(
Expand All @@ -476,7 +484,8 @@ async def _wait_for_tasks() -> Any: # type: ignore
)
for task in unfinished:
task.cancel()
await asyncio.wait(unfinished)
if unfinished:
await asyncio.wait(unfinished)
return finished.result()

result = loop.run_until_complete(_wait_for_tasks())
Expand Down Expand Up @@ -564,7 +573,8 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals
request_signature=request_event_signature,
deliver_signature=deliver_event_signature,
)
send_request(
print("Sending request...")
transaction_digest = send_request(
crypto=crypto,
ledger_api=ledger_api,
mech_contract=mech_contract,
Expand All @@ -576,6 +586,10 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals
timeout=timeout,
sleep=sleep,
)
transaction_url_formatted = mech_config.transaction_url.format(
transaction_digest=transaction_digest
)
print(f"Transaction sent: {transaction_url_formatted}")
print("Waiting for transaction receipt...")
request_id = watch_for_request_id(
wss=wss,
Expand All @@ -584,6 +598,7 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals
request_signature=request_event_signature,
)
print(f"Created on-chain request with ID {request_id}")
print("Waiting for Mech response...")
data_url = wait_for_data_url(
request_id=request_id,
wss=wss,
Expand All @@ -594,8 +609,9 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals
crypto=crypto,
confirmation_type=confirmation_type,
)

print(f"Data arrived: {data_url}")
data = requests.get(f"{data_url}/{request_id}").json()
print(f"Data from agent: {data}")
return data
if data_url:
print(f"Data arrived: {data_url}")
data = requests.get(f"{data_url}/{request_id}").json()
print(f"Data from agent: {data}")
return data
return None
37 changes: 22 additions & 15 deletions mech_client/wss.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,19 +170,26 @@ async def watch_for_data_url_from_wss( # pylint: disable=too-many-arguments
:rtype: Any
"""
with ThreadPoolExecutor() as executor:
while True:
msg = await loop.run_in_executor(executor=executor, func=wss.recv)
data = json.loads(msg)
tx_hash = data["params"]["result"]["transactionHash"]
tx_receipt = await loop.run_in_executor(
executor, wait_for_receipt, tx_hash, ledger_api
try:
while True:
msg = await loop.run_in_executor(executor=executor, func=wss.recv)
data = json.loads(msg)
tx_hash = data["params"]["result"]["transactionHash"]
tx_receipt = await loop.run_in_executor(
executor, wait_for_receipt, tx_hash, ledger_api
)
event_signature = tx_receipt["logs"][0]["topics"][0].hex()
if event_signature != deliver_signature:
continue

rich_logs = mech_contract.events.Deliver().process_receipt(tx_receipt)
data = cast(bytes, rich_logs[0]["args"]["data"])
if request_id != str(rich_logs[0]["args"]["requestId"]):
continue
return f"https://gateway.autonolas.tech/ipfs/f01701220{data.hex()}"
except websocket.WebSocketConnectionClosedException as e:
print(f"WebSocketConnectionClosedException {repr(e)}")
print(
"Error: The WSS connection was likely closed by the remote party. Please, try using another WSS provider."
)
event_signature = tx_receipt["logs"][0]["topics"][0].hex()
if event_signature != deliver_signature:
continue

rich_logs = mech_contract.events.Deliver().process_receipt(tx_receipt)
data = cast(bytes, rich_logs[0]["args"]["data"])
if request_id != str(rich_logs[0]["args"]["requestId"]):
continue
return f"https://gateway.autonolas.tech/ipfs/f01701220{data.hex()}"
return None

0 comments on commit 238a714

Please sign in to comment.