feat(coordinator-api,docs): integrate developer platform and governance routers, complete phase 3 documentation
- Add developer_platform and governance_enhanced router imports to coordinator-api main.py - Include developer_platform and governance_enhanced routers with /v1 prefix - Refactor governance_service.py delegation logic to use delegatee_id directly and add logging - Remove redundant session.add() calls, rely on session.refresh() after commit - Update governance service docstring to reflect multi
This commit is contained in:
794
apps/coordinator-api/src/app/routers/developer_platform.py
Normal file
794
apps/coordinator-api/src/app/routers/developer_platform.py
Normal file
@@ -0,0 +1,794 @@
|
||||
"""
|
||||
Developer Platform API Router
|
||||
REST API endpoints for the developer ecosystem including bounties, certifications, and regional hubs
|
||||
"""
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Optional, Dict, Any
|
||||
from uuid import uuid4
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Depends, Query, BackgroundTasks
|
||||
from fastapi.responses import JSONResponse
|
||||
from sqlmodel import Session, select, func
|
||||
|
||||
from ..services.database import get_session
|
||||
from ..domain.developer_platform import (
|
||||
DeveloperProfile, DeveloperCertification, RegionalHub,
|
||||
BountyTask, BountySubmission, BountyStatus, CertificationLevel
|
||||
)
|
||||
from ..services.developer_platform_service import DeveloperPlatformService
|
||||
from ..schemas.developer_platform import (
|
||||
DeveloperCreate, BountyCreate, BountySubmissionCreate, CertificationGrant
|
||||
)
|
||||
from ..services.governance_service import GovernanceService
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/developer-platform",
|
||||
tags=["Developer Platform"]
|
||||
)
|
||||
|
||||
# Dependency injection
|
||||
def get_developer_platform_service(session: Session = Depends(get_session)) -> DeveloperPlatformService:
|
||||
return DeveloperPlatformService(session)
|
||||
|
||||
def get_governance_service(session: Session = Depends(get_session)) -> GovernanceService:
|
||||
return GovernanceService(session)
|
||||
|
||||
|
||||
# Developer Management Endpoints
|
||||
@router.post("/register", response_model=Dict[str, Any])
|
||||
async def register_developer(
|
||||
request: DeveloperCreate,
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Register a new developer profile"""
|
||||
|
||||
try:
|
||||
profile = await dev_service.register_developer(request)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"profile_id": profile.id,
|
||||
"wallet_address": profile.wallet_address,
|
||||
"reputation_score": profile.reputation_score,
|
||||
"created_at": profile.created_at.isoformat(),
|
||||
"message": "Developer profile registered successfully"
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error registering developer: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/profile/{wallet_address}", response_model=Dict[str, Any])
|
||||
async def get_developer_profile(
|
||||
wallet_address: str,
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get developer profile by wallet address"""
|
||||
|
||||
try:
|
||||
profile = await dev_service.get_developer_profile(wallet_address)
|
||||
if not profile:
|
||||
raise HTTPException(status_code=404, detail="Developer profile not found")
|
||||
|
||||
return {
|
||||
"id": profile.id,
|
||||
"wallet_address": profile.wallet_address,
|
||||
"github_handle": profile.github_handle,
|
||||
"email": profile.email,
|
||||
"reputation_score": profile.reputation_score,
|
||||
"total_earned_aitbc": profile.total_earned_aitbc,
|
||||
"skills": profile.skills,
|
||||
"is_active": profile.is_active,
|
||||
"created_at": profile.created_at.isoformat(),
|
||||
"updated_at": profile.updated_at.isoformat()
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting developer profile: {str(e)}")
|
||||
|
||||
|
||||
@router.put("/profile/{wallet_address}", response_model=Dict[str, Any])
|
||||
async def update_developer_profile(
|
||||
wallet_address: str,
|
||||
updates: Dict[str, Any],
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Update developer profile"""
|
||||
|
||||
try:
|
||||
profile = await dev_service.update_developer_profile(wallet_address, updates)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"profile_id": profile.id,
|
||||
"wallet_address": profile.wallet_address,
|
||||
"updated_at": profile.updated_at.isoformat(),
|
||||
"message": "Developer profile updated successfully"
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error updating developer profile: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/leaderboard", response_model=List[Dict[str, Any]])
|
||||
async def get_leaderboard(
|
||||
limit: int = Query(100, ge=1, le=500, description="Maximum number of developers"),
|
||||
offset: int = Query(0, ge=0, description="Offset for pagination"),
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Get developer leaderboard sorted by reputation score"""
|
||||
|
||||
try:
|
||||
developers = await dev_service.get_leaderboard(limit, offset)
|
||||
|
||||
return [
|
||||
{
|
||||
"rank": offset + i + 1,
|
||||
"id": dev.id,
|
||||
"wallet_address": dev.wallet_address,
|
||||
"github_handle": dev.github_handle,
|
||||
"reputation_score": dev.reputation_score,
|
||||
"total_earned_aitbc": dev.total_earned_aitbc,
|
||||
"skills_count": len(dev.skills),
|
||||
"created_at": dev.created_at.isoformat()
|
||||
}
|
||||
for i, dev in enumerate(developers)
|
||||
]
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting leaderboard: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/stats/{wallet_address}", response_model=Dict[str, Any])
|
||||
async def get_developer_stats(
|
||||
wallet_address: str,
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get comprehensive developer statistics"""
|
||||
|
||||
try:
|
||||
stats = await dev_service.get_developer_stats(wallet_address)
|
||||
return stats
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting developer stats: {str(e)}")
|
||||
|
||||
|
||||
# Bounty Management Endpoints
|
||||
@router.post("/bounties", response_model=Dict[str, Any])
|
||||
async def create_bounty(
|
||||
request: BountyCreate,
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Create a new bounty task"""
|
||||
|
||||
try:
|
||||
bounty = await dev_service.create_bounty(request)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"bounty_id": bounty.id,
|
||||
"title": bounty.title,
|
||||
"reward_amount": bounty.reward_amount,
|
||||
"difficulty_level": bounty.difficulty_level.value,
|
||||
"status": bounty.status.value,
|
||||
"created_at": bounty.created_at.isoformat(),
|
||||
"deadline": bounty.deadline.isoformat() if bounty.deadline else None,
|
||||
"message": "Bounty created successfully"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error creating bounty: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/bounties", response_model=List[Dict[str, Any]])
|
||||
async def list_bounties(
|
||||
status: Optional[BountyStatus] = Query(None, description="Filter by bounty status"),
|
||||
limit: int = Query(100, ge=1, le=500, description="Maximum number of bounties"),
|
||||
offset: int = Query(0, ge=0, description="Offset for pagination"),
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""List bounty tasks with optional status filter"""
|
||||
|
||||
try:
|
||||
bounties = await dev_service.list_bounties(status, limit, offset)
|
||||
|
||||
return [
|
||||
{
|
||||
"id": bounty.id,
|
||||
"title": bounty.title,
|
||||
"description": bounty.description[:200] + "..." if len(bounty.description) > 200 else bounty.description,
|
||||
"reward_amount": bounty.reward_amount,
|
||||
"difficulty_level": bounty.difficulty_level.value,
|
||||
"required_skills": bounty.required_skills,
|
||||
"status": bounty.status.value,
|
||||
"creator_address": bounty.creator_address,
|
||||
"created_at": bounty.created_at.isoformat(),
|
||||
"deadline": bounty.deadline.isoformat() if bounty.deadline else None
|
||||
}
|
||||
for bounty in bounties
|
||||
]
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error listing bounties: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/bounties/{bounty_id}", response_model=Dict[str, Any])
|
||||
async def get_bounty_details(
|
||||
bounty_id: str,
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get detailed bounty information"""
|
||||
|
||||
try:
|
||||
bounty_details = await dev_service.get_bounty_details(bounty_id)
|
||||
return bounty_details
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting bounty details: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/bounties/{bounty_id}/submit", response_model=Dict[str, Any])
|
||||
async def submit_bounty_solution(
|
||||
bounty_id: str,
|
||||
request: BountySubmissionCreate,
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Submit a solution for a bounty"""
|
||||
|
||||
try:
|
||||
submission = await dev_service.submit_bounty(bounty_id, request)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"submission_id": submission.id,
|
||||
"bounty_id": bounty_id,
|
||||
"developer_id": request.developer_id,
|
||||
"github_pr_url": submission.github_pr_url,
|
||||
"submitted_at": submission.submitted_at.isoformat(),
|
||||
"status": "submitted",
|
||||
"message": "Bounty solution submitted successfully"
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error submitting bounty solution: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/bounties/my-submissions", response_model=List[Dict[str, Any]])
|
||||
async def get_my_submissions(
|
||||
developer_id: str,
|
||||
limit: int = Query(100, ge=1, le=500, description="Maximum number of submissions"),
|
||||
offset: int = Query(0, ge=0, description="Offset for pagination"),
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Get all submissions by a developer"""
|
||||
|
||||
try:
|
||||
submissions = await dev_service.get_my_submissions(developer_id)
|
||||
|
||||
return [
|
||||
{
|
||||
"id": sub.id,
|
||||
"bounty_id": sub.bounty_id,
|
||||
"bounty_title": sub.bounty.title,
|
||||
"reward_amount": sub.bounty.reward_amount,
|
||||
"github_pr_url": sub.github_pr_url,
|
||||
"submission_notes": sub.submission_notes,
|
||||
"is_approved": sub.is_approved,
|
||||
"review_notes": sub.review_notes,
|
||||
"submitted_at": sub.submitted_at.isoformat(),
|
||||
"reviewed_at": sub.reviewed_at.isoformat() if sub.reviewed_at else None
|
||||
}
|
||||
for sub in submissions[offset:offset + limit]
|
||||
]
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting submissions: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/bounties/{bounty_id}/review", response_model=Dict[str, Any])
|
||||
async def review_bounty_submission(
|
||||
submission_id: str,
|
||||
reviewer_address: str,
|
||||
review_notes: str,
|
||||
approved: bool = Query(True, description="Whether to approve the submission"),
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Review and approve/reject a bounty submission"""
|
||||
|
||||
try:
|
||||
if approved:
|
||||
submission = await dev_service.approve_submission(submission_id, reviewer_address, review_notes)
|
||||
else:
|
||||
# In a real implementation, would have a reject method
|
||||
raise HTTPException(status_code=400, detail="Rejection not implemented in this demo")
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"submission_id": submission.id,
|
||||
"bounty_id": submission.bounty_id,
|
||||
"developer_address": submission.developer.wallet_address,
|
||||
"reward_amount": submission.bounty.reward_amount,
|
||||
"is_approved": submission.is_approved,
|
||||
"tx_hash_reward": submission.tx_hash_reward,
|
||||
"reviewed_at": submission.reviewed_at.isoformat(),
|
||||
"message": "Submission approved and reward distributed"
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error reviewing submission: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/bounties/stats", response_model=Dict[str, Any])
|
||||
async def get_bounty_statistics(
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get comprehensive bounty statistics"""
|
||||
|
||||
try:
|
||||
stats = await dev_service.get_bounty_statistics()
|
||||
return stats
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting bounty statistics: {str(e)}")
|
||||
|
||||
|
||||
# Certification Management Endpoints
|
||||
@router.post("/certifications", response_model=Dict[str, Any])
|
||||
async def grant_certification(
|
||||
request: CertificationGrant,
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Grant a certification to a developer"""
|
||||
|
||||
try:
|
||||
certification = await dev_service.grant_certification(request)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"certification_id": certification.id,
|
||||
"developer_id": request.developer_id,
|
||||
"certification_name": request.certification_name,
|
||||
"level": request.level.value,
|
||||
"issued_by": request.issued_by,
|
||||
"ipfs_credential_cid": request.ipfs_credential_cid,
|
||||
"granted_at": certification.granted_at.isoformat(),
|
||||
"message": "Certification granted successfully"
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error granting certification: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/certifications/{wallet_address}", response_model=List[Dict[str, Any]])
|
||||
async def get_developer_certifications(
|
||||
wallet_address: str,
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Get certifications for a developer"""
|
||||
|
||||
try:
|
||||
profile = await dev_service.get_developer_profile(wallet_address)
|
||||
if not profile:
|
||||
raise HTTPException(status_code=404, detail="Developer profile not found")
|
||||
|
||||
certifications = session.exec(
|
||||
select(DeveloperCertification).where(DeveloperCertification.developer_id == profile.id)
|
||||
).all()
|
||||
|
||||
return [
|
||||
{
|
||||
"id": cert.id,
|
||||
"certification_name": cert.certification_name,
|
||||
"level": cert.level.value,
|
||||
"issued_by": cert.issued_by,
|
||||
"ipfs_credential_cid": cert.ipfs_credential_cid,
|
||||
"granted_at": cert.granted_at.isoformat(),
|
||||
"is_verified": True
|
||||
}
|
||||
for cert in certifications
|
||||
]
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting certifications: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/certifications/verify/{certification_id}", response_model=Dict[str, Any])
|
||||
async def verify_certification(
|
||||
certification_id: str,
|
||||
session: Session = Depends(get_session)
|
||||
) -> Dict[str, Any]:
|
||||
"""Verify a certification by ID"""
|
||||
|
||||
try:
|
||||
certification = session.get(DeveloperCertification, certification_id)
|
||||
if not certification:
|
||||
raise HTTPException(status_code=404, detail="Certification not found")
|
||||
|
||||
return {
|
||||
"certification_id": certification_id,
|
||||
"certification_name": certification.certification_name,
|
||||
"level": certification.level.value,
|
||||
"developer_id": certification.developer_id,
|
||||
"issued_by": certification.issued_by,
|
||||
"granted_at": certification.granted_at.isoformat(),
|
||||
"is_valid": True,
|
||||
"verification_timestamp": datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error verifying certification: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/certifications/types", response_model=List[Dict[str, Any]])
|
||||
async def get_certification_types() -> List[Dict[str, Any]]:
|
||||
"""Get available certification types"""
|
||||
|
||||
try:
|
||||
certification_types = [
|
||||
{
|
||||
"name": "Blockchain Development",
|
||||
"levels": [level.value for level in CertificationLevel],
|
||||
"description": "Blockchain and smart contract development skills",
|
||||
"skills_required": ["solidity", "web3", "defi"]
|
||||
},
|
||||
{
|
||||
"name": "AI/ML Development",
|
||||
"levels": [level.value for level in CertificationLevel],
|
||||
"description": "Artificial Intelligence and Machine Learning development",
|
||||
"skills_required": ["python", "tensorflow", "pytorch"]
|
||||
},
|
||||
{
|
||||
"name": "Full-Stack Development",
|
||||
"levels": [level.value for level in CertificationLevel],
|
||||
"description": "Complete web application development",
|
||||
"skills_required": ["javascript", "react", "nodejs"]
|
||||
},
|
||||
{
|
||||
"name": "DevOps Engineering",
|
||||
"levels": [level.value for level in CertificationLevel],
|
||||
"description": "Development operations and infrastructure",
|
||||
"skills_required": ["docker", "kubernetes", "ci-cd"]
|
||||
}
|
||||
]
|
||||
|
||||
return certification_types
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting certification types: {str(e)}")
|
||||
|
||||
|
||||
# Regional Hub Management Endpoints
|
||||
@router.post("/hubs", response_model=Dict[str, Any])
|
||||
async def create_regional_hub(
|
||||
name: str,
|
||||
region: str,
|
||||
description: str,
|
||||
manager_address: str,
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Create a regional developer hub"""
|
||||
|
||||
try:
|
||||
hub = await dev_service.create_regional_hub(name, region, description, manager_address)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"hub_id": hub.id,
|
||||
"name": hub.name,
|
||||
"region": hub.region,
|
||||
"description": hub.description,
|
||||
"manager_address": hub.manager_address,
|
||||
"is_active": hub.is_active,
|
||||
"created_at": hub.created_at.isoformat(),
|
||||
"message": "Regional hub created successfully"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error creating regional hub: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/hubs", response_model=List[Dict[str, Any]])
|
||||
async def get_regional_hubs(
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Get all regional developer hubs"""
|
||||
|
||||
try:
|
||||
hubs = await dev_service.get_regional_hubs()
|
||||
|
||||
return [
|
||||
{
|
||||
"id": hub.id,
|
||||
"name": hub.name,
|
||||
"region": hub.region,
|
||||
"description": hub.description,
|
||||
"manager_address": hub.manager_address,
|
||||
"developer_count": 0, # Would be calculated from hub membership
|
||||
"is_active": hub.is_active,
|
||||
"created_at": hub.created_at.isoformat()
|
||||
}
|
||||
for hub in hubs
|
||||
]
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting regional hubs: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/hubs/{hub_id}/developers", response_model=List[Dict[str, Any]])
|
||||
async def get_hub_developers(
|
||||
hub_id: str,
|
||||
limit: int = Query(100, ge=1, le=500, description="Maximum number of developers"),
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Get developers in a regional hub"""
|
||||
|
||||
try:
|
||||
developers = await dev_service.get_hub_developers(hub_id)
|
||||
|
||||
return [
|
||||
{
|
||||
"id": dev.id,
|
||||
"wallet_address": dev.wallet_address,
|
||||
"github_handle": dev.github_handle,
|
||||
"reputation_score": dev.reputation_score,
|
||||
"skills": dev.skills,
|
||||
"joined_at": dev.created_at.isoformat()
|
||||
}
|
||||
for dev in developers[:limit]
|
||||
]
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting hub developers: {str(e)}")
|
||||
|
||||
|
||||
# Staking & Rewards Endpoints
|
||||
@router.post("/stake", response_model=Dict[str, Any])
|
||||
async def stake_on_developer(
|
||||
staker_address: str,
|
||||
developer_address: str,
|
||||
amount: float,
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Stake AITBC tokens on a developer"""
|
||||
|
||||
try:
|
||||
staking_info = await dev_service.stake_on_developer(staker_address, developer_address, amount)
|
||||
|
||||
return staking_info
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error staking on developer: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/staking/{address}", response_model=Dict[str, Any])
|
||||
async def get_staking_info(
|
||||
address: str,
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get staking information for an address"""
|
||||
|
||||
try:
|
||||
staking_info = await dev_service.get_staking_info(address)
|
||||
return staking_info
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting staking info: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/unstake", response_model=Dict[str, Any])
|
||||
async def unstake_tokens(
|
||||
staking_id: str,
|
||||
amount: float,
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Unstake tokens from a developer"""
|
||||
|
||||
try:
|
||||
unstake_info = await dev_service.unstake_tokens(staking_id, amount)
|
||||
return unstake_info
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error unstaking tokens: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/rewards/{address}", response_model=Dict[str, Any])
|
||||
async def get_rewards(
|
||||
address: str,
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get reward information for an address"""
|
||||
|
||||
try:
|
||||
rewards = await dev_service.get_rewards(address)
|
||||
return rewards
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting rewards: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/claim-rewards", response_model=Dict[str, Any])
|
||||
async def claim_rewards(
|
||||
address: str,
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Claim pending rewards"""
|
||||
|
||||
try:
|
||||
claim_info = await dev_service.claim_rewards(address)
|
||||
return claim_info
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error claiming rewards: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/staking-stats", response_model=Dict[str, Any])
|
||||
async def get_staking_statistics(
|
||||
session: Session = Depends(get_session)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get comprehensive staking statistics"""
|
||||
|
||||
try:
|
||||
# Mock implementation - would query real staking data
|
||||
stats = {
|
||||
"total_staked_amount": 1000000.0,
|
||||
"active_stakers": 500,
|
||||
"active_developers_staked": 150,
|
||||
"average_apy": 7.5,
|
||||
"total_rewards_distributed": 50000.0,
|
||||
"staking_utilization": 65.0,
|
||||
"top_staked_developers": [
|
||||
{"address": "0x123...", "staked_amount": 50000.0, "apy": 12.5},
|
||||
{"address": "0x456...", "staked_amount": 35000.0, "apy": 10.0},
|
||||
{"address": "0x789...", "staked_amount": 25000.0, "apy": 8.5}
|
||||
]
|
||||
}
|
||||
|
||||
return stats
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting staking statistics: {str(e)}")
|
||||
|
||||
|
||||
# Platform Analytics Endpoints
|
||||
@router.get("/analytics/overview", response_model=Dict[str, Any])
|
||||
async def get_platform_overview(
|
||||
session: Session = Depends(get_session),
|
||||
dev_service: DeveloperPlatformService = Depends(get_developer_platform_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get platform overview analytics"""
|
||||
|
||||
try:
|
||||
# Get bounty statistics
|
||||
bounty_stats = await dev_service.get_bounty_statistics()
|
||||
|
||||
# Get developer statistics
|
||||
total_developers = session.exec(select(DeveloperProfile)).count()
|
||||
active_developers = session.exec(
|
||||
select(DeveloperProfile).where(DeveloperProfile.is_active == True)
|
||||
).count()
|
||||
|
||||
# Get certification statistics
|
||||
total_certifications = session.exec(select(DeveloperCertification)).count()
|
||||
|
||||
# Get regional hub statistics
|
||||
total_hubs = session.exec(select(RegionalHub)).count()
|
||||
|
||||
return {
|
||||
"developers": {
|
||||
"total": total_developers,
|
||||
"active": active_developers,
|
||||
"new_this_month": 25, # Mock data
|
||||
"average_reputation": 45.5
|
||||
},
|
||||
"bounties": bounty_stats,
|
||||
"certifications": {
|
||||
"total_granted": total_certifications,
|
||||
"new_this_month": 15, # Mock data
|
||||
"most_common_level": "intermediate"
|
||||
},
|
||||
"regional_hubs": {
|
||||
"total": total_hubs,
|
||||
"active": total_hubs, # Mock: all hubs are active
|
||||
"regions_covered": 12 # Mock data
|
||||
},
|
||||
"staking": {
|
||||
"total_staked": 1000000.0, # Mock data
|
||||
"active_stakers": 500,
|
||||
"average_apy": 7.5
|
||||
},
|
||||
"generated_at": datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting platform overview: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/health", response_model=Dict[str, Any])
|
||||
async def get_platform_health(
|
||||
session: Session = Depends(get_session)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get developer platform health status"""
|
||||
|
||||
try:
|
||||
# Check database connectivity
|
||||
try:
|
||||
developer_count = session.exec(select(func.count(DeveloperProfile.id))).scalar()
|
||||
database_status = "healthy"
|
||||
except Exception:
|
||||
database_status = "unhealthy"
|
||||
developer_count = 0
|
||||
|
||||
# Mock service health checks
|
||||
services_status = {
|
||||
"database": database_status,
|
||||
"blockchain": "healthy", # Would check actual blockchain connectivity
|
||||
"ipfs": "healthy", # Would check IPFS connectivity
|
||||
"smart_contracts": "healthy" # Would check smart contract deployment
|
||||
}
|
||||
|
||||
overall_status = "healthy" if all(status == "healthy" for status in services_status.values()) else "degraded"
|
||||
|
||||
return {
|
||||
"status": overall_status,
|
||||
"services": services_status,
|
||||
"metrics": {
|
||||
"total_developers": developer_count,
|
||||
"active_bounties": 25, # Mock data
|
||||
"pending_submissions": 8, # Mock data
|
||||
"system_uptime": "99.9%"
|
||||
},
|
||||
"last_updated": datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting platform health: {str(e)}")
|
||||
@@ -0,0 +1,664 @@
|
||||
"""
|
||||
Global Marketplace Integration API Router
|
||||
REST API endpoints for integrated global marketplace with cross-chain capabilities
|
||||
"""
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Optional, Dict, Any
|
||||
from uuid import uuid4
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Depends, Query, BackgroundTasks
|
||||
from fastapi.responses import JSONResponse
|
||||
from sqlmodel import Session, select, func, Field
|
||||
|
||||
from ..services.database import get_session
|
||||
from ..domain.global_marketplace import (
|
||||
GlobalMarketplaceOffer, GlobalMarketplaceTransaction, GlobalMarketplaceAnalytics,
|
||||
MarketplaceRegion, RegionStatus, MarketplaceStatus
|
||||
)
|
||||
from ..services.global_marketplace_integration import (
|
||||
GlobalMarketplaceIntegrationService, IntegrationStatus, CrossChainOfferStatus
|
||||
)
|
||||
from ..services.cross_chain_bridge_enhanced import BridgeProtocol
|
||||
from ..services.multi_chain_transaction_manager import TransactionPriority
|
||||
from ..agent_identity.manager import AgentIdentityManager
|
||||
from ..reputation.engine import CrossChainReputationEngine
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/global-marketplace-integration",
|
||||
tags=["Global Marketplace Integration"]
|
||||
)
|
||||
|
||||
# Dependency injection
|
||||
def get_integration_service(session: Session = Depends(get_session)) -> GlobalMarketplaceIntegrationService:
|
||||
return GlobalMarketplaceIntegrationService(session)
|
||||
|
||||
def get_agent_identity_manager(session: Session = Depends(get_session)) -> AgentIdentityManager:
|
||||
return AgentIdentityManager(session)
|
||||
|
||||
def get_reputation_engine(session: Session = Depends(get_session)) -> CrossChainReputationEngine:
|
||||
return CrossChainReputationEngine(session)
|
||||
|
||||
|
||||
# Cross-Chain Marketplace Offer Endpoints
|
||||
@router.post("/offers/create-cross-chain", response_model=Dict[str, Any])
|
||||
async def create_cross_chain_marketplace_offer(
|
||||
agent_id: str,
|
||||
service_type: str,
|
||||
resource_specification: Dict[str, Any],
|
||||
base_price: float,
|
||||
currency: str = "USD",
|
||||
total_capacity: int = 100,
|
||||
regions_available: Optional[List[str]] = None,
|
||||
supported_chains: Optional[List[int]] = None,
|
||||
cross_chain_pricing: Optional[Dict[int, float]] = None,
|
||||
auto_bridge_enabled: bool = True,
|
||||
reputation_threshold: float = 500.0,
|
||||
deadline_minutes: int = 60,
|
||||
session: Session = Depends(get_session),
|
||||
integration_service: GlobalMarketplaceIntegrationService = Depends(get_integration_service),
|
||||
identity_manager: AgentIdentityManager = Depends(get_agent_identity_manager)
|
||||
) -> Dict[str, Any]:
|
||||
"""Create a cross-chain enabled marketplace offer"""
|
||||
|
||||
try:
|
||||
# Validate agent identity
|
||||
identity = await identity_manager.get_identity(agent_id)
|
||||
if not identity:
|
||||
raise HTTPException(status_code=404, detail="Agent identity not found")
|
||||
|
||||
# Create cross-chain marketplace offer
|
||||
offer = await integration_service.create_cross_chain_marketplace_offer(
|
||||
agent_id=agent_id,
|
||||
service_type=service_type,
|
||||
resource_specification=resource_specification,
|
||||
base_price=base_price,
|
||||
currency=currency,
|
||||
total_capacity=total_capacity,
|
||||
regions_available=regions_available,
|
||||
supported_chains=supported_chains,
|
||||
cross_chain_pricing=cross_chain_pricing,
|
||||
auto_bridge_enabled=auto_bridge_enabled,
|
||||
reputation_threshold=reputation_threshold,
|
||||
deadline_minutes=deadline_minutes
|
||||
)
|
||||
|
||||
return offer
|
||||
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error creating cross-chain offer: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/offers/cross-chain", response_model=List[Dict[str, Any]])
|
||||
async def get_integrated_marketplace_offers(
|
||||
region: Optional[str] = Query(None, description="Filter by region"),
|
||||
service_type: Optional[str] = Query(None, description="Filter by service type"),
|
||||
chain_id: Optional[int] = Query(None, description="Filter by blockchain chain"),
|
||||
min_reputation: Optional[float] = Query(None, description="Minimum reputation score"),
|
||||
include_cross_chain: bool = Query(True, description="Include cross-chain information"),
|
||||
limit: int = Query(100, ge=1, le=500, description="Maximum number of offers"),
|
||||
offset: int = Query(0, ge=0, description="Offset for pagination"),
|
||||
session: Session = Depends(get_session),
|
||||
integration_service: GlobalMarketplaceIntegrationService = Depends(get_integration_service)
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Get integrated marketplace offers with cross-chain capabilities"""
|
||||
|
||||
try:
|
||||
offers = await integration_service.get_integrated_marketplace_offers(
|
||||
region=region,
|
||||
service_type=service_type,
|
||||
chain_id=chain_id,
|
||||
min_reputation=min_reputation,
|
||||
include_cross_chain=include_cross_chain,
|
||||
limit=limit,
|
||||
offset=offset
|
||||
)
|
||||
|
||||
return offers
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting integrated offers: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/offers/{offer_id}/cross-chain-details", response_model=Dict[str, Any])
|
||||
async def get_cross_chain_offer_details(
|
||||
offer_id: str,
|
||||
session: Session = Depends(get_session),
|
||||
integration_service: GlobalMarketplaceIntegrationService = Depends(get_integration_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get detailed cross-chain information for a specific offer"""
|
||||
|
||||
try:
|
||||
# Get the offer
|
||||
stmt = select(GlobalMarketplaceOffer).where(GlobalMarketplaceOffer.id == offer_id)
|
||||
offer = session.exec(stmt).first()
|
||||
|
||||
if not offer:
|
||||
raise HTTPException(status_code=404, detail="Offer not found")
|
||||
|
||||
# Get cross-chain availability
|
||||
cross_chain_availability = await integration_service._get_cross_chain_availability(offer)
|
||||
|
||||
return {
|
||||
"offer_id": offer.id,
|
||||
"agent_id": offer.agent_id,
|
||||
"service_type": offer.service_type,
|
||||
"resource_specification": offer.resource_specification,
|
||||
"base_price": offer.base_price,
|
||||
"currency": offer.currency,
|
||||
"price_per_region": offer.price_per_region,
|
||||
"cross_chain_pricing": offer.cross_chain_pricing,
|
||||
"total_capacity": offer.total_capacity,
|
||||
"available_capacity": offer.available_capacity,
|
||||
"regions_available": offer.regions_available,
|
||||
"supported_chains": offer.supported_chains,
|
||||
"global_status": offer.global_status,
|
||||
"global_rating": offer.global_rating,
|
||||
"total_transactions": offer.total_transactions,
|
||||
"success_rate": offer.success_rate,
|
||||
"cross_chain_availability": cross_chain_availability,
|
||||
"created_at": offer.created_at.isoformat(),
|
||||
"updated_at": offer.updated_at.isoformat()
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting cross-chain offer details: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/offers/{offer_id}/optimize-pricing", response_model=Dict[str, Any])
|
||||
async def optimize_offer_pricing(
|
||||
offer_id: str,
|
||||
optimization_strategy: str = Query("balanced", description="Pricing optimization strategy"),
|
||||
target_regions: Optional[List[str]] = Query(None, description="Target regions for optimization"),
|
||||
target_chains: Optional[List[int]] = Query(None, description="Target chains for optimization"),
|
||||
session: Session = Depends(get_session),
|
||||
integration_service: GlobalMarketplaceIntegrationService = Depends(get_integration_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Optimize pricing for a global marketplace offer"""
|
||||
|
||||
try:
|
||||
optimization = await integration_service.optimize_global_offer_pricing(
|
||||
offer_id=offer_id,
|
||||
optimization_strategy=optimization_strategy,
|
||||
target_regions=target_regions,
|
||||
target_chains=target_chains
|
||||
)
|
||||
|
||||
return optimization
|
||||
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error optimizing offer pricing: {str(e)}")
|
||||
|
||||
|
||||
# Cross-Chain Transaction Endpoints
|
||||
@router.post("/transactions/execute-cross-chain", response_model=Dict[str, Any])
|
||||
async def execute_cross_chain_transaction(
|
||||
buyer_id: str,
|
||||
offer_id: str,
|
||||
quantity: int,
|
||||
source_chain: Optional[int] = None,
|
||||
target_chain: Optional[int] = None,
|
||||
source_region: str = "global",
|
||||
target_region: str = "global",
|
||||
payment_method: str = "crypto",
|
||||
bridge_protocol: Optional[BridgeProtocol] = None,
|
||||
priority: TransactionPriority = TransactionPriority.MEDIUM,
|
||||
auto_execute_bridge: bool = True,
|
||||
session: Session = Depends(get_session),
|
||||
integration_service: GlobalMarketplaceIntegrationService = Depends(get_integration_service),
|
||||
identity_manager: AgentIdentityManager = Depends(get_agent_identity_manager)
|
||||
) -> Dict[str, Any]:
|
||||
"""Execute a cross-chain marketplace transaction"""
|
||||
|
||||
try:
|
||||
# Validate buyer identity
|
||||
identity = await identity_manager.get_identity(buyer_id)
|
||||
if not identity:
|
||||
raise HTTPException(status_code=404, detail="Buyer identity not found")
|
||||
|
||||
# Execute cross-chain transaction
|
||||
transaction = await integration_service.execute_cross_chain_transaction(
|
||||
buyer_id=buyer_id,
|
||||
offer_id=offer_id,
|
||||
quantity=quantity,
|
||||
source_chain=source_chain,
|
||||
target_chain=target_chain,
|
||||
source_region=source_region,
|
||||
target_region=target_region,
|
||||
payment_method=payment_method,
|
||||
bridge_protocol=bridge_protocol,
|
||||
priority=priority,
|
||||
auto_execute_bridge=auto_execute_bridge
|
||||
)
|
||||
|
||||
return transaction
|
||||
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error executing cross-chain transaction: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/transactions/cross-chain", response_model=List[Dict[str, Any]])
|
||||
async def get_cross_chain_transactions(
|
||||
buyer_id: Optional[str] = Query(None, description="Filter by buyer ID"),
|
||||
seller_id: Optional[str] = Query(None, description="Filter by seller ID"),
|
||||
source_chain: Optional[int] = Query(None, description="Filter by source chain"),
|
||||
target_chain: Optional[int] = Query(None, description="Filter by target chain"),
|
||||
status: Optional[str] = Query(None, description="Filter by transaction status"),
|
||||
limit: int = Query(100, ge=1, le=500, description="Maximum number of transactions"),
|
||||
offset: int = Query(0, ge=0, description="Offset for pagination"),
|
||||
session: Session = Depends(get_session),
|
||||
integration_service: GlobalMarketplaceIntegrationService = Depends(get_integration_service)
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Get cross-chain marketplace transactions"""
|
||||
|
||||
try:
|
||||
# Get global transactions with cross-chain filter
|
||||
transactions = await integration_service.marketplace_service.get_global_transactions(
|
||||
user_id=buyer_id or seller_id,
|
||||
status=status,
|
||||
limit=limit,
|
||||
offset=offset
|
||||
)
|
||||
|
||||
# Filter for cross-chain transactions
|
||||
cross_chain_transactions = []
|
||||
for tx in transactions:
|
||||
if tx.source_chain and tx.target_chain and tx.source_chain != tx.target_chain:
|
||||
if (not source_chain or tx.source_chain == source_chain) and \
|
||||
(not target_chain or tx.target_chain == target_chain):
|
||||
cross_chain_transactions.append({
|
||||
"id": tx.id,
|
||||
"buyer_id": tx.buyer_id,
|
||||
"seller_id": tx.seller_id,
|
||||
"offer_id": tx.offer_id,
|
||||
"service_type": tx.service_type,
|
||||
"quantity": tx.quantity,
|
||||
"unit_price": tx.unit_price,
|
||||
"total_amount": tx.total_amount,
|
||||
"currency": tx.currency,
|
||||
"source_chain": tx.source_chain,
|
||||
"target_chain": tx.target_chain,
|
||||
"cross_chain_fee": tx.cross_chain_fee,
|
||||
"bridge_transaction_id": tx.bridge_transaction_id,
|
||||
"source_region": tx.source_region,
|
||||
"target_region": tx.target_region,
|
||||
"status": tx.status,
|
||||
"payment_status": tx.payment_status,
|
||||
"delivery_status": tx.delivery_status,
|
||||
"created_at": tx.created_at.isoformat(),
|
||||
"updated_at": tx.updated_at.isoformat()
|
||||
})
|
||||
|
||||
return cross_chain_transactions
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting cross-chain transactions: {str(e)}")
|
||||
|
||||
|
||||
# Analytics and Monitoring Endpoints
|
||||
@router.get("/analytics/cross-chain", response_model=Dict[str, Any])
|
||||
async def get_cross_chain_analytics(
|
||||
time_period_hours: int = Query(24, ge=1, le=8760, description="Time period in hours"),
|
||||
region: Optional[str] = Query(None, description="Filter by region"),
|
||||
chain_id: Optional[int] = Query(None, description="Filter by blockchain chain"),
|
||||
session: Session = Depends(get_session),
|
||||
integration_service: GlobalMarketplaceIntegrationService = Depends(get_integration_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get comprehensive cross-chain analytics"""
|
||||
|
||||
try:
|
||||
analytics = await integration_service.get_cross_chain_analytics(
|
||||
time_period_hours=time_period_hours,
|
||||
region=region,
|
||||
chain_id=chain_id
|
||||
)
|
||||
|
||||
return analytics
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting cross-chain analytics: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/analytics/marketplace-integration", response_model=Dict[str, Any])
|
||||
async def get_marketplace_integration_analytics(
|
||||
session: Session = Depends(get_session),
|
||||
integration_service: GlobalMarketplaceIntegrationService = Depends(get_integration_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get marketplace integration status and metrics"""
|
||||
|
||||
try:
|
||||
# Get integration metrics
|
||||
integration_metrics = integration_service.metrics
|
||||
|
||||
# Get active regions
|
||||
active_regions = await integration_service.region_manager._get_active_regions()
|
||||
|
||||
# Get supported chains
|
||||
supported_chains = [1, 137, 56, 42161, 10, 43114] # From wallet adapter factory
|
||||
|
||||
return {
|
||||
"integration_status": IntegrationStatus.ACTIVE.value,
|
||||
"total_integrated_offers": integration_metrics["total_integrated_offers"],
|
||||
"cross_chain_transactions": integration_metrics["cross_chain_transactions"],
|
||||
"regional_distributions": integration_metrics["regional_distributions"],
|
||||
"integration_success_rate": integration_metrics["integration_success_rate"],
|
||||
"average_integration_time": integration_metrics["average_integration_time"],
|
||||
"active_regions": len(active_regions),
|
||||
"supported_chains": len(supported_chains),
|
||||
"integration_config": integration_service.integration_config,
|
||||
"last_updated": datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting marketplace integration analytics: {str(e)}")
|
||||
|
||||
|
||||
# Configuration and Status Endpoints
|
||||
@router.get("/status", response_model=Dict[str, Any])
|
||||
async def get_integration_status(
|
||||
session: Session = Depends(get_session),
|
||||
integration_service: GlobalMarketplaceIntegrationService = Depends(get_integration_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get global marketplace integration status"""
|
||||
|
||||
try:
|
||||
# Get service status
|
||||
services_status = {
|
||||
"marketplace_service": "active",
|
||||
"region_manager": "active",
|
||||
"bridge_service": "active" if integration_service.bridge_service else "inactive",
|
||||
"transaction_manager": "active" if integration_service.tx_manager else "inactive",
|
||||
"reputation_engine": "active"
|
||||
}
|
||||
|
||||
# Get integration metrics
|
||||
metrics = integration_service.metrics
|
||||
|
||||
# Get configuration
|
||||
config = integration_service.integration_config
|
||||
|
||||
return {
|
||||
"status": IntegrationStatus.ACTIVE.value,
|
||||
"services": services_status,
|
||||
"metrics": metrics,
|
||||
"configuration": config,
|
||||
"supported_features": {
|
||||
"auto_cross_chain_listing": config["auto_cross_chain_listing"],
|
||||
"cross_chain_pricing": config["cross_chain_pricing_enabled"],
|
||||
"regional_pricing": config["regional_pricing_enabled"],
|
||||
"reputation_based_ranking": config["reputation_based_ranking"],
|
||||
"auto_bridge_execution": config["auto_bridge_execution"],
|
||||
"multi_chain_wallet_support": config["multi_chain_wallet_support"]
|
||||
},
|
||||
"last_updated": datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting integration status: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/config", response_model=Dict[str, Any])
|
||||
async def get_integration_config(
|
||||
session: Session = Depends(get_session),
|
||||
integration_service: GlobalMarketplaceIntegrationService = Depends(get_integration_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get global marketplace integration configuration"""
|
||||
|
||||
try:
|
||||
config = integration_service.integration_config
|
||||
|
||||
# Get available optimization strategies
|
||||
optimization_strategies = {
|
||||
"balanced": {
|
||||
"name": "Balanced",
|
||||
"description": "Moderate pricing adjustments based on market conditions",
|
||||
"price_range": "±10%"
|
||||
},
|
||||
"aggressive": {
|
||||
"name": "Aggressive",
|
||||
"description": "Lower prices to maximize volume and market share",
|
||||
"price_range": "-10% to -20%"
|
||||
},
|
||||
"premium": {
|
||||
"name": "Premium",
|
||||
"description": "Higher prices to maximize margins for premium services",
|
||||
"price_range": "+10% to +25%"
|
||||
}
|
||||
}
|
||||
|
||||
# Get supported bridge protocols
|
||||
bridge_protocols = {
|
||||
protocol.value: {
|
||||
"name": protocol.value.replace("_", " ").title(),
|
||||
"description": f"{protocol.value.replace('_', ' ').title()} protocol for cross-chain transfers",
|
||||
"recommended_for": {
|
||||
"atomic_swap": "small to medium transfers",
|
||||
"htlc": "high-security transfers",
|
||||
"liquidity_pool": "large transfers",
|
||||
"wrapped_token": "token wrapping"
|
||||
}.get(protocol.value, "general transfers")
|
||||
}
|
||||
for protocol in BridgeProtocol
|
||||
}
|
||||
|
||||
return {
|
||||
"integration_config": config,
|
||||
"optimization_strategies": optimization_strategies,
|
||||
"bridge_protocols": bridge_protocols,
|
||||
"transaction_priorities": {
|
||||
priority.value: {
|
||||
"name": priority.value.title(),
|
||||
"description": f"{priority.value.title()} priority transactions",
|
||||
"processing_multiplier": {
|
||||
TransactionPriority.LOW.value: 1.5,
|
||||
TransactionPriority.MEDIUM.value: 1.0,
|
||||
TransactionPriority.HIGH.value: 0.8,
|
||||
TransactionPriority.URGENT.value: 0.7,
|
||||
TransactionPriority.CRITICAL.value: 0.5
|
||||
}.get(priority.value, 1.0)
|
||||
}
|
||||
for priority in TransactionPriority
|
||||
},
|
||||
"last_updated": datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting integration config: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/config/update", response_model=Dict[str, Any])
|
||||
async def update_integration_config(
|
||||
config_updates: Dict[str, Any],
|
||||
session: Session = Depends(get_session),
|
||||
integration_service: GlobalMarketplaceIntegrationService = Depends(get_integration_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Update global marketplace integration configuration"""
|
||||
|
||||
try:
|
||||
# Validate configuration updates
|
||||
valid_keys = integration_service.integration_config.keys()
|
||||
for key in config_updates:
|
||||
if key not in valid_keys:
|
||||
raise ValueError(f"Invalid configuration key: {key}")
|
||||
|
||||
# Update configuration
|
||||
for key, value in config_updates.items():
|
||||
integration_service.integration_config[key] = value
|
||||
|
||||
return {
|
||||
"updated_config": integration_service.integration_config,
|
||||
"updated_keys": list(config_updates.keys()),
|
||||
"updated_at": datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error updating integration config: {str(e)}")
|
||||
|
||||
|
||||
# Health and Diagnostics Endpoints
|
||||
@router.get("/health", response_model=Dict[str, Any])
|
||||
async def get_integration_health(
|
||||
session: Session = Depends(get_session),
|
||||
integration_service: GlobalMarketplaceIntegrationService = Depends(get_integration_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get global marketplace integration health status"""
|
||||
|
||||
try:
|
||||
# Check service health
|
||||
health_status = {
|
||||
"overall_status": "healthy",
|
||||
"services": {},
|
||||
"metrics": {},
|
||||
"issues": []
|
||||
}
|
||||
|
||||
# Check marketplace service
|
||||
try:
|
||||
offers = await integration_service.marketplace_service.get_global_offers(limit=1)
|
||||
health_status["services"]["marketplace_service"] = "healthy"
|
||||
except Exception as e:
|
||||
health_status["services"]["marketplace_service"] = "unhealthy"
|
||||
health_status["issues"].append(f"Marketplace service error: {str(e)}")
|
||||
|
||||
# Check region manager
|
||||
try:
|
||||
regions = await integration_service.region_manager._get_active_regions()
|
||||
health_status["services"]["region_manager"] = "healthy"
|
||||
health_status["metrics"]["active_regions"] = len(regions)
|
||||
except Exception as e:
|
||||
health_status["services"]["region_manager"] = "unhealthy"
|
||||
health_status["issues"].append(f"Region manager error: {str(e)}")
|
||||
|
||||
# Check bridge service
|
||||
if integration_service.bridge_service:
|
||||
try:
|
||||
stats = await integration_service.bridge_service.get_bridge_statistics(1)
|
||||
health_status["services"]["bridge_service"] = "healthy"
|
||||
health_status["metrics"]["bridge_requests"] = stats["total_requests"]
|
||||
except Exception as e:
|
||||
health_status["services"]["bridge_service"] = "unhealthy"
|
||||
health_status["issues"].append(f"Bridge service error: {str(e)}")
|
||||
|
||||
# Check transaction manager
|
||||
if integration_service.tx_manager:
|
||||
try:
|
||||
stats = await integration_service.tx_manager.get_transaction_statistics(1)
|
||||
health_status["services"]["transaction_manager"] = "healthy"
|
||||
health_status["metrics"]["transactions"] = stats["total_transactions"]
|
||||
except Exception as e:
|
||||
health_status["services"]["transaction_manager"] = "unhealthy"
|
||||
health_status["issues"].append(f"Transaction manager error: {str(e)}")
|
||||
|
||||
# Determine overall status
|
||||
if health_status["issues"]:
|
||||
health_status["overall_status"] = "degraded"
|
||||
|
||||
health_status["last_updated"] = datetime.utcnow().isoformat()
|
||||
|
||||
return health_status
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting integration health: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/diagnostics/run", response_model=Dict[str, Any])
|
||||
async def run_integration_diagnostics(
|
||||
diagnostic_type: str = Query("full", description="Type of diagnostic to run"),
|
||||
session: Session = Depends(get_session),
|
||||
integration_service: GlobalMarketplaceIntegrationService = Depends(get_integration_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Run integration diagnostics"""
|
||||
|
||||
try:
|
||||
diagnostics = {
|
||||
"diagnostic_type": diagnostic_type,
|
||||
"started_at": datetime.utcnow().isoformat(),
|
||||
"results": {}
|
||||
}
|
||||
|
||||
if diagnostic_type == "full" or diagnostic_type == "services":
|
||||
# Test services
|
||||
diagnostics["results"]["services"] = {}
|
||||
|
||||
# Test marketplace service
|
||||
try:
|
||||
offers = await integration_service.marketplace_service.get_global_offers(limit=1)
|
||||
diagnostics["results"]["services"]["marketplace_service"] = {
|
||||
"status": "healthy",
|
||||
"offers_accessible": True
|
||||
}
|
||||
except Exception as e:
|
||||
diagnostics["results"]["services"]["marketplace_service"] = {
|
||||
"status": "unhealthy",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
# Test region manager
|
||||
try:
|
||||
regions = await integration_service.region_manager._get_active_regions()
|
||||
diagnostics["results"]["services"]["region_manager"] = {
|
||||
"status": "healthy",
|
||||
"active_regions": len(regions)
|
||||
}
|
||||
except Exception as e:
|
||||
diagnostics["results"]["services"]["region_manager"] = {
|
||||
"status": "unhealthy",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
if diagnostic_type == "full" or diagnostic_type == "cross-chain":
|
||||
# Test cross-chain functionality
|
||||
diagnostics["results"]["cross_chain"] = {}
|
||||
|
||||
if integration_service.bridge_service:
|
||||
try:
|
||||
stats = await integration_service.bridge_service.get_bridge_statistics(1)
|
||||
diagnostics["results"]["cross_chain"]["bridge_service"] = {
|
||||
"status": "healthy",
|
||||
"statistics": stats
|
||||
}
|
||||
except Exception as e:
|
||||
diagnostics["results"]["cross_chain"]["bridge_service"] = {
|
||||
"status": "unhealthy",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
if integration_service.tx_manager:
|
||||
try:
|
||||
stats = await integration_service.tx_manager.get_transaction_statistics(1)
|
||||
diagnostics["results"]["cross_chain"]["transaction_manager"] = {
|
||||
"status": "healthy",
|
||||
"statistics": stats
|
||||
}
|
||||
except Exception as e:
|
||||
diagnostics["results"]["cross_chain"]["transaction_manager"] = {
|
||||
"status": "unhealthy",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
if diagnostic_type == "full" or diagnostic_type == "performance":
|
||||
# Test performance
|
||||
diagnostics["results"]["performance"] = {
|
||||
"integration_metrics": integration_service.metrics,
|
||||
"configuration": integration_service.integration_config
|
||||
}
|
||||
|
||||
diagnostics["completed_at"] = datetime.utcnow().isoformat()
|
||||
diagnostics["duration_seconds"] = (
|
||||
datetime.utcnow() - datetime.fromisoformat(diagnostics["started_at"])
|
||||
).total_seconds()
|
||||
|
||||
return diagnostics
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error running diagnostics: {str(e)}")
|
||||
576
apps/coordinator-api/src/app/routers/governance_enhanced.py
Normal file
576
apps/coordinator-api/src/app/routers/governance_enhanced.py
Normal file
@@ -0,0 +1,576 @@
|
||||
"""
|
||||
Enhanced Governance API Router
|
||||
REST API endpoints for multi-jurisdictional DAO governance, regional councils, treasury management, and staking
|
||||
"""
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Optional, Dict, Any
|
||||
from uuid import uuid4
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Depends, Query, BackgroundTasks
|
||||
from fastapi.responses import JSONResponse
|
||||
from sqlmodel import Session, select, func
|
||||
|
||||
from ..services.database import get_session
|
||||
from ..domain.governance import (
|
||||
GovernanceProfile, Proposal, Vote, DaoTreasury, TransparencyReport,
|
||||
ProposalStatus, VoteType, GovernanceRole
|
||||
)
|
||||
from ..services.governance_service import GovernanceService
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/governance-enhanced",
|
||||
tags=["Enhanced Governance"]
|
||||
)
|
||||
|
||||
# Dependency injection
|
||||
def get_governance_service(session: Session = Depends(get_session)) -> GovernanceService:
|
||||
return GovernanceService(session)
|
||||
|
||||
|
||||
# Regional Council Management Endpoints
|
||||
@router.post("/regional-councils", response_model=Dict[str, Any])
|
||||
async def create_regional_council(
|
||||
region: str,
|
||||
council_name: str,
|
||||
jurisdiction: str,
|
||||
council_members: List[str],
|
||||
budget_allocation: float,
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Create a regional governance council"""
|
||||
|
||||
try:
|
||||
council = await governance_service.create_regional_council(
|
||||
region, council_name, jurisdiction, council_members, budget_allocation
|
||||
)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"council": council,
|
||||
"message": f"Regional council '{council_name}' created successfully in {region}"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error creating regional council: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/regional-councils", response_model=List[Dict[str, Any]])
|
||||
async def get_regional_councils(
|
||||
region: Optional[str] = Query(None, description="Filter by region"),
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Get regional governance councils"""
|
||||
|
||||
try:
|
||||
councils = await governance_service.get_regional_councils(region)
|
||||
return councils
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting regional councils: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/regional-proposals", response_model=Dict[str, Any])
|
||||
async def create_regional_proposal(
|
||||
council_id: str,
|
||||
title: str,
|
||||
description: str,
|
||||
proposal_type: str,
|
||||
amount_requested: float,
|
||||
proposer_address: str,
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Create a proposal for a specific regional council"""
|
||||
|
||||
try:
|
||||
proposal = await governance_service.create_regional_proposal(
|
||||
council_id, title, description, proposal_type, amount_requested, proposer_address
|
||||
)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"proposal": proposal,
|
||||
"message": f"Regional proposal '{title}' created successfully"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error creating regional proposal: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/regional-proposals/{proposal_id}/vote", response_model=Dict[str, Any])
|
||||
async def vote_on_regional_proposal(
|
||||
proposal_id: str,
|
||||
voter_address: str,
|
||||
vote_type: VoteType,
|
||||
voting_power: float,
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Vote on a regional proposal"""
|
||||
|
||||
try:
|
||||
vote = await governance_service.vote_on_regional_proposal(
|
||||
proposal_id, voter_address, vote_type, voting_power
|
||||
)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"vote": vote,
|
||||
"message": f"Vote cast successfully on proposal {proposal_id}"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error voting on proposal: {str(e)}")
|
||||
|
||||
|
||||
# Treasury Management Endpoints
|
||||
@router.get("/treasury/balance", response_model=Dict[str, Any])
|
||||
async def get_treasury_balance(
|
||||
region: Optional[str] = Query(None, description="Filter by region"),
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get treasury balance for global or specific region"""
|
||||
|
||||
try:
|
||||
balance = await governance_service.get_treasury_balance(region)
|
||||
return balance
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting treasury balance: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/treasury/allocate", response_model=Dict[str, Any])
|
||||
async def allocate_treasury_funds(
|
||||
council_id: str,
|
||||
amount: float,
|
||||
purpose: str,
|
||||
recipient_address: str,
|
||||
approver_address: str,
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Allocate treasury funds to a regional council or project"""
|
||||
|
||||
try:
|
||||
allocation = await governance_service.allocate_treasury_funds(
|
||||
council_id, amount, purpose, recipient_address, approver_address
|
||||
)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"allocation": allocation,
|
||||
"message": f"Treasury funds allocated successfully: {amount} AITBC"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error allocating treasury funds: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/treasury/transactions", response_model=List[Dict[str, Any]])
|
||||
async def get_treasury_transactions(
|
||||
limit: int = Query(100, ge=1, le=500, description="Maximum number of transactions"),
|
||||
offset: int = Query(0, ge=0, description="Offset for pagination"),
|
||||
region: Optional[str] = Query(None, description="Filter by region"),
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Get treasury transaction history"""
|
||||
|
||||
try:
|
||||
transactions = await governance_service.get_treasury_transactions(limit, offset, region)
|
||||
return transactions
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting treasury transactions: {str(e)}")
|
||||
|
||||
|
||||
# Staking & Rewards Endpoints
|
||||
@router.post("/staking/pools", response_model=Dict[str, Any])
|
||||
async def create_staking_pool(
|
||||
pool_name: str,
|
||||
developer_address: str,
|
||||
base_apy: float,
|
||||
reputation_multiplier: float,
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Create a staking pool for an agent developer"""
|
||||
|
||||
try:
|
||||
pool = await governance_service.create_staking_pool(
|
||||
pool_name, developer_address, base_apy, reputation_multiplier
|
||||
)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"pool": pool,
|
||||
"message": f"Staking pool '{pool_name}' created successfully"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error creating staking pool: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/staking/pools", response_model=List[Dict[str, Any]])
|
||||
async def get_developer_staking_pools(
|
||||
developer_address: Optional[str] = Query(None, description="Filter by developer address"),
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Get staking pools for a specific developer or all pools"""
|
||||
|
||||
try:
|
||||
pools = await governance_service.get_developer_staking_pools(developer_address)
|
||||
return pools
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting staking pools: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/staking/calculate-rewards", response_model=Dict[str, Any])
|
||||
async def calculate_staking_rewards(
|
||||
pool_id: str,
|
||||
staker_address: str,
|
||||
amount: float,
|
||||
duration_days: int,
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Calculate staking rewards for a specific position"""
|
||||
|
||||
try:
|
||||
rewards = await governance_service.calculate_staking_rewards(
|
||||
pool_id, staker_address, amount, duration_days
|
||||
)
|
||||
return rewards
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error calculating staking rewards: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/staking/distribute-rewards/{pool_id}", response_model=Dict[str, Any])
|
||||
async def distribute_staking_rewards(
|
||||
pool_id: str,
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Distribute rewards to all stakers in a pool"""
|
||||
|
||||
try:
|
||||
distribution = await governance_service.distribute_staking_rewards(pool_id)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"distribution": distribution,
|
||||
"message": f"Rewards distributed successfully for pool {pool_id}"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error distributing staking rewards: {str(e)}")
|
||||
|
||||
|
||||
# Analytics and Monitoring Endpoints
|
||||
@router.get("/analytics/governance", response_model=Dict[str, Any])
|
||||
async def get_governance_analytics(
|
||||
time_period_days: int = Query(30, ge=1, le=365, description="Time period in days"),
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get comprehensive governance analytics"""
|
||||
|
||||
try:
|
||||
analytics = await governance_service.get_governance_analytics(time_period_days)
|
||||
return analytics
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting governance analytics: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/analytics/regional-health/{region}", response_model=Dict[str, Any])
|
||||
async def get_regional_governance_health(
|
||||
region: str,
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get health metrics for a specific region's governance"""
|
||||
|
||||
try:
|
||||
health = await governance_service.get_regional_governance_health(region)
|
||||
return health
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting regional governance health: {str(e)}")
|
||||
|
||||
|
||||
# Enhanced Profile Management
|
||||
@router.post("/profiles/create", response_model=Dict[str, Any])
|
||||
async def create_governance_profile(
|
||||
user_id: str,
|
||||
initial_voting_power: float = 0.0,
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Create or get a governance profile"""
|
||||
|
||||
try:
|
||||
profile = await governance_service.get_or_create_profile(user_id, initial_voting_power)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"profile_id": profile.profile_id,
|
||||
"user_id": profile.user_id,
|
||||
"role": profile.role.value,
|
||||
"voting_power": profile.voting_power,
|
||||
"delegated_power": profile.delegated_power,
|
||||
"total_votes_cast": profile.total_votes_cast,
|
||||
"joined_at": profile.joined_at.isoformat(),
|
||||
"message": "Governance profile created successfully"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error creating governance profile: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/profiles/delegate", response_model=Dict[str, Any])
|
||||
async def delegate_votes(
|
||||
delegator_id: str,
|
||||
delegatee_id: str,
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Delegate voting power from one profile to another"""
|
||||
|
||||
try:
|
||||
delegator = await governance_service.delegate_votes(delegator_id, delegatee_id)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"delegator_id": delegator_id,
|
||||
"delegatee_id": delegatee_id,
|
||||
"delegated_power": delegator.voting_power,
|
||||
"delegate_to": delegator.delegate_to,
|
||||
"message": "Votes delegated successfully"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error delegating votes: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/profiles/{user_id}", response_model=Dict[str, Any])
|
||||
async def get_governance_profile(
|
||||
user_id: str,
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get governance profile by user ID"""
|
||||
|
||||
try:
|
||||
profile = await governance_service.get_or_create_profile(user_id)
|
||||
|
||||
return {
|
||||
"profile_id": profile.profile_id,
|
||||
"user_id": profile.user_id,
|
||||
"role": profile.role.value,
|
||||
"voting_power": profile.voting_power,
|
||||
"delegated_power": profile.delegated_power,
|
||||
"total_votes_cast": profile.total_votes_cast,
|
||||
"proposals_created": profile.proposals_created,
|
||||
"proposals_passed": profile.proposals_passed,
|
||||
"delegate_to": profile.delegate_to,
|
||||
"joined_at": profile.joined_at.isoformat(),
|
||||
"last_voted_at": profile.last_voted_at.isoformat() if profile.last_voted_at else None
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting governance profile: {str(e)}")
|
||||
|
||||
|
||||
# Multi-Jurisdictional Compliance
|
||||
@router.get("/jurisdictions", response_model=List[Dict[str, Any]])
|
||||
async def get_supported_jurisdictions() -> List[Dict[str, Any]]:
|
||||
"""Get list of supported jurisdictions and their requirements"""
|
||||
|
||||
try:
|
||||
jurisdictions = [
|
||||
{
|
||||
"code": "US",
|
||||
"name": "United States",
|
||||
"region": "global",
|
||||
"requirements": {
|
||||
"kyc_required": True,
|
||||
"aml_required": True,
|
||||
"tax_reporting": True,
|
||||
"minimum_stake": 1000.0,
|
||||
"voting_threshold": 100.0
|
||||
},
|
||||
"supported_councils": ["us-east", "us-west", "us-central"]
|
||||
},
|
||||
{
|
||||
"code": "EU",
|
||||
"name": "European Union",
|
||||
"region": "global",
|
||||
"requirements": {
|
||||
"kyc_required": True,
|
||||
"aml_required": True,
|
||||
"gdpr_compliance": True,
|
||||
"minimum_stake": 800.0,
|
||||
"voting_threshold": 80.0
|
||||
},
|
||||
"supported_councils": ["eu-west", "eu-central", "eu-north"]
|
||||
},
|
||||
{
|
||||
"code": "SG",
|
||||
"name": "Singapore",
|
||||
"region": "asia-pacific",
|
||||
"requirements": {
|
||||
"kyc_required": True,
|
||||
"aml_required": True,
|
||||
"tax_reporting": True,
|
||||
"minimum_stake": 500.0,
|
||||
"voting_threshold": 50.0
|
||||
},
|
||||
"supported_councils": ["asia-pacific", "sea"]
|
||||
}
|
||||
]
|
||||
|
||||
return jurisdictions
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting jurisdictions: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/compliance/check/{user_address}", response_model=Dict[str, Any])
|
||||
async def check_compliance_status(
|
||||
user_address: str,
|
||||
jurisdiction: str,
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Check compliance status for a user in a specific jurisdiction"""
|
||||
|
||||
try:
|
||||
# Mock compliance check - would integrate with real compliance systems
|
||||
compliance_status = {
|
||||
"user_address": user_address,
|
||||
"jurisdiction": jurisdiction,
|
||||
"is_compliant": True,
|
||||
"compliance_level": "full",
|
||||
"last_check": datetime.utcnow().isoformat(),
|
||||
"requirements_met": {
|
||||
"kyc_verified": True,
|
||||
"aml_screened": True,
|
||||
"tax_id_provided": True,
|
||||
"minimum_stake_met": True
|
||||
},
|
||||
"restrictions": [],
|
||||
"next_review_date": (datetime.utcnow() + timedelta(days=365)).isoformat()
|
||||
}
|
||||
|
||||
return compliance_status
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error checking compliance status: {str(e)}")
|
||||
|
||||
|
||||
# System Health and Status
|
||||
@router.get("/health", response_model=Dict[str, Any])
|
||||
async def get_governance_system_health(
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get overall governance system health status"""
|
||||
|
||||
try:
|
||||
# Check database connectivity
|
||||
try:
|
||||
profile_count = session.exec(select(func.count(GovernanceProfile.profile_id))).scalar()
|
||||
database_status = "healthy"
|
||||
except Exception:
|
||||
database_status = "unhealthy"
|
||||
profile_count = 0
|
||||
|
||||
# Mock service health checks
|
||||
services_status = {
|
||||
"database": database_status,
|
||||
"treasury_contracts": "healthy",
|
||||
"staking_contracts": "healthy",
|
||||
"regional_councils": "healthy",
|
||||
"compliance_systems": "healthy"
|
||||
}
|
||||
|
||||
overall_status = "healthy" if all(status == "healthy" for status in services_status.values()) else "degraded"
|
||||
|
||||
# Get basic metrics
|
||||
analytics = await governance_service.get_governance_analytics(7) # Last 7 days
|
||||
|
||||
health_data = {
|
||||
"status": overall_status,
|
||||
"services": services_status,
|
||||
"metrics": {
|
||||
"total_profiles": profile_count,
|
||||
"active_proposals": analytics["proposals"]["still_active"],
|
||||
"regional_councils": analytics["regional_councils"]["total_councils"],
|
||||
"treasury_balance": analytics["treasury"]["total_allocations"],
|
||||
"staking_pools": analytics["staking"]["active_pools"]
|
||||
},
|
||||
"last_updated": datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
return health_data
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting system health: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/status", response_model=Dict[str, Any])
|
||||
async def get_governance_platform_status(
|
||||
session: Session = Depends(get_session),
|
||||
governance_service: GovernanceService = Depends(get_governance_service)
|
||||
) -> Dict[str, Any]:
|
||||
"""Get comprehensive platform status information"""
|
||||
|
||||
try:
|
||||
# Get analytics for overview
|
||||
analytics = await governance_service.get_governance_analytics(30)
|
||||
|
||||
# Get regional councils
|
||||
councils = await governance_service.get_regional_councils()
|
||||
|
||||
# Get treasury balance
|
||||
treasury = await governance_service.get_treasury_balance()
|
||||
|
||||
status_data = {
|
||||
"platform": "AITBC Enhanced Governance",
|
||||
"version": "2.0.0",
|
||||
"status": "operational",
|
||||
"features": {
|
||||
"multi_jurisdictional_support": True,
|
||||
"regional_councils": len(councils),
|
||||
"treasury_management": True,
|
||||
"staking_rewards": True,
|
||||
"compliance_integration": True
|
||||
},
|
||||
"statistics": analytics,
|
||||
"treasury": treasury,
|
||||
"regional_coverage": {
|
||||
"total_regions": len(set(c["region"] for c in councils)),
|
||||
"active_councils": len(councils),
|
||||
"supported_jurisdictions": 3
|
||||
},
|
||||
"performance": {
|
||||
"average_proposal_time": "2.5 days",
|
||||
"voting_participation": f"{analytics['voting']['average_voter_participation']}%",
|
||||
"treasury_utilization": f"{analytics['treasury']['utilization_rate']}%",
|
||||
"staking_apy": f"{analytics['staking']['average_apy']}%"
|
||||
},
|
||||
"last_updated": datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
return status_data
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error getting platform status: {str(e)}")
|
||||
Reference in New Issue
Block a user