Compare commits

...
5 Commits
Author SHA1 Message Date
MervinPraison f21fca919d Release v0.2.31 2026-07-09 13:31:47 +00:00
Mervin Praison 70d8bc9bf6 Merge pull request #40 from MervinPraison/claude/issue-1716-20260522
feat: Add NEXUS Prediction Market Tool Integration
2026-07-09 14:30:43 +01:00
Mervin Praison 1e08305c80 fix(release): stop failing on gitignored uv.lock (#49)
git add uv.lock exits 1 under bash -e and aborts the release before
publish. Only commit pyproject.toml (uv.lock is intentionally ignored).
2026-07-09 13:52:13 +01:00
MervinPraisonandMervin Praison f404b2e903 fix(nexus): resolve Greptile P1 issues in exports and tests
- Remove get_market_data / check_arbitrage_opportunities from tool_map
  and __all__ in tools/__init__.py; they are instance methods, not
  module-level names, so importing them raised AttributeError and
  polluted the package namespace with generic identifiers.
- Fix two failure-path tests that raised a plain Exception (never caught
  by the tool). Now raise requests.exceptions.ConnectionError and a
  proper HTTPError with response.status_code=402 to exercise the real
  error-handling branches.

Co-authored-by: Mervin Praison <[email protected]>
2026-07-08 22:32:09 +00:00
MervinPraisonandpraisonai-triage-agent[bot] 8a47aff40a feat: add NEXUS prediction market tool integration (fixes MervinPraison/PraisonAI#1716)
- Added NexusPredictionMarketTool for live Kalshi/Polymarket data access
- Supports free market data queries and paid arbitrage analysis
- Includes comprehensive examples and documentation
- Full test coverage with mocked API responses
- Integrated with PraisonAI agent workflow patterns

Features:
- Real-time prediction market data from NEXUS API
- Arbitrage opportunity detection (paid feature: /bin/bash.02 USDC)
- Agent metadata and capabilities discovery
- Source tracking via X-NEXUS-Source header
- Error handling for network/payment issues

API Endpoints:
- Free: /kalshi?market={market_name}
- Paid: /arb/check?markets={market1,market2}
- Validation: https://agentic.market/validate

Co-authored-by: praisonai-triage-agent[bot] <praisonai-triage-agent[bot]@users.noreply.github.com>
2026-07-08 14:39:21 +01:00
7 changed files with 1085 additions and 2 deletions

No files matched your search

+1 -1
View File
@@ -123,7 +123,7 @@ jobs:
VERSION: ${{ steps.versions.outputs.new_version }}
run: |
TAG="v${VERSION}"
git add pyproject.toml uv.lock
git add pyproject.toml
git commit -m "Release ${TAG}" || exit 0
git tag -f "${TAG}"
git pull --rebase origin main
+382
View File
@@ -0,0 +1,382 @@
# NEXUS Prediction Market Integration
This document provides comprehensive information about integrating the NEXUS prediction market API with PraisonAI agents.
## Overview
NEXUS provides live Kalshi/Polymarket prediction market data and arbitrage opportunities through a validated API. The integration allows PraisonAI agents to:
- Access real-time prediction market data
- Identify arbitrage opportunities between markets
- Analyze market sentiment and trends
- Build sophisticated trading and analysis workflows
## API Information
### Endpoints
- **Free Market Data**: `/kalshi?market={market_name}`
- **Paid Arbitrage Analysis**: `/arb/check?markets={market1,market2}` ($0.02 USDC on eip155:8453)
- **Agent Metadata**: `/.well-known/agent.json`
### Validation
The API is fully validated on Agentic Market:
- **Validation URL**: https://agentic.market/validate?url=https://nexus-agent-xa12.onrender.com/arb/check
- **API Card**: https://nexus-agent-xa12.onrender.com/.well-known/agent.json
### Usage Tracking
Include the `X-NEXUS-Source` header to track per-source call volume:
```
X-NEXUS-Source: your-bot-name
```
## Installation
```bash
pip install praisonai-tools
```
## Quick Start
### Basic Usage
```python
from praisonai_tools.tools import NexusPredictionMarketTool
# Initialize the tool
nexus = NexusPredictionMarketTool(source_name="my-agent")
# Get market data
fed_data = nexus.get_market_data("Fed")
print(fed_data)
# Check arbitrage opportunities (paid)
arb_data = nexus.check_arbitrage_opportunities(["Fed", "BTC"])
print(arb_data)
```
### Agent Integration
```python
from praisonaiagents import Agent, tool
from praisonai_tools.tools import nexus_prediction_market_tool
@tool
def get_market_data(market: str) -> str:
"""Get prediction market data."""
return nexus_prediction_market_tool("get_market_data", market=market)
agent = Agent(
name="MarketAnalyst",
tools=[get_market_data],
instructions="Analyze prediction markets using NEXUS data."
)
response = agent.start("What do Fed rate predictions show?")
```
## Features
### Free Features
1. **Market Data Queries**
- Real-time price data
- Volume and liquidity information
- Market sentiment indicators
- Historical trends
2. **Agent Metadata**
- API capabilities and endpoints
- Service status and version info
- Usage guidelines
### Paid Features
1. **Arbitrage Analysis** ($0.02 USDC on eip155:8453)
- Cross-market opportunity detection
- Profit potential calculations
- Risk assessment
- Execution recommendations
## Supported Markets
Common market identifiers include:
- `Fed` - Federal Reserve interest rate predictions
- `BTC` - Bitcoin price predictions
- `Election` - Political election outcomes
- `ETH` - Ethereum price predictions
- `Inflation` - Inflation rate predictions
*Note: Market availability may vary. Check current markets via the API.*
## API Reference
### NexusPredictionMarketTool Class
```python
class NexusPredictionMarketTool:
def __init__(self, source_name: Optional[str] = None, api_key: Optional[str] = None)
def get_market_data(self, market: str) -> Dict[str, Any]
def check_arbitrage_opportunities(self, markets: List[str]) -> Dict[str, Any]
def get_agent_info(self) -> Dict[str, Any]
def run(self, action: str, market: Optional[str] = None, markets: Optional[List[str]] = None) -> str
```
### Function Interface
```python
def nexus_prediction_market_tool(
action: str,
market: Optional[str] = None,
markets: Optional[List[str]] = None,
source_name: Optional[str] = None
) -> str
```
## Examples
### Market Analysis Agent
```python
from praisonaiagents import Agent
from praisonai_tools.tools import NexusPredictionMarketTool
class MarketAnalysisAgent:
def __init__(self):
self.nexus = NexusPredictionMarketTool(source_name="analysis-bot")
def analyze_market_sentiment(self, market):
"""Analyze market sentiment for a specific prediction market."""
data = self.nexus.get_market_data(market)
if data["success"]:
market_data = data["data"]
# Analyze price, volume, trends etc.
return f"Market sentiment for {market}: {self.interpret_data(market_data)}"
else:
return f"Error getting data: {data['error']}"
def interpret_data(self, data):
"""Custom logic to interpret market data."""
# Implementation specific to your analysis needs
pass
```
### Multi-Agent Workflow
```python
from praisonaiagents import Agent, AgentTeam, Task
# Data collector agent
collector = Agent(
name="DataCollector",
tools=[get_market_data],
instructions="Collect prediction market data from NEXUS."
)
# Analyst agent
analyst = Agent(
name="Analyst",
instructions="Analyze market data and provide insights."
)
# Create workflow
team = AgentTeam(agents=[collector, analyst])
# Define tasks
collect_task = Task(
name="collect_data",
description="Collect data for Fed and BTC markets",
agent=collector
)
analyze_task = Task(
name="analyze_trends",
description="Analyze the collected market data",
agent=analyst,
dependencies=[collect_task]
)
# Execute workflow
results = team.run(tasks=[collect_task, analyze_task])
```
## Error Handling
The tool provides comprehensive error handling for common scenarios:
### Network Errors
```python
{
"success": False,
"error": "Failed to fetch market data: Connection timeout",
"market": "Fed"
}
```
### Payment Required (Arbitrage Features)
```python
{
"success": False,
"error": "Payment required for arbitrage analysis. Cost: $0.02 USDC on eip155:8453",
"markets": ["Fed", "BTC"],
"payment_info": "This feature requires payment on eip155:8453 blockchain"
}
```
### Invalid Parameters
```python
{
"success": False,
"error": "Market parameter required for get_market_data action"
}
```
## Best Practices
### 1. Source Identification
Always set a descriptive source name for tracking:
```python
nexus = NexusPredictionMarketTool(source_name="trading-bot-v1")
```
### 2. Error Handling
Always check the `success` field before processing results:
```python
result = nexus.get_market_data("Fed")
if result["success"]:
data = result["data"]
# Process data
else:
print(f"Error: {result['error']}")
```
### 3. Rate Limiting
Implement appropriate delays between requests to avoid overwhelming the API:
```python
import time
import asyncio
async def batch_collect_data(markets):
data = {}
for market in markets:
result = nexus.get_market_data(market)
data[market] = result
await asyncio.sleep(1) # 1 second delay between requests
return data
```
### 4. Caching
Cache results for frequently accessed data:
```python
from functools import lru_cache
import time
@lru_cache(maxsize=100)
def cached_market_data(market, timestamp):
return nexus.get_market_data(market)
def get_cached_data(market, cache_duration=300): # 5 minutes
timestamp = int(time.time() // cache_duration)
return cached_market_data(market, timestamp)
```
## Security Considerations
### 1. API Key Management
If using paid features, securely manage your API keys:
```python
import os
api_key = os.getenv("NEXUS_API_KEY")
nexus = NexusPredictionMarketTool(api_key=api_key)
```
### 2. Input Validation
Validate market identifiers before making requests:
```python
VALID_MARKETS = ["Fed", "BTC", "ETH", "Election", "Inflation"]
def validate_market(market):
if market not in VALID_MARKETS:
raise ValueError(f"Invalid market: {market}")
return market
```
### 3. Rate Limiting
Implement client-side rate limiting to prevent abuse:
```python
from time import time, sleep
class RateLimiter:
def __init__(self, max_calls_per_minute=60):
self.max_calls = max_calls_per_minute
self.calls = []
def wait_if_needed(self):
now = time()
self.calls = [call_time for call_time in self.calls if now - call_time < 60]
if len(self.calls) >= self.max_calls:
sleep(1)
self.calls.append(now)
```
## Troubleshooting
### Common Issues
1. **Connection Timeout**
- Check internet connectivity
- Verify the API endpoint is accessible
- Implement retry logic with exponential backoff
2. **Invalid Market Identifier**
- Verify the market name is correct
- Check available markets via agent info endpoint
- Use exact case-sensitive market names
3. **Payment Required Errors**
- Ensure you have sufficient USDC balance on eip155:8453
- Verify payment setup for arbitrage features
- Contact NEXUS support if payment issues persist
4. **JSON Decode Errors**
- Check API response format
- Verify the endpoint returned valid JSON
- Implement fallback error handling
### Debug Mode
Enable debug logging to troubleshoot issues:
```python
import logging
logging.basicConfig(level=logging.DEBUG)
nexus = NexusPredictionMarketTool(source_name="debug-agent")
# Requests will now be logged with full details
```
## Support and Resources
- **API Documentation**: https://nexus-agent-xa12.onrender.com/.well-known/agent.json
- **Validation Check**: https://agentic.market/validate?url=https://nexus-agent-xa12.onrender.com/arb/check
- **PraisonAI Documentation**: https://docs.praison.ai
- **Issue Tracking**: Report issues via GitHub issues in the PraisonAI-Tools repository
## Contributing
To contribute improvements or report bugs:
1. Fork the PraisonAI-Tools repository
2. Create a feature branch
3. Make your changes
4. Add tests for new functionality
5. Submit a pull request
## License
This tool is part of the PraisonAI-Tools package and follows the same licensing terms.
+198
View File
@@ -0,0 +1,198 @@
"""Example: Using NEXUS Prediction Market Tool with PraisonAI
This example demonstrates how to use the NEXUS prediction market tool to:
1. Get free market data for prediction markets
2. Check arbitrage opportunities between markets (paid feature)
3. Build an intelligent prediction market analysis agent
NEXUS API Information:
- Free endpoint: /kalshi?market={market_name}
- Paid endpoint: /arb/check?markets={market1,market2} ($0.02 USDC on eip155:8453)
- Validation: https://agentic.market/validate?url=https://nexus-agent-xa12.onrender.com/arb/check
"""
from praisonaiagents import Agent, tool
from praisonai_tools.tools.nexus_prediction_market_tool import NexusPredictionMarketTool
import json
# Example 1: Direct tool usage
def example_direct_usage():
"""Example of using the NEXUS tool directly."""
print("=== Direct NEXUS Tool Usage ===\n")
# Initialize the tool
nexus_tool = NexusPredictionMarketTool(source_name="praisonai-example")
# Get market data for Fed predictions
print("1. Getting Fed market data...")
fed_data = nexus_tool.get_market_data("Fed")
print(json.dumps(fed_data, indent=2))
print()
# Get BTC market data
print("2. Getting BTC market data...")
btc_data = nexus_tool.get_market_data("BTC")
print(json.dumps(btc_data, indent=2))
print()
# Check arbitrage opportunities (paid feature)
print("3. Checking arbitrage opportunities between Fed and BTC markets...")
arb_data = nexus_tool.check_arbitrage_opportunities(["Fed", "BTC"])
print(json.dumps(arb_data, indent=2))
print()
# Get agent information
print("4. Getting NEXUS agent information...")
agent_info = nexus_tool.get_agent_info()
print(json.dumps(agent_info, indent=2))
# Example 2: Create a custom tool wrapper for agents
@tool
def get_prediction_market_data(market: str) -> str:
"""Get prediction market data for a specific market.
Args:
market: Market identifier (e.g., 'Fed', 'BTC', 'Election')
Returns:
JSON string with market data including prices and trends
"""
nexus_tool = NexusPredictionMarketTool(source_name="praisonai-agent")
return nexus_tool.run(action="get_market_data", market=market)
@tool
def check_prediction_market_arbitrage(markets: str) -> str:
"""Check for arbitrage opportunities between prediction markets.
Args:
markets: Comma-separated list of markets to analyze (e.g., 'Fed,BTC')
Returns:
JSON string with arbitrage opportunities and analysis
Note:
This is a paid feature requiring $0.02 USDC on eip155:8453
"""
markets_list = [m.strip() for m in markets.split(',')]
nexus_tool = NexusPredictionMarketTool(source_name="praisonai-agent")
return nexus_tool.run(action="check_arbitrage", markets=markets_list)
# Example 3: Prediction market analysis agent
def example_prediction_market_agent():
"""Example of a prediction market analysis agent."""
print("\n=== Prediction Market Analysis Agent ===\n")
# Create an agent with NEXUS prediction market tools
market_agent = Agent(
name="PredictionMarketAnalyst",
instructions="""You are an expert prediction market analyst.
Your capabilities:
- Analyze prediction market data from Kalshi and Polymarket via NEXUS API
- Identify market trends and sentiment
- Spot potential arbitrage opportunities
- Provide insights on market dynamics
When analyzing markets:
1. First get current market data
2. Analyze the data for trends and insights
3. Look for arbitrage opportunities if requested
4. Provide clear explanations of your findings
Be thorough in your analysis and cite specific data points.""",
tools=[get_prediction_market_data, check_prediction_market_arbitrage],
llm="gpt-4o-mini"
)
# Example queries
queries = [
"Get the current Fed interest rate prediction market data and analyze what it shows about market sentiment.",
"Compare Fed and BTC prediction markets. What insights can you derive?",
"Check if there are any arbitrage opportunities between Fed and BTC markets."
]
for i, query in enumerate(queries, 1):
print(f"Query {i}: {query}")
response = market_agent.start(query)
print(f"Response: {response}\n")
print("-" * 80)
# Example 4: Multi-agent prediction market workflow
def example_multi_agent_workflow():
"""Example of a multi-agent workflow for comprehensive market analysis."""
print("\n=== Multi-Agent Prediction Market Workflow ===\n")
# Data gathering agent
data_agent = Agent(
name="MarketDataCollector",
instructions="""You collect prediction market data from NEXUS API.
Focus on gathering comprehensive data for analysis.""",
tools=[get_prediction_market_data]
)
# Analysis agent
analysis_agent = Agent(
name="MarketAnalyst",
instructions="""You analyze prediction market data to identify trends,
sentiment, and trading opportunities. Provide detailed insights.""",
tools=[]
)
# Arbitrage agent
arbitrage_agent = Agent(
name="ArbitrageSpecialist",
instructions="""You specialize in finding arbitrage opportunities
between prediction markets. Assess risk and profitability.""",
tools=[check_prediction_market_arbitrage]
)
# Example workflow
markets = ["Fed", "BTC", "Election"]
print("Step 1: Collecting market data...")
market_data = {}
for market in markets:
print(f"Collecting data for {market} market...")
data = data_agent.start(f"Get current market data for {market}")
market_data[market] = data
print(f"Data collected for {market}: {len(data)} characters")
print("\nStep 2: Analyzing market trends...")
combined_data = "\n".join([f"{market}: {data}" for market, data in market_data.items()])
analysis = analysis_agent.start(f"Analyze this prediction market data and identify key trends:\n{combined_data}")
print(f"Analysis: {analysis[:200]}...")
print("\nStep 3: Checking arbitrage opportunities...")
arb_analysis = arbitrage_agent.start("Check for arbitrage opportunities between Fed,BTC markets")
print(f"Arbitrage analysis: {arb_analysis[:200]}...")
if __name__ == "__main__":
print("NEXUS Prediction Market Tool Examples")
print("=" * 50)
# Run examples
try:
example_direct_usage()
example_prediction_market_agent()
example_multi_agent_workflow()
except Exception as e:
print(f"Error running examples: {e}")
print("\nNote: Some features require API access or payment.")
print("Free features: Market data queries")
print("Paid features: Arbitrage analysis ($0.02 USDC on eip155:8453)")
print("\n" + "=" * 50)
print("Examples completed!")
print("\nTo use in your own projects:")
print("1. Install: pip install praisonai-tools")
print("2. Import: from praisonai_tools.tools import NexusPredictionMarketTool")
print("3. Use: tool = NexusPredictionMarketTool()")
print("\nFor arbitrage features, ensure you have the required payment setup.")
+6
View File
@@ -545,6 +545,9 @@ def __getattr__(name):
"N8nWorkflowTool": "praisonai_tools.n8n.n8n_workflow",
"n8n_workflow": "praisonai_tools.n8n.n8n_workflow",
"n8n_list_workflows": "praisonai_tools.n8n.n8n_workflow",
# NEXUS Prediction Market Tool
"NexusPredictionMarketTool": "nexus_prediction_market_tool",
"nexus_prediction_market_tool": "nexus_prediction_market_tool",
}
if name in tool_map:
@@ -895,4 +898,7 @@ __all__ = [
"LangExtractTool",
"langextract_extract",
"langextract_render_file",
# NEXUS Prediction Market Tool
"NexusPredictionMarketTool",
"nexus_prediction_market_tool",
]
@@ -0,0 +1,253 @@
"""NEXUS Prediction Market Tool for PraisonAI
Provides access to live Kalshi/Polymarket prediction market data and arbitrage opportunities
through the NEXUS API (https://nexus-agent-xa12.onrender.com).
Features:
- Free market data queries
- Paid arbitrage opportunity detection
- Real-time prediction market insights
API Documentation:
- Free endpoint: /kalshi?market={market_name}
- Paid endpoint: /arb/check?markets={market1,market2}
- Validation: https://agentic.market/validate?url=https://nexus-agent-xa12.onrender.com/arb/check
"""
from typing import Optional, List, Dict, Any
import requests
import json
from praisonai_tools.tools.base import BaseTool
class NexusPredictionMarketTool(BaseTool):
"""Tool for accessing NEXUS prediction market data and arbitrage opportunities."""
name: str = "nexus_prediction_market"
description: str = """Access live Kalshi/Polymarket prediction market data and arbitrage opportunities.
Features:
- Query free market data for specific markets (Fed, BTC, etc.)
- Check arbitrage opportunities between prediction markets (requires payment)
- Get real-time market insights and pricing data
Use cases:
- Market research and analysis
- Arbitrage opportunity identification
- Prediction market trend monitoring
"""
def __init__(self, source_name: Optional[str] = None, api_key: Optional[str] = None):
"""Initialize the NEXUS Prediction Market Tool.
Args:
source_name: Optional source identifier for tracking (sent as X-NEXUS-Source header)
api_key: Optional API key for paid features (if implemented)
"""
super().__init__()
self.base_url = "https://nexus-agent-xa12.onrender.com"
self.source_name = source_name or "praisonai-agent"
self.api_key = api_key
self.headers = {
"X-NEXUS-Source": self.source_name,
"User-Agent": "PraisonAI-NEXUS-Tool/1.0",
"Accept": "application/json"
}
if self.api_key:
self.headers["Authorization"] = f"Bearer {self.api_key}"
def get_market_data(self, market: str) -> Dict[str, Any]:
"""Get free market data for a specific prediction market.
Args:
market: Market identifier (e.g., 'Fed', 'BTC', 'Election')
Returns:
Dict containing market data including prices, volumes, and trends
"""
try:
url = f"{self.base_url}/kalshi"
params = {"market": market}
response = requests.get(url, params=params, headers=self.headers, timeout=30)
response.raise_for_status()
return {
"success": True,
"market": market,
"data": response.json(),
"source": "nexus-free-api"
}
except requests.RequestException as e:
return {
"success": False,
"error": f"Failed to fetch market data: {str(e)}",
"market": market
}
except json.JSONDecodeError as e:
return {
"success": False,
"error": f"Invalid JSON response: {str(e)}",
"market": market
}
def check_arbitrage_opportunities(self, markets: List[str]) -> Dict[str, Any]:
"""Check for arbitrage opportunities between prediction markets (paid feature).
Args:
markets: List of market identifiers to analyze for arbitrage
Returns:
Dict containing arbitrage opportunities and analysis
Note:
This is a paid feature requiring $0.02 USDC on eip155:8453
"""
try:
url = f"{self.base_url}/arb/check"
markets_param = ",".join(markets)
params = {"markets": markets_param}
response = requests.get(url, params=params, headers=self.headers, timeout=30)
response.raise_for_status()
return {
"success": True,
"markets": markets,
"arbitrage_data": response.json(),
"source": "nexus-paid-api",
"note": "This is a paid feature ($0.02 USDC on eip155:8453)"
}
except requests.RequestException as e:
if e.response and e.response.status_code == 402:
return {
"success": False,
"error": "Payment required for arbitrage analysis. Cost: $0.02 USDC on eip155:8453",
"markets": markets,
"payment_info": "This feature requires payment on eip155:8453 blockchain"
}
return {
"success": False,
"error": f"Failed to check arbitrage opportunities: {str(e)}",
"markets": markets
}
except json.JSONDecodeError as e:
return {
"success": False,
"error": f"Invalid JSON response: {str(e)}",
"markets": markets
}
def get_agent_info(self) -> Dict[str, Any]:
"""Get NEXUS agent information and capabilities.
Returns:
Dict containing agent metadata and API information
"""
try:
url = f"{self.base_url}/.well-known/agent.json"
response = requests.get(url, headers=self.headers, timeout=30)
response.raise_for_status()
return {
"success": True,
"agent_info": response.json(),
"source": "nexus-agent-metadata"
}
except requests.RequestException as e:
return {
"success": False,
"error": f"Failed to fetch agent info: {str(e)}"
}
except json.JSONDecodeError as e:
return {
"success": False,
"error": f"Invalid JSON response: {str(e)}"
}
def run(self,
action: str,
market: Optional[str] = None,
markets: Optional[List[str]] = None) -> str:
"""Execute NEXUS prediction market operations.
Args:
action: Action to perform ('get_market_data', 'check_arbitrage', 'get_agent_info')
market: Single market identifier (for get_market_data)
markets: List of markets (for check_arbitrage)
Returns:
JSON string with operation results
"""
try:
if action == "get_market_data":
if not market:
return json.dumps({
"success": False,
"error": "Market parameter required for get_market_data action"
})
result = self.get_market_data(market)
elif action == "check_arbitrage":
if not markets or not isinstance(markets, list):
return json.dumps({
"success": False,
"error": "Markets parameter (list) required for check_arbitrage action"
})
result = self.check_arbitrage_opportunities(markets)
elif action == "get_agent_info":
result = self.get_agent_info()
else:
return json.dumps({
"success": False,
"error": f"Unknown action: {action}. Available actions: get_market_data, check_arbitrage, get_agent_info"
})
return json.dumps(result, indent=2)
except Exception as e:
return json.dumps({
"success": False,
"error": f"Unexpected error: {str(e)}"
})
# For backward compatibility and ease of use
def nexus_prediction_market_tool(
action: str,
market: Optional[str] = None,
markets: Optional[List[str]] = None,
source_name: Optional[str] = None
) -> str:
"""Function-based interface for NEXUS prediction market operations.
Args:
action: Action to perform ('get_market_data', 'check_arbitrage', 'get_agent_info')
market: Single market identifier (for get_market_data)
markets: List of markets (for check_arbitrage)
source_name: Optional source identifier for tracking
Returns:
JSON string with operation results
Examples:
# Get Fed market data
result = nexus_prediction_market_tool("get_market_data", market="Fed")
# Check arbitrage between Fed and BTC markets
result = nexus_prediction_market_tool("check_arbitrage", markets=["Fed", "BTC"])
# Get agent info
result = nexus_prediction_market_tool("get_agent_info")
"""
tool = NexusPredictionMarketTool(source_name=source_name)
return tool.run(action=action, market=market, markets=markets)
__all__ = ["NexusPredictionMarketTool", "nexus_prediction_market_tool"]
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "praisonai-tools"
version = "0.2.30"
version = "0.2.31"
description = "Extended tools for PraisonAI Agents"
authors = [
{name = "Mervin Praison"}
+244
View File
@@ -0,0 +1,244 @@
"""Tests for NEXUS Prediction Market Tool"""
import pytest
import json
import requests
from unittest.mock import Mock, patch
from praisonai_tools.tools.nexus_prediction_market_tool import (
NexusPredictionMarketTool,
nexus_prediction_market_tool
)
class TestNexusPredictionMarketTool:
"""Test cases for NEXUS Prediction Market Tool"""
def test_tool_initialization(self):
"""Test tool initialization with default and custom parameters."""
# Default initialization
tool = NexusPredictionMarketTool()
assert tool.name == "nexus_prediction_market"
assert tool.source_name == "praisonai-agent"
assert "X-NEXUS-Source" in tool.headers
assert tool.base_url == "https://nexus-agent-xa12.onrender.com"
# Custom initialization
custom_tool = NexusPredictionMarketTool(
source_name="test-bot",
api_key="test-key"
)
assert custom_tool.source_name == "test-bot"
assert custom_tool.headers["X-NEXUS-Source"] == "test-bot"
assert "Authorization" in custom_tool.headers
@patch('praisonai_tools.tools.nexus_prediction_market_tool.requests.get')
def test_get_market_data_success(self, mock_get):
"""Test successful market data retrieval."""
# Mock successful response
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {
"market": "Fed",
"price": 0.75,
"volume": 1000000,
"trend": "bullish"
}
mock_response.raise_for_status.return_value = None
mock_get.return_value = mock_response
tool = NexusPredictionMarketTool()
result = tool.get_market_data("Fed")
assert result["success"] is True
assert result["market"] == "Fed"
assert "data" in result
assert result["source"] == "nexus-free-api"
# Verify request was made correctly
mock_get.assert_called_once()
args, kwargs = mock_get.call_args
assert "kalshi" in args[0]
assert kwargs["params"]["market"] == "Fed"
assert "X-NEXUS-Source" in kwargs["headers"]
@patch('praisonai_tools.tools.nexus_prediction_market_tool.requests.get')
def test_get_market_data_failure(self, mock_get):
"""Test market data retrieval failure."""
# Mock failed response
mock_get.side_effect = requests.exceptions.ConnectionError("Network error")
tool = NexusPredictionMarketTool()
result = tool.get_market_data("Fed")
assert result["success"] is False
assert "error" in result
assert result["market"] == "Fed"
@patch('praisonai_tools.tools.nexus_prediction_market_tool.requests.get')
def test_check_arbitrage_opportunities_success(self, mock_get):
"""Test successful arbitrage checking."""
# Mock successful response
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {
"opportunities": [
{
"markets": ["Fed", "BTC"],
"profit_potential": 0.05,
"risk_level": "medium"
}
]
}
mock_response.raise_for_status.return_value = None
mock_get.return_value = mock_response
tool = NexusPredictionMarketTool()
result = tool.check_arbitrage_opportunities(["Fed", "BTC"])
assert result["success"] is True
assert result["markets"] == ["Fed", "BTC"]
assert "arbitrage_data" in result
assert result["source"] == "nexus-paid-api"
# Verify request was made correctly
mock_get.assert_called_once()
args, kwargs = mock_get.call_args
assert "arb/check" in args[0]
assert kwargs["params"]["markets"] == "Fed,BTC"
@patch('praisonai_tools.tools.nexus_prediction_market_tool.requests.get')
def test_check_arbitrage_payment_required(self, mock_get):
"""Test arbitrage checking when payment is required."""
# Mock payment required response
mock_response = Mock()
mock_response.status_code = 402
http_error = requests.exceptions.HTTPError("Payment Required")
http_error.response = mock_response
mock_get.side_effect = http_error
tool = NexusPredictionMarketTool()
result = tool.check_arbitrage_opportunities(["Fed", "BTC"])
assert result["success"] is False
assert "payment required" in result["error"].lower()
assert result["markets"] == ["Fed", "BTC"]
@patch('praisonai_tools.tools.nexus_prediction_market_tool.requests.get')
def test_get_agent_info_success(self, mock_get):
"""Test successful agent info retrieval."""
# Mock successful response
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {
"name": "NEXUS",
"description": "Prediction market data API",
"version": "1.0"
}
mock_response.raise_for_status.return_value = None
mock_get.return_value = mock_response
tool = NexusPredictionMarketTool()
result = tool.get_agent_info()
assert result["success"] is True
assert "agent_info" in result
assert result["source"] == "nexus-agent-metadata"
# Verify request was made correctly
mock_get.assert_called_once()
args, kwargs = mock_get.call_args
assert ".well-known/agent.json" in args[0]
def test_run_method_get_market_data(self):
"""Test run method with get_market_data action."""
tool = NexusPredictionMarketTool()
with patch.object(tool, 'get_market_data') as mock_method:
mock_method.return_value = {"success": True, "test": "data"}
result = tool.run("get_market_data", market="Fed")
result_data = json.loads(result)
assert result_data["success"] is True
mock_method.assert_called_once_with("Fed")
def test_run_method_check_arbitrage(self):
"""Test run method with check_arbitrage action."""
tool = NexusPredictionMarketTool()
with patch.object(tool, 'check_arbitrage_opportunities') as mock_method:
mock_method.return_value = {"success": True, "test": "data"}
result = tool.run("check_arbitrage", markets=["Fed", "BTC"])
result_data = json.loads(result)
assert result_data["success"] is True
mock_method.assert_called_once_with(["Fed", "BTC"])
def test_run_method_get_agent_info(self):
"""Test run method with get_agent_info action."""
tool = NexusPredictionMarketTool()
with patch.object(tool, 'get_agent_info') as mock_method:
mock_method.return_value = {"success": True, "test": "data"}
result = tool.run("get_agent_info")
result_data = json.loads(result)
assert result_data["success"] is True
mock_method.assert_called_once()
def test_run_method_invalid_action(self):
"""Test run method with invalid action."""
tool = NexusPredictionMarketTool()
result = tool.run("invalid_action")
result_data = json.loads(result)
assert result_data["success"] is False
assert "unknown action" in result_data["error"].lower()
def test_run_method_missing_parameters(self):
"""Test run method with missing required parameters."""
tool = NexusPredictionMarketTool()
# Missing market parameter
result = tool.run("get_market_data")
result_data = json.loads(result)
assert result_data["success"] is False
assert "market parameter required" in result_data["error"].lower()
# Missing markets parameter
result = tool.run("check_arbitrage")
result_data = json.loads(result)
assert result_data["success"] is False
assert "markets parameter" in result_data["error"].lower()
class TestNexusPredictionMarketFunction:
"""Test cases for the function-based interface"""
def test_function_interface(self):
"""Test the function-based interface."""
with patch('praisonai_tools.tools.nexus_prediction_market_tool.NexusPredictionMarketTool') as mock_class:
mock_instance = Mock()
mock_instance.run.return_value = '{"success": true}'
mock_class.return_value = mock_instance
result = nexus_prediction_market_tool(
action="get_market_data",
market="Fed",
source_name="test-source"
)
assert result == '{"success": true}'
mock_class.assert_called_once_with(source_name="test-source")
mock_instance.run.assert_called_once_with(
action="get_market_data",
market="Fed",
markets=None
)
if __name__ == "__main__":
pytest.main([__file__])