fix: Better error detection for AVE API commands
- Added _is_error_output helper to detect errors in CLI output - API errors like 'API error 403' now show proper error message instead of 'No price data available' - Updated all command execution methods to use the helper
This commit is contained in:
@@ -472,6 +472,15 @@ class ConversationalAgent:
|
|||||||
# Track pending command after acknowledgment
|
# Track pending command after acknowledgment
|
||||||
self.pending_command = None
|
self.pending_command = None
|
||||||
|
|
||||||
|
def _is_error_output(self, code: int, output: str) -> bool:
|
||||||
|
"""Check if the command output contains an error."""
|
||||||
|
if code != 0:
|
||||||
|
return True
|
||||||
|
# Check for common error patterns in output
|
||||||
|
if output.startswith("Error:") or "API error" in output or "api key invalid" in output.lower():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def _handle_slash_command(self, user_message: str) -> Dict[str, Any]:
|
def _handle_slash_command(self, user_message: str) -> Dict[str, Any]:
|
||||||
"""Handle slash command help requests.
|
"""Handle slash command help requests.
|
||||||
|
|
||||||
@@ -664,54 +673,53 @@ class ConversationalAgent:
|
|||||||
"trending",
|
"trending",
|
||||||
["--chain", "bsc", "--page-size", "10"],
|
["--chain", "bsc", "--page-size", "10"],
|
||||||
)
|
)
|
||||||
if code == 0:
|
if self._is_error_output(code, output):
|
||||||
try:
|
return {
|
||||||
data = json.loads(output)
|
"response": f"Failed to get trending tokens: {output}",
|
||||||
# Handle both dict with 'tokens' key and direct list
|
"thinking": None,
|
||||||
data_field = data.get("data", [])
|
"strategy_updated": False,
|
||||||
if isinstance(data_field, list):
|
"strategy_needs_confirmation": False,
|
||||||
tokens = data_field
|
"success": True,
|
||||||
else:
|
}
|
||||||
tokens = data_field.get("tokens", [])
|
try:
|
||||||
if tokens:
|
data = json.loads(output)
|
||||||
token_list = ""
|
# Handle both dict with 'tokens' key and direct list
|
||||||
for t in tokens[:10]:
|
data_field = data.get("data", [])
|
||||||
addr = t.get("token", "")
|
if isinstance(data_field, list):
|
||||||
symbol = t.get("symbol", "")
|
tokens = data_field
|
||||||
name = t.get("name", "")
|
else:
|
||||||
price_change = t.get("token_price_change_24h", "N/A")
|
tokens = data_field.get("tokens", [])
|
||||||
mc = t.get("market_cap", "N/A")
|
if tokens:
|
||||||
try:
|
token_list = ""
|
||||||
mc_str = f"${float(mc):,.0f}"
|
for t in tokens[:10]:
|
||||||
except (ValueError, TypeError):
|
addr = t.get("token", "")
|
||||||
mc_str = str(mc)
|
symbol = t.get("symbol", "")
|
||||||
token_list += f"- **{symbol}** ({name}): `{addr}` - MC: {mc_str} - 24h: {price_change}%\n"
|
name = t.get("name", "")
|
||||||
return {
|
price_change = t.get("token_price_change_24h", "N/A")
|
||||||
"response": f"📈 **Trending Tokens on BSC:**\n\n{token_list}\nWould you like me to set up a strategy for any of these?",
|
mc = t.get("market_cap", "N/A")
|
||||||
"thinking": None,
|
try:
|
||||||
"strategy_updated": False,
|
mc_str = f"${float(mc):,.0f}"
|
||||||
"strategy_needs_confirmation": False,
|
except (ValueError, TypeError):
|
||||||
"success": True,
|
mc_str = str(mc)
|
||||||
}
|
token_list += f"- **{symbol}** ({name}): `{addr}` - MC: {mc_str} - 24h: {price_change}%\n"
|
||||||
else:
|
|
||||||
return {
|
|
||||||
"response": "No trending tokens found on BSC right now. Try again later!",
|
|
||||||
"thinking": None,
|
|
||||||
"strategy_updated": False,
|
|
||||||
"strategy_needs_confirmation": False,
|
|
||||||
"success": True,
|
|
||||||
}
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
return {
|
return {
|
||||||
"response": f"Failed to parse trending data: {output[:200]}",
|
"response": f"📈 **Trending Tokens on BSC:**\n\n{token_list}\nWould you like me to set up a strategy for any of these?",
|
||||||
"thinking": None,
|
"thinking": None,
|
||||||
"strategy_updated": False,
|
"strategy_updated": False,
|
||||||
"strategy_needs_confirmation": False,
|
"strategy_needs_confirmation": False,
|
||||||
"success": True,
|
"success": True,
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
|
return {
|
||||||
|
"response": "No trending tokens found on BSC right now. Try again later!",
|
||||||
|
"thinking": None,
|
||||||
|
"strategy_updated": False,
|
||||||
|
"strategy_needs_confirmation": False,
|
||||||
|
"success": True,
|
||||||
|
}
|
||||||
|
except json.JSONDecodeError:
|
||||||
return {
|
return {
|
||||||
"response": f"Failed to get trending tokens: {output}",
|
"response": f"Failed to parse trending data: {output[:200]}",
|
||||||
"thinking": None,
|
"thinking": None,
|
||||||
"strategy_updated": False,
|
"strategy_updated": False,
|
||||||
"strategy_needs_confirmation": False,
|
"strategy_needs_confirmation": False,
|
||||||
@@ -733,54 +741,53 @@ class ConversationalAgent:
|
|||||||
"search",
|
"search",
|
||||||
["--keyword", keyword.strip(), "--chain", "bsc", "--limit", "10"],
|
["--keyword", keyword.strip(), "--chain", "bsc", "--limit", "10"],
|
||||||
)
|
)
|
||||||
if code == 0:
|
if self._is_error_output(code, output):
|
||||||
try:
|
return {
|
||||||
data = json.loads(output)
|
"response": f"Failed to search tokens: {output}",
|
||||||
# Handle both dict with 'tokens' key and direct list
|
"thinking": None,
|
||||||
data_field = data.get("data", [])
|
"strategy_updated": False,
|
||||||
if isinstance(data_field, list):
|
"strategy_needs_confirmation": False,
|
||||||
tokens = data_field
|
"success": True,
|
||||||
else:
|
}
|
||||||
tokens = data_field.get("tokens", [])
|
try:
|
||||||
if tokens:
|
data = json.loads(output)
|
||||||
token_list = ""
|
# Handle both dict with 'tokens' key and direct list
|
||||||
for t in tokens[:10]:
|
data_field = data.get("data", [])
|
||||||
addr = t.get("token", "")
|
if isinstance(data_field, list):
|
||||||
symbol = t.get("symbol", "")
|
tokens = data_field
|
||||||
name = t.get("name", "")
|
else:
|
||||||
price_change = t.get("token_price_change_24h", "N/A")
|
tokens = data_field.get("tokens", [])
|
||||||
mc = t.get("market_cap", "N/A")
|
if tokens:
|
||||||
try:
|
token_list = ""
|
||||||
mc_str = f"${float(mc):,.0f}"
|
for t in tokens[:10]:
|
||||||
except (ValueError, TypeError):
|
addr = t.get("token", "")
|
||||||
mc_str = str(mc)
|
symbol = t.get("symbol", "")
|
||||||
token_list += f"- **{symbol}** ({name}): `{addr}` - MC: {mc_str} - 24h: {price_change}%\n"
|
name = t.get("name", "")
|
||||||
return {
|
price_change = t.get("token_price_change_24h", "N/A")
|
||||||
"response": f"🔍 **Search Results for '{keyword}':**\n\n{token_list}\nWould you like me to set up a strategy for any of these?",
|
mc = t.get("market_cap", "N/A")
|
||||||
"thinking": None,
|
try:
|
||||||
"strategy_updated": False,
|
mc_str = f"${float(mc):,.0f}"
|
||||||
"strategy_needs_confirmation": False,
|
except (ValueError, TypeError):
|
||||||
"success": True,
|
mc_str = str(mc)
|
||||||
}
|
token_list += f"- **{symbol}** ({name}): `{addr}` - MC: {mc_str} - 24h: {price_change}%\n"
|
||||||
else:
|
|
||||||
return {
|
|
||||||
"response": f"No tokens found for '{keyword}'. Try a different keyword.",
|
|
||||||
"thinking": None,
|
|
||||||
"strategy_updated": False,
|
|
||||||
"strategy_needs_confirmation": False,
|
|
||||||
"success": True,
|
|
||||||
}
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
return {
|
return {
|
||||||
"response": f"Failed to parse search results: {output[:200]}",
|
"response": f"🔍 **Search Results for '{keyword}':**\n\n{token_list}\nWould you like me to set up a strategy for any of these?",
|
||||||
"thinking": None,
|
"thinking": None,
|
||||||
"strategy_updated": False,
|
"strategy_updated": False,
|
||||||
"strategy_needs_confirmation": False,
|
"strategy_needs_confirmation": False,
|
||||||
"success": True,
|
"success": True,
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
|
return {
|
||||||
|
"response": f"No tokens found for '{keyword}'. Try a different keyword.",
|
||||||
|
"thinking": None,
|
||||||
|
"strategy_updated": False,
|
||||||
|
"strategy_needs_confirmation": False,
|
||||||
|
"success": True,
|
||||||
|
}
|
||||||
|
except json.JSONDecodeError:
|
||||||
return {
|
return {
|
||||||
"response": f"Failed to search tokens: {output}",
|
"response": f"Failed to parse search results: {output[:200]}",
|
||||||
"thinking": None,
|
"thinking": None,
|
||||||
"strategy_updated": False,
|
"strategy_updated": False,
|
||||||
"strategy_needs_confirmation": False,
|
"strategy_needs_confirmation": False,
|
||||||
@@ -802,69 +809,68 @@ class ConversationalAgent:
|
|||||||
"risk",
|
"risk",
|
||||||
["--address", address.strip(), "--chain", "bsc"],
|
["--address", address.strip(), "--chain", "bsc"],
|
||||||
)
|
)
|
||||||
if code == 0:
|
if self._is_error_output(code, output):
|
||||||
try:
|
return {
|
||||||
data = json.loads(output)
|
"response": f"Failed to get risk data: {output}",
|
||||||
data_field = data.get("data")
|
"thinking": None,
|
||||||
risk_data = data_field if isinstance(data_field, dict) else {}
|
"strategy_updated": False,
|
||||||
if risk_data:
|
"strategy_needs_confirmation": False,
|
||||||
is_honeypot = risk_data.get("is_honeypot", "unknown")
|
"success": True,
|
||||||
buy_tax = risk_data.get("buy_tax", 0)
|
}
|
||||||
sell_tax = risk_data.get("sell_tax", 0)
|
try:
|
||||||
status = risk_data.get("status", "unknown")
|
data = json.loads(output)
|
||||||
# Convert is_honeypot to string
|
data_field = data.get("data")
|
||||||
if isinstance(is_honeypot, bool):
|
risk_data = data_field if isinstance(data_field, dict) else {}
|
||||||
is_honeypot_str = str(is_honeypot).lower()
|
if risk_data:
|
||||||
elif isinstance(is_honeypot, int):
|
is_honeypot = risk_data.get("is_honeypot", "unknown")
|
||||||
is_honeypot_str = "true" if is_honeypot == 1 else "false" if is_honeypot == 0 else "unknown"
|
buy_tax = risk_data.get("buy_tax", 0)
|
||||||
else:
|
sell_tax = risk_data.get("sell_tax", 0)
|
||||||
is_honeypot_str = str(is_honeypot).lower() if is_honeypot else "unknown"
|
status = risk_data.get("status", "unknown")
|
||||||
# Convert tax values
|
# Convert is_honeypot to string
|
||||||
try:
|
if isinstance(is_honeypot, bool):
|
||||||
buy_tax_val = float(buy_tax) if buy_tax not in (None, "N/A") else 0
|
is_honeypot_str = str(is_honeypot).lower()
|
||||||
except (ValueError, TypeError):
|
elif isinstance(is_honeypot, int):
|
||||||
buy_tax_val = 0
|
is_honeypot_str = "true" if is_honeypot == 1 else "false" if is_honeypot == 0 else "unknown"
|
||||||
try:
|
|
||||||
sell_tax_val = float(sell_tax) if sell_tax not in (None, "N/A") else 0
|
|
||||||
except (ValueError, TypeError):
|
|
||||||
sell_tax_val = 0
|
|
||||||
risk_text = f"🛡️ **Risk Analysis for `{address}`**\n\n"
|
|
||||||
risk_text += f"- Status: {status}\n"
|
|
||||||
risk_text += f"- Honeypot: {is_honeypot_str}\n"
|
|
||||||
risk_text += f"- Buy Tax: {buy_tax}%\n"
|
|
||||||
risk_text += f"- Sell Tax: {sell_tax}%\n"
|
|
||||||
if is_honeypot_str == "true":
|
|
||||||
risk_text += "\n⚠️ **Warning: This token appears to be a honeypot. Do not buy!**"
|
|
||||||
elif buy_tax_val > 10 or sell_tax_val > 10:
|
|
||||||
risk_text += "\n⚠️ **Warning: High tax detected. Trade with caution!**"
|
|
||||||
else:
|
|
||||||
risk_text += "\n✅ This token appears safe to trade."
|
|
||||||
return {
|
|
||||||
"response": risk_text,
|
|
||||||
"thinking": None,
|
|
||||||
"strategy_updated": False,
|
|
||||||
"strategy_needs_confirmation": False,
|
|
||||||
"success": True,
|
|
||||||
}
|
|
||||||
else:
|
else:
|
||||||
return {
|
is_honeypot_str = str(is_honeypot).lower() if is_honeypot else "unknown"
|
||||||
"response": f"No risk data available for `{address}`",
|
# Convert tax values
|
||||||
"thinking": None,
|
try:
|
||||||
"strategy_updated": False,
|
buy_tax_val = float(buy_tax) if buy_tax not in (None, "N/A") else 0
|
||||||
"strategy_needs_confirmation": False,
|
except (ValueError, TypeError):
|
||||||
"success": True,
|
buy_tax_val = 0
|
||||||
}
|
try:
|
||||||
except json.JSONDecodeError:
|
sell_tax_val = float(sell_tax) if sell_tax not in (None, "N/A") else 0
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
sell_tax_val = 0
|
||||||
|
risk_text = f"🛡️ **Risk Analysis for `{address}`**\n\n"
|
||||||
|
risk_text += f"- Status: {status}\n"
|
||||||
|
risk_text += f"- Honeypot: {is_honeypot_str}\n"
|
||||||
|
risk_text += f"- Buy Tax: {buy_tax}%\n"
|
||||||
|
risk_text += f"- Sell Tax: {sell_tax}%\n"
|
||||||
|
if is_honeypot_str == "true":
|
||||||
|
risk_text += "\n⚠️ **Warning: This token appears to be a honeypot. Do not buy!**"
|
||||||
|
elif buy_tax_val > 10 or sell_tax_val > 10:
|
||||||
|
risk_text += "\n⚠️ **Warning: High tax detected. Trade with caution!**"
|
||||||
|
else:
|
||||||
|
risk_text += "\n✅ This token appears safe to trade."
|
||||||
return {
|
return {
|
||||||
"response": f"Failed to parse risk data: {output[:200]}",
|
"response": risk_text,
|
||||||
"thinking": None,
|
"thinking": None,
|
||||||
"strategy_updated": False,
|
"strategy_updated": False,
|
||||||
"strategy_needs_confirmation": False,
|
"strategy_needs_confirmation": False,
|
||||||
"success": True,
|
"success": True,
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
|
return {
|
||||||
|
"response": f"No risk data available for `{address}`",
|
||||||
|
"thinking": None,
|
||||||
|
"strategy_updated": False,
|
||||||
|
"strategy_needs_confirmation": False,
|
||||||
|
"success": True,
|
||||||
|
}
|
||||||
|
except json.JSONDecodeError:
|
||||||
return {
|
return {
|
||||||
"response": f"Failed to get risk data: {output}",
|
"response": f"Failed to parse risk data: {output[:200]}",
|
||||||
"thinking": None,
|
"thinking": None,
|
||||||
"strategy_updated": False,
|
"strategy_updated": False,
|
||||||
"strategy_needs_confirmation": False,
|
"strategy_needs_confirmation": False,
|
||||||
@@ -994,44 +1000,43 @@ class ConversationalAgent:
|
|||||||
"price",
|
"price",
|
||||||
["--tokens"] + tokens_list,
|
["--tokens"] + tokens_list,
|
||||||
)
|
)
|
||||||
if code == 0:
|
if self._is_error_output(code, output):
|
||||||
try:
|
return {
|
||||||
data = json.loads(output)
|
"response": f"Failed to get prices: {output}",
|
||||||
prices = data.get("data", {})
|
"thinking": None,
|
||||||
if not isinstance(prices, dict):
|
"strategy_updated": False,
|
||||||
prices = {}
|
"strategy_needs_confirmation": False,
|
||||||
if prices:
|
"success": True,
|
||||||
price_text = "💰 **Token Prices:**\n"
|
}
|
||||||
for token_id, price_data in prices.items():
|
try:
|
||||||
price = price_data.get("price", "N/A") if isinstance(price_data, dict) else "N/A"
|
data = json.loads(output)
|
||||||
change_24h = price_data.get("token_price_change_24h", "N/A") if isinstance(price_data, dict) else "N/A"
|
prices = data.get("data", {})
|
||||||
price_text += f"- {token_id}: ${price} (24h: {change_24h}%)\n"
|
if not isinstance(prices, dict):
|
||||||
return {
|
prices = {}
|
||||||
"response": price_text,
|
if prices:
|
||||||
"thinking": None,
|
price_text = "💰 **Token Prices:**\n"
|
||||||
"strategy_updated": False,
|
for token_id, price_data in prices.items():
|
||||||
"strategy_needs_confirmation": False,
|
price = price_data.get("price", "N/A") if isinstance(price_data, dict) else "N/A"
|
||||||
"success": True,
|
change_24h = price_data.get("token_price_change_24h", "N/A") if isinstance(price_data, dict) else "N/A"
|
||||||
}
|
price_text += f"- {token_id}: ${price} (24h: {change_24h}%)\n"
|
||||||
else:
|
|
||||||
return {
|
|
||||||
"response": "No price data available.",
|
|
||||||
"thinking": None,
|
|
||||||
"strategy_updated": False,
|
|
||||||
"strategy_needs_confirmation": False,
|
|
||||||
"success": True,
|
|
||||||
}
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
return {
|
return {
|
||||||
"response": f"Failed to parse price data: {output[:200]}",
|
"response": price_text,
|
||||||
"thinking": None,
|
"thinking": None,
|
||||||
"strategy_updated": False,
|
"strategy_updated": False,
|
||||||
"strategy_needs_confirmation": False,
|
"strategy_needs_confirmation": False,
|
||||||
"success": True,
|
"success": True,
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
|
return {
|
||||||
|
"response": "No price data available.",
|
||||||
|
"thinking": None,
|
||||||
|
"strategy_updated": False,
|
||||||
|
"strategy_needs_confirmation": False,
|
||||||
|
"success": True,
|
||||||
|
}
|
||||||
|
except json.JSONDecodeError:
|
||||||
return {
|
return {
|
||||||
"response": f"Failed to get prices: {output}",
|
"response": f"Failed to parse price data: {output[:200]}",
|
||||||
"thinking": None,
|
"thinking": None,
|
||||||
"strategy_updated": False,
|
"strategy_updated": False,
|
||||||
"strategy_needs_confirmation": False,
|
"strategy_needs_confirmation": False,
|
||||||
|
|||||||
Reference in New Issue
Block a user