mirror of
https://github.com/MervinPraison/PraisonAI-Tools.git
synced 2026-11-13 05:01:37 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f21fca919d | ||
|
|
70d8bc9bf6 | ||
|
|
1e08305c80 | ||
|
|
f404b2e903 | ||
|
|
8a47aff40a |
No files matched your search
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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.")
|
||||
@@ -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
@@ -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"}
|
||||
|
||||
@@ -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__])
|
||||
Reference in new issue
Block a user