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:
@@ -30,7 +30,9 @@ from .routers import (
|
||||
agent_identity,
|
||||
global_marketplace,
|
||||
cross_chain_integration,
|
||||
global_marketplace_integration
|
||||
global_marketplace_integration,
|
||||
developer_platform,
|
||||
governance_enhanced
|
||||
)
|
||||
from .routers.ml_zk_proofs import router as ml_zk_proofs
|
||||
from .routers.community import router as community_router
|
||||
@@ -231,6 +233,8 @@ def create_app() -> FastAPI:
|
||||
app.include_router(global_marketplace, prefix="/v1")
|
||||
app.include_router(cross_chain_integration, prefix="/v1")
|
||||
app.include_router(global_marketplace_integration, prefix="/v1")
|
||||
app.include_router(developer_platform, prefix="/v1")
|
||||
app.include_router(governance_enhanced, prefix="/v1")
|
||||
|
||||
# Add Prometheus metrics endpoint
|
||||
metrics_app = make_asgi_app()
|
||||
|
||||
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)}")
|
||||
@@ -0,0 +1,780 @@
|
||||
"""
|
||||
Global Marketplace Integration Service
|
||||
Integration service that combines global marketplace operations with cross-chain capabilities
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Dict, List, Optional, Any, Tuple, Union
|
||||
from uuid import uuid4
|
||||
from decimal import Decimal
|
||||
from enum import Enum
|
||||
import json
|
||||
from aitbc.logging import get_logger
|
||||
|
||||
from sqlmodel import Session, select, update, delete, func, Field
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
|
||||
from ..domain.global_marketplace import (
|
||||
GlobalMarketplaceOffer, GlobalMarketplaceTransaction, GlobalMarketplaceAnalytics,
|
||||
MarketplaceRegion, RegionStatus, MarketplaceStatus
|
||||
)
|
||||
from ..domain.cross_chain_bridge import BridgeRequestStatus
|
||||
from ..agent_identity.wallet_adapter_enhanced import WalletAdapterFactory, SecurityLevel
|
||||
from ..services.global_marketplace import GlobalMarketplaceService, RegionManager
|
||||
from ..services.cross_chain_bridge_enhanced import CrossChainBridgeService, BridgeProtocol
|
||||
from ..services.multi_chain_transaction_manager import MultiChainTransactionManager, TransactionPriority
|
||||
from ..reputation.engine import CrossChainReputationEngine
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
class IntegrationStatus(str, Enum):
|
||||
"""Global marketplace integration status"""
|
||||
ACTIVE = "active"
|
||||
INACTIVE = "inactive"
|
||||
MAINTENANCE = "maintenance"
|
||||
DEGRADED = "degraded"
|
||||
|
||||
|
||||
class CrossChainOfferStatus(str, Enum):
|
||||
"""Cross-chain offer status"""
|
||||
AVAILABLE = "available"
|
||||
PENDING = "pending"
|
||||
ACTIVE = "active"
|
||||
COMPLETED = "completed"
|
||||
CANCELLED = "cancelled"
|
||||
EXPIRED = "expired"
|
||||
|
||||
|
||||
class GlobalMarketplaceIntegrationService:
|
||||
"""Service that integrates global marketplace with cross-chain capabilities"""
|
||||
|
||||
def __init__(self, session: Session):
|
||||
self.session = session
|
||||
self.marketplace_service = GlobalMarketplaceService(session)
|
||||
self.region_manager = RegionManager(session)
|
||||
self.bridge_service: Optional[CrossChainBridgeService] = None
|
||||
self.tx_manager: Optional[MultiChainTransactionManager] = None
|
||||
self.reputation_engine = CrossChainReputationEngine(session)
|
||||
|
||||
# Integration configuration
|
||||
self.integration_config = {
|
||||
"auto_cross_chain_listing": True,
|
||||
"cross_chain_pricing_enabled": True,
|
||||
"regional_pricing_enabled": True,
|
||||
"reputation_based_ranking": True,
|
||||
"auto_bridge_execution": True,
|
||||
"multi_chain_wallet_support": True
|
||||
}
|
||||
|
||||
# Performance metrics
|
||||
self.metrics = {
|
||||
"total_integrated_offers": 0,
|
||||
"cross_chain_transactions": 0,
|
||||
"regional_distributions": 0,
|
||||
"integration_success_rate": 0.0,
|
||||
"average_integration_time": 0.0
|
||||
}
|
||||
|
||||
async def initialize_integration(
|
||||
self,
|
||||
chain_configs: Dict[int, Dict[str, Any]],
|
||||
bridge_config: Dict[str, Any],
|
||||
tx_manager_config: Dict[str, Any]
|
||||
) -> None:
|
||||
"""Initialize global marketplace integration services"""
|
||||
|
||||
try:
|
||||
# Initialize bridge service
|
||||
self.bridge_service = CrossChainBridgeService(session)
|
||||
await self.bridge_service.initialize_bridge(chain_configs)
|
||||
|
||||
# Initialize transaction manager
|
||||
self.tx_manager = MultiChainTransactionManager(session)
|
||||
await self.tx_manager.initialize(chain_configs)
|
||||
|
||||
logger.info("Global marketplace integration services initialized")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error initializing integration services: {e}")
|
||||
raise
|
||||
|
||||
async def create_cross_chain_marketplace_offer(
|
||||
self,
|
||||
agent_id: str,
|
||||
service_type: str,
|
||||
resource_specification: Dict[str, Any],
|
||||
base_price: float,
|
||||
currency: str = "USD",
|
||||
total_capacity: int = 100,
|
||||
regions_available: List[str] = None,
|
||||
supported_chains: 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
|
||||
) -> Dict[str, Any]:
|
||||
"""Create a cross-chain enabled marketplace offer"""
|
||||
|
||||
try:
|
||||
# Validate agent reputation
|
||||
reputation_summary = await self.reputation_engine.get_agent_reputation_summary(agent_id)
|
||||
if reputation_summary.get('trust_score', 0) < reputation_threshold:
|
||||
raise ValueError(f"Insufficient reputation: {reputation_summary.get('trust_score', 0)} < {reputation_threshold}")
|
||||
|
||||
# Get active regions
|
||||
active_regions = await self.region_manager._get_active_regions()
|
||||
if not regions_available:
|
||||
regions_available = [region.region_code for region in active_regions]
|
||||
|
||||
# Get supported chains
|
||||
if not supported_chains:
|
||||
supported_chains = WalletAdapterFactory.get_supported_chains()
|
||||
|
||||
# Calculate cross-chain pricing if not provided
|
||||
if not cross_chain_pricing and self.integration_config["cross_chain_pricing_enabled"]:
|
||||
cross_chain_pricing = await self._calculate_cross_chain_pricing(
|
||||
base_price, supported_chains, regions_available
|
||||
)
|
||||
|
||||
# Create global marketplace offer
|
||||
from ..domain.global_marketplace import GlobalMarketplaceOfferRequest
|
||||
|
||||
offer_request = GlobalMarketplaceOfferRequest(
|
||||
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,
|
||||
dynamic_pricing_enabled=self.integration_config["regional_pricing_enabled"],
|
||||
expires_at=datetime.utcnow() + timedelta(minutes=deadline_minutes)
|
||||
)
|
||||
|
||||
global_offer = await self.marketplace_service.create_global_offer(offer_request, None)
|
||||
|
||||
# Update with cross-chain pricing
|
||||
if cross_chain_pricing:
|
||||
global_offer.cross_chain_pricing = cross_chain_pricing
|
||||
self.session.commit()
|
||||
|
||||
# Create cross-chain listings if enabled
|
||||
cross_chain_listings = []
|
||||
if self.integration_config["auto_cross_chain_listing"]:
|
||||
cross_chain_listings = await self._create_cross_chain_listings(global_offer)
|
||||
|
||||
logger.info(f"Created cross-chain marketplace offer {global_offer.id}")
|
||||
|
||||
return {
|
||||
"offer_id": global_offer.id,
|
||||
"agent_id": agent_id,
|
||||
"service_type": service_type,
|
||||
"base_price": base_price,
|
||||
"currency": currency,
|
||||
"total_capacity": total_capacity,
|
||||
"available_capacity": global_offer.available_capacity,
|
||||
"regions_available": global_offer.regions_available,
|
||||
"supported_chains": global_offer.supported_chains,
|
||||
"cross_chain_pricing": global_offer.cross_chain_pricing,
|
||||
"cross_chain_listings": cross_chain_listings,
|
||||
"auto_bridge_enabled": auto_bridge_enabled,
|
||||
"status": global_offer.global_status.value,
|
||||
"created_at": global_offer.created_at.isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error creating cross-chain marketplace offer: {e}")
|
||||
self.session.rollback()
|
||||
raise
|
||||
|
||||
async def execute_cross_chain_transaction(
|
||||
self,
|
||||
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
|
||||
) -> Dict[str, Any]:
|
||||
"""Execute a cross-chain marketplace transaction"""
|
||||
|
||||
try:
|
||||
# Get the global offer
|
||||
stmt = select(GlobalMarketplaceOffer).where(GlobalMarketplaceOffer.id == offer_id)
|
||||
offer = self.session.exec(stmt).first()
|
||||
|
||||
if not offer:
|
||||
raise ValueError("Offer not found")
|
||||
|
||||
if offer.available_capacity < quantity:
|
||||
raise ValueError("Insufficient capacity")
|
||||
|
||||
# Validate buyer reputation
|
||||
buyer_reputation = await self.reputation_engine.get_agent_reputation_summary(buyer_id)
|
||||
if buyer_reputation.get('trust_score', 0) < 300: # Minimum for transactions
|
||||
raise ValueError("Insufficient buyer reputation")
|
||||
|
||||
# Determine optimal chains if not specified
|
||||
if not source_chain or not target_chain:
|
||||
source_chain, target_chain = await self._determine_optimal_chains(
|
||||
buyer_id, offer, source_region, target_region
|
||||
)
|
||||
|
||||
# Calculate pricing
|
||||
unit_price = offer.base_price
|
||||
if source_chain in offer.cross_chain_pricing:
|
||||
unit_price = offer.cross_chain_pricing[source_chain]
|
||||
|
||||
total_amount = unit_price * quantity
|
||||
|
||||
# Create global marketplace transaction
|
||||
from ..domain.global_marketplace import GlobalMarketplaceTransactionRequest
|
||||
|
||||
tx_request = GlobalMarketplaceTransactionRequest(
|
||||
buyer_id=buyer_id,
|
||||
offer_id=offer_id,
|
||||
quantity=quantity,
|
||||
source_region=source_region,
|
||||
target_region=target_region,
|
||||
payment_method=payment_method,
|
||||
source_chain=source_chain,
|
||||
target_chain=target_chain
|
||||
)
|
||||
|
||||
global_transaction = await self.marketplace_service.create_global_transaction(
|
||||
tx_request, None
|
||||
)
|
||||
|
||||
# Update offer capacity
|
||||
offer.available_capacity -= quantity
|
||||
offer.total_transactions += 1
|
||||
offer.updated_at = datetime.utcnow()
|
||||
|
||||
# Execute cross-chain bridge if needed and enabled
|
||||
bridge_transaction_id = None
|
||||
if source_chain != target_chain and auto_execute_bridge and self.integration_config["auto_bridge_execution"]:
|
||||
bridge_result = await self._execute_cross_chain_bridge(
|
||||
buyer_id, source_chain, target_chain, total_amount,
|
||||
bridge_protocol, priority
|
||||
)
|
||||
bridge_transaction_id = bridge_result["bridge_request_id"]
|
||||
|
||||
# Update transaction with bridge info
|
||||
global_transaction.bridge_transaction_id = bridge_transaction_id
|
||||
global_transaction.cross_chain_fee = bridge_result.get("total_fee", 0)
|
||||
|
||||
self.session.commit()
|
||||
|
||||
logger.info(f"Executed cross-chain transaction {global_transaction.id}")
|
||||
|
||||
return {
|
||||
"transaction_id": global_transaction.id,
|
||||
"buyer_id": buyer_id,
|
||||
"seller_id": offer.agent_id,
|
||||
"offer_id": offer_id,
|
||||
"service_type": offer.service_type,
|
||||
"quantity": quantity,
|
||||
"unit_price": unit_price,
|
||||
"total_amount": total_amount + global_transaction.cross_chain_fee,
|
||||
"currency": offer.currency,
|
||||
"source_chain": source_chain,
|
||||
"target_chain": target_chain,
|
||||
"bridge_transaction_id": bridge_transaction_id,
|
||||
"cross_chain_fee": global_transaction.cross_chain_fee,
|
||||
"source_region": source_region,
|
||||
"target_region": target_region,
|
||||
"status": global_transaction.status,
|
||||
"created_at": global_transaction.created_at.isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error executing cross-chain transaction: {e}")
|
||||
self.session.rollback()
|
||||
raise
|
||||
|
||||
async def get_integrated_marketplace_offers(
|
||||
self,
|
||||
region: Optional[str] = None,
|
||||
service_type: Optional[str] = None,
|
||||
chain_id: Optional[int] = None,
|
||||
min_reputation: Optional[float] = None,
|
||||
include_cross_chain: bool = True,
|
||||
limit: int = 100,
|
||||
offset: int = 0
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Get integrated marketplace offers with cross-chain capabilities"""
|
||||
|
||||
try:
|
||||
# Get base offers
|
||||
offers = await self.marketplace_service.get_global_offers(
|
||||
region=region,
|
||||
service_type=service_type,
|
||||
limit=limit,
|
||||
offset=offset
|
||||
)
|
||||
|
||||
integrated_offers = []
|
||||
for offer in offers:
|
||||
# Filter by reputation if specified
|
||||
if min_reputation:
|
||||
reputation_summary = await self.reputation_engine.get_agent_reputation_summary(offer.agent_id)
|
||||
if reputation_summary.get('trust_score', 0) < min_reputation:
|
||||
continue
|
||||
|
||||
# Filter by chain if specified
|
||||
if chain_id and chain_id not in offer.supported_chains:
|
||||
continue
|
||||
|
||||
# Create integrated offer data
|
||||
integrated_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,
|
||||
"total_capacity": offer.total_capacity,
|
||||
"available_capacity": offer.available_capacity,
|
||||
"regions_available": offer.regions_available,
|
||||
"supported_chains": offer.supported_chains,
|
||||
"cross_chain_pricing": offer.cross_chain_pricing if include_cross_chain else {},
|
||||
"global_status": offer.global_status,
|
||||
"global_rating": offer.global_rating,
|
||||
"total_transactions": offer.total_transactions,
|
||||
"success_rate": offer.success_rate,
|
||||
"created_at": offer.created_at.isoformat(),
|
||||
"updated_at": offer.updated_at.isoformat()
|
||||
}
|
||||
|
||||
# Add cross-chain availability if requested
|
||||
if include_cross_chain:
|
||||
integrated_offer["cross_chain_availability"] = await self._get_cross_chain_availability(offer)
|
||||
|
||||
integrated_offers.append(integrated_offer)
|
||||
|
||||
return integrated_offers
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting integrated marketplace offers: {e}")
|
||||
raise
|
||||
|
||||
async def get_cross_chain_analytics(
|
||||
self,
|
||||
time_period_hours: int = 24,
|
||||
region: Optional[str] = None,
|
||||
chain_id: Optional[int] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""Get comprehensive cross-chain analytics"""
|
||||
|
||||
try:
|
||||
# Get base marketplace analytics
|
||||
from ..domain.global_marketplace import GlobalMarketplaceAnalyticsRequest
|
||||
|
||||
end_time = datetime.utcnow()
|
||||
start_time = end_time - timedelta(hours=time_period_hours)
|
||||
|
||||
analytics_request = GlobalMarketplaceAnalyticsRequest(
|
||||
period_type="hourly",
|
||||
start_date=start_time,
|
||||
end_date=end_time,
|
||||
region=region or "global",
|
||||
metrics=[],
|
||||
include_cross_chain=True,
|
||||
include_regional=True
|
||||
)
|
||||
|
||||
marketplace_analytics = await self.marketplace_service.get_marketplace_analytics(analytics_request)
|
||||
|
||||
# Get bridge statistics
|
||||
bridge_stats = await self.bridge_service.get_bridge_statistics(time_period_hours)
|
||||
|
||||
# Get transaction statistics
|
||||
tx_stats = await self.tx_manager.get_transaction_statistics(time_period_hours, chain_id)
|
||||
|
||||
# Calculate cross-chain metrics
|
||||
cross_chain_metrics = await self._calculate_cross_chain_metrics(
|
||||
time_period_hours, region, chain_id
|
||||
)
|
||||
|
||||
return {
|
||||
"time_period_hours": time_period_hours,
|
||||
"region": region or "global",
|
||||
"chain_id": chain_id,
|
||||
"marketplace_analytics": marketplace_analytics,
|
||||
"bridge_statistics": bridge_stats,
|
||||
"transaction_statistics": tx_stats,
|
||||
"cross_chain_metrics": cross_chain_metrics,
|
||||
"integration_metrics": self.metrics,
|
||||
"generated_at": datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting cross-chain analytics: {e}")
|
||||
raise
|
||||
|
||||
async def optimize_global_offer_pricing(
|
||||
self,
|
||||
offer_id: str,
|
||||
optimization_strategy: str = "balanced",
|
||||
target_regions: Optional[List[str]] = None,
|
||||
target_chains: Optional[List[int]] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""Optimize pricing for a global marketplace offer"""
|
||||
|
||||
try:
|
||||
# Get the offer
|
||||
stmt = select(GlobalMarketplaceOffer).where(GlobalMarketplaceOffer.id == offer_id)
|
||||
offer = self.session.exec(stmt).first()
|
||||
|
||||
if not offer:
|
||||
raise ValueError("Offer not found")
|
||||
|
||||
# Get current market conditions
|
||||
market_conditions = await self._analyze_market_conditions(
|
||||
offer.service_type, target_regions, target_chains
|
||||
)
|
||||
|
||||
# Calculate optimized pricing
|
||||
optimized_pricing = await self._calculate_optimized_pricing(
|
||||
offer, market_conditions, optimization_strategy
|
||||
)
|
||||
|
||||
# Update offer with optimized pricing
|
||||
offer.price_per_region = optimized_pricing["regional_pricing"]
|
||||
offer.cross_chain_pricing = optimized_pricing["cross_chain_pricing"]
|
||||
offer.updated_at = datetime.utcnow()
|
||||
|
||||
self.session.commit()
|
||||
|
||||
logger.info(f"Optimized pricing for offer {offer_id}")
|
||||
|
||||
return {
|
||||
"offer_id": offer_id,
|
||||
"optimization_strategy": optimization_strategy,
|
||||
"market_conditions": market_conditions,
|
||||
"optimized_pricing": optimized_pricing,
|
||||
"price_improvement": optimized_pricing.get("price_improvement", 0),
|
||||
"updated_at": offer.updated_at.isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error optimizing offer pricing: {e}")
|
||||
self.session.rollback()
|
||||
raise
|
||||
|
||||
# Private methods
|
||||
async def _calculate_cross_chain_pricing(
|
||||
self,
|
||||
base_price: float,
|
||||
supported_chains: List[int],
|
||||
regions: List[str]
|
||||
) -> Dict[int, float]:
|
||||
"""Calculate cross-chain pricing for different chains"""
|
||||
|
||||
try:
|
||||
cross_chain_pricing = {}
|
||||
|
||||
# Get chain-specific factors
|
||||
for chain_id in supported_chains:
|
||||
chain_info = WalletAdapterFactory.get_chain_info(chain_id)
|
||||
|
||||
# Base pricing factors
|
||||
gas_factor = 1.0
|
||||
popularity_factor = 1.0
|
||||
liquidity_factor = 1.0
|
||||
|
||||
# Adjust based on chain characteristics
|
||||
if chain_id == 1: # Ethereum
|
||||
gas_factor = 1.2 # Higher gas costs
|
||||
popularity_factor = 1.1 # High popularity
|
||||
elif chain_id == 137: # Polygon
|
||||
gas_factor = 0.8 # Lower gas costs
|
||||
popularity_factor = 0.9 # Good popularity
|
||||
elif chain_id == 56: # BSC
|
||||
gas_factor = 0.7 # Lower gas costs
|
||||
popularity_factor = 0.8 # Moderate popularity
|
||||
elif chain_id in [42161, 10]: # L2s
|
||||
gas_factor = 0.6 # Much lower gas costs
|
||||
popularity_factor = 0.7 # Growing popularity
|
||||
|
||||
# Calculate final price
|
||||
chain_price = base_price * gas_factor * popularity_factor * liquidity_factor
|
||||
cross_chain_pricing[chain_id] = chain_price
|
||||
|
||||
return cross_chain_pricing
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error calculating cross-chain pricing: {e}")
|
||||
return {}
|
||||
|
||||
async def _create_cross_chain_listings(self, offer: GlobalMarketplaceOffer) -> List[Dict[str, Any]]:
|
||||
"""Create cross-chain listings for a global offer"""
|
||||
|
||||
try:
|
||||
listings = []
|
||||
|
||||
for chain_id in offer.supported_chains:
|
||||
listing = {
|
||||
"offer_id": offer.id,
|
||||
"chain_id": chain_id,
|
||||
"price": offer.cross_chain_pricing.get(chain_id, offer.base_price),
|
||||
"currency": offer.currency,
|
||||
"capacity": offer.available_capacity,
|
||||
"status": CrossChainOfferStatus.AVAILABLE.value,
|
||||
"created_at": datetime.utcnow().isoformat()
|
||||
}
|
||||
listings.append(listing)
|
||||
|
||||
return listings
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error creating cross-chain listings: {e}")
|
||||
return []
|
||||
|
||||
async def _determine_optimal_chains(
|
||||
self,
|
||||
buyer_id: str,
|
||||
offer: GlobalMarketplaceOffer,
|
||||
source_region: str,
|
||||
target_region: str
|
||||
) -> Tuple[int, int]:
|
||||
"""Determine optimal source and target chains"""
|
||||
|
||||
try:
|
||||
# Get buyer's preferred chains (could be based on wallet, history, etc.)
|
||||
buyer_chains = WalletAdapterFactory.get_supported_chains()
|
||||
|
||||
# Find common chains
|
||||
common_chains = list(set(offer.supported_chains) & set(buyer_chains))
|
||||
|
||||
if not common_chains:
|
||||
# Fallback to most popular chains
|
||||
common_chains = [1, 137] # Ethereum and Polygon
|
||||
|
||||
# Select source chain (prefer buyer's region or lowest cost)
|
||||
source_chain = common_chains[0]
|
||||
if len(common_chains) > 1:
|
||||
# Choose based on gas price
|
||||
min_gas_chain = min(common_chains, key=lambda x: WalletAdapterFactory.get_chain_info(x).get("gas_price", 20))
|
||||
source_chain = min_gas_chain
|
||||
|
||||
# Select target chain (could be same as source for simplicity)
|
||||
target_chain = source_chain
|
||||
|
||||
return source_chain, target_chain
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error determining optimal chains: {e}")
|
||||
return 1, 137 # Default to Ethereum and Polygon
|
||||
|
||||
async def _execute_cross_chain_bridge(
|
||||
self,
|
||||
user_id: str,
|
||||
source_chain: int,
|
||||
target_chain: int,
|
||||
amount: float,
|
||||
protocol: Optional[BridgeProtocol],
|
||||
priority: TransactionPriority
|
||||
) -> Dict[str, Any]:
|
||||
"""Execute cross-chain bridge for transaction"""
|
||||
|
||||
try:
|
||||
# Get user's address (simplified)
|
||||
user_address = f"0x{hashlib.sha256(user_id.encode()).hexdigest()[:40]}"
|
||||
|
||||
# Create bridge request
|
||||
bridge_request = await self.bridge_service.create_bridge_request(
|
||||
user_address=user_address,
|
||||
source_chain_id=source_chain,
|
||||
target_chain_id=target_chain,
|
||||
amount=amount,
|
||||
protocol=protocol,
|
||||
security_level=BridgeSecurityLevel.MEDIUM,
|
||||
deadline_minutes=30
|
||||
)
|
||||
|
||||
return bridge_request
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error executing cross-chain bridge: {e}")
|
||||
raise
|
||||
|
||||
async def _get_cross_chain_availability(self, offer: GlobalMarketplaceOffer) -> Dict[str, Any]:
|
||||
"""Get cross-chain availability for an offer"""
|
||||
|
||||
try:
|
||||
availability = {
|
||||
"total_chains": len(offer.supported_chains),
|
||||
"available_chains": offer.supported_chains,
|
||||
"pricing_available": bool(offer.cross_chain_pricing),
|
||||
"bridge_enabled": self.integration_config["auto_bridge_execution"],
|
||||
"regional_availability": {}
|
||||
}
|
||||
|
||||
# Check regional availability
|
||||
for region in offer.regions_available:
|
||||
region_availability = {
|
||||
"available": True,
|
||||
"chains_available": offer.supported_chains,
|
||||
"pricing": offer.price_per_region.get(region, offer.base_price)
|
||||
}
|
||||
availability["regional_availability"][region] = region_availability
|
||||
|
||||
return availability
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting cross-chain availability: {e}")
|
||||
return {}
|
||||
|
||||
async def _calculate_cross_chain_metrics(
|
||||
self,
|
||||
time_period_hours: int,
|
||||
region: Optional[str],
|
||||
chain_id: Optional[int]
|
||||
) -> Dict[str, Any]:
|
||||
"""Calculate cross-chain specific metrics"""
|
||||
|
||||
try:
|
||||
# Mock implementation - would calculate real metrics
|
||||
metrics = {
|
||||
"cross_chain_volume": 0.0,
|
||||
"cross_chain_transactions": 0,
|
||||
"average_cross_chain_time": 0.0,
|
||||
"cross_chain_success_rate": 0.0,
|
||||
"chain_utilization": {},
|
||||
"regional_distribution": {}
|
||||
}
|
||||
|
||||
# Calculate chain utilization
|
||||
for chain_id in WalletAdapterFactory.get_supported_chains():
|
||||
metrics["chain_utilization"][str(chain_id)] = {
|
||||
"volume": 0.0,
|
||||
"transactions": 0,
|
||||
"success_rate": 0.0
|
||||
}
|
||||
|
||||
return metrics
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error calculating cross-chain metrics: {e}")
|
||||
return {}
|
||||
|
||||
async def _analyze_market_conditions(
|
||||
self,
|
||||
service_type: str,
|
||||
target_regions: Optional[List[str]],
|
||||
target_chains: Optional[List[int]]
|
||||
) -> Dict[str, Any]:
|
||||
"""Analyze current market conditions"""
|
||||
|
||||
try:
|
||||
# Mock implementation - would analyze real market data
|
||||
conditions = {
|
||||
"demand_level": "medium",
|
||||
"competition_level": "medium",
|
||||
"price_trend": "stable",
|
||||
"regional_conditions": {},
|
||||
"chain_conditions": {}
|
||||
}
|
||||
|
||||
# Analyze regional conditions
|
||||
if target_regions:
|
||||
for region in target_regions:
|
||||
conditions["regional_conditions"][region] = {
|
||||
"demand": "medium",
|
||||
"supply": "medium",
|
||||
"price_pressure": "stable"
|
||||
}
|
||||
|
||||
# Analyze chain conditions
|
||||
if target_chains:
|
||||
for chain_id in target_chains:
|
||||
chain_info = WalletAdapterFactory.get_chain_info(chain_id)
|
||||
conditions["chain_conditions"][str(chain_id)] = {
|
||||
"gas_price": chain_info.get("gas_price", 20),
|
||||
"network_activity": "medium",
|
||||
"congestion": "low"
|
||||
}
|
||||
|
||||
return conditions
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error analyzing market conditions: {e}")
|
||||
return {}
|
||||
|
||||
async def _calculate_optimized_pricing(
|
||||
self,
|
||||
offer: GlobalMarketplaceOffer,
|
||||
market_conditions: Dict[str, Any],
|
||||
strategy: str
|
||||
) -> Dict[str, Any]:
|
||||
"""Calculate optimized pricing based on strategy"""
|
||||
|
||||
try:
|
||||
optimized_pricing = {
|
||||
"regional_pricing": {},
|
||||
"cross_chain_pricing": {},
|
||||
"price_improvement": 0.0
|
||||
}
|
||||
|
||||
# Base pricing
|
||||
base_price = offer.base_price
|
||||
|
||||
if strategy == "balanced":
|
||||
# Balanced approach - moderate adjustments
|
||||
for region in offer.regions_available:
|
||||
regional_condition = market_conditions["regional_conditions"].get(region, {})
|
||||
demand_multiplier = 1.0
|
||||
|
||||
if regional_condition.get("demand") == "high":
|
||||
demand_multiplier = 1.1
|
||||
elif regional_condition.get("demand") == "low":
|
||||
demand_multiplier = 0.9
|
||||
|
||||
optimized_pricing["regional_pricing"][region] = base_price * demand_multiplier
|
||||
|
||||
for chain_id in offer.supported_chains:
|
||||
chain_condition = market_conditions["chain_conditions"].get(str(chain_id), {})
|
||||
chain_multiplier = 1.0
|
||||
|
||||
if chain_condition.get("congestion") == "high":
|
||||
chain_multiplier = 1.05
|
||||
elif chain_condition.get("congestion") == "low":
|
||||
chain_multiplier = 0.95
|
||||
|
||||
optimized_pricing["cross_chain_pricing"][chain_id] = base_price * chain_multiplier
|
||||
|
||||
elif strategy == "aggressive":
|
||||
# Aggressive pricing - maximize volume
|
||||
for region in offer.regions_available:
|
||||
optimized_pricing["regional_pricing"][region] = base_price * 0.9
|
||||
|
||||
for chain_id in offer.supported_chains:
|
||||
optimized_pricing["cross_chain_pricing"][chain_id] = base_price * 0.85
|
||||
|
||||
optimized_pricing["price_improvement"] = -0.1 # 10% reduction
|
||||
|
||||
elif strategy == "premium":
|
||||
# Premium pricing - maximize margin
|
||||
for region in offer.regions_available:
|
||||
optimized_pricing["regional_pricing"][region] = base_price * 1.15
|
||||
|
||||
for chain_id in offer.supported_chains:
|
||||
optimized_pricing["cross_chain_pricing"][chain_id] = base_price * 1.1
|
||||
|
||||
optimized_pricing["price_improvement"] = 0.1 # 10% increase
|
||||
|
||||
return optimized_pricing
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error calculating optimized pricing: {e}")
|
||||
return {"regional_pricing": {}, "cross_chain_pricing": {}, "price_improvement": 0.0}
|
||||
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
Decentralized Governance Service
|
||||
Implements the OpenClaw DAO, voting mechanisms, and proposal lifecycle
|
||||
Enhanced with multi-jurisdictional support and regional governance
|
||||
"""
|
||||
|
||||
from typing import Optional, List, Dict, Any
|
||||
@@ -50,18 +51,18 @@ class GovernanceService:
|
||||
old_delegatee = self.session.exec(select(GovernanceProfile).where(GovernanceProfile.profile_id == delegator.delegate_to)).first()
|
||||
if old_delegatee:
|
||||
old_delegatee.delegated_power -= delegator.voting_power
|
||||
self.session.add(old_delegatee)
|
||||
|
||||
# Set new delegation
|
||||
delegator.delegate_to = delegatee.profile_id
|
||||
# Apply new delegation
|
||||
delegator.delegate_to = delegatee_id
|
||||
delegatee.delegated_power += delegator.voting_power
|
||||
|
||||
self.session.add(delegator)
|
||||
self.session.add(delegatee)
|
||||
self.session.commit()
|
||||
self.session.refresh(delegator)
|
||||
self.session.refresh(delegatee)
|
||||
|
||||
logger.info(f"Votes delegated from {delegator_id} to {delegatee_id}")
|
||||
return delegator
|
||||
|
||||
|
||||
async def create_proposal(self, proposer_id: str, data: Dict[str, Any]) -> Proposal:
|
||||
"""Create a new governance proposal"""
|
||||
proposer = self.session.exec(select(GovernanceProfile).where(GovernanceProfile.profile_id == proposer_id)).first()
|
||||
|
||||
Reference in New Issue
Block a user