| """ |
| RMI Apify Integration -- Free/cheap external actors as MCP tools. |
| Actors: Arkham wallet intelligence, web scraping, Twitter data. |
| """ |
|
|
| import logging |
| import os |
| from typing import Any |
|
|
| logger = logging.getLogger("rmi_apify") |
|
|
| APIFY_TOKEN = os.getenv("APIFY_API_TOKEN", "") |
| APIFY_BASE = "https://api.apify.com/v2" |
|
|
|
|
| def _apify_call(actor_id: str, run_input: dict, timeout: int = 120) -> dict | None: |
| """Run an Apify actor and return results.""" |
| if not APIFY_TOKEN: |
| return {"error": "APIFY_API_TOKEN not configured"} |
|
|
| import httpx |
|
|
| try: |
| |
| resp = httpx.post( |
| f"{APIFY_BASE}/acts/{actor_id}/runs?waitForFinish={timeout}", |
| headers={"Authorization": f"Bearer {APIFY_TOKEN}", "Content-Type": "application/json"}, |
| json=run_input, |
| timeout=timeout + 30, |
| ) |
| if resp.status_code != 200 and resp.status_code != 201: |
| return {"error": f"Actor start failed: HTTP {resp.status_code}"} |
|
|
| run_data = resp.json().get("data", {}) |
| dataset_id = run_data.get("defaultDatasetId") |
| if not dataset_id: |
| return {"error": "No dataset ID returned"} |
|
|
| |
| items_resp = httpx.get( |
| f"{APIFY_BASE}/datasets/{dataset_id}/items", |
| headers={"Authorization": f"Bearer {APIFY_TOKEN}"}, |
| timeout=30, |
| ) |
| if items_resp.status_code != 200: |
| return {"error": f"Dataset fetch failed: HTTP {items_resp.status_code}"} |
|
|
| return {"data": items_resp.json(), "run_id": run_data.get("id")} |
|
|
| except Exception as e: |
| return {"error": str(e)[:200]} |
|
|
|
|
| def arkham_wallet_intel(address: str) -> dict[str, Any]: |
| """Get Arkham Intelligence wallet data. Near-free via Apify (~$0.03/wallet).""" |
| return _apify_call( |
| "BFRkJAsA9XBVgzoce", |
| { |
| "walletAddresses": [address], |
| "dataType": "intelligence", |
| "proxyConfiguration": {"useApifyProxy": True}, |
| }, |
| ) |
|
|
|
|
| def arkham_wallet_portfolio(address: str, date: str | None = None) -> dict[str, Any]: |
| """Get Arkham wallet portfolio/holdings.""" |
| return _apify_call( |
| "BFRkJAsA9XBVgzoce", |
| { |
| "walletAddresses": [address], |
| "dataType": "portfolio", |
| "portfolioDate": date, |
| "proxyConfiguration": {"useApifyProxy": True}, |
| }, |
| ) |
|
|