fix: replace datetime.UTC with timezone.utc for Python 3.12+ compatibility
Some checks failed
API Endpoint Tests / test-api-endpoints (push) Successful in 22s
Blockchain Synchronization Verification / sync-verification (push) Successful in 3s
CLI Tests / test-cli (push) Failing after 13s
Cross-Chain Functionality Tests / test-cross-chain-sync (push) Failing after 3s
Cross-Chain Functionality Tests / test-cross-chain-transactions (push) Successful in 3s
Cross-Chain Functionality Tests / test-cross-chain-bridge (push) Has been skipped
Cross-Chain Functionality Tests / test-multi-chain-consensus (push) Failing after 3s
Cross-Chain Functionality Tests / aggregate-results (push) Has been skipped
Cross-Node Transaction Testing / transaction-test (push) Successful in 2s
Deploy to Testnet / deploy-testnet (push) Successful in 1m34s
Documentation Validation / validate-docs (push) Failing after 10s
Documentation Validation / validate-policies-strict (push) Successful in 3s
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Node Failover Simulation / failover-test (push) Has been cancelled
Python Tests / test-python (push) Has been cancelled
Integration Tests / test-service-integration (push) Successful in 2m42s
Multi-Chain Island Architecture Tests / test-multi-chain-island (push) Successful in 3s
Multi-Node Blockchain Health Monitoring / health-check (push) Successful in 5s
P2P Network Verification / p2p-verification (push) Successful in 3s
Package Tests / Python package - aitbc-agent-sdk (push) Failing after 33s
Package Tests / Python package - aitbc-core (push) Successful in 17s
Package Tests / Python package - aitbc-crypto (push) Successful in 11s
Security Scanning / security-scan (push) Has been cancelled
Package Tests / Python package - aitbc-sdk (push) Successful in 13s
Package Tests / JavaScript package - aitbc-sdk-js (push) Successful in 9s
Package Tests / JavaScript package - aitbc-token (push) Successful in 17s
Staking Tests / test-staking-service (push) Failing after 6s
Staking Tests / test-staking-integration (push) Has been skipped
Staking Tests / test-staking-contract (push) Has been skipped
Staking Tests / run-staking-test-runner (push) Has been skipped

This commit is contained in:
aitbc
2026-05-09 12:03:26 +02:00
parent 14449b0758
commit d26e6d3772
152 changed files with 848 additions and 848 deletions

View File

@@ -8,7 +8,7 @@ import asyncio
import aiohttp import aiohttp
import json import json
from typing import Dict, Any, List, Optional from typing import Dict, Any, List, Optional
from datetime import datetime, UTC from datetime import datetime, timezone
class AITBCServiceIntegration: class AITBCServiceIntegration:
"""Integration layer for AITBC services""" """Integration layer for AITBC services"""
@@ -110,7 +110,7 @@ class AgentServiceBridge:
self.active_agents[agent_id] = { self.active_agents[agent_id] = {
"config": agent_config, "config": agent_config,
"registration": registration_result, "registration": registration_result,
"started_at": datetime.now(datetime.UTC) "started_at": datetime.now(timezone.utc)
} }
return True return True
else: else:
@@ -182,7 +182,7 @@ class AgentServiceBridge:
"volatility": "medium", "volatility": "medium",
"recommendation": "hold" "recommendation": "hold"
}, },
"timestamp": datetime.now(datetime.UTC).isoformat() "timestamp": datetime.now(timezone.utc).isoformat()
} }
return {"status": "success", "result": analysis_result} return {"status": "success", "result": analysis_result}
@@ -221,7 +221,7 @@ class AgentServiceBridge:
"check_type": task_data.get("check_type", "basic"), "check_type": task_data.get("check_type", "basic"),
"status": "passed", "status": "passed",
"checks_performed": ["kyc", "aml", "sanctions"], "checks_performed": ["kyc", "aml", "sanctions"],
"timestamp": datetime.now(datetime.UTC).isoformat() "timestamp": datetime.now(timezone.utc).isoformat()
} }
return {"status": "success", "result": compliance_result} return {"status": "success", "result": compliance_result}

View File

@@ -9,7 +9,7 @@ import json
import logging import logging
import time import time
from typing import Dict, Any, List from typing import Dict, Any, List
from datetime import datetime, UTC from datetime import datetime, timezone
import sys import sys
import os import os
@@ -112,7 +112,7 @@ class ComplianceAgent:
"alert_type": "compliance_failure", "alert_type": "compliance_failure",
"severity": "high", "severity": "high",
"details": result, "details": result,
"timestamp": datetime.now(datetime.UTC).isoformat() "timestamp": datetime.now(timezone.utc).isoformat()
} }
# In a real implementation, this would send to alert system # In a real implementation, this would send to alert system

View File

@@ -10,7 +10,7 @@ from typing import List, Optional, Dict, Any
import json import json
import uuid import uuid
import os import os
from datetime import datetime, UTC from datetime import datetime, timezone
import sqlite3 import sqlite3
from contextlib import contextmanager from contextlib import contextmanager
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
@@ -247,7 +247,7 @@ async def get_task_status():
}, },
"queue_sizes": queue_sizes "queue_sizes": queue_sizes
}, },
"timestamp": datetime.now(datetime.UTC).isoformat() "timestamp": datetime.now(timezone.utc).isoformat()
} }
# Agent Management Endpoints # Agent Management Endpoints
@@ -272,7 +272,7 @@ async def register_agent(request: AgentRegistrationRequest):
json.dumps(request.services), json.dumps(request.services),
json.dumps(request.endpoints), json.dumps(request.endpoints),
json.dumps(request.metadata), json.dumps(request.metadata),
datetime.now(datetime.UTC), datetime.now(timezone.utc),
1.0 1.0
)) ))
conn.commit() conn.commit()
@@ -284,7 +284,7 @@ async def register_agent(request: AgentRegistrationRequest):
"status": "success", "status": "success",
"message": f"Agent {request.agent_id} registered successfully", "message": f"Agent {request.agent_id} registered successfully",
"agent_id": request.agent_id, "agent_id": request.agent_id,
"registered_at": datetime.now(datetime.UTC).isoformat() "registered_at": datetime.now(timezone.utc).isoformat()
} }
except Exception as e: except Exception as e:
print(f"ERROR: Failed to register agent: {str(e)}") print(f"ERROR: Failed to register agent: {str(e)}")
@@ -345,7 +345,7 @@ async def discover_agents(query: Dict[str, Any]):
for agent in agents for agent in agents
], ],
"count": len(agents), "count": len(agents),
"timestamp": datetime.now(datetime.UTC).isoformat() "timestamp": datetime.now(timezone.utc).isoformat()
} }
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=f"Error discovering agents: {str(e)}") raise HTTPException(status_code=500, detail=f"Error discovering agents: {str(e)}")
@@ -374,7 +374,7 @@ async def get_agent(agent_id: str):
"registration_time": agent["registration_time"], "registration_time": agent["registration_time"],
"health_score": agent["health_score"] "health_score": agent["health_score"]
}, },
"timestamp": datetime.now(datetime.UTC).isoformat() "timestamp": datetime.now(timezone.utc).isoformat()
} }
except HTTPException: except HTTPException:
raise raise
@@ -390,7 +390,7 @@ async def update_agent_status(agent_id: str, request: AgentStatusUpdate):
conn.execute(''' conn.execute('''
UPDATE agents SET status = ?, last_heartbeat = ? UPDATE agents SET status = ?, last_heartbeat = ?
WHERE id = ? WHERE id = ?
''', (request.status, datetime.now(datetime.UTC), agent_id)) ''', (request.status, datetime.now(timezone.utc), agent_id))
# Update load metrics if provided # Update load metrics if provided
if request.load_metrics: if request.load_metrics:
@@ -404,7 +404,7 @@ async def update_agent_status(agent_id: str, request: AgentStatusUpdate):
"message": f"Agent {agent_id} status updated", "message": f"Agent {agent_id} status updated",
"agent_id": agent_id, "agent_id": agent_id,
"new_status": request.status, "new_status": request.status,
"updated_at": datetime.now(datetime.UTC).isoformat() "updated_at": datetime.now(timezone.utc).isoformat()
} }
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=f"Error updating agent status: {str(e)}") raise HTTPException(status_code=500, detail=f"Error updating agent status: {str(e)}")
@@ -417,12 +417,12 @@ async def agent_heartbeat(agent_id: str):
conn.execute(''' conn.execute('''
UPDATE agents SET last_heartbeat = ? UPDATE agents SET last_heartbeat = ?
WHERE id = ? WHERE id = ?
''', (datetime.now(datetime.UTC), agent_id)) ''', (datetime.now(timezone.utc), agent_id))
return { return {
"status": "success", "status": "success",
"message": f"Heartbeat received for agent {agent_id}", "message": f"Heartbeat received for agent {agent_id}",
"timestamp": datetime.now(datetime.UTC).isoformat() "timestamp": datetime.now(timezone.utc).isoformat()
} }
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=f"Error updating heartbeat: {str(e)}") raise HTTPException(status_code=500, detail=f"Error updating heartbeat: {str(e)}")

View File

@@ -5,7 +5,7 @@ Handles message creation, routing, and delivery between agents
import json import json
import uuid import uuid
from datetime import datetime, UTC from datetime import datetime, timezone
from typing import Dict, Any, Optional, List from typing import Dict, Any, Optional, List
from enum import Enum from enum import Enum
@@ -43,7 +43,7 @@ class MessageProtocol:
"receiver_id": receiver_id, "receiver_id": receiver_id,
"message_type": message_type.value, "message_type": message_type.value,
"content": content, "content": content,
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"status": "pending" "status": "pending"
} }
@@ -54,7 +54,7 @@ class MessageProtocol:
"""Send a message to the receiver""" """Send a message to the receiver"""
try: try:
message["status"] = "sent" message["status"] = "sent"
message["sent_timestamp"] = datetime.now(datetime.UTC).isoformat() message["sent_timestamp"] = datetime.now(timezone.utc).isoformat()
return True return True
except Exception: except Exception:
message["status"] = "failed" message["status"] = "failed"
@@ -65,7 +65,7 @@ class MessageProtocol:
for message in self.messages: for message in self.messages:
if message["message_id"] == message_id: if message["message_id"] == message_id:
message["status"] = "received" message["status"] = "received"
message["received_timestamp"] = datetime.now(datetime.UTC).isoformat() message["received_timestamp"] = datetime.now(timezone.utc).isoformat()
return message return message
return None return None

View File

@@ -4,7 +4,7 @@ Handles task creation, assignment, and tracking
""" """
import uuid import uuid
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from typing import Dict, Any, Optional, List from typing import Dict, Any, Optional, List
from enum import Enum from enum import Enum
@@ -42,8 +42,8 @@ class Task:
self.priority = priority self.priority = priority
self.created_by = created_by or assigned_to self.created_by = created_by or assigned_to
self.status = TaskStatus.PENDING self.status = TaskStatus.PENDING
self.created_at = datetime.now(datetime.UTC) self.created_at = datetime.now(timezone.utc)
self.updated_at = datetime.now(datetime.UTC) self.updated_at = datetime.now(timezone.utc)
self.completed_at = None self.completed_at = None
self.result = None self.result = None
self.error = None self.error = None
@@ -94,10 +94,10 @@ class TaskManager:
return False return False
task.status = status task.status = status
task.updated_at = datetime.now(datetime.UTC) task.updated_at = datetime.now(timezone.utc)
if status == TaskStatus.COMPLETED: if status == TaskStatus.COMPLETED:
task.completed_at = datetime.now(datetime.UTC) task.completed_at = datetime.now(timezone.utc)
task.result = result task.result = result
elif status == TaskStatus.FAILED: elif status == TaskStatus.FAILED:
task.error = error task.error = error
@@ -120,7 +120,7 @@ class TaskManager:
def get_overdue_tasks(self, hours: int = 24) -> List[Task]: def get_overdue_tasks(self, hours: int = 24) -> List[Task]:
"""Get tasks that are overdue""" """Get tasks that are overdue"""
cutoff_time = datetime.now(datetime.UTC) - timedelta(hours=hours) cutoff_time = datetime.now(timezone.utc) - timedelta(hours=hours)
return [ return [
task for task in self.tasks.values() task for task in self.tasks.values()
if task.status in [TaskStatus.PENDING, TaskStatus.IN_PROGRESS] and if task.status in [TaskStatus.PENDING, TaskStatus.IN_PROGRESS] and

View File

@@ -11,7 +11,7 @@ import json
import time import time
import uuid import uuid
import os import os
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
import sqlite3 import sqlite3
from contextlib import contextmanager from contextlib import contextmanager
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
@@ -149,7 +149,7 @@ async def list_agents(
@app.get("/api/health") @app.get("/api/health")
async def health_check(): async def health_check():
"""Health check endpoint""" """Health check endpoint"""
return {"status": "ok", "timestamp": datetime.now(datetime.UTC)} return {"status": "ok", "timestamp": datetime.now(timezone.utc)}
if __name__ == "__main__": if __name__ == "__main__":
import uvicorn import uvicorn

View File

@@ -7,7 +7,7 @@ Basic AI-powered trading and analytics
import asyncio import asyncio
import json import json
import numpy as np import numpy as np
from datetime import datetime, UTC from datetime import datetime, timezone
from fastapi import FastAPI from fastapi import FastAPI
from pydantic import BaseModel from pydantic import BaseModel
from typing import Dict, Any, List from typing import Dict, Any, List
@@ -58,7 +58,7 @@ class SimpleAITradingEngine:
'overall_sentiment': np.random.choice(['bullish', 'bearish', 'neutral']) 'overall_sentiment': np.random.choice(['bullish', 'bearish', 'neutral'])
} }
}, },
'timestamp': datetime.now(datetime.UTC) 'timestamp': datetime.now(timezone.utc)
} }
async def make_trading_decision(self, symbol: str) -> Dict[str, Any]: async def make_trading_decision(self, symbol: str) -> Dict[str, Any]:
@@ -90,7 +90,7 @@ class SimpleAITradingEngine:
'quantity': quantity, 'quantity': quantity,
'price': analysis['current_price'], 'price': analysis['current_price'],
'reasoning': f"Signal strength: {signal_strength:.3f}", 'reasoning': f"Signal strength: {signal_strength:.3f}",
'timestamp': datetime.now(datetime.UTC) 'timestamp': datetime.now(timezone.utc)
} }
# Global AI engine # Global AI engine
@@ -104,7 +104,7 @@ async def analyze_market(request: AnalysisRequest):
return { return {
"status": "success", "status": "success",
"analysis": analysis, "analysis": analysis,
"timestamp": datetime.now(datetime.UTC) "timestamp": datetime.now(timezone.utc)
} }
except Exception as e: except Exception as e:
return {"status": "error", "message": "Analysis failed"} return {"status": "error", "message": "Analysis failed"}
@@ -118,7 +118,7 @@ async def execute_ai_trade(request: TradingRequest):
return { return {
"status": "success", "status": "success",
"decision": decision, "decision": decision,
"timestamp": datetime.now(datetime.UTC) "timestamp": datetime.now(timezone.utc)
} }
except Exception as e: except Exception as e:
return {"status": "error", "message": "Analysis failed"} return {"status": "error", "message": "Analysis failed"}
@@ -136,7 +136,7 @@ async def predict_market(symbol: str):
"risk": analysis['ai_predictions']['risk_assessment'], "risk": analysis['ai_predictions']['risk_assessment'],
"sentiment": analysis['ai_predictions']['sentiment_analysis'] "sentiment": analysis['ai_predictions']['sentiment_analysis']
}, },
"timestamp": datetime.now(datetime.UTC) "timestamp": datetime.now(timezone.utc)
} }
except Exception as e: except Exception as e:
return {"status": "error", "message": "Analysis failed"} return {"status": "error", "message": "Analysis failed"}
@@ -152,7 +152,7 @@ async def get_ai_dashboard():
'total_volume': np.random.uniform(100000, 1000000), 'total_volume': np.random.uniform(100000, 1000000),
'active_symbols': len(symbols), 'active_symbols': len(symbols),
'ai_models_active': 3, 'ai_models_active': 3,
'last_update': datetime.now(datetime.UTC) 'last_update': datetime.now(timezone.utc)
}, },
'symbol_analysis': {} 'symbol_analysis': {}
} }
@@ -169,7 +169,7 @@ async def get_ai_dashboard():
return { return {
"status": "success", "status": "success",
"dashboard": dashboard_data, "dashboard": dashboard_data,
"timestamp": datetime.now(datetime.UTC) "timestamp": datetime.now(timezone.utc)
} }
except Exception as e: except Exception as e:
return {"status": "error", "message": "Analysis failed"} return {"status": "error", "message": "Analysis failed"}
@@ -192,13 +192,13 @@ async def get_ai_status():
"risk_assessment", "risk_assessment",
"sentiment_analysis" "sentiment_analysis"
], ],
"timestamp": datetime.now(datetime.UTC) "timestamp": datetime.now(timezone.utc)
} }
@app.get("/api/health") @app.get("/api/health")
async def health_check(): async def health_check():
"""Health check endpoint""" """Health check endpoint"""
return {"status": "ok", "timestamp": datetime.now(datetime.UTC)} return {"status": "ok", "timestamp": datetime.now(timezone.utc)}
if __name__ == "__main__": if __name__ == "__main__":
import uvicorn import uvicorn

View File

@@ -5,7 +5,7 @@ import sys
import sys import sys
from pathlib import Path from pathlib import Path
from unittest.mock import Mock, patch, MagicMock from unittest.mock import Mock, patch, MagicMock
from datetime import datetime, UTC from datetime import datetime, timezone
# Mock numpy before importing # Mock numpy before importing
@@ -68,7 +68,7 @@ async def test_make_trading_decision_extreme_confidence():
'risk_assessment': {'risk_score': 0.0, 'volatility': 0.01}, 'risk_assessment': {'risk_score': 0.0, 'volatility': 0.01},
'sentiment_analysis': {'sentiment_score': 1.0, 'overall_sentiment': 'bullish'} 'sentiment_analysis': {'sentiment_score': 1.0, 'overall_sentiment': 'bullish'}
}, },
'timestamp': datetime.now(datetime.UTC) 'timestamp': datetime.now(timezone.utc)
} }
result = await engine.make_trading_decision('AITBC/BTC') result = await engine.make_trading_decision('AITBC/BTC')
@@ -155,7 +155,7 @@ async def test_signal_strength_boundary_buy():
'risk_assessment': {'risk_score': 0.0, 'volatility': 0.01}, 'risk_assessment': {'risk_score': 0.0, 'volatility': 0.01},
'sentiment_analysis': {'sentiment_score': 0.5, 'overall_sentiment': 'bullish'} 'sentiment_analysis': {'sentiment_score': 0.5, 'overall_sentiment': 'bullish'}
}, },
'timestamp': datetime.now(datetime.UTC) 'timestamp': datetime.now(timezone.utc)
} }
result = await engine.make_trading_decision('AITBC/BTC') result = await engine.make_trading_decision('AITBC/BTC')

View File

@@ -4,7 +4,7 @@ import pytest
import sys import sys
import sys import sys
from pathlib import Path from pathlib import Path
from datetime import datetime, UTC from datetime import datetime, timezone
from unittest.mock import Mock, patch, MagicMock from unittest.mock import Mock, patch, MagicMock
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@@ -98,7 +98,7 @@ def test_get_ai_dashboard_endpoint():
'risk_assessment': {'risk_score': 0.5, 'volatility': 0.03}, 'risk_assessment': {'risk_score': 0.5, 'volatility': 0.03},
'sentiment_analysis': {'sentiment_score': 0.5, 'overall_sentiment': 'bullish'} 'sentiment_analysis': {'sentiment_score': 0.5, 'overall_sentiment': 'bullish'}
}, },
'timestamp': datetime.now(datetime.UTC) 'timestamp': datetime.now(timezone.utc)
} }
mock_decision.return_value = { mock_decision.return_value = {
@@ -108,7 +108,7 @@ def test_get_ai_dashboard_endpoint():
'quantity': 500, 'quantity': 500,
'price': 0.005, 'price': 0.005,
'reasoning': 'Test reasoning', 'reasoning': 'Test reasoning',
'timestamp': datetime.now(datetime.UTC) 'timestamp': datetime.now(timezone.utc)
} }
response = client.get("/api/ai/dashboard") response = client.get("/api/ai/dashboard")

View File

@@ -8,7 +8,7 @@ sys.path.insert(0, 'src')
from aitbc_chain.database import session_scope, init_db from aitbc_chain.database import session_scope, init_db
from aitbc_chain.models import Block from aitbc_chain.models import Block
from datetime import datetime, UTC from datetime import datetime, timezone
import hashlib import hashlib
def compute_block_hash(height: int, parent_hash: str, timestamp: datetime) -> str: def compute_block_hash(height: int, parent_hash: str, timestamp: datetime) -> str:
@@ -31,7 +31,7 @@ def create_genesis():
return return
# Create genesis block # Create genesis block
timestamp = datetime.now(datetime.UTC) timestamp = datetime.now(timezone.utc)
genesis_hash = compute_block_hash(0, "0x00", timestamp) genesis_hash = compute_block_hash(0, "0x00", timestamp)
genesis = Block( genesis = Block(
height=0, height=0,

View File

@@ -1,11 +1,11 @@
from aitbc_chain.database import session_scope, init_db from aitbc_chain.database import session_scope, init_db
from aitbc_chain.models import Account from aitbc_chain.models import Account
from datetime import datetime, UTC from datetime import datetime, timezone
def fix(): def fix():
init_db() init_db()
with session_scope() as session: with session_scope() as session:
acc = Account(chain_id="ait-mainnet", address="aitbc1genesis", balance=10000000, nonce=0, updated_at=datetime.now(datetime.UTC), account_type="regular", metadata="{}") acc = Account(chain_id="ait-mainnet", address="aitbc1genesis", balance=10000000, nonce=0, updated_at=datetime.now(timezone.utc), account_type="regular", metadata="{}")
session.merge(acc) session.merge(acc)
session.commit() session.commit()
print("Added aitbc1genesis to mainnet") print("Added aitbc1genesis to mainnet")

View File

@@ -18,7 +18,7 @@ import base64
import os import os
import sys import sys
from pathlib import Path from pathlib import Path
from datetime import datetime, UTC from datetime import datetime, timezone
from typing import Dict, List, Any, Optional from typing import Dict, List, Any, Optional
from cryptography.hazmat.primitives.asymmetric import ed25519 from cryptography.hazmat.primitives.asymmetric import ed25519
@@ -233,7 +233,7 @@ def initialize_genesis_database(genesis_block: Dict, allocations: List[Dict], db
alloc["address"], alloc["address"],
alloc["balance"], alloc["balance"],
alloc["nonce"], alloc["nonce"],
datetime.now(datetime.UTC).isoformat() datetime.now(timezone.utc).isoformat()
) )
) )

View File

@@ -8,7 +8,7 @@ of agent compromise.
from typing import Dict, List, Optional, Tuple from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
import json import json
from eth_account import Account from eth_account import Account
from eth_utils import to_checksum_address from eth_utils import to_checksum_address
@@ -37,7 +37,7 @@ class AgentSecurityProfile:
def __post_init__(self): def __post_init__(self):
if self.created_at is None: if self.created_at is None:
self.created_at = datetime.now(datetime.UTC) self.created_at = datetime.now(timezone.utc)
class AgentWalletSecurity: class AgentWalletSecurity:
@@ -423,7 +423,7 @@ class AgentWalletSecurity:
def _log_security_event(self, **kwargs): def _log_security_event(self, **kwargs):
"""Log a security event""" """Log a security event"""
event = { event = {
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
**kwargs **kwargs
} }
self.security_events.append(event) self.security_events.append(event)
@@ -469,7 +469,7 @@ class AgentWalletSecurity:
return { return {
"status": "disabled", "status": "disabled",
"agent_address": agent_address, "agent_address": agent_address,
"disabled_at": datetime.now(datetime.UTC).isoformat(), "disabled_at": datetime.now(timezone.utc).isoformat(),
"guardian": guardian_address "guardian": guardian_address
} }
@@ -527,7 +527,7 @@ def generate_security_report() -> Dict:
recent_events = agent_wallet_security.get_security_events(limit=20) recent_events = agent_wallet_security.get_security_events(limit=20)
return { return {
"generated_at": datetime.now(datetime.UTC).isoformat(), "generated_at": datetime.now(timezone.utc).isoformat(),
"summary": { "summary": {
"total_protected_agents": total_agents, "total_protected_agents": total_agents,
"active_agents": active_agents, "active_agents": active_agents,
@@ -580,5 +580,5 @@ def detect_suspicious_activity(agent_address: str, hours: int = 24) -> Dict:
"suspicious_activity": len(suspicious_patterns) > 0, "suspicious_activity": len(suspicious_patterns) > 0,
"suspicious_patterns": suspicious_patterns, "suspicious_patterns": suspicious_patterns,
"analysis_period_hours": hours, "analysis_period_hours": hours,
"analyzed_at": datetime.now(datetime.UTC).isoformat() "analyzed_at": datetime.now(timezone.utc).isoformat()
} }

View File

@@ -12,7 +12,7 @@ wallets from unlimited spending in case of compromise. It provides:
from typing import Dict, List, Optional, Tuple from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
import json import json
import os import os
import sqlite3 import sqlite3
@@ -248,7 +248,7 @@ class GuardianContract:
def _get_spent_in_period(self, period: str, timestamp: datetime = None) -> int: def _get_spent_in_period(self, period: str, timestamp: datetime = None) -> int:
"""Calculate total spent in given period""" """Calculate total spent in given period"""
if timestamp is None: if timestamp is None:
timestamp = datetime.now(datetime.UTC) timestamp = datetime.now(timezone.utc)
period_key = self._get_period_key(timestamp, period) period_key = self._get_period_key(timestamp, period)
@@ -265,7 +265,7 @@ class GuardianContract:
def _check_spending_limits(self, amount: int, timestamp: datetime = None) -> Tuple[bool, str]: def _check_spending_limits(self, amount: int, timestamp: datetime = None) -> Tuple[bool, str]:
"""Check if amount exceeds spending limits""" """Check if amount exceeds spending limits"""
if timestamp is None: if timestamp is None:
timestamp = datetime.now(datetime.UTC) timestamp = datetime.now(timezone.utc)
# Check per-transaction limit # Check per-transaction limit
if amount > self.config.limits.per_transaction: if amount > self.config.limits.per_transaction:
@@ -350,7 +350,7 @@ class GuardianContract:
"to": to_address, "to": to_address,
"amount": amount, "amount": amount,
"data": data, "data": data,
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"nonce": self.nonce, "nonce": self.nonce,
"status": "pending" "status": "pending"
} }
@@ -360,7 +360,7 @@ class GuardianContract:
# Check if time lock is required # Check if time lock is required
if self._requires_time_lock(amount): if self._requires_time_lock(amount):
unlock_time = datetime.now(datetime.UTC) + timedelta(hours=self.config.time_lock.delay_hours) unlock_time = datetime.now(timezone.utc) + timedelta(hours=self.config.time_lock.delay_hours)
operation["unlock_time"] = unlock_time.isoformat() operation["unlock_time"] = unlock_time.isoformat()
operation["status"] = "time_locked" operation["status"] = "time_locked"
@@ -406,7 +406,7 @@ class GuardianContract:
# Check if operation is time locked # Check if operation is time locked
if operation["status"] == "time_locked": if operation["status"] == "time_locked":
unlock_time = datetime.fromisoformat(operation["unlock_time"]) unlock_time = datetime.fromisoformat(operation["unlock_time"])
if datetime.now(datetime.UTC) < unlock_time: if datetime.now(timezone.utc) < unlock_time:
return { return {
"status": "error", "status": "error",
"reason": f"Operation locked until {unlock_time.isoformat()}" "reason": f"Operation locked until {unlock_time.isoformat()}"
@@ -432,7 +432,7 @@ class GuardianContract:
"amount": operation["amount"], "amount": operation["amount"],
"data": operation.get("data", ""), "data": operation.get("data", ""),
"timestamp": operation["timestamp"], "timestamp": operation["timestamp"],
"executed_at": datetime.now(datetime.UTC).isoformat(), "executed_at": datetime.now(timezone.utc).isoformat(),
"status": "completed", "status": "completed",
"nonce": operation["nonce"] "nonce": operation["nonce"]
} }
@@ -479,7 +479,7 @@ class GuardianContract:
return { return {
"status": "paused", "status": "paused",
"paused_at": datetime.now(datetime.UTC).isoformat(), "paused_at": datetime.now(timezone.utc).isoformat(),
"guardian": guardian_address, "guardian": guardian_address,
"message": "Emergency pause activated - all operations halted" "message": "Emergency pause activated - all operations halted"
} }
@@ -513,7 +513,7 @@ class GuardianContract:
return { return {
"status": "unpaused", "status": "unpaused",
"unpaused_at": datetime.now(datetime.UTC).isoformat(), "unpaused_at": datetime.now(timezone.utc).isoformat(),
"message": "Emergency pause lifted - operations resumed" "message": "Emergency pause lifted - operations resumed"
} }
@@ -541,13 +541,13 @@ class GuardianContract:
"status": "updated", "status": "updated",
"old_limits": old_limits, "old_limits": old_limits,
"new_limits": new_limits, "new_limits": new_limits,
"updated_at": datetime.now(datetime.UTC).isoformat(), "updated_at": datetime.now(timezone.utc).isoformat(),
"guardian": guardian_address "guardian": guardian_address
} }
def get_spending_status(self) -> Dict: def get_spending_status(self) -> Dict:
"""Get current spending status and limits""" """Get current spending status and limits"""
now = datetime.now(datetime.UTC) now = datetime.now(timezone.utc)
return { return {
"agent_address": self.agent_address, "agent_address": self.agent_address,

View File

@@ -5,7 +5,7 @@ Fixes the critical vulnerability where spending limits were lost on restart
from typing import Dict, List, Optional, Tuple from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from sqlalchemy import create_engine, Column, String, Integer, Float, DateTime, Index from sqlalchemy import create_engine, Column, String, Integer, Float, DateTime, Index
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session from sqlalchemy.orm import sessionmaker, Session
@@ -25,7 +25,7 @@ class SpendingRecord(Base):
period_key = Column(String, index=True) period_key = Column(String, index=True)
amount = Column(Float) amount = Column(Float)
transaction_hash = Column(String) transaction_hash = Column(String)
timestamp = Column(DateTime, default=datetime.now(datetime.UTC)) timestamp = Column(DateTime, default=datetime.now(timezone.utc))
# Composite indexes for performance # Composite indexes for performance
__table_args__ = ( __table_args__ = (
@@ -45,7 +45,7 @@ class SpendingLimit(Base):
per_week = Column(Float) per_week = Column(Float)
time_lock_threshold = Column(Float) time_lock_threshold = Column(Float)
time_lock_delay_hours = Column(Integer) time_lock_delay_hours = Column(Integer)
updated_at = Column(DateTime, default=datetime.now(datetime.UTC)) updated_at = Column(DateTime, default=datetime.now(timezone.utc))
updated_by = Column(String) # Guardian who updated updated_by = Column(String) # Guardian who updated
@@ -57,7 +57,7 @@ class GuardianAuthorization(Base):
agent_address = Column(String, index=True) agent_address = Column(String, index=True)
guardian_address = Column(String, index=True) guardian_address = Column(String, index=True)
is_active = Column(Boolean, default=True) is_active = Column(Boolean, default=True)
added_at = Column(DateTime, default=datetime.now(datetime.UTC)) added_at = Column(DateTime, default=datetime.now(timezone.utc))
added_by = Column(String) added_by = Column(String)
@@ -112,7 +112,7 @@ class PersistentSpendingTracker:
Total amount spent in period Total amount spent in period
""" """
if timestamp is None: if timestamp is None:
timestamp = datetime.now(datetime.UTC) timestamp = datetime.now(timezone.utc)
period_key = self._get_period_key(timestamp, period) period_key = self._get_period_key(timestamp, period)
agent_address = to_checksum_address(agent_address) agent_address = to_checksum_address(agent_address)
@@ -140,7 +140,7 @@ class PersistentSpendingTracker:
True if recorded successfully True if recorded successfully
""" """
if timestamp is None: if timestamp is None:
timestamp = datetime.now(datetime.UTC) timestamp = datetime.now(timezone.utc)
agent_address = to_checksum_address(agent_address) agent_address = to_checksum_address(agent_address)
@@ -184,7 +184,7 @@ class PersistentSpendingTracker:
Spending check result Spending check result
""" """
if timestamp is None: if timestamp is None:
timestamp = datetime.now(datetime.UTC) timestamp = datetime.now(timezone.utc)
agent_address = to_checksum_address(agent_address) agent_address = to_checksum_address(agent_address)
@@ -312,7 +312,7 @@ class PersistentSpendingTracker:
limits.per_week = new_limits.get("per_week", limits.per_week) limits.per_week = new_limits.get("per_week", limits.per_week)
limits.time_lock_threshold = new_limits.get("time_lock_threshold", limits.time_lock_threshold) limits.time_lock_threshold = new_limits.get("time_lock_threshold", limits.time_lock_threshold)
limits.time_lock_delay_hours = new_limits.get("time_lock_delay_hours", limits.time_lock_delay_hours) limits.time_lock_delay_hours = new_limits.get("time_lock_delay_hours", limits.time_lock_delay_hours)
limits.updated_at = datetime.now(datetime.UTC) limits.updated_at = datetime.now(timezone.utc)
limits.updated_by = guardian_address limits.updated_by = guardian_address
else: else:
limits = SpendingLimit( limits = SpendingLimit(
@@ -323,7 +323,7 @@ class PersistentSpendingTracker:
per_week=new_limits.get("per_week", 100000.0), per_week=new_limits.get("per_week", 100000.0),
time_lock_threshold=new_limits.get("time_lock_threshold", 5000.0), time_lock_threshold=new_limits.get("time_lock_threshold", 5000.0),
time_lock_delay_hours=new_limits.get("time_lock_delay_hours", 24), time_lock_delay_hours=new_limits.get("time_lock_delay_hours", 24),
updated_at=datetime.now(datetime.UTC), updated_at=datetime.now(timezone.utc),
updated_by=guardian_address updated_by=guardian_address
) )
session.add(limits) session.add(limits)
@@ -361,7 +361,7 @@ class PersistentSpendingTracker:
if existing: if existing:
existing.is_active = True existing.is_active = True
existing.added_at = datetime.now(datetime.UTC) existing.added_at = datetime.now(timezone.utc)
existing.added_by = added_by existing.added_by = added_by
else: else:
auth = GuardianAuthorization( auth = GuardianAuthorization(
@@ -369,7 +369,7 @@ class PersistentSpendingTracker:
agent_address=agent_address, agent_address=agent_address,
guardian_address=guardian_address, guardian_address=guardian_address,
is_active=True, is_active=True,
added_at=datetime.now(datetime.UTC), added_at=datetime.now(timezone.utc),
added_by=added_by added_by=added_by
) )
session.add(auth) session.add(auth)
@@ -415,7 +415,7 @@ class PersistentSpendingTracker:
Spending summary Spending summary
""" """
agent_address = to_checksum_address(agent_address) agent_address = to_checksum_address(agent_address)
now = datetime.now(datetime.UTC) now = datetime.now(timezone.utc)
# Get current spending # Get current spending
current_spent = { current_spent = {

View File

@@ -1,7 +1,7 @@
"""Cross-chain synchronization for testing multi-chain scenarios.""" """Cross-chain synchronization for testing multi-chain scenarios."""
import asyncio import asyncio
from datetime import datetime, UTC from datetime import datetime, timezone
from typing import Any, Dict, List from typing import Any, Dict, List

View File

@@ -4,7 +4,7 @@ import asyncio
import json import json
import time import time
from typing import Any, Dict, Optional, List from typing import Any, Dict, Optional, List
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from fastapi import APIRouter, HTTPException, status from fastapi import APIRouter, HTTPException, status
from pydantic import BaseModel, Field, model_validator from pydantic import BaseModel, Field, model_validator
@@ -478,12 +478,12 @@ async def submit_marketplace_transaction(tx_data: Dict[str, Any]) -> Dict[str, A
sender=sender_addr, sender=sender_addr,
recipient=recipient_addr, recipient=recipient_addr,
payload=tx_data.get("payload", {}), payload=tx_data.get("payload", {}),
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
nonce=tx_nonce, nonce=tx_nonce,
value=amount, value=amount,
fee=fee, fee=fee,
status="pending", status="pending",
timestamp=datetime.now(datetime.UTC).isoformat() timestamp=datetime.now(timezone.utc).isoformat()
) )
session.add(transaction) session.add(transaction)
@@ -798,9 +798,9 @@ async def import_block(block_data: dict) -> Dict[str, Any]:
try: try:
timestamp = datetime.fromisoformat(timestamp.replace('Z', '+00:00')) timestamp = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
except ValueError: except ValueError:
timestamp = datetime.now(datetime.UTC) timestamp = datetime.now(timezone.utc)
elif timestamp is None: elif timestamp is None:
timestamp = datetime.now(datetime.UTC) timestamp = datetime.now(timezone.utc)
with session_scope(chain_id) as session: with session_scope(chain_id) as session:
# Check for hash conflicts across chains # Check for hash conflicts across chains
@@ -1046,7 +1046,7 @@ async def import_chain(import_data: dict) -> Dict[str, Any]:
_logger.info(f"Importing {len(unique_blocks)} unique blocks (filtered from {len(blocks)} total)") _logger.info(f"Importing {len(unique_blocks)} unique blocks (filtered from {len(blocks)} total)")
for block_data in unique_blocks: for block_data in unique_blocks:
block_timestamp = _parse_datetime_value(block_data.get("timestamp"), "block timestamp") or datetime.now(datetime.UTC) block_timestamp = _parse_datetime_value(block_data.get("timestamp"), "block timestamp") or datetime.now(timezone.utc)
block = Block( block = Block(
chain_id=chain_id, chain_id=chain_id,
height=block_data["height"], height=block_data["height"],

View File

@@ -11,7 +11,7 @@ from typing import Dict, List, Optional, Tuple
from sqlmodel import Session, select from sqlmodel import Session, select
from sqlalchemy import select, text from sqlalchemy import select, text
from datetime import datetime, UTC from datetime import datetime, timezone
from ..models import Account, Transaction, Receipt from ..models import Account, Transaction, Receipt
from ..logger import get_logger from ..logger import get_logger
@@ -242,7 +242,7 @@ class StateTransition:
# Update receipt status # Update receipt status
receipt.status = "claimed" receipt.status = "claimed"
receipt.claimed_at = datetime.now(datetime.UTC) receipt.claimed_at = datetime.now(timezone.utc)
receipt.claimed_by = sender_addr receipt.claimed_by = sender_addr
logger.info( logger.info(

View File

@@ -8,7 +8,7 @@ import hmac
import json import json
import time import time
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime, UTC from datetime import datetime, timezone
from typing import Any, Dict, List, Optional, Tuple from typing import Any, Dict, List, Optional, Tuple
import httpx import httpx
@@ -508,9 +508,9 @@ class ChainSync:
block_hash = block_data["hash"] block_hash = block_data["hash"]
timestamp_str = block_data.get("timestamp", "") timestamp_str = block_data.get("timestamp", "")
try: try:
timestamp = datetime.fromisoformat(timestamp_str) if timestamp_str else datetime.now(datetime.UTC) timestamp = datetime.fromisoformat(timestamp_str) if timestamp_str else datetime.now(timezone.utc)
except (ValueError, TypeError): except (ValueError, TypeError):
timestamp = datetime.now(datetime.UTC) timestamp = datetime.now(timezone.utc)
tx_count = block_data.get("tx_count", 0) tx_count = block_data.get("tx_count", 0)
if transactions: if transactions:

View File

@@ -5,7 +5,7 @@ from __future__ import annotations
import sys import sys
import asyncio import asyncio
import pytest import pytest
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from unittest.mock import AsyncMock, Mock, patch from unittest.mock import AsyncMock, Mock, patch
from typing import Generator from typing import Generator
@@ -192,7 +192,7 @@ class TestPoAProposer:
hash="0xparent", hash="0xparent",
parent_hash="0x00", parent_hash="0x00",
proposer="previous-proposer", proposer="previous-proposer",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
tx_count=0, tx_count=0,
) )
test_db.add(parent) test_db.add(parent)
@@ -231,16 +231,16 @@ class TestPoAProposer:
hash="0xhead", hash="0xhead",
parent_hash="0x00", parent_hash="0x00",
proposer="test-proposer", proposer="test-proposer",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
tx_count=0, tx_count=0,
) )
test_db.add(head) test_db.add(head)
test_db.commit() test_db.commit()
# Should wait for the configured interval # Should wait for the configured interval
start_time = datetime.now(datetime.UTC) start_time = datetime.now(timezone.utc)
await proposer._wait_until_next_slot() await proposer._wait_until_next_slot()
elapsed = (datetime.now(datetime.UTC) - start_time).total_seconds() elapsed = (datetime.now(timezone.utc) - start_time).total_seconds()
# Should wait at least some time (but less than full interval since block is recent) # Should wait at least some time (but less than full interval since block is recent)
assert elapsed >= 0.1 assert elapsed >= 0.1
@@ -255,7 +255,7 @@ class TestPoAProposer:
hash="0xhead", hash="0xhead",
parent_hash="0x00", parent_hash="0x00",
proposer="test-proposer", proposer="test-proposer",
timestamp=datetime.now(datetime.UTC) - timedelta(seconds=10), timestamp=datetime.now(timezone.utc) - timedelta(seconds=10),
tx_count=0, tx_count=0,
) )
test_db.add(head) test_db.add(head)
@@ -263,9 +263,9 @@ class TestPoAProposer:
# Set stop event and wait # Set stop event and wait
proposer._stop_event.set() proposer._stop_event.set()
start_time = datetime.now(datetime.UTC) start_time = datetime.now(timezone.utc)
await proposer._wait_until_next_slot() await proposer._wait_until_next_slot()
elapsed = (datetime.now(datetime.UTC) - start_time).total_seconds() elapsed = (datetime.now(timezone.utc) - start_time).total_seconds()
# Should return immediately due to stop event # Should return immediately due to stop event
assert elapsed < 0.1 assert elapsed < 0.1
@@ -290,7 +290,7 @@ class TestPoAProposer:
"""Test block hash computation.""" """Test block hash computation."""
height = 1 height = 1
parent_hash = "0xparent" parent_hash = "0xparent"
timestamp = datetime.now(datetime.UTC) timestamp = datetime.now(timezone.utc)
processed_txs = [] processed_txs = []
block_hash = proposer._compute_block_hash(height, parent_hash, timestamp, processed_txs) block_hash = proposer._compute_block_hash(height, parent_hash, timestamp, processed_txs)
@@ -303,7 +303,7 @@ class TestPoAProposer:
"""Test block hash computation with transactions.""" """Test block hash computation with transactions."""
height = 1 height = 1
parent_hash = "0xparent" parent_hash = "0xparent"
timestamp = datetime.now(datetime.UTC) timestamp = datetime.now(timezone.utc)
mock_tx = Mock() mock_tx = Mock()
mock_tx.tx_hash = "0xtx" mock_tx.tx_hash = "0xtx"
@@ -324,7 +324,7 @@ class TestPoAProposer:
hash="0xexisting", hash="0xexisting",
parent_hash="0x00", parent_hash="0x00",
proposer="test-proposer", proposer="test-proposer",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
tx_count=0, tx_count=0,
) )
test_db.add(block) test_db.add(block)

View File

@@ -6,7 +6,7 @@ import sys
import pytest import pytest
import tempfile import tempfile
import shutil import shutil
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from pathlib import Path from pathlib import Path
from unittest.mock import patch, Mock from unittest.mock import patch, Mock
from typing import Generator from typing import Generator
@@ -113,7 +113,7 @@ class TestGuardianContract:
def test_spending_limit_check_hourly(self, guardian_contract: GuardianContract) -> None: def test_spending_limit_check_hourly(self, guardian_contract: GuardianContract) -> None:
"""Test hourly spending limit.""" """Test hourly spending limit."""
# Add some spending history # Add some spending history
base_time = datetime.now(datetime.UTC) base_time = datetime.now(timezone.utc)
guardian_contract.spending_history = [ guardian_contract.spending_history = [
{ {
"operation_id": "op1", "operation_id": "op1",
@@ -139,7 +139,7 @@ class TestGuardianContract:
def test_spending_limit_check_daily(self, guardian_contract: GuardianContract) -> None: def test_spending_limit_check_daily(self, guardian_contract: GuardianContract) -> None:
"""Test daily spending limit.""" """Test daily spending limit."""
# Add spending history across the day # Add spending history across the day
base_time = datetime.now(datetime.UTC) base_time = datetime.now(timezone.utc)
guardian_contract.spending_history = [ guardian_contract.spending_history = [
{ {
"operation_id": "op1", "operation_id": "op1",
@@ -165,7 +165,7 @@ class TestGuardianContract:
def test_spending_limit_check_weekly(self, guardian_contract: GuardianContract) -> None: def test_spending_limit_check_weekly(self, guardian_contract: GuardianContract) -> None:
"""Test weekly spending limit.""" """Test weekly spending limit."""
# Add spending history across the week # Add spending history across the week
base_time = datetime.now(datetime.UTC) base_time = datetime.now(timezone.utc)
guardian_contract.spending_history = [ guardian_contract.spending_history = [
{ {
"operation_id": "op1", "operation_id": "op1",

View File

@@ -4,7 +4,7 @@ import hashlib
import time import time
import sys import sys
import pytest import pytest
from datetime import datetime, UTC from datetime import datetime, timezone
from contextlib import contextmanager from contextlib import contextmanager
from unittest.mock import AsyncMock, Mock from unittest.mock import AsyncMock, Mock
@@ -70,7 +70,7 @@ class TestProposerSignatureValidator:
def test_valid_block(self): def test_valid_block(self):
v = ProposerSignatureValidator() v = ProposerSignatureValidator()
ts = datetime.now(datetime.UTC) ts = datetime.now(timezone.utc)
bh = _make_block_hash("test", 1, "0x00", ts) bh = _make_block_hash("test", 1, "0x00", ts)
ok, reason = v.validate_block_signature({ ok, reason = v.validate_block_signature({
"height": 1, "hash": bh, "parent_hash": "0x00", "height": 1, "hash": bh, "parent_hash": "0x00",
@@ -83,7 +83,7 @@ class TestProposerSignatureValidator:
v = ProposerSignatureValidator() v = ProposerSignatureValidator()
ok, reason = v.validate_block_signature({ ok, reason = v.validate_block_signature({
"height": 1, "hash": "0x" + "a" * 64, "parent_hash": "0x00", "height": 1, "hash": "0x" + "a" * 64, "parent_hash": "0x00",
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
}) })
assert ok is False assert ok is False
assert "Missing proposer" in reason assert "Missing proposer" in reason
@@ -92,7 +92,7 @@ class TestProposerSignatureValidator:
v = ProposerSignatureValidator() v = ProposerSignatureValidator()
ok, reason = v.validate_block_signature({ ok, reason = v.validate_block_signature({
"height": 1, "hash": "badhash", "parent_hash": "0x00", "height": 1, "hash": "badhash", "parent_hash": "0x00",
"proposer": "node-a", "timestamp": datetime.now(datetime.UTC).isoformat(), "proposer": "node-a", "timestamp": datetime.now(timezone.utc).isoformat(),
}) })
assert ok is False assert ok is False
assert "Invalid block hash" in reason assert "Invalid block hash" in reason
@@ -101,14 +101,14 @@ class TestProposerSignatureValidator:
v = ProposerSignatureValidator() v = ProposerSignatureValidator()
ok, reason = v.validate_block_signature({ ok, reason = v.validate_block_signature({
"height": 1, "hash": "0xabc", "parent_hash": "0x00", "height": 1, "hash": "0xabc", "parent_hash": "0x00",
"proposer": "node-a", "timestamp": datetime.now(datetime.UTC).isoformat(), "proposer": "node-a", "timestamp": datetime.now(timezone.utc).isoformat(),
}) })
assert ok is False assert ok is False
assert "Invalid hash length" in reason assert "Invalid hash length" in reason
def test_untrusted_proposer_rejected(self): def test_untrusted_proposer_rejected(self):
v = ProposerSignatureValidator(trusted_proposers=["node-a", "node-b"]) v = ProposerSignatureValidator(trusted_proposers=["node-a", "node-b"])
ts = datetime.now(datetime.UTC) ts = datetime.now(timezone.utc)
bh = _make_block_hash("test", 1, "0x00", ts) bh = _make_block_hash("test", 1, "0x00", ts)
ok, reason = v.validate_block_signature({ ok, reason = v.validate_block_signature({
"height": 1, "hash": bh, "parent_hash": "0x00", "height": 1, "hash": bh, "parent_hash": "0x00",
@@ -119,7 +119,7 @@ class TestProposerSignatureValidator:
def test_trusted_proposer_accepted(self): def test_trusted_proposer_accepted(self):
v = ProposerSignatureValidator(trusted_proposers=["node-a"]) v = ProposerSignatureValidator(trusted_proposers=["node-a"])
ts = datetime.now(datetime.UTC) ts = datetime.now(timezone.utc)
bh = _make_block_hash("test", 1, "0x00", ts) bh = _make_block_hash("test", 1, "0x00", ts)
ok, reason = v.validate_block_signature({ ok, reason = v.validate_block_signature({
"height": 1, "hash": bh, "parent_hash": "0x00", "height": 1, "hash": bh, "parent_hash": "0x00",
@@ -149,7 +149,7 @@ class TestChainSyncAppend:
def test_append_to_empty_chain(self, session_factory): def test_append_to_empty_chain(self, session_factory):
sync = ChainSync(session_factory, chain_id="test", validate_signatures=False) sync = ChainSync(session_factory, chain_id="test", validate_signatures=False)
ts = datetime.now(datetime.UTC) ts = datetime.now(timezone.utc)
bh = _make_block_hash("test", 0, "0x00", ts) bh = _make_block_hash("test", 0, "0x00", ts)
result = sync.import_block({ result = sync.import_block({
"height": 0, "hash": bh, "parent_hash": "0x00", "height": 0, "hash": bh, "parent_hash": "0x00",
@@ -316,7 +316,7 @@ class TestChainSyncSignatureValidation:
def test_untrusted_proposer_rejected_on_import(self, session_factory): def test_untrusted_proposer_rejected_on_import(self, session_factory):
validator = ProposerSignatureValidator(trusted_proposers=["node-a"]) validator = ProposerSignatureValidator(trusted_proposers=["node-a"])
sync = ChainSync(session_factory, chain_id="test", validator=validator, validate_signatures=True) sync = ChainSync(session_factory, chain_id="test", validator=validator, validate_signatures=True)
ts = datetime.now(datetime.UTC) ts = datetime.now(timezone.utc)
bh = _make_block_hash("test", 0, "0x00", ts) bh = _make_block_hash("test", 0, "0x00", ts)
result = sync.import_block({ result = sync.import_block({
"height": 0, "hash": bh, "parent_hash": "0x00", "height": 0, "hash": bh, "parent_hash": "0x00",
@@ -328,7 +328,7 @@ class TestChainSyncSignatureValidation:
def test_trusted_proposer_accepted_on_import(self, session_factory): def test_trusted_proposer_accepted_on_import(self, session_factory):
validator = ProposerSignatureValidator(trusted_proposers=["node-a"]) validator = ProposerSignatureValidator(trusted_proposers=["node-a"])
sync = ChainSync(session_factory, chain_id="test", validator=validator, validate_signatures=True) sync = ChainSync(session_factory, chain_id="test", validator=validator, validate_signatures=True)
ts = datetime.now(datetime.UTC) ts = datetime.now(timezone.utc)
bh = _make_block_hash("test", 0, "0x00", ts) bh = _make_block_hash("test", 0, "0x00", ts)
result = sync.import_block({ result = sync.import_block({
"height": 0, "hash": bh, "parent_hash": "0x00", "height": 0, "hash": bh, "parent_hash": "0x00",
@@ -339,7 +339,7 @@ class TestChainSyncSignatureValidation:
def test_validation_disabled(self, session_factory): def test_validation_disabled(self, session_factory):
validator = ProposerSignatureValidator(trusted_proposers=["node-a"]) validator = ProposerSignatureValidator(trusted_proposers=["node-a"])
sync = ChainSync(session_factory, chain_id="test", validator=validator, validate_signatures=False) sync = ChainSync(session_factory, chain_id="test", validator=validator, validate_signatures=False)
ts = datetime.now(datetime.UTC) ts = datetime.now(timezone.utc)
bh = _make_block_hash("test", 0, "0x00", ts) bh = _make_block_hash("test", 0, "0x00", ts)
result = sync.import_block({ result = sync.import_block({
"height": 0, "hash": bh, "parent_hash": "0x00", "height": 0, "hash": bh, "parent_hash": "0x00",
@@ -379,7 +379,7 @@ class TestSyncMetrics:
def test_accepted_block_increments_metrics(self, session_factory): def test_accepted_block_increments_metrics(self, session_factory):
sync = ChainSync(session_factory, chain_id="test", validate_signatures=False) sync = ChainSync(session_factory, chain_id="test", validate_signatures=False)
ts = datetime.now(datetime.UTC) ts = datetime.now(timezone.utc)
bh = _make_block_hash("test", 0, "0x00", ts) bh = _make_block_hash("test", 0, "0x00", ts)
sync.import_block({ sync.import_block({
"height": 0, "hash": bh, "parent_hash": "0x00", "height": 0, "hash": bh, "parent_hash": "0x00",
@@ -392,7 +392,7 @@ class TestSyncMetrics:
def test_rejected_block_increments_metrics(self, session_factory): def test_rejected_block_increments_metrics(self, session_factory):
validator = ProposerSignatureValidator(trusted_proposers=["node-a"]) validator = ProposerSignatureValidator(trusted_proposers=["node-a"])
sync = ChainSync(session_factory, chain_id="test", validator=validator, validate_signatures=True) sync = ChainSync(session_factory, chain_id="test", validator=validator, validate_signatures=True)
ts = datetime.now(datetime.UTC) ts = datetime.now(timezone.utc)
bh = _make_block_hash("test", 0, "0x00", ts) bh = _make_block_hash("test", 0, "0x00", ts)
sync.import_block({ sync.import_block({
"height": 0, "hash": bh, "parent_hash": "0x00", "height": 0, "hash": bh, "parent_hash": "0x00",

View File

@@ -5,7 +5,7 @@ Handles KYC/AML, regulatory compliance, and monitoring
import asyncio import asyncio
import json import json
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from pathlib import Path from pathlib import Path
from typing import Dict, Any, List, Optional from typing import Dict, Any, List, Optional
from fastapi import FastAPI, HTTPException from fastapi import FastAPI, HTTPException
@@ -68,7 +68,7 @@ async def root():
return { return {
"service": "AITBC Compliance Service", "service": "AITBC Compliance Service",
"status": "running", "status": "running",
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"version": "1.0.0" "version": "1.0.0"
} }
@@ -97,7 +97,7 @@ async def submit_kyc(kyc_request: KYCRequest):
"document_number": kyc_request.document_number, "document_number": kyc_request.document_number,
"address": kyc_request.address, "address": kyc_request.address,
"status": "pending", "status": "pending",
"submitted_at": datetime.now(datetime.UTC).isoformat(), "submitted_at": datetime.now(timezone.utc).isoformat(),
"reviewed_at": None, "reviewed_at": None,
"approved_at": None, "approved_at": None,
"risk_score": "medium", "risk_score": "medium",
@@ -111,8 +111,8 @@ async def submit_kyc(kyc_request: KYCRequest):
# Auto-approve for demo (in production, this would involve actual verification) # Auto-approve for demo (in production, this would involve actual verification)
kyc_record["status"] = "approved" kyc_record["status"] = "approved"
kyc_record["reviewed_at"] = datetime.now(datetime.UTC).isoformat() kyc_record["reviewed_at"] = datetime.now(timezone.utc).isoformat()
kyc_record["approved_at"] = datetime.now(datetime.UTC).isoformat() kyc_record["approved_at"] = datetime.now(timezone.utc).isoformat()
kyc_record["risk_score"] = "low" kyc_record["risk_score"] = "low"
logger.info(f"KYC approved for user: {kyc_request.user_id}") logger.info(f"KYC approved for user: {kyc_request.user_id}")
@@ -146,7 +146,7 @@ async def list_kyc_records():
@app.post("/api/v1/compliance/report") @app.post("/api/v1/compliance/report")
async def create_compliance_report(report: ComplianceReport): async def create_compliance_report(report: ComplianceReport):
"""Create a compliance report""" """Create a compliance report"""
report_id = f"report_{int(datetime.now(datetime.UTC).timestamp())}" report_id = f"report_{int(datetime.now(timezone.utc).timestamp())}"
compliance_record = { compliance_record = {
"report_id": report_id, "report_id": report_id,
@@ -155,7 +155,7 @@ async def create_compliance_report(report: ComplianceReport):
"severity": report.severity, "severity": report.severity,
"details": report.details, "details": report.details,
"status": "open", "status": "open",
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"assigned_to": None, "assigned_to": None,
"resolved_at": None, "resolved_at": None,
"resolution": None "resolution": None
@@ -195,7 +195,7 @@ async def monitor_transaction(transaction: TransactionMonitoring):
"currency": transaction.currency, "currency": transaction.currency,
"counterparty": transaction.counterparty, "counterparty": transaction.counterparty,
"timestamp": transaction.timestamp.isoformat(), "timestamp": transaction.timestamp.isoformat(),
"monitored_at": datetime.now(datetime.UTC).isoformat(), "monitored_at": datetime.now(timezone.utc).isoformat(),
"risk_score": calculate_transaction_risk(transaction), "risk_score": calculate_transaction_risk(transaction),
"flags": [], "flags": [],
"status": "monitored" "status": "monitored"
@@ -232,7 +232,7 @@ async def list_monitored_transactions():
@app.post("/api/v1/rules/create") @app.post("/api/v1/rules/create")
async def create_compliance_rule(rule_data: Dict[str, Any]): async def create_compliance_rule(rule_data: Dict[str, Any]):
"""Create a new compliance rule""" """Create a new compliance rule"""
rule_id = f"rule_{int(datetime.now(datetime.UTC).timestamp())}" rule_id = f"rule_{int(datetime.now(timezone.utc).timestamp())}"
rule = { rule = {
"rule_id": rule_id, "rule_id": rule_id,
@@ -243,7 +243,7 @@ async def create_compliance_rule(rule_data: Dict[str, Any]):
"actions": rule_data.get("actions", []), "actions": rule_data.get("actions", []),
"severity": rule_data.get("severity", "medium"), "severity": rule_data.get("severity", "medium"),
"active": True, "active": True,
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"trigger_count": 0 "trigger_count": 0
} }
@@ -294,7 +294,7 @@ async def compliance_dashboard():
}, },
"risk_distribution": get_risk_distribution(), "risk_distribution": get_risk_distribution(),
"recent_activity": get_recent_activity(), "recent_activity": get_recent_activity(),
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
# Helper functions # Helper functions
@@ -337,7 +337,7 @@ def check_suspicious_patterns(transaction: TransactionMonitoring) -> List[str]:
recent_transactions = [t for t in user_transactions recent_transactions = [t for t in user_transactions
if datetime.fromisoformat(t["monitored_at"]) > if datetime.fromisoformat(t["monitored_at"]) >
datetime.now(datetime.UTC) - timedelta(hours=1)] datetime.now(timezone.utc) - timedelta(hours=1)]
if len(recent_transactions) > 5: if len(recent_transactions) > 5:
flags.append("rapid_transactions") flags.append("rapid_transactions")
@@ -385,7 +385,7 @@ def get_recent_activity() -> List[Dict]:
recent_kyc = [r for r in kyc_records.values() recent_kyc = [r for r in kyc_records.values()
if r.get("approved_at") and if r.get("approved_at") and
datetime.fromisoformat(r["approved_at"]) > datetime.fromisoformat(r["approved_at"]) >
datetime.now(datetime.UTC) - timedelta(hours=24)] datetime.now(timezone.utc) - timedelta(hours=24)]
for kyc in recent_kyc[:5]: for kyc in recent_kyc[:5]:
activities.append({ activities.append({
@@ -397,7 +397,7 @@ def get_recent_activity() -> List[Dict]:
# Recent compliance reports # Recent compliance reports
recent_reports = [r for r in compliance_reports.values() recent_reports = [r for r in compliance_reports.values()
if datetime.fromisoformat(r["created_at"]) > if datetime.fromisoformat(r["created_at"]) >
datetime.now(datetime.UTC) - timedelta(hours=24)] datetime.now(timezone.utc) - timedelta(hours=24)]
for report in recent_reports[:5]: for report in recent_reports[:5]:
activities.append({ activities.append({
@@ -418,7 +418,7 @@ async def periodic_compliance_checks():
await asyncio.sleep(300) # Check every 5 minutes await asyncio.sleep(300) # Check every 5 minutes
# Check for expired KYC records # Check for expired KYC records
current_time = datetime.now(datetime.UTC) current_time = datetime.now(timezone.utc)
for user_id, kyc_record in kyc_records.items(): for user_id, kyc_record in kyc_records.items():
if kyc_record["status"] == "approved": if kyc_record["status"] == "approved":
approved_time = datetime.fromisoformat(kyc_record["approved_at"]) approved_time = datetime.fromisoformat(kyc_record["approved_at"])

View File

@@ -6,7 +6,7 @@ import sys
from pathlib import Path from pathlib import Path
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, KYCRequest, ComplianceReport, TransactionMonitoring, kyc_records, compliance_reports, suspicious_transactions, compliance_rules from main import app, KYCRequest, ComplianceReport, TransactionMonitoring, kyc_records, compliance_reports, suspicious_transactions, compliance_rules
@@ -62,7 +62,7 @@ def test_transaction_monitoring_zero_amount():
amount=0.0, amount=0.0,
currency="BTC", currency="BTC",
counterparty="counterparty1", counterparty="counterparty1",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert tx.amount == 0.0 assert tx.amount == 0.0
@@ -76,7 +76,7 @@ def test_transaction_monitoring_negative_amount():
amount=-1000.0, amount=-1000.0,
currency="BTC", currency="BTC",
counterparty="counterparty1", counterparty="counterparty1",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert tx.amount == -1000.0 assert tx.amount == -1000.0

View File

@@ -6,7 +6,7 @@ import sys
from pathlib import Path from pathlib import Path
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, KYCRequest, ComplianceReport, TransactionMonitoring, kyc_records, compliance_reports, suspicious_transactions, compliance_rules from main import app, KYCRequest, ComplianceReport, TransactionMonitoring, kyc_records, compliance_reports, suspicious_transactions, compliance_rules
@@ -171,7 +171,7 @@ def test_monitor_transaction():
amount=1000.0, amount=1000.0,
currency="BTC", currency="BTC",
counterparty="counterparty1", counterparty="counterparty1",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
response = client.post("/api/v1/monitoring/transaction", json=tx.model_dump(mode='json')) response = client.post("/api/v1/monitoring/transaction", json=tx.model_dump(mode='json'))
assert response.status_code == 200 assert response.status_code == 200
@@ -190,7 +190,7 @@ def test_monitor_suspicious_transaction():
amount=100000.0, amount=100000.0,
currency="BTC", currency="BTC",
counterparty="high_risk_entity_1", counterparty="high_risk_entity_1",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
response = client.post("/api/v1/monitoring/transaction", json=tx.model_dump(mode='json')) response = client.post("/api/v1/monitoring/transaction", json=tx.model_dump(mode='json'))
assert response.status_code == 200 assert response.status_code == 200

View File

@@ -5,7 +5,7 @@ import sys
import sys import sys
from pathlib import Path from pathlib import Path
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, KYCRequest, ComplianceReport, TransactionMonitoring, calculate_transaction_risk, check_suspicious_patterns from main import app, KYCRequest, ComplianceReport, TransactionMonitoring, calculate_transaction_risk, check_suspicious_patterns
@@ -62,7 +62,7 @@ def test_transaction_monitoring_model():
amount=1000.0, amount=1000.0,
currency="BTC", currency="BTC",
counterparty="counterparty1", counterparty="counterparty1",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert tx.transaction_id == "tx123" assert tx.transaction_id == "tx123"
assert tx.user_id == "user123" assert tx.user_id == "user123"
@@ -125,7 +125,7 @@ def test_check_suspicious_patterns_high_value():
amount=100000.0, amount=100000.0,
currency="BTC", currency="BTC",
counterparty="counterparty1", counterparty="counterparty1",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
flags = check_suspicious_patterns(tx) flags = check_suspicious_patterns(tx)
assert "high_value_transaction" in flags assert "high_value_transaction" in flags
@@ -140,7 +140,7 @@ def test_check_suspicious_patterns_high_risk_counterparty():
amount=1000.0, amount=1000.0,
currency="BTC", currency="BTC",
counterparty="high_risk_entity_1", counterparty="high_risk_entity_1",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
flags = check_suspicious_patterns(tx) flags = check_suspicious_patterns(tx)
assert "high_risk_counterparty" in flags assert "high_risk_counterparty" in flags
@@ -155,7 +155,7 @@ def test_check_suspicious_patterns_none():
amount=1000.0, amount=1000.0,
currency="BTC", currency="BTC",
counterparty="safe_counterparty", counterparty="safe_counterparty",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
flags = check_suspicious_patterns(tx) flags = check_suspicious_patterns(tx)
assert len(flags) == 0 assert len(flags) == 0

View File

@@ -6,7 +6,7 @@ Demonstrates basic usage of the Agent Identity SDK
import asyncio import asyncio
import json import json
from datetime import datetime, UTC from datetime import datetime, timezone
from typing import Dict, Any from typing import Dict, Any
# Import SDK components # Import SDK components
@@ -94,7 +94,7 @@ async def basic_identity_example():
"agent_id": identity.agent_id, "agent_id": identity.agent_id,
"chain_id": mapping.chain_id, "chain_id": mapping.chain_id,
"chain_address": mapping.chain_address, "chain_address": mapping.chain_address,
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"verification_method": "demo" "verification_method": "demo"
} }
@@ -234,7 +234,7 @@ async def advanced_transaction_example():
"description": "Updated description with new capabilities", "description": "Updated description with new capabilities",
"metadata": { "metadata": {
"version": "1.1.0", "version": "1.1.0",
"last_updated": datetime.now(datetime.UTC).isoformat() "last_updated": datetime.now(timezone.utc).isoformat()
}, },
"tags": ["demo", "ai", "updated"] "tags": ["demo", "ai", "updated"]
} }

View File

@@ -6,7 +6,7 @@ Complete deployment procedures for the agent orchestration system
import asyncio import asyncio
import json import json
from aitbc.logging import get_logger from aitbc.logging import get_logger
from datetime import datetime, UTC from datetime import datetime, timezone
from typing import Dict, List, Optional, Any from typing import Dict, List, Optional, Any
from pathlib import Path from pathlib import Path
@@ -30,7 +30,7 @@ class AgentOrchestrationDeployment:
"""Deploy complete agent orchestration system to production""" """Deploy complete agent orchestration system to production"""
deployment_result = { deployment_result = {
"deployment_id": f"prod_deploy_{datetime.now(datetime.UTC).strftime('%Y%m%d_%H%M%S')}", "deployment_id": f"prod_deploy_{datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')}",
"status": "in_progress", "status": "in_progress",
"steps_completed": [], "steps_completed": [],
"steps_failed": [], "steps_failed": [],

View File

@@ -6,7 +6,7 @@ Ongoing maintenance, monitoring, and enhancement of the complete system
import asyncio import asyncio
import json import json
from aitbc.logging import get_logger from aitbc.logging import get_logger
from datetime import datetime, UTC from datetime import datetime, timezone
from typing import Dict, List, Optional, Any from typing import Dict, List, Optional, Any
from enum import Enum from enum import Enum
@@ -73,7 +73,7 @@ class SystemMaintenanceManager:
"""Perform comprehensive maintenance cycle""" """Perform comprehensive maintenance cycle"""
maintenance_result = { maintenance_result = {
"maintenance_cycle": f"maintenance_{datetime.now(datetime.UTC).strftime('%Y%m%d_%H%M%S')}", "maintenance_cycle": f"maintenance_{datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')}",
"status": "in_progress", "status": "in_progress",
"categories_completed": [], "categories_completed": [],
"enhancements_implemented": [], "enhancements_implemented": [],

View File

@@ -5,7 +5,7 @@ Provides unified agent identification and cross-chain compatibility
import hashlib import hashlib
import json import json
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from typing import Any from typing import Any
from uuid import uuid4 from uuid import uuid4
@@ -90,7 +90,7 @@ class AgentIdentityCore:
if hasattr(identity, field): if hasattr(identity, field):
setattr(identity, field, value) setattr(identity, field, value)
identity.updated_at = datetime.now(datetime.UTC) identity.updated_at = datetime.now(timezone.utc)
self.session.commit() self.session.commit()
self.session.refresh(identity) self.session.refresh(identity)
@@ -133,7 +133,7 @@ class AgentIdentityCore:
# Update identity's supported chains # Update identity's supported chains
if chain_id not in identity.supported_chains: if chain_id not in identity.supported_chains:
identity.supported_chains.append(str(chain_id)) identity.supported_chains.append(str(chain_id))
identity.updated_at = datetime.now(datetime.UTC) identity.updated_at = datetime.now(timezone.utc)
self.session.commit() self.session.commit()
logger.info(f"Registered cross-chain identity: {identity_id} -> {chain_id}:{chain_address}") logger.info(f"Registered cross-chain identity: {identity_id} -> {chain_id}:{chain_address}")
@@ -190,7 +190,7 @@ class AgentIdentityCore:
# Update mapping verification status # Update mapping verification status
mapping.is_verified = True mapping.is_verified = True
mapping.verified_at = datetime.now(datetime.UTC) mapping.verified_at = datetime.now(timezone.utc)
mapping.verification_proof = proof_data mapping.verification_proof = proof_data
self.session.commit() self.session.commit()
@@ -198,7 +198,7 @@ class AgentIdentityCore:
identity = await self.get_identity(identity_id) identity = await self.get_identity(identity_id)
if identity and chain_id == identity.primary_chain: if identity and chain_id == identity.primary_chain:
identity.is_verified = True identity.is_verified = True
identity.verified_at = datetime.now(datetime.UTC) identity.verified_at = datetime.now(timezone.utc)
identity.verification_level = verification_type identity.verification_level = verification_type
self.session.commit() self.session.commit()
@@ -242,7 +242,7 @@ class AgentIdentityCore:
else: else:
setattr(mapping, field, value) setattr(mapping, field, value)
mapping.updated_at = datetime.now(datetime.UTC) mapping.updated_at = datetime.now(timezone.utc)
self.session.commit() self.session.commit()
self.session.refresh(mapping) self.session.refresh(mapping)
@@ -260,11 +260,11 @@ class AgentIdentityCore:
# Update identity status # Update identity status
identity.status = IdentityStatus.REVOKED identity.status = IdentityStatus.REVOKED
identity.is_verified = False identity.is_verified = False
identity.updated_at = datetime.now(datetime.UTC) identity.updated_at = datetime.now(timezone.utc)
# Add revocation reason to identity_data # Add revocation reason to identity_data
identity.identity_data["revocation_reason"] = reason identity.identity_data["revocation_reason"] = reason
identity.identity_data["revoked_at"] = datetime.now(datetime.UTC).isoformat() identity.identity_data["revoked_at"] = datetime.now(timezone.utc).isoformat()
self.session.commit() self.session.commit()
@@ -280,11 +280,11 @@ class AgentIdentityCore:
# Update identity status # Update identity status
identity.status = IdentityStatus.SUSPENDED identity.status = IdentityStatus.SUSPENDED
identity.updated_at = datetime.now(datetime.UTC) identity.updated_at = datetime.now(timezone.utc)
# Add suspension reason to identity_data # Add suspension reason to identity_data
identity.identity_data["suspension_reason"] = reason identity.identity_data["suspension_reason"] = reason
identity.identity_data["suspended_at"] = datetime.now(datetime.UTC).isoformat() identity.identity_data["suspended_at"] = datetime.now(timezone.utc).isoformat()
self.session.commit() self.session.commit()
@@ -303,7 +303,7 @@ class AgentIdentityCore:
# Update identity status # Update identity status
identity.status = IdentityStatus.ACTIVE identity.status = IdentityStatus.ACTIVE
identity.updated_at = datetime.now(datetime.UTC) identity.updated_at = datetime.now(timezone.utc)
# Clear suspension identity_data # Clear suspension identity_data
if "suspension_reason" in identity.identity_data: if "suspension_reason" in identity.identity_data:
@@ -336,8 +336,8 @@ class AgentIdentityCore:
volume_factor = min(amount / 1000.0, 1.0) # Cap at 1.0 for amounts > 1000 volume_factor = min(amount / 1000.0, 1.0) # Cap at 1.0 for amounts > 1000
identity.reputation_score = base_score * (0.7 + 0.3 * volume_factor) identity.reputation_score = base_score * (0.7 + 0.3 * volume_factor)
identity.last_activity = datetime.now(datetime.UTC) identity.last_activity = datetime.now(timezone.utc)
identity.updated_at = datetime.now(datetime.UTC) identity.updated_at = datetime.now(timezone.utc)
self.session.commit() self.session.commit()
self.session.refresh(identity) self.session.refresh(identity)
@@ -452,7 +452,7 @@ class AgentIdentityCore:
"owner_address": identity.owner_address, "owner_address": identity.owner_address,
"chain_id": chain_id, "chain_id": chain_id,
"chain_address": mapping.chain_address, "chain_address": mapping.chain_address,
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"nonce": str(uuid4()), "nonce": str(uuid4()),
} }
@@ -463,5 +463,5 @@ class AgentIdentityCore:
return { return {
"proof_data": proof_data, "proof_data": proof_data,
"proof_hash": proof_hash, "proof_hash": proof_hash,
"expires_at": (datetime.now(datetime.UTC) + timedelta(hours=24)).isoformat(), "expires_at": (datetime.now(timezone.utc) + timedelta(hours=24)).isoformat(),
} }

View File

@@ -3,7 +3,7 @@ Agent Identity Manager Implementation
High-level manager for agent identity operations and cross-chain management High-level manager for agent identity operations and cross-chain management
""" """
from datetime import datetime, UTC from datetime import datetime, timezone
from typing import Any from typing import Any
from uuid import uuid4 from uuid import uuid4
@@ -171,7 +171,7 @@ class AgentIdentityManager:
# Update identity reputation # Update identity reputation
await self.core.update_reputation(agent_id, True, 0) # This will recalculate based on new data await self.core.update_reputation(agent_id, True, 0) # This will recalculate based on new data
identity.reputation_score = aggregated_score identity.reputation_score = aggregated_score
identity.updated_at = datetime.now(datetime.UTC) identity.updated_at = datetime.now(timezone.utc)
self.session.commit() self.session.commit()
else: else:
aggregated_score = identity.reputation_score aggregated_score = identity.reputation_score
@@ -181,7 +181,7 @@ class AgentIdentityManager:
"aggregated_reputation": aggregated_score, "aggregated_reputation": aggregated_score,
"chain_reputations": reputation_scores, "chain_reputations": reputation_scores,
"verified_chains": list(verified_chains) if "verified_chains" in locals() else [], "verified_chains": list(verified_chains) if "verified_chains" in locals() else [],
"sync_timestamp": datetime.now(datetime.UTC).isoformat(), "sync_timestamp": datetime.now(timezone.utc).isoformat(),
} }
except Exception as e: except Exception as e:
@@ -449,12 +449,12 @@ class AgentIdentityManager:
"supported_chains": supported_chains, "supported_chains": supported_chains,
"cleaned_verifications": cleaned_count, "cleaned_verifications": cleaned_count,
"issues": issues, "issues": issues,
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
} }
except Exception as e: except Exception as e:
logger.error(f"Failed to get registry health: {e}") logger.error(f"Failed to get registry health: {e}")
return {"status": "error", "error": "Health check failed", "timestamp": datetime.now(datetime.UTC).isoformat()} return {"status": "error", "error": "Health check failed", "timestamp": datetime.now(timezone.utc).isoformat()}
async def export_agent_identity(self, agent_id: str, format: str = "json") -> dict[str, Any]: async def export_agent_identity(self, agent_id: str, format: str = "json") -> dict[str, Any]:
"""Export agent identity data for backup or migration""" """Export agent identity data for backup or migration"""
@@ -469,7 +469,7 @@ class AgentIdentityManager:
# Prepare export data # Prepare export data
export_data = { export_data = {
"export_version": "1.0", "export_version": "1.0",
"export_timestamp": datetime.now(datetime.UTC).isoformat(), "export_timestamp": datetime.now(timezone.utc).isoformat(),
"agent_id": agent_id, "agent_id": agent_id,
"identity": summary["identity"], "identity": summary["identity"],
"cross_chain_mappings": summary["cross_chain"]["mappings"], "cross_chain_mappings": summary["cross_chain"]["mappings"],
@@ -541,7 +541,7 @@ class AgentIdentityManager:
"identity_id": identity.id, "identity_id": identity.id,
"import_successful": True, "import_successful": True,
"restored_mappings": len(chain_mappings), "restored_mappings": len(chain_mappings),
"import_timestamp": datetime.now(datetime.UTC).isoformat(), "import_timestamp": datetime.now(timezone.utc).isoformat(),
} }
except Exception as e: except Exception as e:

View File

@@ -5,7 +5,7 @@ Registry for cross-chain agent identity mapping and synchronization
import hashlib import hashlib
import json import json
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from typing import Any from typing import Any
from uuid import uuid4 from uuid import uuid4
@@ -97,7 +97,7 @@ class CrossChainRegistry:
registration_results.append({"chain_id": chain_id, "chain_address": chain_address, "error": str(e)}) registration_results.append({"chain_id": chain_id, "chain_address": chain_address, "error": str(e)})
# Update identity # Update identity
identity.updated_at = datetime.now(datetime.UTC) identity.updated_at = datetime.now(timezone.utc)
self.session.commit() self.session.commit()
return { return {
@@ -143,7 +143,7 @@ class CrossChainRegistry:
old_address = mapping.chain_address old_address = mapping.chain_address
mapping.chain_address = new_address.lower() mapping.chain_address = new_address.lower()
mapping.updated_at = datetime.now(datetime.UTC) mapping.updated_at = datetime.now(timezone.utc)
# Reset verification status since address changed # Reset verification status since address changed
mapping.is_verified = False mapping.is_verified = False
@@ -195,7 +195,7 @@ class CrossChainRegistry:
proof_hash=proof_hash, proof_hash=proof_hash,
proof_data=proof_data, proof_data=proof_data,
verification_result="approved", verification_result="approved",
expires_at=datetime.now(datetime.UTC) + timedelta(days=30), expires_at=datetime.now(timezone.utc) + timedelta(days=30),
) )
self.session.add(verification) self.session.add(verification)
@@ -204,7 +204,7 @@ class CrossChainRegistry:
# Update mapping verification status # Update mapping verification status
mapping.is_verified = True mapping.is_verified = True
mapping.verified_at = datetime.now(datetime.UTC) mapping.verified_at = datetime.now(timezone.utc)
mapping.verification_proof = proof_data mapping.verification_proof = proof_data
self.session.commit() self.session.commit()
@@ -212,7 +212,7 @@ class CrossChainRegistry:
if self._is_higher_verification_level(verification_type, identity.verification_level): if self._is_higher_verification_level(verification_type, identity.verification_level):
identity.verification_level = verification_type identity.verification_level = verification_type
identity.is_verified = True identity.is_verified = True
identity.verified_at = datetime.now(datetime.UTC) identity.verified_at = datetime.now(timezone.utc)
self.session.commit() self.session.commit()
logger.info(f"Verified cross-chain identity: {identity_id} on chain {chain_id}") logger.info(f"Verified cross-chain identity: {identity_id} on chain {chain_id}")
@@ -229,14 +229,14 @@ class CrossChainRegistry:
mapping.is_verified = False mapping.is_verified = False
mapping.verified_at = None mapping.verified_at = None
mapping.verification_proof = None mapping.verification_proof = None
mapping.updated_at = datetime.now(datetime.UTC) mapping.updated_at = datetime.now(timezone.utc)
# Add revocation to metadata # Add revocation to metadata
if not mapping.chain_metadata: if not mapping.chain_metadata:
mapping.chain_metadata = {} mapping.chain_metadata = {}
mapping.chain_metadata["verification_revoked"] = True mapping.chain_metadata["verification_revoked"] = True
mapping.chain_metadata["revocation_reason"] = reason mapping.chain_metadata["revocation_reason"] = reason
mapping.chain_metadata["revoked_at"] = datetime.now(datetime.UTC).isoformat() mapping.chain_metadata["revoked_at"] = datetime.now(timezone.utc).isoformat()
self.session.commit() self.session.commit()
@@ -453,7 +453,7 @@ class CrossChainRegistry:
async def cleanup_expired_verifications(self) -> int: async def cleanup_expired_verifications(self) -> int:
"""Clean up expired verification records""" """Clean up expired verification records"""
current_time = datetime.now(datetime.UTC) current_time = datetime.now(timezone.utc)
# Find expired verifications # Find expired verifications
stmt = select(IdentityVerification).where(IdentityVerification.expires_at < current_time) stmt = select(IdentityVerification).where(IdentityVerification.expires_at < current_time)

View File

@@ -4,7 +4,7 @@ Provides blockchain-agnostic wallet interface for agents
""" """
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from datetime import datetime, UTC from datetime import datetime, timezone
from decimal import Decimal from decimal import Decimal
from typing import Any from typing import Any
@@ -69,7 +69,7 @@ class EthereumWalletAdapter(WalletAdapter):
"wallet_address": f"0x{'0' * 40}", # Mock address "wallet_address": f"0x{'0' * 40}", # Mock address
"contract_address": f"0x{'1' * 40}", # Mock contract "contract_address": f"0x{'1' * 40}", # Mock contract
"transaction_hash": f"0x{'2' * 64}", # Mock tx hash "transaction_hash": f"0x{'2' * 64}", # Mock tx hash
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
} }
async def get_balance(self, wallet_address: str) -> Decimal: async def get_balance(self, wallet_address: str) -> Decimal:
@@ -91,7 +91,7 @@ class EthereumWalletAdapter(WalletAdapter):
"gas_price": "20000000000", "gas_price": "20000000000",
"status": "success", "status": "success",
"block_number": 12345, "block_number": 12345,
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
} }
async def get_transaction_history(self, wallet_address: str, limit: int = 50, offset: int = 0) -> list[dict[str, Any]]: async def get_transaction_history(self, wallet_address: str, limit: int = 50, offset: int = 0) -> list[dict[str, Any]]:
@@ -105,7 +105,7 @@ class EthereumWalletAdapter(WalletAdapter):
"amount": "0.1", "amount": "0.1",
"gas_used": "21000", "gas_used": "21000",
"block_number": 12344, "block_number": 12344,
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
} }
] ]
@@ -269,7 +269,7 @@ class MultiChainWalletAdapter:
# Update wallet in database # Update wallet in database
wallet.total_spent += float(amount) wallet.total_spent += float(amount)
wallet.last_transaction = datetime.now(datetime.UTC) wallet.last_transaction = datetime.now(timezone.utc)
wallet.transaction_count += 1 wallet.transaction_count += 1
self.session.commit() self.session.commit()
@@ -312,7 +312,7 @@ class MultiChainWalletAdapter:
if hasattr(wallet, field): if hasattr(wallet, field):
setattr(wallet, field, value) setattr(wallet, field, value)
wallet.updated_at = datetime.now(datetime.UTC) wallet.updated_at = datetime.now(timezone.utc)
self.session.commit() self.session.commit()
self.session.refresh(wallet) self.session.refresh(wallet)
@@ -338,7 +338,7 @@ class MultiChainWalletAdapter:
# Deactivate wallet # Deactivate wallet
wallet.is_active = False wallet.is_active = False
wallet.updated_at = datetime.now(datetime.UTC) wallet.updated_at = datetime.now(timezone.utc)
self.session.commit() self.session.commit()

View File

@@ -7,7 +7,7 @@ import hashlib
import json import json
import secrets import secrets
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from datetime import datetime, UTC from datetime import datetime, timezone
from decimal import Decimal from decimal import Decimal
from enum import StrEnum from enum import StrEnum
from typing import Any from typing import Any
@@ -124,7 +124,7 @@ class EnhancedWalletAdapter(ABC):
"""Securely sign a message""" """Securely sign a message"""
try: try:
# Add timestamp and nonce for replay protection # Add timestamp and nonce for replay protection
timestamp = str(int(datetime.now(datetime.UTC).timestamp())) timestamp = str(int(datetime.now(timezone.utc).timestamp()))
nonce = secrets.token_hex(16) nonce = secrets.token_hex(16)
message_to_sign = f"{message}:{timestamp}:{nonce}" message_to_sign = f"{message}:{timestamp}:{nonce}"
@@ -194,7 +194,7 @@ class EthereumWalletAdapter(EnhancedWalletAdapter):
"chain_type": self.chain_type.value, "chain_type": self.chain_type.value,
"owner_address": owner_address, "owner_address": owner_address,
"security_level": self.security_level.value, "security_level": self.security_level.value,
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"status": WalletStatus.ACTIVE.value, "status": WalletStatus.ACTIVE.value,
"security_config": security_config, "security_config": security_config,
"nonce": 0, "nonce": 0,
@@ -227,7 +227,7 @@ class EthereumWalletAdapter(EnhancedWalletAdapter):
"chain_id": self.chain_id, "chain_id": self.chain_id,
"eth_balance": eth_balance, "eth_balance": eth_balance,
"token_balances": {}, "token_balances": {},
"last_updated": datetime.now(datetime.UTC).isoformat(), "last_updated": datetime.now(timezone.utc).isoformat(),
} }
# Get token balances if specified # Get token balances if specified
@@ -304,7 +304,7 @@ class EthereumWalletAdapter(EnhancedWalletAdapter):
"gas_limit": gas_limit, "gas_limit": gas_limit,
"gas_price": gas_price, "gas_price": gas_price,
"status": TransactionStatus.PENDING.value, "status": TransactionStatus.PENDING.value,
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
} }
logger.info(f"Executed Ethereum transaction {tx_hash} from {from_address} to {to_address}") logger.info(f"Executed Ethereum transaction {tx_hash} from {from_address} to {to_address}")
@@ -331,7 +331,7 @@ class EthereumWalletAdapter(EnhancedWalletAdapter):
"gas_used": None, "gas_used": None,
"effective_gas_price": None, "effective_gas_price": None,
"logs": [], "logs": [],
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
} }
# Get transaction details # Get transaction details
@@ -348,7 +348,7 @@ class EthereumWalletAdapter(EnhancedWalletAdapter):
"from": tx_data.get("from"), "from": tx_data.get("from"),
"to": tx_data.get("to"), "to": tx_data.get("to"),
"value": int(tx_data.get("value", "0x0"), 16), "value": int(tx_data.get("value", "0x0"), 16),
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
} }
return result return result

View File

@@ -4,7 +4,7 @@ Exception classes and error response schemas for AITBC coordinator
Provides structured error responses for consistent API error handling. Provides structured error responses for consistent API error handling.
""" """
from datetime import datetime, UTC from datetime import datetime, timezone
from typing import Any from typing import Any
from pydantic import BaseModel, Field from pydantic import BaseModel, Field

View File

@@ -122,7 +122,7 @@ class ServiceRegistry(BaseModel):
"""Service registry containing all available services""" """Service registry containing all available services"""
version: str = Field("1.0.0", description="Registry version") version: str = Field("1.0.0", description="Registry version")
last_updated: datetime = Field(default_factory=datetime.now(datetime.UTC), description="Last update time") last_updated: datetime = Field(default_factory=datetime.now(timezone.utc), description="Last update time")
services: dict[str, ServiceDefinition] = Field(..., description="Service definitions by ID") services: dict[str, ServiceDefinition] = Field(..., description="Service definitions by ID")
def get_service(self, service_id: str) -> ServiceDefinition | None: def get_service(self, service_id: str) -> ServiceDefinition | None:

View File

@@ -3,7 +3,7 @@ Repository layer for confidential transactions
""" """
from base64 import b64decode from base64 import b64decode
from datetime import datetime, UTC from datetime import datetime, timezone
from sqlalchemy import and_, delete, select, update from sqlalchemy import and_, delete, select, update
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
@@ -131,7 +131,7 @@ class ParticipantKeyRepository:
stmt = ( stmt = (
update(ParticipantKeyDB) update(ParticipantKeyDB)
.where(ParticipantKeyDB.participant_id == participant_id) .where(ParticipantKeyDB.participant_id == participant_id)
.values(active=active, revoked_at=datetime.now(datetime.UTC) if not active else None, revoke_reason=reason) .values(active=active, revoked_at=datetime.now(timezone.utc) if not active else None, revoke_reason=reason)
) )
result = await session.execute(stmt) result = await session.execute(stmt)
@@ -309,7 +309,7 @@ class AuditAuthorizationRepository:
and_( and_(
AuditAuthorizationDB.id == authorization_id, AuditAuthorizationDB.id == authorization_id,
AuditAuthorizationDB.active, AuditAuthorizationDB.active,
AuditAuthorizationDB.expires_at > datetime.now(datetime.UTC), AuditAuthorizationDB.expires_at > datetime.now(timezone.utc),
) )
) )
@@ -321,7 +321,7 @@ class AuditAuthorizationRepository:
stmt = ( stmt = (
update(AuditAuthorizationDB) update(AuditAuthorizationDB)
.where(AuditAuthorizationDB.id == authorization_id) .where(AuditAuthorizationDB.id == authorization_id)
.values(active=False, revoked_at=datetime.now(datetime.UTC)) .values(active=False, revoked_at=datetime.now(timezone.utc))
) )
result = await session.execute(stmt) result = await session.execute(stmt)
@@ -331,7 +331,7 @@ class AuditAuthorizationRepository:
async def cleanup_expired(self, session: AsyncSession) -> int: async def cleanup_expired(self, session: AsyncSession) -> int:
"""Clean up expired authorizations""" """Clean up expired authorizations"""
stmt = update(AuditAuthorizationDB).where(AuditAuthorizationDB.expires_at < datetime.now(datetime.UTC)).values(active=False) stmt = update(AuditAuthorizationDB).where(AuditAuthorizationDB.expires_at < datetime.now(timezone.utc)).values(active=False)
result = await session.execute(stmt) result = await session.execute(stmt)
await session.commit() await session.commit()

View File

@@ -3,7 +3,7 @@ Cross-Chain Reputation Aggregator
Aggregates reputation data from multiple blockchains and normalizes scores Aggregates reputation data from multiple blockchains and normalizes scores
""" """
from datetime import datetime, UTC from datetime import datetime, timezone
from typing import Any from typing import Any
from aitbc import get_logger from aitbc import get_logger
@@ -147,7 +147,7 @@ class CrossChainReputationAggregator:
{ {
"agent_id": agent_id, "agent_id": agent_id,
"anomaly_type": "low_consistency", "anomaly_type": "low_consistency",
"detected_at": datetime.now(datetime.UTC), "detected_at": datetime.now(timezone.utc),
"description": f"Low consistency score: {aggregation.consistency_score:.2f}", "description": f"Low consistency score: {aggregation.consistency_score:.2f}",
"severity": "high" if aggregation.consistency_score < 0.5 else "medium", "severity": "high" if aggregation.consistency_score < 0.5 else "medium",
"consistency_score": aggregation.consistency_score, "consistency_score": aggregation.consistency_score,
@@ -162,7 +162,7 @@ class CrossChainReputationAggregator:
{ {
"agent_id": agent_id, "agent_id": agent_id,
"anomaly_type": "high_variance", "anomaly_type": "high_variance",
"detected_at": datetime.now(datetime.UTC), "detected_at": datetime.now(timezone.utc),
"description": f"High score variance: {aggregation.score_variance:.2f}", "description": f"High score variance: {aggregation.score_variance:.2f}",
"severity": "high" if aggregation.score_variance > 0.5 else "medium", "severity": "high" if aggregation.score_variance > 0.5 else "medium",
"score_variance": aggregation.score_variance, "score_variance": aggregation.score_variance,
@@ -180,7 +180,7 @@ class CrossChainReputationAggregator:
{ {
"agent_id": agent_id, "agent_id": agent_id,
"anomaly_type": "missing_chain_data", "anomaly_type": "missing_chain_data",
"detected_at": datetime.now(datetime.UTC), "detected_at": datetime.now(timezone.utc),
"description": f"Missing data for chains: {list(missing_chains)}", "description": f"Missing data for chains: {list(missing_chains)}",
"severity": "medium", "severity": "medium",
"missing_chains": list(missing_chains), "missing_chains": list(missing_chains),
@@ -221,7 +221,7 @@ class CrossChainReputationAggregator:
# Update reputation # Update reputation
reputation.trust_score = new_score * 1000 # Convert to 0-1000 scale reputation.trust_score = new_score * 1000 # Convert to 0-1000 scale
reputation.reputation_level = self._determine_reputation_level(new_score) reputation.reputation_level = self._determine_reputation_level(new_score)
reputation.updated_at = datetime.now(datetime.UTC) reputation.updated_at = datetime.now(timezone.utc)
# Create event record # Create event record
event = ReputationEvent( event = ReputationEvent(
@@ -231,7 +231,7 @@ class CrossChainReputationAggregator:
trust_score_before=reputation.trust_score, trust_score_before=reputation.trust_score,
trust_score_after=reputation.trust_score, trust_score_after=reputation.trust_score,
event_data=update, event_data=update,
occurred_at=datetime.now(datetime.UTC), occurred_at=datetime.now(timezone.utc),
) )
self.session.add(event) self.session.add(event)
@@ -242,8 +242,8 @@ class CrossChainReputationAggregator:
agent_id=agent_id, agent_id=agent_id,
trust_score=new_score * 1000, trust_score=new_score * 1000,
reputation_level=self._determine_reputation_level(new_score), reputation_level=self._determine_reputation_level(new_score),
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
updated_at=datetime.now(datetime.UTC), updated_at=datetime.now(timezone.utc),
) )
self.session.add(reputation) self.session.add(reputation)
@@ -316,7 +316,7 @@ class CrossChainReputationAggregator:
"reputation_distribution": distribution, "reputation_distribution": distribution,
"total_transactions": total_transactions, "total_transactions": total_transactions,
"success_rate": success_rate, "success_rate": success_rate,
"last_updated": datetime.now(datetime.UTC), "last_updated": datetime.now(timezone.utc),
} }
except Exception as e: except Exception as e:
@@ -430,7 +430,7 @@ class CrossChainReputationAggregator:
aggregation.score_variance = variance aggregation.score_variance = variance
aggregation.score_range = score_range aggregation.score_range = score_range
aggregation.consistency_score = consistency_score aggregation.consistency_score = consistency_score
aggregation.last_updated = datetime.now(datetime.UTC) aggregation.last_updated = datetime.now(timezone.utc)
else: else:
aggregation = CrossChainReputationAggregation( aggregation = CrossChainReputationAggregation(
agent_id=agent_id, agent_id=agent_id,
@@ -441,8 +441,8 @@ class CrossChainReputationAggregator:
score_range=score_range, score_range=score_range,
consistency_score=consistency_score, consistency_score=consistency_score,
verification_status="pending", verification_status="pending",
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
last_updated=datetime.now(datetime.UTC), last_updated=datetime.now(timezone.utc),
) )
self.session.add(aggregation) self.session.add(aggregation)

View File

@@ -3,7 +3,7 @@ Cross-Chain Reputation Engine
Core reputation calculation and aggregation engine for multi-chain agent reputation Core reputation calculation and aggregation engine for multi-chain agent reputation
""" """
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from typing import Any from typing import Any
from aitbc import get_logger from aitbc import get_logger
@@ -57,8 +57,8 @@ class CrossChainReputationEngine:
agent_id=agent_id, agent_id=agent_id,
trust_score=score * 1000, # Convert to 0-1000 scale trust_score=score * 1000, # Convert to 0-1000 scale
reputation_level=self._determine_reputation_level(score), reputation_level=self._determine_reputation_level(score),
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
updated_at=datetime.now(datetime.UTC), updated_at=datetime.now(timezone.utc),
) )
self.session.add(new_reputation) self.session.add(new_reputation)
@@ -152,8 +152,8 @@ class CrossChainReputationEngine:
agent_id=agent_id, agent_id=agent_id,
trust_score=max(0, min(1000, (base_score + impact_score) * 1000)), trust_score=max(0, min(1000, (base_score + impact_score) * 1000)),
reputation_level=self._determine_reputation_level(base_score + impact_score), reputation_level=self._determine_reputation_level(base_score + impact_score),
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
updated_at=datetime.now(datetime.UTC), updated_at=datetime.now(timezone.utc),
) )
self.session.add(reputation) self.session.add(reputation)
@@ -164,7 +164,7 @@ class CrossChainReputationEngine:
reputation.trust_score = new_score * 1000 reputation.trust_score = new_score * 1000
reputation.reputation_level = self._determine_reputation_level(new_score) reputation.reputation_level = self._determine_reputation_level(new_score)
reputation.updated_at = datetime.now(datetime.UTC) reputation.updated_at = datetime.now(timezone.utc)
# Create reputation event record # Create reputation event record
event = ReputationEvent( event = ReputationEvent(
@@ -174,7 +174,7 @@ class CrossChainReputationEngine:
trust_score_before=reputation.trust_score - (impact_score * 1000), trust_score_before=reputation.trust_score - (impact_score * 1000),
trust_score_after=reputation.trust_score, trust_score_after=reputation.trust_score,
event_data=event_data, event_data=event_data,
occurred_at=datetime.now(datetime.UTC), occurred_at=datetime.now(timezone.utc),
) )
self.session.add(event) self.session.add(event)
@@ -195,7 +195,7 @@ class CrossChainReputationEngine:
try: try:
# Get reputation events for the period # Get reputation events for the period
cutoff_date = datetime.now(datetime.UTC) - timedelta(days=days) cutoff_date = datetime.now(timezone.utc) - timedelta(days=days)
stmt = ( stmt = (
select(ReputationEvent) select(ReputationEvent)
@@ -295,7 +295,7 @@ class CrossChainReputationEngine:
reputation.trust_score = new_score * 1000 reputation.trust_score = new_score * 1000
reputation.reputation_level = self._determine_reputation_level(new_score) reputation.reputation_level = self._determine_reputation_level(new_score)
reputation.updated_at = datetime.now(datetime.UTC) reputation.updated_at = datetime.now(timezone.utc)
# Update transaction metrics if available # Update transaction metrics if available
if "transaction_count" in transaction_data: if "transaction_count" in transaction_data:
@@ -364,7 +364,7 @@ class CrossChainReputationEngine:
aggregation.score_variance = variance aggregation.score_variance = variance
aggregation.score_range = score_range aggregation.score_range = score_range
aggregation.consistency_score = consistency_score aggregation.consistency_score = consistency_score
aggregation.last_updated = datetime.now(datetime.UTC) aggregation.last_updated = datetime.now(timezone.utc)
else: else:
# Create new aggregation # Create new aggregation
aggregation = CrossChainReputationAggregation( aggregation = CrossChainReputationAggregation(
@@ -376,8 +376,8 @@ class CrossChainReputationEngine:
score_range=score_range, score_range=score_range,
consistency_score=consistency_score, consistency_score=consistency_score,
verification_status="pending", verification_status="pending",
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
last_updated=datetime.now(datetime.UTC), last_updated=datetime.now(timezone.utc),
) )
self.session.add(aggregation) self.session.add(aggregation)
@@ -440,7 +440,7 @@ class CrossChainReputationEngine:
"total_transactions": getattr(reputation, "transaction_count", 0), "total_transactions": getattr(reputation, "transaction_count", 0),
"success_rate": getattr(reputation, "success_rate", 0.0), "success_rate": getattr(reputation, "success_rate", 0.0),
"dispute_count": getattr(reputation, "dispute_count", 0), "dispute_count": getattr(reputation, "dispute_count", 0),
"last_activity": getattr(reputation, "last_activity", datetime.now(datetime.UTC)), "last_activity": getattr(reputation, "last_activity", datetime.now(timezone.utc)),
"cross_chain": { "cross_chain": {
"aggregated_score": aggregation.aggregated_score if aggregation else 0.0, "aggregated_score": aggregation.aggregated_score if aggregation else 0.0,
"chain_count": aggregation.chain_count if aggregation else 0, "chain_count": aggregation.chain_count if aggregation else 0,

View File

@@ -358,7 +358,7 @@ class PricingError(BaseModel):
error_code: str = Field(..., description="Error code") error_code: str = Field(..., description="Error code")
message: str = Field(..., description="Error message") message: str = Field(..., description="Error message")
details: dict[str, Any] | None = Field(None, description="Additional error details") details: dict[str, Any] | None = Field(None, description="Additional error details")
timestamp: datetime = Field(default_factory=datetime.now(datetime.UTC), description="Error timestamp") timestamp: datetime = Field(default_factory=datetime.now(timezone.utc), description="Error timestamp")
class Config: class Config:
json_encoders = {datetime: lambda v: v.isoformat()} json_encoders = {datetime: lambda v: v.isoformat()}

View File

@@ -6,7 +6,7 @@ Python SDK for enterprise clients to integrate with AITBC platform
import hashlib import hashlib
import secrets import secrets
from dataclasses import dataclass, field from dataclasses import dataclass, field
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from enum import StrEnum from enum import StrEnum
from typing import Any from typing import Any
@@ -162,7 +162,7 @@ class EnterpriseClient:
# Store tokens # Store tokens
self.access_token = auth_data["access_token"] self.access_token = auth_data["access_token"]
self.refresh_token = auth_data.get("refresh_token") self.refresh_token = auth_data.get("refresh_token")
self.token_expires_at = datetime.now(datetime.UTC) + timedelta(seconds=auth_data["expires_in"]) self.token_expires_at = datetime.now(timezone.utc) + timedelta(seconds=auth_data["expires_in"])
# Update session headers # Update session headers
self.session.headers["Authorization"] = f"Bearer {self.access_token}" self.session.headers["Authorization"] = f"Bearer {self.access_token}"
@@ -175,7 +175,7 @@ class EnterpriseClient:
async def _ensure_valid_token(self): async def _ensure_valid_token(self):
"""Ensure we have a valid access token""" """Ensure we have a valid access token"""
if not self.access_token or (self.token_expires_at and datetime.now(datetime.UTC) >= self.token_expires_at): if not self.access_token or (self.token_expires_at and datetime.now(timezone.utc) >= self.token_expires_at):
await self.authenticate() await self.authenticate()
async def create_integration(self, integration_config: IntegrationConfig) -> APIResponse: async def create_integration(self, integration_config: IntegrationConfig) -> APIResponse:

View File

@@ -5,7 +5,7 @@ Base interfaces for cross-chain settlement bridges
import json import json
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime, UTC from datetime import datetime, timezone
from enum import Enum from enum import Enum
from typing import Any from typing import Any
@@ -51,7 +51,7 @@ class SettlementMessage:
def __post_init__(self): def __post_init__(self):
if self.created_at is None: if self.created_at is None:
self.created_at = datetime.now(datetime.UTC) self.created_at = datetime.now(timezone.utc)
@dataclass @dataclass
@@ -69,7 +69,7 @@ class SettlementResult:
def __post_init__(self): def __post_init__(self):
if self.created_at is None: if self.created_at is None:
self.created_at = datetime.now(datetime.UTC) self.created_at = datetime.now(timezone.utc)
class BridgeAdapter(ABC): class BridgeAdapter(ABC):
@@ -220,7 +220,7 @@ class EthereumBridge(BridgeAdapter):
transaction_hash="0x" + "0" * 64, # Mock hash transaction_hash="0x" + "0" * 64, # Mock hash
gas_used=gas_estimate, gas_used=gas_estimate,
fee_paid=int(self.config.default_fee), fee_paid=int(self.config.default_fee),
completed_at=datetime.now(datetime.UTC) completed_at=datetime.now(timezone.utc)
) )
return result return result

View File

@@ -3,7 +3,7 @@ Settlement hooks for coordinator API integration
""" """
import asyncio import asyncio
from datetime import datetime, UTC from datetime import datetime, timezone
from typing import Any from typing import Any
from aitbc import get_logger from aitbc import get_logger
@@ -210,7 +210,7 @@ class SettlementHook:
"""Generate a unique nonce for settlement""" """Generate a unique nonce for settlement"""
# This would generate a unique nonce # This would generate a unique nonce
# For now, use timestamp # For now, use timestamp
return int(datetime.now(datetime.UTC).timestamp()) return int(datetime.now(timezone.utc).timestamp())
async def _sign_settlement_message(self, job: Job) -> str: async def _sign_settlement_message(self, job: Job) -> str:
"""Sign the settlement message""" """Sign the settlement message"""

View File

@@ -4,7 +4,7 @@ Bridge manager for cross-chain settlements
import asyncio import asyncio
from dataclasses import asdict from dataclasses import asdict
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from typing import Any from typing import Any
from .bridges.base import BridgeAdapter, BridgeConfig, BridgeError, BridgeStatus, SettlementMessage, SettlementResult from .bridges.base import BridgeAdapter, BridgeConfig, BridgeError, BridgeStatus, SettlementMessage, SettlementResult
@@ -240,9 +240,9 @@ class BridgeManager:
async def _monitor_settlement(self, message_id: str) -> None: async def _monitor_settlement(self, message_id: str) -> None:
"""Monitor settlement until completion""" """Monitor settlement until completion"""
max_wait_time = timedelta(hours=1) max_wait_time = timedelta(hours=1)
start_time = datetime.now(datetime.UTC) start_time = datetime.now(timezone.utc)
while datetime.now(datetime.UTC) - start_time < max_wait_time: while datetime.now(timezone.utc) - start_time < max_wait_time:
# Check status # Check status
result = await self.get_settlement_status(message_id) result = await self.get_settlement_status(message_id)

View File

@@ -4,7 +4,7 @@ Storage layer for cross-chain settlements
import asyncio import asyncio
import json import json
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from typing import Any from typing import Any
from .bridges.base import BridgeStatus, SettlementMessage from .bridges.base import BridgeStatus, SettlementMessage
@@ -49,7 +49,7 @@ class SettlementStorage:
message.signature, message.signature,
bridge_name, bridge_name,
status.value, status.value,
message.created_at or datetime.now(datetime.UTC), message.created_at or datetime.now(timezone.utc),
), ),
) )
@@ -90,7 +90,7 @@ class SettlementStorage:
return return
updates.append(f"updated_at = ${param_count}") updates.append(f"updated_at = ${param_count}")
params.append(datetime.now(datetime.UTC)) params.append(datetime.now(timezone.utc))
param_count += 1 param_count += 1
params.append(message_id) params.append(message_id)
@@ -258,8 +258,8 @@ class InMemorySettlementStorage(SettlementStorage):
"signature": message.signature, "signature": message.signature,
"bridge_name": bridge_name, "bridge_name": bridge_name,
"status": status.value, "status": status.value,
"created_at": message.created_at or datetime.now(datetime.UTC), "created_at": message.created_at or datetime.now(timezone.utc),
"updated_at": datetime.now(datetime.UTC), "updated_at": datetime.now(timezone.utc),
} }
async def update_settlement( async def update_settlement(
@@ -285,7 +285,7 @@ class InMemorySettlementStorage(SettlementStorage):
if completed_at is not None: if completed_at is not None:
settlement["completed_at"] = completed_at settlement["completed_at"] = completed_at
settlement["updated_at"] = datetime.now(datetime.UTC) settlement["updated_at"] = datetime.now(timezone.utc)
async def get_settlement(self, message_id: str) -> dict[str, Any] | None: async def get_settlement(self, message_id: str) -> dict[str, Any] | None:
async with self._lock: async with self._lock:
@@ -316,7 +316,7 @@ class InMemorySettlementStorage(SettlementStorage):
# Time range filtering # Time range filtering
if time_range is not None: if time_range is not None:
cutoff = datetime.now(datetime.UTC) - timedelta(hours=time_range) cutoff = datetime.now(timezone.utc) - timedelta(hours=time_range)
if settlement["created_at"] < cutoff: if settlement["created_at"] < cutoff:
continue continue
@@ -345,7 +345,7 @@ class InMemorySettlementStorage(SettlementStorage):
async def cleanup_old_settlements(self, days: int = 30) -> int: async def cleanup_old_settlements(self, days: int = 30) -> int:
async with self._lock: async with self._lock:
cutoff = datetime.now(datetime.UTC) - timedelta(days=days) cutoff = datetime.now(timezone.utc) - timedelta(days=days)
to_delete = [ to_delete = [
msg_id msg_id

View File

@@ -13,7 +13,7 @@ from sqlalchemy.orm import Session, sessionmaker
from aitbc import get_logger from aitbc import get_logger
logger = get_logger(__name__) logger = get_logger(__name__)
from datetime import datetime, UTC from datetime import datetime, timezone
from .config_pg import settings from .config_pg import settings
@@ -237,6 +237,6 @@ def check_db_health() -> dict[str, Any]:
try: try:
adapter = get_db_adapter() adapter = get_db_adapter()
adapter.execute_query("SELECT 1 as health_check") adapter.execute_query("SELECT 1 as health_check")
return {"status": "healthy", "database": "postgresql", "timestamp": datetime.now(datetime.UTC).isoformat()} return {"status": "healthy", "database": "postgresql", "timestamp": datetime.now(timezone.utc).isoformat()}
except Exception as e: except Exception as e:
return {"status": "unhealthy", "error": str(e), "timestamp": datetime.now(datetime.UTC).isoformat()} return {"status": "unhealthy", "error": str(e), "timestamp": datetime.now(timezone.utc).isoformat()}

View File

@@ -20,7 +20,7 @@ class GovernanceProposal(SQLModel, table=True):
target: dict[str, Any] | None = Field(default_factory=dict, sa_column=Column(JSON)) target: dict[str, Any] | None = Field(default_factory=dict, sa_column=Column(JSON))
proposer: str = Field(max_length=255, index=True) proposer: str = Field(max_length=255, index=True)
status: str = Field(default="active", max_length=20) # active, passed, rejected, executed, expired status: str = Field(default="active", max_length=20) # active, passed, rejected, executed, expired
created_at: datetime = Field(default_factory=datetime.now(datetime.UTC)) created_at: datetime = Field(default_factory=datetime.now(timezone.utc))
voting_deadline: datetime voting_deadline: datetime
quorum_threshold: float = Field(default=0.1) # Percentage of total voting power quorum_threshold: float = Field(default=0.1) # Percentage of total voting power
approval_threshold: float = Field(default=0.5) # Percentage of votes in favor approval_threshold: float = Field(default=0.5) # Percentage of votes in favor
@@ -40,7 +40,7 @@ class ProposalVote(SQLModel, table=True):
vote: str = Field(max_length=10) # for, against, abstain vote: str = Field(max_length=10) # for, against, abstain
voting_power: int = Field(default=0) # Amount of voting power at time of vote voting_power: int = Field(default=0) # Amount of voting power at time of vote
reason: str | None = Field(max_length=500) reason: str | None = Field(max_length=500)
voted_at: datetime = Field(default_factory=datetime.now(datetime.UTC)) voted_at: datetime = Field(default_factory=datetime.now(timezone.utc))
# Relationships # Relationships
proposal: GovernanceProposal = Relationship(back_populates="votes") proposal: GovernanceProposal = Relationship(back_populates="votes")
@@ -57,7 +57,7 @@ class TreasuryTransaction(SQLModel, table=True):
token: str = Field(default="AITBC", max_length=20) token: str = Field(default="AITBC", max_length=20)
transaction_hash: str | None = Field(max_length=255) transaction_hash: str | None = Field(max_length=255)
status: str = Field(default="pending", max_length=20) # pending, confirmed, failed status: str = Field(default="pending", max_length=20) # pending, confirmed, failed
created_at: datetime = Field(default_factory=datetime.now(datetime.UTC)) created_at: datetime = Field(default_factory=datetime.now(timezone.utc))
confirmed_at: datetime | None = None confirmed_at: datetime | None = None
memo: str | None = Field(max_length=500) memo: str | None = Field(max_length=500)
@@ -72,7 +72,7 @@ class GovernanceParameter(SQLModel, table=True):
min_value: str | None = Field(max_length=100) min_value: str | None = Field(max_length=100)
max_value: str | None = Field(max_length=100) max_value: str | None = Field(max_length=100)
value_type: str = Field(max_length=20) # string, number, boolean, json value_type: str = Field(max_length=20) # string, number, boolean, json
updated_at: datetime = Field(default_factory=datetime.now(datetime.UTC)) updated_at: datetime = Field(default_factory=datetime.now(timezone.utc))
updated_by_proposal: str | None = Field(foreign_key="governanceproposal.id") updated_by_proposal: str | None = Field(foreign_key="governanceproposal.id")
@@ -82,7 +82,7 @@ class VotingPowerSnapshot(SQLModel, table=True):
id: str = Field(default_factory=lambda: str(uuid4()), primary_key=True) id: str = Field(default_factory=lambda: str(uuid4()), primary_key=True)
user_id: str = Field(max_length=255, index=True) user_id: str = Field(max_length=255, index=True)
voting_power: int voting_power: int
snapshot_time: datetime = Field(default_factory=datetime.now(datetime.UTC), index=True) snapshot_time: datetime = Field(default_factory=datetime.now(timezone.utc), index=True)
block_number: int | None = Field(index=True) block_number: int | None = Field(index=True)
model_config = ConfigDict( model_config = ConfigDict(
@@ -101,7 +101,7 @@ class ProtocolUpgrade(SQLModel, table=True):
upgrade_type: str = Field(max_length=50) # hard_fork, soft_fork, patch upgrade_type: str = Field(max_length=50) # hard_fork, soft_fork, patch
activation_block: int | None activation_block: int | None
status: str = Field(default="pending", max_length=20) # pending, active, failed status: str = Field(default="pending", max_length=20) # pending, active, failed
created_at: datetime = Field(default_factory=datetime.now(datetime.UTC)) created_at: datetime = Field(default_factory=datetime.now(timezone.utc))
activated_at: datetime | None = None activated_at: datetime | None = None
rollback_available: bool = Field(default=False) rollback_available: bool = Field(default=False)

View File

@@ -1,7 +1,7 @@
import json import json
import os import os
from collections import deque from collections import deque
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from typing import Any from typing import Any
from urllib import error, request from urllib import error, request
@@ -36,7 +36,7 @@ class AlertDispatcher:
try: try:
self._deliver(name, alert) self._deliver(name, alert)
self._last_sent[name] = datetime.now(datetime.UTC) self._last_sent[name] = datetime.now(timezone.utc)
results["sent"].append(name) results["sent"].append(name)
self._record_alert(name, alert, delivery_status="sent") self._record_alert(name, alert, delivery_status="sent")
except Exception as exc: except Exception as exc:
@@ -62,7 +62,7 @@ class AlertDispatcher:
last_sent = self._last_sent.get(name) last_sent = self._last_sent.get(name)
if last_sent is None: if last_sent is None:
return False return False
return datetime.now(datetime.UTC) - last_sent < timedelta(seconds=self.cooldown_seconds) return datetime.now(timezone.utc) - last_sent < timedelta(seconds=self.cooldown_seconds)
def _record_alert( def _record_alert(
self, self,
@@ -71,9 +71,9 @@ class AlertDispatcher:
delivery_status: str, delivery_status: str,
error_message: str | None = None, error_message: str | None = None,
) -> None: ) -> None:
timestamp = datetime.now(datetime.UTC).isoformat() timestamp = datetime.now(timezone.utc).isoformat()
record = { record = {
"id": f"metrics_alert_{name}_{int(datetime.now(datetime.UTC).timestamp() * 1000)}", "id": f"metrics_alert_{name}_{int(datetime.now(timezone.utc).timestamp() * 1000)}",
"deployment_id": None, "deployment_id": None,
"severity": alert.get("status", "critical"), "severity": alert.get("status", "critical"),
"message": f"Threshold triggered for {name}", "message": f"Threshold triggered for {name}",
@@ -96,7 +96,7 @@ class AlertDispatcher:
"status": alert.get("status", "critical"), "status": alert.get("status", "critical"),
"value": alert.get("value"), "value": alert.get("value"),
"threshold": alert.get("threshold"), "threshold": alert.get("threshold"),
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
} }
if webhook_url: if webhook_url:

View File

@@ -7,7 +7,7 @@ import sys
import pytest import pytest
import asyncio import asyncio
from unittest.mock import AsyncMock, patch from unittest.mock import AsyncMock, patch
from datetime import datetime, UTC from datetime import datetime, timezone
from app.agent_identity.sdk.client import AgentIdentityClient from app.agent_identity.sdk.client import AgentIdentityClient
from app.agent_identity.sdk.models import ( from app.agent_identity.sdk.models import (
@@ -328,16 +328,16 @@ class TestModels:
status=IdentityStatus.ACTIVE, status=IdentityStatus.ACTIVE,
verification_level=VerificationType.BASIC, verification_level=VerificationType.BASIC,
is_verified=True, is_verified=True,
verified_at=datetime.now(datetime.UTC), verified_at=datetime.now(timezone.utc),
supported_chains=['1', '137'], supported_chains=['1', '137'],
primary_chain=1, primary_chain=1,
reputation_score=85.5, reputation_score=85.5,
total_transactions=100, total_transactions=100,
successful_transactions=95, successful_transactions=95,
success_rate=0.95, success_rate=0.95,
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
updated_at=datetime.now(datetime.UTC), updated_at=datetime.now(timezone.utc),
last_activity=datetime.now(datetime.UTC), last_activity=datetime.now(timezone.utc),
metadata={'key': 'value'}, metadata={'key': 'value'},
tags=['test', 'agent'] tags=['test', 'agent']
) )
@@ -358,14 +358,14 @@ class TestModels:
chain_type=ChainType.ETHEREUM, chain_type=ChainType.ETHEREUM,
chain_address='0x123...', chain_address='0x123...',
is_verified=True, is_verified=True,
verified_at=datetime.now(datetime.UTC), verified_at=datetime.now(timezone.utc),
wallet_address='0x456...', wallet_address='0x456...',
wallet_type='agent-wallet', wallet_type='agent-wallet',
chain_metadata={'test': 'data'}, chain_metadata={'test': 'data'},
last_transaction=datetime.now(datetime.UTC), last_transaction=datetime.now(timezone.utc),
transaction_count=10, transaction_count=10,
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
updated_at=datetime.now(datetime.UTC) updated_at=datetime.now(timezone.utc)
) )
assert mapping.id == 'mapping_123' assert mapping.id == 'mapping_123'
@@ -391,10 +391,10 @@ class TestModels:
requires_multisig=False, requires_multisig=False,
multisig_threshold=1, multisig_threshold=1,
multisig_signers=['0x123...'], multisig_signers=['0x123...'],
last_transaction=datetime.now(datetime.UTC), last_transaction=datetime.now(timezone.utc),
transaction_count=5, transaction_count=5,
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
updated_at=datetime.now(datetime.UTC) updated_at=datetime.now(timezone.utc)
) )
assert wallet.id == 'wallet_123' assert wallet.id == 'wallet_123'

View File

@@ -7,7 +7,7 @@ import sys
import asyncio import asyncio
import uuid import uuid
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from decimal import Decimal from decimal import Decimal
from unittest.mock import MagicMock, AsyncMock, patch from unittest.mock import MagicMock, AsyncMock, patch
from dataclasses import dataclass from dataclasses import dataclass
@@ -51,9 +51,9 @@ class FakeQuota:
def __post_init__(self): def __post_init__(self):
if self.period_start is None: if self.period_start is None:
self.period_start = datetime.now(datetime.UTC) - timedelta(hours=1) self.period_start = datetime.now(timezone.utc) - timedelta(hours=1)
if self.period_end is None: if self.period_end is None:
self.period_end = datetime.now(datetime.UTC) + timedelta(hours=23) self.period_end = datetime.now(timezone.utc) + timedelta(hours=23)
@dataclass @dataclass
@@ -93,7 +93,7 @@ class InMemoryBillingStore:
return self.tenants.get(tenant_id) return self.tenants.get(tenant_id)
def get_active_quota(self, tenant_id: str, resource_type: str): def get_active_quota(self, tenant_id: str, resource_type: str):
now = datetime.now(datetime.UTC) now = datetime.now(timezone.utc)
for q in self.quotas: for q in self.quotas:
if (q.tenant_id == tenant_id if (q.tenant_id == tenant_id
and q.resource_type == resource_type and q.resource_type == resource_type
@@ -119,7 +119,7 @@ async def apply_credit(store: InMemoryBillingStore, tenant_id: str, amount: Deci
"tenant_id": tenant_id, "tenant_id": tenant_id,
"amount": amount, "amount": amount,
"reason": reason, "reason": reason,
"timestamp": datetime.now(datetime.UTC), "timestamp": datetime.now(timezone.utc),
}) })
return True return True
@@ -138,7 +138,7 @@ async def apply_charge(store: InMemoryBillingStore, tenant_id: str, amount: Deci
"tenant_id": tenant_id, "tenant_id": tenant_id,
"amount": amount, "amount": amount,
"reason": reason, "reason": reason,
"timestamp": datetime.now(datetime.UTC), "timestamp": datetime.now(timezone.utc),
}) })
return True return True
@@ -161,7 +161,7 @@ async def adjust_quota(
async def reset_daily_quotas(store: InMemoryBillingStore) -> int: async def reset_daily_quotas(store: InMemoryBillingStore) -> int:
"""Reset used_value to 0 for all daily quotas whose period has ended.""" """Reset used_value to 0 for all daily quotas whose period has ended."""
now = datetime.now(datetime.UTC) now = datetime.now(timezone.utc)
count = 0 count = 0
for q in store.quotas: for q in store.quotas:
if q.period_type == "daily" and q.is_active and q.period_end <= now: if q.period_type == "daily" and q.is_active and q.period_end <= now:
@@ -197,7 +197,7 @@ async def generate_monthly_invoices(store: InMemoryBillingStore) -> list[str]:
if not tenant_usage: if not tenant_usage:
continue continue
total = sum(r.total_cost for r in tenant_usage) total = sum(r.total_cost for r in tenant_usage)
inv_id = f"INV-{tenant.slug}-{datetime.now(datetime.UTC).strftime('%Y%m')}-{len(generated)+1:04d}" inv_id = f"INV-{tenant.slug}-{datetime.now(timezone.utc).strftime('%Y%m')}-{len(generated)+1:04d}"
store.invoices_generated.append(inv_id) store.invoices_generated.append(inv_id)
generated.append(inv_id) generated.append(inv_id)
return generated return generated
@@ -254,8 +254,8 @@ def store():
id="q2", tenant_id="t1", resource_type="api_calls", id="q2", tenant_id="t1", resource_type="api_calls",
limit_value=Decimal("10000"), used_value=Decimal("5000"), limit_value=Decimal("10000"), used_value=Decimal("5000"),
period_type="daily", period_type="daily",
period_start=datetime.now(datetime.UTC) - timedelta(days=2), period_start=datetime.now(timezone.utc) - timedelta(days=2),
period_end=datetime.now(datetime.UTC) - timedelta(hours=1), # expired period_end=datetime.now(timezone.utc) - timedelta(hours=1), # expired
)) ))
return s return s
@@ -345,7 +345,7 @@ class TestResetDailyQuotas:
assert count == 1 # q2 is expired daily assert count == 1 # q2 is expired daily
q2 = store.quotas[1] q2 = store.quotas[1]
assert q2.used_value == Decimal("0") assert q2.used_value == Decimal("0")
assert q2.period_end > datetime.now(datetime.UTC) assert q2.period_end > datetime.now(timezone.utc)
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_does_not_reset_active_quotas(self, store): async def test_does_not_reset_active_quotas(self, store):

View File

@@ -5,7 +5,7 @@ Handles real exchange connections and trading operations
import asyncio import asyncio
import json import json
from datetime import datetime, UTC from datetime import datetime, timezone
from pathlib import Path from pathlib import Path
from typing import Dict, Any, List, Optional from typing import Dict, Any, List, Optional
import aiohttp import aiohttp
@@ -54,7 +54,7 @@ async def root():
return { return {
"service": "AITBC Exchange Integration", "service": "AITBC Exchange Integration",
"status": "running", "status": "running",
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"version": "1.0.0" "version": "1.0.0"
} }
@@ -83,7 +83,7 @@ async def register_exchange(registration: ExchangeRegistration):
"sandbox": registration.sandbox, "sandbox": registration.sandbox,
"description": registration.description, "description": registration.description,
"connected": False, "connected": False,
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"last_sync": None, "last_sync": None,
"trading_pairs": [] "trading_pairs": []
} }
@@ -116,7 +116,7 @@ async def connect_exchange(exchange_id: str):
await asyncio.sleep(1) # Simulate connection delay await asyncio.sleep(1) # Simulate connection delay
exchange["connected"] = True exchange["connected"] = True
exchange["last_sync"] = datetime.now(datetime.UTC).isoformat() exchange["last_sync"] = datetime.now(timezone.utc).isoformat()
logger.info(f"Exchange connected: {exchange_id}") logger.info(f"Exchange connected: {exchange_id}")
@@ -144,7 +144,7 @@ async def create_trading_pair(pair: TradingPair):
"price_precision": pair.price_precision, "price_precision": pair.price_precision,
"quantity_precision": pair.quantity_precision, "quantity_precision": pair.quantity_precision,
"status": "active", "status": "active",
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"current_price": None, "current_price": None,
"volume_24h": 0.0, "volume_24h": 0.0,
"orders": [] "orders": []
@@ -186,7 +186,7 @@ async def create_order(order: OrderRequest):
raise HTTPException(status_code=404, detail="Trading pair not found") raise HTTPException(status_code=404, detail="Trading pair not found")
# Generate order ID # Generate order ID
order_id = f"order_{int(datetime.now(datetime.UTC).timestamp())}" order_id = f"order_{int(datetime.now(timezone.utc).timestamp())}"
# Create order # Create order
order_data = { order_data = {
@@ -197,7 +197,7 @@ async def create_order(order: OrderRequest):
"quantity": order.quantity, "quantity": order.quantity,
"price": order.price, "price": order.price,
"status": "submitted", "status": "submitted",
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"filled_quantity": 0.0, "filled_quantity": 0.0,
"remaining_quantity": order.quantity, "remaining_quantity": order.quantity,
"average_price": None "average_price": None
@@ -216,7 +216,7 @@ async def create_order(order: OrderRequest):
order_data["filled_quantity"] = order.quantity order_data["filled_quantity"] = order.quantity
order_data["remaining_quantity"] = 0.0 order_data["remaining_quantity"] = 0.0
order_data["average_price"] = order.price or 0.00001 # Default price for demo order_data["average_price"] = order.price or 0.00001 # Default price for demo
order_data["filled_at"] = datetime.now(datetime.UTC).isoformat() order_data["filled_at"] = datetime.now(timezone.utc).isoformat()
logger.info(f"Order created and filled: {order_id}") logger.info(f"Order created and filled: {order_id}")
@@ -263,7 +263,7 @@ async def update_market_price(pair_id: str, price_data: Dict[str, Any]):
pair = trading_pairs[pair_id] pair = trading_pairs[pair_id]
pair["current_price"] = price_data.get("price") pair["current_price"] = price_data.get("price")
pair["volume_24h"] = price_data.get("volume", pair["volume_24h"]) pair["volume_24h"] = price_data.get("volume", pair["volume_24h"])
pair["last_price_update"] = datetime.now(datetime.UTC).isoformat() pair["last_price_update"] = datetime.now(timezone.utc).isoformat()
return { return {
"pair_id": pair_id, "pair_id": pair_id,
@@ -286,7 +286,7 @@ async def get_market_data():
return { return {
"market_data": market_data, "market_data": market_data,
"total_pairs": len(market_data), "total_pairs": len(market_data),
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
# Background task for simulating market data # Background task for simulating market data
@@ -305,7 +305,7 @@ async def simulate_market_data():
pair["current_price"] = new_price pair["current_price"] = new_price
pair["volume_24h"] += random.uniform(100, 1000) pair["volume_24h"] += random.uniform(100, 1000)
pair["last_price_update"] = datetime.now(datetime.UTC).isoformat() pair["last_price_update"] = datetime.now(timezone.utc).isoformat()
# Start background task on startup # Start background task on startup
@app.on_event("startup") @app.on_event("startup")

View File

@@ -3,7 +3,7 @@
FastAPI backend for the AITBC Trade Exchange FastAPI backend for the AITBC Trade Exchange
""" """
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from typing import List, Optional from typing import List, Optional
from fastapi import FastAPI, Depends, HTTPException, status, Header from fastapi import FastAPI, Depends, HTTPException, status, Header
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
@@ -123,7 +123,7 @@ def create_mock_trades(db: Session):
import random import random
# Create mock trades over the last hour # Create mock trades over the last hour
now = datetime.now(datetime.UTC) now = datetime.now(timezone.utc)
trades = [] trades = []
for i in range(20): for i in range(20):
@@ -278,7 +278,7 @@ def try_match_order(order: Order, db: Session):
amount=trade_amount, amount=trade_amount,
price=match.price, price=match.price,
total=trade_total, total=trade_total,
trade_hash=f"trade_{datetime.now(datetime.UTC).timestamp()}" trade_hash=f"trade_{datetime.now(timezone.utc).timestamp()}"
) )
db.add(trade) db.add(trade)
@@ -344,7 +344,7 @@ def logout_user(token: str = Header(..., alias="Authorization")):
@app.get("/api/health") @app.get("/api/health")
def health_check(): def health_check():
"""Health check endpoint""" """Health check endpoint"""
return {"status": "ok", "timestamp": datetime.now(datetime.UTC)} return {"status": "ok", "timestamp": datetime.now(timezone.utc)}
if __name__ == "__main__": if __name__ == "__main__":
import uvicorn import uvicorn

View File

@@ -22,7 +22,7 @@ class User(Base):
password_hash = Column(String(255), nullable=False) password_hash = Column(String(255), nullable=False)
bitcoin_address = Column(String(100), unique=True, nullable=False) bitcoin_address = Column(String(100), unique=True, nullable=False)
aitbc_address = Column(String(100), unique=True, nullable=False) aitbc_address = Column(String(100), unique=True, nullable=False)
created_at = Column(DateTime, default=datetime.now(datetime.UTC)) created_at = Column(DateTime, default=datetime.now(timezone.utc))
is_active = Column(Boolean, default=True) is_active = Column(Boolean, default=True)
# Relationships # Relationships
@@ -46,8 +46,8 @@ class Order(Base):
filled = Column(Float, default=0.0) # Amount filled filled = Column(Float, default=0.0) # Amount filled
remaining = Column(Float, nullable=False) # Amount remaining to fill remaining = Column(Float, nullable=False) # Amount remaining to fill
status = Column(String(20), default='OPEN') # OPEN, PARTIALLY_FILLED, FILLED, CANCELLED status = Column(String(20), default='OPEN') # OPEN, PARTIALLY_FILLED, FILLED, CANCELLED
created_at = Column(DateTime, default=datetime.now(datetime.UTC)) created_at = Column(DateTime, default=datetime.now(timezone.utc))
updated_at = Column(DateTime, default=datetime.now(datetime.UTC), onupdate=datetime.now(datetime.UTC)) updated_at = Column(DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc))
# Relationships # Relationships
user = relationship("User", back_populates="orders") user = relationship("User", back_populates="orders")
@@ -74,7 +74,7 @@ class Trade(Base):
price = Column(Float, nullable=False) # Trade price in BTC price = Column(Float, nullable=False) # Trade price in BTC
total = Column(Float, nullable=False) # Total value in BTC total = Column(Float, nullable=False) # Total value in BTC
trade_hash = Column(String(100), unique=True, nullable=False) # Blockchain transaction hash trade_hash = Column(String(100), unique=True, nullable=False) # Blockchain transaction hash
created_at = Column(DateTime, default=datetime.now(datetime.UTC)) created_at = Column(DateTime, default=datetime.now(timezone.utc))
# Relationships # Relationships
buyer = relationship("User", back_populates="trades", foreign_keys=[buyer_id]) buyer = relationship("User", back_populates="trades", foreign_keys=[buyer_id])
@@ -100,7 +100,7 @@ class Balance(Base):
aitbc_balance = Column(Float, default=0.0) aitbc_balance = Column(Float, default=0.0)
btc_locked = Column(Float, default=0.0) # Locked in open orders btc_locked = Column(Float, default=0.0) # Locked in open orders
aitbc_locked = Column(Float, default=0.0) # Locked in open orders aitbc_locked = Column(Float, default=0.0) # Locked in open orders
updated_at = Column(DateTime, default=datetime.now(datetime.UTC), onupdate=datetime.now(datetime.UTC)) updated_at = Column(DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc))
# Relationship # Relationship
user = relationship("User") user = relationship("User")

View File

@@ -8,7 +8,7 @@ import asyncio
import ccxt import ccxt
import json import json
import time import time
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from typing import Dict, List, Optional, Any, Tuple from typing import Dict, List, Optional, Any, Tuple
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum from enum import Enum
@@ -105,7 +105,7 @@ class RealExchangeManager:
self.health_status[exchange_name] = ExchangeHealth( self.health_status[exchange_name] = ExchangeHealth(
status=ExchangeStatus.CONNECTED, status=ExchangeStatus.CONNECTED,
latency_ms=0.0, latency_ms=0.0,
last_check=datetime.now(datetime.UTC) last_check=datetime.now(timezone.utc)
) )
logger.info(f"✅ Connected to {exchange_name}") logger.info(f"✅ Connected to {exchange_name}")
@@ -116,7 +116,7 @@ class RealExchangeManager:
self.health_status[exchange_name] = ExchangeHealth( self.health_status[exchange_name] = ExchangeHealth(
status=ExchangeStatus.ERROR, status=ExchangeStatus.ERROR,
latency_ms=0.0, latency_ms=0.0,
last_check=datetime.now(datetime.UTC), last_check=datetime.now(timezone.utc),
error_message=str(e) error_message=str(e)
) )
return False return False

View File

@@ -2,7 +2,7 @@
"""Seed initial market price for the exchange""" """Seed initial market price for the exchange"""
import sqlite3 import sqlite3
from datetime import datetime, UTC from datetime import datetime, timezone
from aitbc.constants import DATA_DIR from aitbc.constants import DATA_DIR
def seed_initial_price(): def seed_initial_price():
@@ -27,7 +27,7 @@ def seed_initial_price():
cursor.execute(''' cursor.execute('''
INSERT INTO trades (amount, price, total, created_at) INSERT INTO trades (amount, price, total, created_at)
VALUES (?, ?, ?, ?) VALUES (?, ?, ?, ?)
''', (amount, price, total, datetime.now(datetime.UTC))) ''', (amount, price, total, datetime.now(timezone.utc)))
# Also create some initial orders for liquidity # Also create some initial orders for liquidity
initial_orders = [ initial_orders = [

View File

@@ -5,7 +5,7 @@ Simple FastAPI backend for the AITBC Trade Exchange (Python 3.13 compatible)
import sqlite3 import sqlite3
import json import json
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from http.server import HTTPServer, BaseHTTPRequestHandler from http.server import HTTPServer, BaseHTTPRequestHandler
import urllib.parse import urllib.parse
import random import random

View File

@@ -7,7 +7,7 @@ import json
import urllib.request import urllib.request
import psycopg2 import psycopg2
from psycopg2.extras import RealDictCursor from psycopg2.extras import RealDictCursor
from datetime import datetime, UTC from datetime import datetime, timezone
from decimal import Decimal from decimal import Decimal
import random import random
@@ -151,7 +151,7 @@ class ExchangeAPIHandler(BaseHTTPRequestHandler):
self.send_json_response({ self.send_json_response({
'status': 'ok', 'status': 'ok',
'database': 'postgresql', 'database': 'postgresql',
'timestamp': datetime.now(datetime.UTC).isoformat() 'timestamp': datetime.now(timezone.utc).isoformat()
}) })
except Exception as e: except Exception as e:
self.send_json_response({ self.send_json_response({

View File

@@ -7,7 +7,7 @@ from pathlib import Path
from exchange_api import OrderCreate, OrderResponse, TradeResponse, OrderBookResponse from exchange_api import OrderCreate, OrderResponse, TradeResponse, OrderBookResponse
from datetime import datetime, UTC from datetime import datetime, timezone
@pytest.mark.unit @pytest.mark.unit
@@ -55,7 +55,7 @@ def test_order_response_zero_remaining():
filled=100.0, filled=100.0,
remaining=0.0, remaining=0.0,
status="FILLED", status="FILLED",
created_at=datetime.now(datetime.UTC) created_at=datetime.now(timezone.utc)
) )
assert order.remaining == 0.0 assert order.remaining == 0.0
assert order.status == "FILLED" assert order.status == "FILLED"
@@ -73,7 +73,7 @@ def test_order_response_empty_status():
filled=0.0, filled=0.0,
remaining=100.0, remaining=100.0,
status="", status="",
created_at=datetime.now(datetime.UTC) created_at=datetime.now(timezone.utc)
) )
assert order.status == "" assert order.status == ""
@@ -86,7 +86,7 @@ def test_trade_response_zero_amount():
amount=0.0, amount=0.0,
price=0.00001, price=0.00001,
total=0.0, total=0.0,
created_at=datetime.now(datetime.UTC) created_at=datetime.now(timezone.utc)
) )
assert trade.amount == 0.0 assert trade.amount == 0.0
assert trade.total == 0.0 assert trade.total == 0.0
@@ -103,7 +103,7 @@ def test_order_book_empty_buys():
@pytest.mark.unit @pytest.mark.unit
def test_order_book_empty_sells(): def test_order_book_empty_sells():
"""Test OrderBookResponse with empty sells""" """Test OrderBookResponse with empty sells"""
from datetime import datetime, UTC from datetime import datetime, timezone
buy_order = OrderResponse( buy_order = OrderResponse(
id=1, id=1,
order_type="BUY", order_type="BUY",
@@ -113,7 +113,7 @@ def test_order_book_empty_sells():
filled=0.0, filled=0.0,
remaining=100.0, remaining=100.0,
status="OPEN", status="OPEN",
created_at=datetime.now(datetime.UTC) created_at=datetime.now(timezone.utc)
) )
orderbook = OrderBookResponse(buys=[buy_order], sells=[]) orderbook = OrderBookResponse(buys=[buy_order], sells=[])
assert len(orderbook.buys) == 1 assert len(orderbook.buys) == 1

View File

@@ -45,7 +45,7 @@ def test_order_create_model_sell():
@pytest.mark.unit @pytest.mark.unit
def test_order_response_model(): def test_order_response_model():
"""Test OrderResponse model""" """Test OrderResponse model"""
from datetime import datetime, UTC from datetime import datetime, timezone
order = OrderResponse( order = OrderResponse(
id=1, id=1,
order_type="BUY", order_type="BUY",
@@ -55,7 +55,7 @@ def test_order_response_model():
filled=0.0, filled=0.0,
remaining=100.0, remaining=100.0,
status="OPEN", status="OPEN",
created_at=datetime.now(datetime.UTC) created_at=datetime.now(timezone.utc)
) )
assert order.id == 1 assert order.id == 1
assert order.order_type == "BUY" assert order.order_type == "BUY"
@@ -66,13 +66,13 @@ def test_order_response_model():
@pytest.mark.unit @pytest.mark.unit
def test_trade_response_model(): def test_trade_response_model():
"""Test TradeResponse model""" """Test TradeResponse model"""
from datetime import datetime, UTC from datetime import datetime, timezone
trade = TradeResponse( trade = TradeResponse(
id=1, id=1,
amount=50.0, amount=50.0,
price=0.00001, price=0.00001,
total=0.0005, total=0.0005,
created_at=datetime.now(datetime.UTC) created_at=datetime.now(timezone.utc)
) )
assert trade.id == 1 assert trade.id == 1
assert trade.amount == 50.0 assert trade.amount == 50.0
@@ -82,7 +82,7 @@ def test_trade_response_model():
@pytest.mark.unit @pytest.mark.unit
def test_order_book_response_model(): def test_order_book_response_model():
"""Test OrderBookResponse model""" """Test OrderBookResponse model"""
from datetime import datetime, UTC from datetime import datetime, timezone
buy_order = OrderResponse( buy_order = OrderResponse(
id=1, id=1,
order_type="BUY", order_type="BUY",
@@ -92,7 +92,7 @@ def test_order_book_response_model():
filled=0.0, filled=0.0,
remaining=100.0, remaining=100.0,
status="OPEN", status="OPEN",
created_at=datetime.now(datetime.UTC) created_at=datetime.now(timezone.utc)
) )
sell_order = OrderResponse( sell_order = OrderResponse(
id=2, id=2,
@@ -103,7 +103,7 @@ def test_order_book_response_model():
filled=0.0, filled=0.0,
remaining=50.0, remaining=50.0,
status="OPEN", status="OPEN",
created_at=datetime.now(datetime.UTC) created_at=datetime.now(timezone.utc)
) )
orderbook = OrderBookResponse(buys=[buy_order], sells=[sell_order]) orderbook = OrderBookResponse(buys=[buy_order], sells=[sell_order])
assert len(orderbook.buys) == 1 assert len(orderbook.buys) == 1

View File

@@ -5,7 +5,7 @@ Handles cross-chain and cross-region AI agent communication with global optimiza
import asyncio import asyncio
import json import json
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from pathlib import Path from pathlib import Path
from typing import Dict, Any, List, Optional from typing import Dict, Any, List, Optional
from fastapi import FastAPI, HTTPException from fastapi import FastAPI, HTTPException
@@ -74,7 +74,7 @@ async def root():
return { return {
"service": "AITBC Global AI Agent Communication Service", "service": "AITBC Global AI Agent Communication Service",
"status": "running", "status": "running",
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"version": "1.0.0" "version": "1.0.0"
} }
@@ -105,8 +105,8 @@ async def register_agent(agent: Agent):
"languages": agent.languages, "languages": agent.languages,
"specialization": agent.specialization, "specialization": agent.specialization,
"performance_score": agent.performance_score, "performance_score": agent.performance_score,
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"last_active": datetime.now(datetime.UTC).isoformat(), "last_active": datetime.now(timezone.utc).isoformat(),
"total_messages_sent": 0, "total_messages_sent": 0,
"total_messages_received": 0, "total_messages_received": 0,
"collaborations_participated": 0, "collaborations_participated": 0,
@@ -188,7 +188,7 @@ async def send_message(message: AgentMessage):
"timestamp": message.timestamp.isoformat(), "timestamp": message.timestamp.isoformat(),
"encryption_key": message.encryption_key, "encryption_key": message.encryption_key,
"status": "delivered", "status": "delivered",
"delivered_at": datetime.now(datetime.UTC).isoformat(), "delivered_at": datetime.now(timezone.utc).isoformat(),
"read_at": None "read_at": None
} }
@@ -285,16 +285,16 @@ async def create_collaboration(session: CollaborationSession):
for participant_id in session.participants: for participant_id in session.participants:
message_record = { message_record = {
"message_id": f"collab_{int(datetime.now(datetime.UTC).timestamp())}", "message_id": f"collab_{int(datetime.now(timezone.utc).timestamp())}",
"sender_id": "system", "sender_id": "system",
"recipient_id": participant_id, "recipient_id": participant_id,
"message_type": "notification", "message_type": "notification",
"content": notification, "content": notification,
"priority": "medium", "priority": "medium",
"language": "english", "language": "english",
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"status": "delivered", "status": "delivered",
"delivered_at": datetime.now(datetime.UTC).isoformat() "delivered_at": datetime.now(timezone.utc).isoformat()
} }
if participant_id not in agent_messages: if participant_id not in agent_messages:
@@ -330,11 +330,11 @@ async def send_collaboration_message(session_id: str, sender_id: str, content: D
# Create collaboration message # Create collaboration message
message_record = { message_record = {
"message_id": f"collab_msg_{int(datetime.now(datetime.UTC).timestamp())}", "message_id": f"collab_msg_{int(datetime.now(timezone.utc).timestamp())}",
"sender_id": sender_id, "sender_id": sender_id,
"session_id": session_id, "session_id": session_id,
"content": content, "content": content,
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"type": "collaboration_message" "type": "collaboration_message"
} }
@@ -351,16 +351,16 @@ async def send_collaboration_message(session_id: str, sender_id: str, content: D
} }
msg_record = { msg_record = {
"message_id": f"notif_{int(datetime.now(datetime.UTC).timestamp())}", "message_id": f"notif_{int(datetime.now(timezone.utc).timestamp())}",
"sender_id": "system", "sender_id": "system",
"recipient_id": participant_id, "recipient_id": participant_id,
"message_type": "notification", "message_type": "notification",
"content": notification, "content": notification,
"priority": "medium", "priority": "medium",
"language": "english", "language": "english",
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"status": "delivered", "status": "delivered",
"delivered_at": datetime.now(datetime.UTC).isoformat() "delivered_at": datetime.now(timezone.utc).isoformat()
} }
if participant_id not in agent_messages: if participant_id not in agent_messages:
@@ -381,7 +381,7 @@ async def record_agent_performance(performance: AgentPerformance):
# Create performance record # Create performance record
performance_record = { performance_record = {
"performance_id": f"perf_{int(datetime.now(datetime.UTC).timestamp())}", "performance_id": f"perf_{int(datetime.now(timezone.utc).timestamp())}",
"agent_id": performance.agent_id, "agent_id": performance.agent_id,
"timestamp": performance.timestamp.isoformat(), "timestamp": performance.timestamp.isoformat(),
"tasks_completed": performance.tasks_completed, "tasks_completed": performance.tasks_completed,
@@ -421,7 +421,7 @@ async def get_agent_performance(agent_id: str, hours: int = 24):
if agent_id not in global_agents: if agent_id not in global_agents:
raise HTTPException(status_code=404, detail="Agent not found") raise HTTPException(status_code=404, detail="Agent not found")
cutoff_time = datetime.now(datetime.UTC) - timedelta(hours=hours) cutoff_time = datetime.now(timezone.utc) - timedelta(hours=hours)
performance_records = agent_performance.get(agent_id, []) performance_records = agent_performance.get(agent_id, [])
recent_performance = [ recent_performance = [
p for p in performance_records p for p in performance_records
@@ -448,7 +448,7 @@ async def get_agent_performance(agent_id: str, hours: int = 24):
"total_tasks_completed": int(total_tasks), "total_tasks_completed": int(total_tasks),
"total_records": len(recent_performance) "total_records": len(recent_performance)
}, },
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/network/dashboard") @app.get("/api/v1/network/dashboard")
@@ -476,7 +476,7 @@ async def get_network_dashboard():
# Recent activity # Recent activity
recent_messages = 0 recent_messages = 0
cutoff_time = datetime.now(datetime.UTC) - timedelta(hours=1) cutoff_time = datetime.now(timezone.utc) - timedelta(hours=1)
for messages in agent_messages.values(): for messages in agent_messages.values():
recent_messages += len([m for m in messages if datetime.fromisoformat(m["timestamp"]) > cutoff_time]) recent_messages += len([m for m in messages if datetime.fromisoformat(m["timestamp"]) > cutoff_time])
@@ -503,7 +503,7 @@ async def get_network_dashboard():
"total_tasks_completed": sum(a["tasks_completed"] for a in global_agents.values()) "total_tasks_completed": sum(a["tasks_completed"] for a in global_agents.values())
} }
}, },
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/network/optimize") @app.get("/api/v1/network/optimize")
@@ -554,7 +554,7 @@ async def optimize_network():
return { return {
"optimization_results": optimization_results, "optimization_results": optimization_results,
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
# Background task for network monitoring # Background task for network monitoring
@@ -564,12 +564,12 @@ async def network_monitoring_task():
await asyncio.sleep(300) # Monitor every 5 minutes await asyncio.sleep(300) # Monitor every 5 minutes
# Update network statistics # Update network statistics
global_network_stats["last_update"] = datetime.now(datetime.UTC).isoformat() global_network_stats["last_update"] = datetime.now(timezone.utc).isoformat()
global_network_stats["total_agents"] = len(global_agents) global_network_stats["total_agents"] = len(global_agents)
global_network_stats["active_agents"] = len([a for a in global_agents.values() if a["status"] == "active"]) global_network_stats["active_agents"] = len([a for a in global_agents.values() if a["status"] == "active"])
# Check for expired collaboration sessions # Check for expired collaboration sessions
current_time = datetime.now(datetime.UTC) current_time = datetime.now(timezone.utc)
for session_id, session in collaboration_sessions.items(): for session_id, session in collaboration_sessions.items():
if datetime.fromisoformat(session["expires_at"]) < current_time and session["status"] == "active": if datetime.fromisoformat(session["expires_at"]) < current_time and session["status"] == "active":
session["status"] = "expired" session["status"] = "expired"
@@ -637,8 +637,8 @@ async def startup_event():
"languages": agent.languages, "languages": agent.languages,
"specialization": agent.specialization, "specialization": agent.specialization,
"performance_score": agent.performance_score, "performance_score": agent.performance_score,
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"last_active": datetime.now(datetime.UTC).isoformat(), "last_active": datetime.now(timezone.utc).isoformat(),
"total_messages_sent": 0, "total_messages_sent": 0,
"total_messages_received": 0, "total_messages_received": 0,
"collaborations_participated": 0, "collaborations_participated": 0,

View File

@@ -5,7 +5,7 @@ import sys
import sys import sys
from pathlib import Path from pathlib import Path
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from main import app, Agent, AgentMessage, CollaborationSession, AgentPerformance, global_agents, agent_messages, collaboration_sessions, agent_performance from main import app, Agent, AgentMessage, CollaborationSession, AgentPerformance, global_agents, agent_messages, collaboration_sessions, agent_performance
@@ -64,7 +64,7 @@ def test_agent_performance_out_of_range_score():
"""Test AgentPerformance with out of range scores""" """Test AgentPerformance with out of range scores"""
performance = AgentPerformance( performance = AgentPerformance(
agent_id="agent_123", agent_id="agent_123",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
tasks_completed=10, tasks_completed=10,
response_time_ms=50.5, response_time_ms=50.5,
accuracy_score=2.0, accuracy_score=2.0,
@@ -86,7 +86,7 @@ def test_agent_message_empty_content():
content={}, content={},
priority="high", priority="high",
language="english", language="english",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert message.content == {} assert message.content == {}
@@ -148,8 +148,8 @@ def test_send_collaboration_message_sender_not_participant():
participants=["agent_123"], participants=["agent_123"],
session_type="research", session_type="research",
objective="Research task", objective="Research task",
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
expires_at=datetime.now(datetime.UTC) + timedelta(hours=1), expires_at=datetime.now(timezone.utc) + timedelta(hours=1),
status="active" status="active"
) )
client.post("/api/v1/collaborations/create", json=session.model_dump(mode='json')) client.post("/api/v1/collaborations/create", json=session.model_dump(mode='json'))

View File

@@ -5,7 +5,7 @@ import sys
import sys import sys
from pathlib import Path from pathlib import Path
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from main import app, Agent, AgentMessage, CollaborationSession, AgentPerformance, global_agents, agent_messages, collaboration_sessions, agent_performance from main import app, Agent, AgentMessage, CollaborationSession, AgentPerformance, global_agents, agent_messages, collaboration_sessions, agent_performance
@@ -194,7 +194,7 @@ def test_send_direct_message():
content={"data": "test"}, content={"data": "test"},
priority="high", priority="high",
language="english", language="english",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
response = client.post("/api/v1/messages/send", json=message.model_dump(mode='json')) response = client.post("/api/v1/messages/send", json=message.model_dump(mode='json'))
assert response.status_code == 200 assert response.status_code == 200
@@ -241,7 +241,7 @@ def test_send_broadcast_message():
content={"data": "test"}, content={"data": "test"},
priority="medium", priority="medium",
language="english", language="english",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
response = client.post("/api/v1/messages/send", json=message.model_dump(mode='json')) response = client.post("/api/v1/messages/send", json=message.model_dump(mode='json'))
assert response.status_code == 200 assert response.status_code == 200
@@ -261,7 +261,7 @@ def test_send_message_sender_not_found():
content={"data": "test"}, content={"data": "test"},
priority="high", priority="high",
language="english", language="english",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
response = client.post("/api/v1/messages/send", json=message.model_dump(mode='json')) response = client.post("/api/v1/messages/send", json=message.model_dump(mode='json'))
assert response.status_code == 400 assert response.status_code == 400
@@ -292,7 +292,7 @@ def test_send_message_recipient_not_found():
content={"data": "test"}, content={"data": "test"},
priority="high", priority="high",
language="english", language="english",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
response = client.post("/api/v1/messages/send", json=message.model_dump(mode='json')) response = client.post("/api/v1/messages/send", json=message.model_dump(mode='json'))
assert response.status_code == 400 assert response.status_code == 400
@@ -377,8 +377,8 @@ def test_create_collaboration():
participants=["agent_123", "agent_456"], participants=["agent_123", "agent_456"],
session_type="task_force", session_type="task_force",
objective="Complete task", objective="Complete task",
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
expires_at=datetime.now(datetime.UTC) + timedelta(hours=1), expires_at=datetime.now(timezone.utc) + timedelta(hours=1),
status="active" status="active"
) )
response = client.post("/api/v1/collaborations/create", json=session.model_dump(mode='json')) response = client.post("/api/v1/collaborations/create", json=session.model_dump(mode='json'))
@@ -396,8 +396,8 @@ def test_create_collaboration_participant_not_found():
participants=["nonexistent"], participants=["nonexistent"],
session_type="task_force", session_type="task_force",
objective="Complete task", objective="Complete task",
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
expires_at=datetime.now(datetime.UTC) + timedelta(hours=1), expires_at=datetime.now(timezone.utc) + timedelta(hours=1),
status="active" status="active"
) )
response = client.post("/api/v1/collaborations/create", json=session.model_dump(mode='json')) response = client.post("/api/v1/collaborations/create", json=session.model_dump(mode='json'))
@@ -427,8 +427,8 @@ def test_get_collaboration():
participants=["agent_123"], participants=["agent_123"],
session_type="research", session_type="research",
objective="Research task", objective="Research task",
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
expires_at=datetime.now(datetime.UTC) + timedelta(hours=1), expires_at=datetime.now(timezone.utc) + timedelta(hours=1),
status="active" status="active"
) )
client.post("/api/v1/collaborations/create", json=session.model_dump(mode='json')) client.post("/api/v1/collaborations/create", json=session.model_dump(mode='json'))
@@ -462,8 +462,8 @@ def test_send_collaboration_message():
participants=["agent_123"], participants=["agent_123"],
session_type="research", session_type="research",
objective="Research task", objective="Research task",
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
expires_at=datetime.now(datetime.UTC) + timedelta(hours=1), expires_at=datetime.now(timezone.utc) + timedelta(hours=1),
status="active" status="active"
) )
client.post("/api/v1/collaborations/create", json=session.model_dump(mode='json')) client.post("/api/v1/collaborations/create", json=session.model_dump(mode='json'))
@@ -493,7 +493,7 @@ def test_record_agent_performance():
performance = AgentPerformance( performance = AgentPerformance(
agent_id="agent_123", agent_id="agent_123",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
tasks_completed=10, tasks_completed=10,
response_time_ms=50.5, response_time_ms=50.5,
accuracy_score=0.95, accuracy_score=0.95,
@@ -513,7 +513,7 @@ def test_record_performance_agent_not_found():
client = TestClient(app) client = TestClient(app)
performance = AgentPerformance( performance = AgentPerformance(
agent_id="nonexistent", agent_id="nonexistent",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
tasks_completed=10, tasks_completed=10,
response_time_ms=50.5, response_time_ms=50.5,
accuracy_score=0.95, accuracy_score=0.95,

View File

@@ -4,7 +4,7 @@ import pytest
import sys import sys
import sys import sys
from pathlib import Path from pathlib import Path
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, Agent, AgentMessage, CollaborationSession, AgentPerformance from main import app, Agent, AgentMessage, CollaborationSession, AgentPerformance
@@ -67,7 +67,7 @@ def test_agent_message_model():
content={"data": "test"}, content={"data": "test"},
priority="high", priority="high",
language="english", language="english",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert message.message_id == "msg_123" assert message.message_id == "msg_123"
assert message.sender_id == "agent_123" assert message.sender_id == "agent_123"
@@ -87,7 +87,7 @@ def test_agent_message_broadcast():
content={"data": "test"}, content={"data": "test"},
priority="medium", priority="medium",
language="english", language="english",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert message.recipient_id is None assert message.recipient_id is None
@@ -100,8 +100,8 @@ def test_collaboration_session_model():
participants=["agent_123", "agent_456"], participants=["agent_123", "agent_456"],
session_type="task_force", session_type="task_force",
objective="Complete trading task", objective="Complete trading task",
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
expires_at=datetime.now(datetime.UTC), expires_at=datetime.now(timezone.utc),
status="active" status="active"
) )
assert session.session_id == "session_123" assert session.session_id == "session_123"
@@ -117,8 +117,8 @@ def test_collaboration_session_empty_participants():
participants=[], participants=[],
session_type="research", session_type="research",
objective="Research task", objective="Research task",
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
expires_at=datetime.now(datetime.UTC), expires_at=datetime.now(timezone.utc),
status="active" status="active"
) )
assert session.participants == [] assert session.participants == []
@@ -129,7 +129,7 @@ def test_agent_performance_model():
"""Test AgentPerformance model""" """Test AgentPerformance model"""
performance = AgentPerformance( performance = AgentPerformance(
agent_id="agent_123", agent_id="agent_123",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
tasks_completed=10, tasks_completed=10,
response_time_ms=50.5, response_time_ms=50.5,
accuracy_score=0.95, accuracy_score=0.95,
@@ -147,7 +147,7 @@ def test_agent_performance_negative_values():
"""Test AgentPerformance with negative values""" """Test AgentPerformance with negative values"""
performance = AgentPerformance( performance = AgentPerformance(
agent_id="agent_123", agent_id="agent_123",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
tasks_completed=-10, tasks_completed=-10,
response_time_ms=-50.5, response_time_ms=-50.5,
accuracy_score=-0.95, accuracy_score=-0.95,

View File

@@ -5,7 +5,7 @@ Handles multi-region deployment, load balancing, and global optimization
import asyncio import asyncio
import json import json
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from pathlib import Path from pathlib import Path
from typing import Dict, Any, List, Optional from typing import Dict, Any, List, Optional
from fastapi import FastAPI, HTTPException from fastapi import FastAPI, HTTPException
@@ -72,7 +72,7 @@ async def root():
return { return {
"service": "AITBC Global Infrastructure Service", "service": "AITBC Global Infrastructure Service",
"status": "running", "status": "running",
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"version": "1.0.0" "version": "1.0.0"
} }
@@ -103,7 +103,7 @@ async def register_region(region: Region):
"current_load": region.current_load, "current_load": region.current_load,
"latency_ms": region.latency_ms, "latency_ms": region.latency_ms,
"compliance_level": region.compliance_level, "compliance_level": region.compliance_level,
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"last_health_check": None, "last_health_check": None,
"services_deployed": [], "services_deployed": [],
"performance_history": [] "performance_history": []
@@ -148,7 +148,7 @@ async def get_region(region_id: str):
@app.post("/api/v1/deployments/create") @app.post("/api/v1/deployments/create")
async def create_deployment(deployment: GlobalDeployment): async def create_deployment(deployment: GlobalDeployment):
"""Create a new global deployment""" """Create a new global deployment"""
deployment_id = f"deploy_{int(datetime.now(datetime.UTC).timestamp())}" deployment_id = f"deploy_{int(datetime.now(timezone.utc).timestamp())}"
# Validate target regions # Validate target regions
for region_id in deployment.target_regions: for region_id in deployment.target_regions:
@@ -164,7 +164,7 @@ async def create_deployment(deployment: GlobalDeployment):
"deployment_strategy": deployment.deployment_strategy, "deployment_strategy": deployment.deployment_strategy,
"health_checks": deployment.health_checks, "health_checks": deployment.health_checks,
"status": "pending", "status": "pending",
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"started_at": None, "started_at": None,
"completed_at": None, "completed_at": None,
"deployment_progress": {}, "deployment_progress": {},
@@ -214,7 +214,7 @@ async def list_deployments(status: Optional[str] = None):
@app.post("/api/v1/load-balancers/create") @app.post("/api/v1/load-balancers/create")
async def create_load_balancer(balancer: LoadBalancer): async def create_load_balancer(balancer: LoadBalancer):
"""Create a new load balancer""" """Create a new load balancer"""
balancer_id = f"lb_{int(datetime.now(datetime.UTC).timestamp())}" balancer_id = f"lb_{int(datetime.now(timezone.utc).timestamp())}"
# Validate target regions # Validate target regions
for region_id in balancer.target_regions: for region_id in balancer.target_regions:
@@ -230,7 +230,7 @@ async def create_load_balancer(balancer: LoadBalancer):
"health_check_interval": balancer.health_check_interval, "health_check_interval": balancer.health_check_interval,
"failover_threshold": balancer.failover_threshold, "failover_threshold": balancer.failover_threshold,
"status": "active", "status": "active",
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"current_weights": {region_id: 1.0 for region_id in balancer.target_regions}, "current_weights": {region_id: 1.0 for region_id in balancer.target_regions},
"health_status": {region_id: "healthy" for region_id in balancer.target_regions}, "health_status": {region_id: "healthy" for region_id in balancer.target_regions},
"total_requests": 0, "total_requests": 0,
@@ -265,7 +265,7 @@ async def list_load_balancers():
async def record_performance_metrics(metrics: PerformanceMetrics): async def record_performance_metrics(metrics: PerformanceMetrics):
"""Record performance metrics for a region""" """Record performance metrics for a region"""
metrics_record = { metrics_record = {
"metrics_id": f"metrics_{int(datetime.now(datetime.UTC).timestamp())}", "metrics_id": f"metrics_{int(datetime.now(timezone.utc).timestamp())}",
"region_id": metrics.region_id, "region_id": metrics.region_id,
"timestamp": metrics.timestamp.isoformat(), "timestamp": metrics.timestamp.isoformat(),
"cpu_usage": metrics.cpu_usage, "cpu_usage": metrics.cpu_usage,
@@ -310,7 +310,7 @@ async def get_region_performance(region_id: str, hours: int = 24):
if region_id not in performance_metrics: if region_id not in performance_metrics:
raise HTTPException(status_code=404, detail="No performance data for region") raise HTTPException(status_code=404, detail="No performance data for region")
cutoff_time = datetime.now(datetime.UTC) - timedelta(hours=hours) cutoff_time = datetime.now(timezone.utc) - timedelta(hours=hours)
recent_metrics = [ recent_metrics = [
m for m in performance_metrics[region_id] m for m in performance_metrics[region_id]
if datetime.fromisoformat(m["timestamp"]) > cutoff_time if datetime.fromisoformat(m["timestamp"]) > cutoff_time
@@ -334,7 +334,7 @@ async def get_region_performance(region_id: str, hours: int = 24):
"average_response_time_ms": round(avg_response_time, 2), "average_response_time_ms": round(avg_response_time, 2),
"total_samples": len(recent_metrics) "total_samples": len(recent_metrics)
}, },
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/compliance/{region_id}") @app.get("/api/v1/compliance/{region_id}")
@@ -350,8 +350,8 @@ async def get_region_compliance(region_id: str):
"compliance_level": global_regions[region_id]["compliance_level"], "compliance_level": global_regions[region_id]["compliance_level"],
"certifications": ["SOC2", "ISO27001", "GDPR"], "certifications": ["SOC2", "ISO27001", "GDPR"],
"data_residency": "compliant", "data_residency": "compliant",
"last_audit": (datetime.now(datetime.UTC) - timedelta(days=90)).isoformat(), "last_audit": (datetime.now(timezone.utc) - timedelta(days=90)).isoformat(),
"next_audit": (datetime.now(datetime.UTC) + timedelta(days=275)).isoformat(), "next_audit": (datetime.now(timezone.utc) + timedelta(days=275)).isoformat(),
"regulations": ["GDPR", "CCPA", "PDPA"], "regulations": ["GDPR", "CCPA", "PDPA"],
"data_protection": "end-to-end-encryption", "data_protection": "end-to-end-encryption",
"access_controls": "role-based-access", "access_controls": "role-based-access",
@@ -410,7 +410,7 @@ async def get_global_dashboard():
"partial_compliance": len([r for r in global_regions.values() if r["compliance_level"] == "partial"]) "partial_compliance": len([r for r in global_regions.values() if r["compliance_level"] == "partial"])
} }
}, },
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
# Core deployment and load balancing functions # Core deployment and load balancing functions
@@ -418,13 +418,13 @@ async def execute_deployment(deployment_id: str):
"""Execute a global deployment""" """Execute a global deployment"""
deployment = deployments[deployment_id] deployment = deployments[deployment_id]
deployment["status"] = "in_progress" deployment["status"] = "in_progress"
deployment["started_at"] = datetime.now(datetime.UTC).isoformat() deployment["started_at"] = datetime.now(timezone.utc).isoformat()
try: try:
for region_id in deployment["target_regions"]: for region_id in deployment["target_regions"]:
deployment["deployment_progress"][region_id] = { deployment["deployment_progress"][region_id] = {
"status": "deploying", "status": "deploying",
"started_at": datetime.now(datetime.UTC).isoformat(), "started_at": datetime.now(timezone.utc).isoformat(),
"progress": 0 "progress": 0
} }
@@ -433,7 +433,7 @@ async def execute_deployment(deployment_id: str):
deployment["deployment_progress"][region_id].update({ deployment["deployment_progress"][region_id].update({
"status": "completed", "status": "completed",
"completed_at": datetime.now(datetime.UTC).isoformat(), "completed_at": datetime.now(timezone.utc).isoformat(),
"progress": 100 "progress": 100
}) })
@@ -443,7 +443,7 @@ async def execute_deployment(deployment_id: str):
global_regions[region_id]["services_deployed"].append(deployment["service_name"]) global_regions[region_id]["services_deployed"].append(deployment["service_name"])
deployment["status"] = "completed" deployment["status"] = "completed"
deployment["completed_at"] = datetime.now(datetime.UTC).isoformat() deployment["completed_at"] = datetime.now(timezone.utc).isoformat()
logger.info(f"Deployment completed: {deployment_id}") logger.info(f"Deployment completed: {deployment_id}")
@@ -516,7 +516,7 @@ async def global_monitoring_task():
await asyncio.sleep(60) # Monitor every minute await asyncio.sleep(60) # Monitor every minute
# Update global monitoring data # Update global monitoring data
global_monitoring["last_update"] = datetime.now(datetime.UTC).isoformat() global_monitoring["last_update"] = datetime.now(timezone.utc).isoformat()
global_monitoring["total_requests"] = sum(lb.get("total_requests", 0) for lb in load_balancers.values()) global_monitoring["total_requests"] = sum(lb.get("total_requests", 0) for lb in load_balancers.values())
global_monitoring["failed_requests"] = sum(lb.get("failed_requests", 0) for lb in load_balancers.values()) global_monitoring["failed_requests"] = sum(lb.get("failed_requests", 0) for lb in load_balancers.values())
@@ -582,7 +582,7 @@ async def startup_event():
"current_load": region.current_load, "current_load": region.current_load,
"latency_ms": region.latency_ms, "latency_ms": region.latency_ms,
"compliance_level": region.compliance_level, "compliance_level": region.compliance_level,
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"last_health_check": None, "last_health_check": None,
"services_deployed": [], "services_deployed": [],
"performance_history": [] "performance_history": []

View File

@@ -5,7 +5,7 @@ import sys
import sys import sys
from pathlib import Path from pathlib import Path
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, Region, GlobalDeployment, LoadBalancer, PerformanceMetrics, global_regions, deployments, load_balancers, performance_metrics from main import app, Region, GlobalDeployment, LoadBalancer, PerformanceMetrics, global_regions, deployments, load_balancers, performance_metrics
@@ -93,7 +93,7 @@ def test_performance_metrics_negative_values():
"""Test PerformanceMetrics with negative values""" """Test PerformanceMetrics with negative values"""
metrics = PerformanceMetrics( metrics = PerformanceMetrics(
region_id="us-east-1", region_id="us-east-1",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
cpu_usage=-50.5, cpu_usage=-50.5,
memory_usage=-60.2, memory_usage=-60.2,
network_io=-1000.5, network_io=-1000.5,

View File

@@ -5,7 +5,7 @@ import sys
import sys import sys
from pathlib import Path from pathlib import Path
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, Region, GlobalDeployment, LoadBalancer, PerformanceMetrics, global_regions, deployments, load_balancers, performance_metrics from main import app, Region, GlobalDeployment, LoadBalancer, PerformanceMetrics, global_regions, deployments, load_balancers, performance_metrics
@@ -278,7 +278,7 @@ def test_record_performance_metrics():
client = TestClient(app) client = TestClient(app)
metrics = PerformanceMetrics( metrics = PerformanceMetrics(
region_id="us-west-1", region_id="us-west-1",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
cpu_usage=50.5, cpu_usage=50.5,
memory_usage=60.2, memory_usage=60.2,
network_io=1000.5, network_io=1000.5,
@@ -300,7 +300,7 @@ def test_get_region_performance():
# Record metrics first # Record metrics first
metrics = PerformanceMetrics( metrics = PerformanceMetrics(
region_id="us-west-1", region_id="us-west-1",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
cpu_usage=50.5, cpu_usage=50.5,
memory_usage=60.2, memory_usage=60.2,
network_io=1000.5, network_io=1000.5,

View File

@@ -4,7 +4,7 @@ import pytest
import sys import sys
import sys import sys
from pathlib import Path from pathlib import Path
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, Region, GlobalDeployment, LoadBalancer, PerformanceMetrics from main import app, Region, GlobalDeployment, LoadBalancer, PerformanceMetrics
@@ -78,7 +78,7 @@ def test_performance_metrics_model():
"""Test PerformanceMetrics model""" """Test PerformanceMetrics model"""
metrics = PerformanceMetrics( metrics = PerformanceMetrics(
region_id="us-east-1", region_id="us-east-1",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
cpu_usage=50.5, cpu_usage=50.5,
memory_usage=60.2, memory_usage=60.2,
network_io=1000.5, network_io=1000.5,

View File

@@ -8,7 +8,7 @@ import time
import sys import sys
import subprocess import subprocess
import os import os
from datetime import datetime, UTC from datetime import datetime, timezone
from typing import Dict, Optional from typing import Dict, Optional
from aitbc import get_logger, AITBCHTTPClient, NetworkError from aitbc import get_logger, AITBCHTTPClient, NetworkError
@@ -216,7 +216,7 @@ def send_heartbeat():
heartbeat_data = { heartbeat_data = {
"status": "active", "status": "active",
"current_jobs": 0, "current_jobs": 0,
"last_seen": datetime.now(datetime.UTC).isoformat(), "last_seen": datetime.now(timezone.utc).isoformat(),
"gpu_utilization": gpu_info["utilization"], "gpu_utilization": gpu_info["utilization"],
"memory_used": gpu_info["memory_used"], "memory_used": gpu_info["memory_used"],
"memory_total": gpu_info["memory_total"], "memory_total": gpu_info["memory_total"],
@@ -228,7 +228,7 @@ def send_heartbeat():
heartbeat_data = { heartbeat_data = {
"status": "active", "status": "active",
"current_jobs": 0, "current_jobs": 0,
"last_seen": datetime.now(datetime.UTC).isoformat(), "last_seen": datetime.now(timezone.utc).isoformat(),
"gpu_utilization": 0, "gpu_utilization": 0,
"memory_used": 0, "memory_used": 0,
"memory_total": 0, "memory_total": 0,

View File

@@ -8,7 +8,7 @@ import time
import sys import sys
import subprocess import subprocess
import os import os
from datetime import datetime, UTC from datetime import datetime, timezone
from typing import Dict, Optional from typing import Dict, Optional
from aitbc import get_logger, AITBCHTTPClient, NetworkError, LOG_DIR from aitbc import get_logger, AITBCHTTPClient, NetworkError, LOG_DIR
@@ -209,7 +209,7 @@ def send_heartbeat():
heartbeat_data = { heartbeat_data = {
"status": "active", "status": "active",
"current_jobs": 0, "current_jobs": 0,
"last_seen": datetime.now(datetime.UTC).isoformat(), "last_seen": datetime.now(timezone.utc).isoformat(),
"gpu_utilization": gpu_info["utilization"], "gpu_utilization": gpu_info["utilization"],
"memory_used": gpu_info["memory_used"], "memory_used": gpu_info["memory_used"],
"memory_total": gpu_info["memory_total"], "memory_total": gpu_info["memory_total"],
@@ -221,7 +221,7 @@ def send_heartbeat():
heartbeat_data = { heartbeat_data = {
"status": "active", "status": "active",
"current_jobs": 0, "current_jobs": 0,
"last_seen": datetime.now(datetime.UTC).isoformat(), "last_seen": datetime.now(timezone.utc).isoformat(),
"gpu_utilization": 0, "gpu_utilization": 0,
"memory_used": 0, "memory_used": 0,
"memory_total": 0, "memory_total": 0,

View File

@@ -5,7 +5,7 @@ Handles intelligent load distribution across global regions
import asyncio import asyncio
import json import json
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from pathlib import Path from pathlib import Path
from typing import Dict, Any, List, Optional from typing import Dict, Any, List, Optional
from fastapi import FastAPI, HTTPException from fastapi import FastAPI, HTTPException
@@ -68,7 +68,7 @@ async def root():
return { return {
"service": "AITBC Multi-Region Load Balancer", "service": "AITBC Multi-Region Load Balancer",
"status": "running", "status": "running",
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"version": "1.0.0" "version": "1.0.0"
} }
@@ -99,10 +99,10 @@ async def create_load_balancing_rule(rule: LoadBalancingRule):
"failover_enabled": rule.failover_enabled, "failover_enabled": rule.failover_enabled,
"session_affinity": rule.session_affinity, "session_affinity": rule.session_affinity,
"status": "active", "status": "active",
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"total_requests": 0, "total_requests": 0,
"failed_requests": 0, "failed_requests": 0,
"last_updated": datetime.now(datetime.UTC).isoformat() "last_updated": datetime.now(timezone.utc).isoformat()
} }
load_balancing_rules[rule.rule_id] = rule_record load_balancing_rules[rule.rule_id] = rule_record
@@ -167,7 +167,7 @@ async def update_rule_weights(rule_id: str, weights: Dict[str, float]):
# Update rule weights # Update rule weights
rule["weights"] = normalized_weights rule["weights"] = normalized_weights
rule["last_updated"] = datetime.now(datetime.UTC).isoformat() rule["last_updated"] = datetime.now(timezone.utc).isoformat()
logger.info(f"Weights updated for rule {rule_id}: {normalized_weights}") logger.info(f"Weights updated for rule {rule_id}: {normalized_weights}")
@@ -193,7 +193,7 @@ async def register_region_health(health: RegionHealth):
return { return {
"region_id": health.region_id, "region_id": health.region_id,
"status": health.status, "status": health.status,
"registered_at": datetime.now(datetime.UTC).isoformat() "registered_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/health") @app.get("/api/v1/health")
@@ -224,7 +224,7 @@ async def create_geographic_rule(rule: GeographicRule):
"priority": rule.priority, "priority": rule.priority,
"latency_threshold_ms": rule.latency_threshold_ms, "latency_threshold_ms": rule.latency_threshold_ms,
"status": "active", "status": "active",
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"usage_count": 0 "usage_count": 0
} }
@@ -256,14 +256,14 @@ async def get_optimal_region(client_region: str, rule_id: Optional[str] = None):
"optimal_region": optimal_region, "optimal_region": optimal_region,
"rule_id": rule_id, "rule_id": rule_id,
"selection_reason": get_selection_reason(optimal_region, client_region, rule_id), "selection_reason": get_selection_reason(optimal_region, client_region, rule_id),
"timestamp": datetime.now(datetime.UTC).isoformat() "timestamp": datetime.now(timezone.utc).isoformat()
} }
@app.post("/api/v1/metrics/record") @app.post("/api/v1/metrics/record")
async def record_balancing_metrics(metrics: LoadBalancingMetrics): async def record_balancing_metrics(metrics: LoadBalancingMetrics):
"""Record load balancing performance metrics""" """Record load balancing performance metrics"""
metrics_record = { metrics_record = {
"metrics_id": f"metrics_{int(datetime.now(datetime.UTC).timestamp())}", "metrics_id": f"metrics_{int(datetime.now(timezone.utc).timestamp())}",
"balancer_id": metrics.balancer_id, "balancer_id": metrics.balancer_id,
"timestamp": metrics.timestamp.isoformat(), "timestamp": metrics.timestamp.isoformat(),
"total_requests": metrics.total_requests, "total_requests": metrics.total_requests,
@@ -294,7 +294,7 @@ async def get_balancing_metrics(rule_id: str, hours: int = 24):
if rule_id not in load_balancing_rules: if rule_id not in load_balancing_rules:
raise HTTPException(status_code=404, detail="Load balancing rule not found") raise HTTPException(status_code=404, detail="Load balancing rule not found")
cutoff_time = datetime.now(datetime.UTC) - timedelta(hours=hours) cutoff_time = datetime.now(timezone.utc) - timedelta(hours=hours)
recent_metrics = [ recent_metrics = [
m for m in balancing_metrics.get(rule_id, []) m for m in balancing_metrics.get(rule_id, [])
if datetime.fromisoformat(m["timestamp"]) > cutoff_time if datetime.fromisoformat(m["timestamp"]) > cutoff_time
@@ -320,7 +320,7 @@ async def get_balancing_metrics(rule_id: str, hours: int = 24):
"total_requests": int(total_requests), "total_requests": int(total_requests),
"total_samples": len(recent_metrics) "total_samples": len(recent_metrics)
}, },
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/dashboard") @app.get("/api/v1/dashboard")
@@ -368,7 +368,7 @@ async def get_load_balancing_dashboard():
"performance": performance_summary, "performance": performance_summary,
"recent_activity": get_recent_activity() "recent_activity": get_recent_activity()
}, },
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
# Core load balancing functions # Core load balancing functions
@@ -534,7 +534,7 @@ def get_recent_activity() -> List[Dict]:
# Recent health changes # Recent health changes
for region_id, health in region_health_status.items(): for region_id, health in region_health_status.items():
if (datetime.now(datetime.UTC) - health.last_check).total_seconds() < 3600: # Last hour if (datetime.now(timezone.utc) - health.last_check).total_seconds() < 3600: # Last hour
activity.append({ activity.append({
"type": "health_check", "type": "health_check",
"region": region_id, "region": region_id,
@@ -544,7 +544,7 @@ def get_recent_activity() -> List[Dict]:
# Recent rule updates # Recent rule updates
for rule_id, rule in load_balancing_rules.items(): for rule_id, rule in load_balancing_rules.items():
if (datetime.now(datetime.UTC) - datetime.fromisoformat(rule["last_updated"])).total_seconds() < 3600: if (datetime.now(timezone.utc) - datetime.fromisoformat(rule["last_updated"])).total_seconds() < 3600:
activity.append({ activity.append({
"type": "rule_update", "type": "rule_update",
"rule_id": rule_id, "rule_id": rule_id,
@@ -598,7 +598,7 @@ async def check_region_health(region_id: str):
response_time_ms=response_time, response_time_ms=response_time,
success_rate=success_rate, success_rate=success_rate,
active_connections=active_connections, active_connections=active_connections,
last_check=datetime.now(datetime.UTC) last_check=datetime.now(timezone.utc)
) )
region_health_status[region_id] = health region_health_status[region_id] = health
@@ -644,10 +644,10 @@ async def startup_event():
"failover_enabled": rule.failover_enabled, "failover_enabled": rule.failover_enabled,
"session_affinity": rule.session_affinity, "session_affinity": rule.session_affinity,
"status": "active", "status": "active",
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"total_requests": 0, "total_requests": 0,
"failed_requests": 0, "failed_requests": 0,
"last_updated": datetime.now(datetime.UTC).isoformat() "last_updated": datetime.now(timezone.utc).isoformat()
} }
load_balancing_rules[rule.rule_id] = rule_record load_balancing_rules[rule.rule_id] = rule_record
@@ -681,7 +681,7 @@ async def startup_event():
"priority": geo_rule.priority, "priority": geo_rule.priority,
"latency_threshold_ms": geo_rule.latency_threshold_ms, "latency_threshold_ms": geo_rule.latency_threshold_ms,
"status": "active", "status": "active",
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"usage_count": 0 "usage_count": 0
} }
geographic_rules[geo_rule.rule_id] = geo_rule_record geographic_rules[geo_rule.rule_id] = geo_rule_record

View File

@@ -5,7 +5,7 @@ import sys
import sys import sys
from pathlib import Path from pathlib import Path
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, LoadBalancingRule, RegionHealth, LoadBalancingMetrics, GeographicRule, load_balancing_rules, region_health_status, balancing_metrics, geographic_rules from main import app, LoadBalancingRule, RegionHealth, LoadBalancingMetrics, GeographicRule, load_balancing_rules, region_health_status, balancing_metrics, geographic_rules
@@ -50,7 +50,7 @@ def test_region_health_negative_success_rate():
response_time_ms=45.5, response_time_ms=45.5,
success_rate=-0.5, success_rate=-0.5,
active_connections=100, active_connections=100,
last_check=datetime.now(datetime.UTC) last_check=datetime.now(timezone.utc)
) )
assert health.success_rate == -0.5 assert health.success_rate == -0.5
@@ -64,7 +64,7 @@ def test_region_health_negative_connections():
response_time_ms=45.5, response_time_ms=45.5,
success_rate=0.99, success_rate=0.99,
active_connections=-100, active_connections=-100,
last_check=datetime.now(datetime.UTC) last_check=datetime.now(timezone.utc)
) )
assert health.active_connections == -100 assert health.active_connections == -100
@@ -74,7 +74,7 @@ def test_load_balancing_metrics_negative_requests():
"""Test LoadBalancingMetrics with negative requests""" """Test LoadBalancingMetrics with negative requests"""
metrics = LoadBalancingMetrics( metrics = LoadBalancingMetrics(
balancer_id="lb_123", balancer_id="lb_123",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
total_requests=-1000, total_requests=-1000,
requests_per_region={}, requests_per_region={},
average_response_time=50.5, average_response_time=50.5,
@@ -89,7 +89,7 @@ def test_load_balancing_metrics_negative_response_time():
"""Test LoadBalancingMetrics with negative response time""" """Test LoadBalancingMetrics with negative response time"""
metrics = LoadBalancingMetrics( metrics = LoadBalancingMetrics(
balancer_id="lb_123", balancer_id="lb_123",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
total_requests=1000, total_requests=1000,
requests_per_region={}, requests_per_region={},
average_response_time=-50.5, average_response_time=-50.5,

View File

@@ -5,7 +5,7 @@ import sys
import sys import sys
from pathlib import Path from pathlib import Path
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, LoadBalancingRule, RegionHealth, LoadBalancingMetrics, GeographicRule, load_balancing_rules, region_health_status, balancing_metrics, geographic_rules from main import app, LoadBalancingRule, RegionHealth, LoadBalancingMetrics, GeographicRule, load_balancing_rules, region_health_status, balancing_metrics, geographic_rules
@@ -193,7 +193,7 @@ def test_register_region_health():
response_time_ms=45.5, response_time_ms=45.5,
success_rate=0.99, success_rate=0.99,
active_connections=100, active_connections=100,
last_check=datetime.now(datetime.UTC) last_check=datetime.now(timezone.utc)
) )
response = client.post("/api/v1/health/register", json=health.model_dump(mode='json')) response = client.post("/api/v1/health/register", json=health.model_dump(mode='json'))
assert response.status_code == 200 assert response.status_code == 200
@@ -286,7 +286,7 @@ def test_record_balancing_metrics():
client = TestClient(app) client = TestClient(app)
metrics = LoadBalancingMetrics( metrics = LoadBalancingMetrics(
balancer_id="lb_123", balancer_id="lb_123",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
total_requests=1000, total_requests=1000,
requests_per_region={"us-east-1": 500}, requests_per_region={"us-east-1": 500},
average_response_time=50.5, average_response_time=50.5,

View File

@@ -4,7 +4,7 @@ import pytest
import sys import sys
import sys import sys
from pathlib import Path from pathlib import Path
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, LoadBalancingRule, RegionHealth, LoadBalancingMetrics, GeographicRule from main import app, LoadBalancingRule, RegionHealth, LoadBalancingMetrics, GeographicRule
@@ -47,7 +47,7 @@ def test_region_health_model():
response_time_ms=45.5, response_time_ms=45.5,
success_rate=0.99, success_rate=0.99,
active_connections=100, active_connections=100,
last_check=datetime.now(datetime.UTC) last_check=datetime.now(timezone.utc)
) )
assert health.region_id == "us-east-1" assert health.region_id == "us-east-1"
assert health.status == "healthy" assert health.status == "healthy"
@@ -61,7 +61,7 @@ def test_load_balancing_metrics_model():
"""Test LoadBalancingMetrics model""" """Test LoadBalancingMetrics model"""
metrics = LoadBalancingMetrics( metrics = LoadBalancingMetrics(
balancer_id="lb_123", balancer_id="lb_123",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
total_requests=1000, total_requests=1000,
requests_per_region={"us-east-1": 500, "eu-west-1": 500}, requests_per_region={"us-east-1": 500, "eu-west-1": 500},
average_response_time=50.5, average_response_time=50.5,
@@ -115,6 +115,6 @@ def test_region_health_negative_response_time():
response_time_ms=-45.5, response_time_ms=-45.5,
success_rate=0.99, success_rate=0.99,
active_connections=100, active_connections=100,
last_check=datetime.now(datetime.UTC) last_check=datetime.now(timezone.utc)
) )
assert health.response_time_ms == -45.5 assert health.response_time_ms == -45.5

View File

@@ -5,7 +5,7 @@ Handles plugin analytics, usage tracking, and performance monitoring
import asyncio import asyncio
import json import json
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from pathlib import Path from pathlib import Path
from typing import Dict, Any, List, Optional from typing import Dict, Any, List, Optional
from fastapi import FastAPI, HTTPException from fastapi import FastAPI, HTTPException
@@ -66,7 +66,7 @@ async def root():
return { return {
"service": "AITBC Plugin Analytics Service", "service": "AITBC Plugin Analytics Service",
"status": "running", "status": "running",
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"version": "1.0.0" "version": "1.0.0"
} }
@@ -85,7 +85,7 @@ async def health_check():
async def record_plugin_usage(usage: PluginUsage): async def record_plugin_usage(usage: PluginUsage):
"""Record plugin usage event""" """Record plugin usage event"""
usage_record = { usage_record = {
"usage_id": f"usage_{int(datetime.now(datetime.UTC).timestamp())}", "usage_id": f"usage_{int(datetime.now(timezone.utc).timestamp())}",
"plugin_id": usage.plugin_id, "plugin_id": usage.plugin_id,
"user_id": usage.user_id, "user_id": usage.user_id,
"action": usage.action, "action": usage.action,
@@ -113,7 +113,7 @@ async def record_plugin_usage(usage: PluginUsage):
async def record_plugin_performance(performance: PluginPerformance): async def record_plugin_performance(performance: PluginPerformance):
"""Record plugin performance metrics""" """Record plugin performance metrics"""
performance_record = { performance_record = {
"performance_id": f"perf_{int(datetime.now(datetime.UTC).timestamp())}", "performance_id": f"perf_{int(datetime.now(timezone.utc).timestamp())}",
"plugin_id": performance.plugin_id, "plugin_id": performance.plugin_id,
"version": performance.version, "version": performance.version,
"cpu_usage": performance.cpu_usage, "cpu_usage": performance.cpu_usage,
@@ -141,7 +141,7 @@ async def record_plugin_performance(performance: PluginPerformance):
async def record_plugin_rating(rating: PluginRating): async def record_plugin_rating(rating: PluginRating):
"""Record plugin rating and review""" """Record plugin rating and review"""
rating_record = { rating_record = {
"rating_id": f"rating_{int(datetime.now(datetime.UTC).timestamp())}", "rating_id": f"rating_{int(datetime.now(timezone.utc).timestamp())}",
"plugin_id": rating.plugin_id, "plugin_id": rating.plugin_id,
"user_id": rating.user_id, "user_id": rating.user_id,
"rating": rating.rating, "rating": rating.rating,
@@ -166,7 +166,7 @@ async def record_plugin_rating(rating: PluginRating):
async def record_plugin_event(event: PluginEvent): async def record_plugin_event(event: PluginEvent):
"""Record generic plugin event""" """Record generic plugin event"""
event_record = { event_record = {
"event_id": f"event_{int(datetime.now(datetime.UTC).timestamp())}", "event_id": f"event_{int(datetime.now(timezone.utc).timestamp())}",
"event_type": event.event_type, "event_type": event.event_type,
"plugin_id": event.plugin_id, "plugin_id": event.plugin_id,
"user_id": event.user_id, "user_id": event.user_id,
@@ -190,7 +190,7 @@ async def record_plugin_event(event: PluginEvent):
@app.get("/api/v1/analytics/usage/{plugin_id}") @app.get("/api/v1/analytics/usage/{plugin_id}")
async def get_plugin_usage(plugin_id: str, days: int = 30): async def get_plugin_usage(plugin_id: str, days: int = 30):
"""Get usage analytics for a specific plugin""" """Get usage analytics for a specific plugin"""
cutoff_date = datetime.now(datetime.UTC) - timedelta(days=days) cutoff_date = datetime.now(timezone.utc) - timedelta(days=days)
usage_records = plugin_usage_data.get(plugin_id, []) usage_records = plugin_usage_data.get(plugin_id, [])
recent_usage = [r for r in usage_records recent_usage = [r for r in usage_records
@@ -204,13 +204,13 @@ async def get_plugin_usage(plugin_id: str, days: int = 30):
"period_days": days, "period_days": days,
"usage_statistics": usage_stats, "usage_statistics": usage_stats,
"total_records": len(recent_usage), "total_records": len(recent_usage),
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/analytics/performance/{plugin_id}") @app.get("/api/v1/analytics/performance/{plugin_id}")
async def get_plugin_performance(plugin_id: str, hours: int = 24): async def get_plugin_performance(plugin_id: str, hours: int = 24):
"""Get performance analytics for a specific plugin""" """Get performance analytics for a specific plugin"""
cutoff_time = datetime.now(datetime.UTC) - timedelta(hours=hours) cutoff_time = datetime.now(timezone.utc) - timedelta(hours=hours)
performance_records = plugin_performance_data.get(plugin_id, []) performance_records = plugin_performance_data.get(plugin_id, [])
recent_performance = [r for r in performance_records recent_performance = [r for r in performance_records
@@ -224,7 +224,7 @@ async def get_plugin_performance(plugin_id: str, hours: int = 24):
"period_hours": hours, "period_hours": hours,
"performance_statistics": performance_stats, "performance_statistics": performance_stats,
"total_records": len(recent_performance), "total_records": len(recent_performance),
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/analytics/ratings/{plugin_id}") @app.get("/api/v1/analytics/ratings/{plugin_id}")
@@ -240,7 +240,7 @@ async def get_plugin_ratings(plugin_id: str):
"rating_statistics": rating_stats, "rating_statistics": rating_stats,
"total_ratings": len(rating_records), "total_ratings": len(rating_records),
"recent_ratings": rating_records[-10:], # Last 10 ratings "recent_ratings": rating_records[-10:], # Last 10 ratings
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/analytics/dashboard") @app.get("/api/v1/analytics/dashboard")
@@ -257,7 +257,7 @@ async def get_analytics_dashboard():
return { return {
"dashboard": dashboard_data, "dashboard": dashboard_data,
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/analytics/trends") @app.get("/api/v1/analytics/trends")
@@ -398,7 +398,7 @@ def get_overview_statistics() -> Dict[str, Any]:
total_ratings = sum(len(data) for data in plugin_ratings.values()) total_ratings = sum(len(data) for data in plugin_ratings.values())
# Calculate active plugins (plugins with usage in last 7 days) # Calculate active plugins (plugins with usage in last 7 days)
cutoff_date = datetime.now(datetime.UTC) - timedelta(days=7) cutoff_date = datetime.now(timezone.utc) - timedelta(days=7)
active_plugins = 0 active_plugins = 0
for plugin_id, usage_records in plugin_usage_data.items(): for plugin_id, usage_records in plugin_usage_data.items():
@@ -417,7 +417,7 @@ def get_overview_statistics() -> Dict[str, Any]:
def get_trending_plugins(limit: int = 10) -> List[Dict]: def get_trending_plugins(limit: int = 10) -> List[Dict]:
"""Get trending plugins based on recent usage""" """Get trending plugins based on recent usage"""
cutoff_date = datetime.now(datetime.UTC) - timedelta(days=7) cutoff_date = datetime.now(timezone.utc) - timedelta(days=7)
plugin_scores = [] plugin_scores = []
@@ -443,7 +443,7 @@ def get_trending_plugins(limit: int = 10) -> List[Dict]:
def get_global_usage_trends(days: int = 30) -> Dict[str, Any]: def get_global_usage_trends(days: int = 30) -> Dict[str, Any]:
"""Get global usage trends""" """Get global usage trends"""
cutoff_date = datetime.now(datetime.UTC) - timedelta(days=days) cutoff_date = datetime.now(timezone.utc) - timedelta(days=days)
global_trends = {} global_trends = {}
for plugin_id, usage_records in plugin_usage_data.items(): for plugin_id, usage_records in plugin_usage_data.items():
@@ -541,14 +541,14 @@ def get_plugin_trends(plugin_id: str, days: int) -> Dict[str, Any]:
"""Get trends for a specific plugin""" """Get trends for a specific plugin"""
plugin_trends = usage_trends.get(plugin_id, {}) plugin_trends = usage_trends.get(plugin_id, {})
cutoff_date = datetime.now(datetime.UTC) - timedelta(days=days) cutoff_date = datetime.now(timezone.utc) - timedelta(days=days)
date_key = cutoff_date.date().isoformat() date_key = cutoff_date.date().isoformat()
return { return {
"plugin_id": plugin_id, "plugin_id": plugin_id,
"trends": plugin_trends, "trends": plugin_trends,
"period_days": days, "period_days": days,
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
# Report generation functions # Report generation functions
@@ -581,7 +581,7 @@ def generate_summary_report(plugin_id: Optional[str] = None) -> Dict[str, Any]:
"usage": get_plugin_usage(plugin_id, days=30), "usage": get_plugin_usage(plugin_id, days=30),
"performance": get_plugin_performance(plugin_id, hours=24), "performance": get_plugin_performance(plugin_id, hours=24),
"ratings": get_plugin_ratings(plugin_id), "ratings": get_plugin_ratings(plugin_id),
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
else: else:
return get_analytics_dashboard() return get_analytics_dashboard()
@@ -613,7 +613,7 @@ def update_analytics_cache():
def cleanup_old_data(): def cleanup_old_data():
"""Clean up old analytics data""" """Clean up old analytics data"""
cutoff_date = datetime.now(datetime.UTC) - timedelta(days=90) cutoff_date = datetime.now(timezone.utc) - timedelta(days=90)
cutoff_iso = cutoff_date.isoformat() cutoff_iso = cutoff_date.isoformat()
# Clean usage data # Clean usage data

View File

@@ -5,7 +5,7 @@ import sys
import sys import sys
from pathlib import Path from pathlib import Path
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, PluginUsage, PluginPerformance, PluginRating, PluginEvent, plugin_usage_data, plugin_performance_data, plugin_ratings, plugin_events from main import app, PluginUsage, PluginPerformance, PluginRating, PluginEvent, plugin_usage_data, plugin_performance_data, plugin_ratings, plugin_events
@@ -32,7 +32,7 @@ def test_plugin_usage_empty_plugin_id():
plugin_id="", plugin_id="",
user_id="user_123", user_id="user_123",
action="install", action="install",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert usage.plugin_id == "" assert usage.plugin_id == ""
@@ -48,7 +48,7 @@ def test_plugin_performance_negative_values():
response_time=-0.1, response_time=-0.1,
error_rate=-0.01, error_rate=-0.01,
uptime=-50.0, uptime=-50.0,
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert perf.cpu_usage == -10.0 assert perf.cpu_usage == -10.0
assert perf.memory_usage == -5.0 assert perf.memory_usage == -5.0
@@ -61,7 +61,7 @@ def test_plugin_rating_out_of_range():
plugin_id="plugin_123", plugin_id="plugin_123",
user_id="user_123", user_id="user_123",
rating=10, rating=10,
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert rating.rating == 10 assert rating.rating == 10
@@ -73,7 +73,7 @@ def test_plugin_rating_zero():
plugin_id="plugin_123", plugin_id="plugin_123",
user_id="user_123", user_id="user_123",
rating=0, rating=0,
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert rating.rating == 0 assert rating.rating == 0
@@ -128,7 +128,7 @@ def test_record_multiple_usage_events():
plugin_id="plugin_123", plugin_id="plugin_123",
user_id=f"user_{i}", user_id=f"user_{i}",
action="use", action="use",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
client.post("/api/v1/analytics/usage", json=usage.model_dump(mode='json')) client.post("/api/v1/analytics/usage", json=usage.model_dump(mode='json'))

View File

@@ -5,7 +5,7 @@ import sys
import sys import sys
from pathlib import Path from pathlib import Path
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, PluginUsage, PluginPerformance, PluginRating, PluginEvent, plugin_usage_data, plugin_performance_data, plugin_ratings, plugin_events from main import app, PluginUsage, PluginPerformance, PluginRating, PluginEvent, plugin_usage_data, plugin_performance_data, plugin_ratings, plugin_events
@@ -56,7 +56,7 @@ def test_record_plugin_usage():
plugin_id="plugin_123", plugin_id="plugin_123",
user_id="user_123", user_id="user_123",
action="install", action="install",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
response = client.post("/api/v1/analytics/usage", json=usage.model_dump(mode='json')) response = client.post("/api/v1/analytics/usage", json=usage.model_dump(mode='json'))
assert response.status_code == 200 assert response.status_code == 200
@@ -77,7 +77,7 @@ def test_record_plugin_performance():
response_time=0.123, response_time=0.123,
error_rate=0.001, error_rate=0.001,
uptime=99.9, uptime=99.9,
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
response = client.post("/api/v1/analytics/performance", json=perf.model_dump(mode='json')) response = client.post("/api/v1/analytics/performance", json=perf.model_dump(mode='json'))
assert response.status_code == 200 assert response.status_code == 200
@@ -95,7 +95,7 @@ def test_record_plugin_rating():
user_id="user_123", user_id="user_123",
rating=5, rating=5,
review="Great plugin!", review="Great plugin!",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
response = client.post("/api/v1/analytics/rating", json=rating.model_dump(mode='json')) response = client.post("/api/v1/analytics/rating", json=rating.model_dump(mode='json'))
assert response.status_code == 200 assert response.status_code == 200
@@ -113,7 +113,7 @@ def test_record_plugin_event():
plugin_id="plugin_123", plugin_id="plugin_123",
user_id="user_123", user_id="user_123",
data={"error": "timeout"}, data={"error": "timeout"},
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
response = client.post("/api/v1/analytics/event", json=event.model_dump(mode='json')) response = client.post("/api/v1/analytics/event", json=event.model_dump(mode='json'))
assert response.status_code == 200 assert response.status_code == 200
@@ -131,7 +131,7 @@ def test_get_plugin_usage():
plugin_id="plugin_123", plugin_id="plugin_123",
user_id="user_123", user_id="user_123",
action="install", action="install",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
client.post("/api/v1/analytics/usage", json=usage.model_dump(mode='json')) client.post("/api/v1/analytics/usage", json=usage.model_dump(mode='json'))
@@ -155,7 +155,7 @@ def test_get_plugin_performance():
response_time=0.123, response_time=0.123,
error_rate=0.001, error_rate=0.001,
uptime=99.9, uptime=99.9,
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
client.post("/api/v1/analytics/performance", json=perf.model_dump(mode='json')) client.post("/api/v1/analytics/performance", json=perf.model_dump(mode='json'))
@@ -175,7 +175,7 @@ def test_get_plugin_ratings():
plugin_id="plugin_123", plugin_id="plugin_123",
user_id="user_123", user_id="user_123",
rating=5, rating=5,
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
client.post("/api/v1/analytics/rating", json=rating.model_dump(mode='json')) client.post("/api/v1/analytics/rating", json=rating.model_dump(mode='json'))

View File

@@ -4,7 +4,7 @@ import pytest
import sys import sys
import sys import sys
from pathlib import Path from pathlib import Path
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, PluginUsage, PluginPerformance, PluginRating, PluginEvent from main import app, PluginUsage, PluginPerformance, PluginRating, PluginEvent
@@ -25,7 +25,7 @@ def test_plugin_usage_model():
plugin_id="plugin_123", plugin_id="plugin_123",
user_id="user_123", user_id="user_123",
action="install", action="install",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
metadata={"source": "marketplace"} metadata={"source": "marketplace"}
) )
assert usage.plugin_id == "plugin_123" assert usage.plugin_id == "plugin_123"
@@ -41,7 +41,7 @@ def test_plugin_usage_defaults():
plugin_id="plugin_123", plugin_id="plugin_123",
user_id="user_123", user_id="user_123",
action="use", action="use",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert usage.metadata == {} assert usage.metadata == {}
@@ -57,7 +57,7 @@ def test_plugin_performance_model():
response_time=0.123, response_time=0.123,
error_rate=0.001, error_rate=0.001,
uptime=99.9, uptime=99.9,
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert perf.plugin_id == "plugin_123" assert perf.plugin_id == "plugin_123"
assert perf.version == "1.0.0" assert perf.version == "1.0.0"
@@ -76,7 +76,7 @@ def test_plugin_rating_model():
user_id="user_123", user_id="user_123",
rating=5, rating=5,
review="Great plugin!", review="Great plugin!",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert rating.plugin_id == "plugin_123" assert rating.plugin_id == "plugin_123"
assert rating.rating == 5 assert rating.rating == 5
@@ -90,7 +90,7 @@ def test_plugin_rating_defaults():
plugin_id="plugin_123", plugin_id="plugin_123",
user_id="user_123", user_id="user_123",
rating=4, rating=4,
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert rating.review is None assert rating.review is None
@@ -103,7 +103,7 @@ def test_plugin_event_model():
plugin_id="plugin_123", plugin_id="plugin_123",
user_id="user_123", user_id="user_123",
data={"error": "timeout"}, data={"error": "timeout"},
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert event.event_type == "error" assert event.event_type == "error"
assert event.plugin_id == "plugin_123" assert event.plugin_id == "plugin_123"
@@ -117,7 +117,7 @@ def test_plugin_event_defaults():
event = PluginEvent( event = PluginEvent(
event_type="info", event_type="info",
plugin_id="plugin_123", plugin_id="plugin_123",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
assert event.user_id is None assert event.user_id is None
assert event.data == {} assert event.data == {}

View File

@@ -5,7 +5,7 @@ Provides web interface and marketplace functionality for plugins
import asyncio import asyncio
import json import json
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from pathlib import Path from pathlib import Path
from typing import Dict, Any, List, Optional from typing import Dict, Any, List, Optional
from fastapi import FastAPI, HTTPException, Request from fastapi import FastAPI, HTTPException, Request
@@ -120,7 +120,7 @@ async def get_featured_plugins_api():
"""Get featured plugins for marketplace""" """Get featured plugins for marketplace"""
return { return {
"featured_plugins": get_featured_plugins(), "featured_plugins": get_featured_plugins(),
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/marketplace/popular") @app.get("/api/v1/marketplace/popular")
@@ -128,7 +128,7 @@ async def get_popular_plugins_api(limit: int = 12):
"""Get popular plugins""" """Get popular plugins"""
return { return {
"popular_plugins": get_popular_plugins(limit), "popular_plugins": get_popular_plugins(limit),
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/marketplace/recent") @app.get("/api/v1/marketplace/recent")
@@ -136,7 +136,7 @@ async def get_recent_plugins_api(limit: int = 12):
"""Get recently added plugins""" """Get recently added plugins"""
return { return {
"recent_plugins": get_recent_plugins(limit), "recent_plugins": get_recent_plugins(limit),
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/marketplace/stats") @app.get("/api/v1/marketplace/stats")
@@ -144,13 +144,13 @@ async def get_marketplace_stats_api():
"""Get marketplace statistics""" """Get marketplace statistics"""
return { return {
"stats": get_marketplace_stats(), "stats": get_marketplace_stats(),
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.post("/api/v1/reviews") @app.post("/api/v1/reviews")
async def create_review(review: MarketplaceReview): async def create_review(review: MarketplaceReview):
"""Create a plugin review""" """Create a plugin review"""
review_id = f"review_{int(datetime.now(datetime.UTC).timestamp())}" review_id = f"review_{int(datetime.now(timezone.utc).timestamp())}"
review_record = { review_record = {
"review_id": review_id, "review_id": review_id,
@@ -162,7 +162,7 @@ async def create_review(review: MarketplaceReview):
"pros": review.pros, "pros": review.pros,
"cons": review.cons, "cons": review.cons,
"helpful_votes": 0, "helpful_votes": 0,
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"verified_purchase": False "verified_purchase": False
} }
@@ -202,7 +202,7 @@ async def get_plugin_reviews_api(plugin_id: str):
@app.post("/api/v1/purchases") @app.post("/api/v1/purchases")
async def create_purchase(purchase: PluginPurchase): async def create_purchase(purchase: PluginPurchase):
"""Create a plugin purchase""" """Create a plugin purchase"""
purchase_id = f"purchase_{int(datetime.now(datetime.UTC).timestamp())}" purchase_id = f"purchase_{int(datetime.now(timezone.utc).timestamp())}"
purchase_record = { purchase_record = {
"purchase_id": purchase_id, "purchase_id": purchase_id,
@@ -211,8 +211,8 @@ async def create_purchase(purchase: PluginPurchase):
"price": purchase.price, "price": purchase.price,
"payment_method": purchase.payment_method, "payment_method": purchase.payment_method,
"status": "completed", "status": "completed",
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"refund_deadline": (datetime.now(datetime.UTC) + timedelta(days=30)).isoformat() "refund_deadline": (datetime.now(timezone.utc) + timedelta(days=30)).isoformat()
} }
if purchase.plugin_id not in purchases: if purchase.plugin_id not in purchases:
@@ -235,7 +235,7 @@ async def create_purchase(purchase: PluginPurchase):
@app.post("/api/v1/developers/apply") @app.post("/api/v1/developers/apply")
async def apply_developer(application: DeveloperApplication): async def apply_developer(application: DeveloperApplication):
"""Apply to become a verified developer""" """Apply to become a verified developer"""
application_id = f"dev_app_{int(datetime.now(datetime.UTC).timestamp())}" application_id = f"dev_app_{int(datetime.now(timezone.utc).timestamp())}"
application_record = { application_record = {
"application_id": application_id, "application_id": application_id,
@@ -247,7 +247,7 @@ async def apply_developer(application: DeveloperApplication):
"github_username": application.github_username, "github_username": application.github_username,
"description": application.description, "description": application.description,
"status": "pending", "status": "pending",
"submitted_at": datetime.now(datetime.UTC).isoformat(), "submitted_at": datetime.now(timezone.utc).isoformat(),
"reviewed_at": None, "reviewed_at": None,
"reviewer_notes": None "reviewer_notes": None
} }
@@ -268,7 +268,7 @@ async def get_verified_developers_api():
return { return {
"verified_developers": get_verified_developers(), "verified_developers": get_verified_developers(),
"total_developers": len(verified_developers), "total_developers": len(verified_developers),
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/revenue/{developer_id}") @app.get("/api/v1/revenue/{developer_id}")
@@ -278,7 +278,7 @@ async def get_developer_revenue(developer_id: str):
"total_revenue": 0.0, "total_revenue": 0.0,
"plugin_revenue": {}, "plugin_revenue": {},
"monthly_revenue": {}, "monthly_revenue": {},
"last_updated": datetime.now(datetime.UTC).isoformat() "last_updated": datetime.now(timezone.utc).isoformat()
}) })
return developer_revenue return developer_revenue
@@ -358,7 +358,7 @@ def get_recent_plugins(limit: int = 12) -> List[Dict]:
"rating": 4.9, "rating": 4.9,
"downloads": 2340, "downloads": 2340,
"price": 199.99, "price": 199.99,
"created_at": (datetime.now(datetime.UTC) - timedelta(days=3)).isoformat() "created_at": (datetime.now(timezone.utc) - timedelta(days=3)).isoformat()
}, },
{ {
"plugin_id": "performance_monitor", "plugin_id": "performance_monitor",
@@ -369,7 +369,7 @@ def get_recent_plugins(limit: int = 12) -> List[Dict]:
"rating": 4.4, "rating": 4.4,
"downloads": 1890, "downloads": 1890,
"price": 59.99, "price": 59.99,
"created_at": (datetime.now(datetime.UTC) - timedelta(days=7)).isoformat() "created_at": (datetime.now(timezone.utc) - timedelta(days=7)).isoformat()
} }
] ]
@@ -414,7 +414,7 @@ def get_plugin_details(plugin_id: str) -> Optional[Dict]:
"downloads": 15420, "downloads": 15420,
"price": 99.99, "price": 99.99,
"version": "2.1.0", "version": "2.1.0",
"last_updated": (datetime.now(datetime.UTC) - timedelta(days=15)).isoformat(), "last_updated": (datetime.now(timezone.utc) - timedelta(days=15)).isoformat(),
"repository_url": "https://github.com/aitbc-labs/ai-trading-bot", "repository_url": "https://github.com/aitbc-labs/ai-trading-bot",
"homepage_url": "https://aitbc-trading-bot.com", "homepage_url": "https://aitbc-trading-bot.com",
"license": "MIT", "license": "MIT",
@@ -442,7 +442,7 @@ def get_plugin_reviews(plugin_id: str) -> List[Dict]:
"pros": ["Easy to use", "Great performance", "Good documentation"], "pros": ["Easy to use", "Great performance", "Good documentation"],
"cons": ["Initial setup complexity"], "cons": ["Initial setup complexity"],
"helpful_votes": 23, "helpful_votes": 23,
"created_at": (datetime.now(datetime.UTC) - timedelta(days=10)).isoformat() "created_at": (datetime.now(timezone.utc) - timedelta(days=10)).isoformat()
}, },
{ {
"review_id": "review_2", "review_id": "review_2",
@@ -453,7 +453,7 @@ def get_plugin_reviews(plugin_id: str) -> List[Dict]:
"pros": ["Powerful features", "Good support"], "pros": ["Powerful features", "Good support"],
"cons": ["UI could be better", "Learning curve"], "cons": ["UI could be better", "Learning curve"],
"helpful_votes": 15, "helpful_votes": 15,
"created_at": (datetime.now(datetime.UTC) - timedelta(days=25)).isoformat() "created_at": (datetime.now(timezone.utc) - timedelta(days=25)).isoformat()
} }
] ]

View File

@@ -6,7 +6,7 @@ Handles plugin registration, discovery, versioning, and security validation
import asyncio import asyncio
import json import json
import hashlib import hashlib
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from pathlib import Path from pathlib import Path
from typing import Dict, Any, List, Optional from typing import Dict, Any, List, Optional
from fastapi import FastAPI, HTTPException, UploadFile, File from fastapi import FastAPI, HTTPException, UploadFile, File
@@ -66,7 +66,7 @@ async def root():
return { return {
"service": "AITBC Plugin Registry", "service": "AITBC Plugin Registry",
"status": "running", "status": "running",
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"version": "1.0.0" "version": "1.0.0"
} }
@@ -79,7 +79,7 @@ async def health_check():
"security_scans": len(security_scans), "security_scans": len(security_scans),
"downloads_today": len([d for downloads_list in downloads.values() "downloads_today": len([d for downloads_list in downloads.values()
for d in downloads_list for d in downloads_list
if datetime.fromisoformat(d["timestamp"]).date() == datetime.now(datetime.UTC).date()]) if datetime.fromisoformat(d["timestamp"]).date() == datetime.now(timezone.utc).date()])
} }
@app.post("/api/v1/plugins/register") @app.post("/api/v1/plugins/register")
@@ -105,8 +105,8 @@ async def register_plugin(plugin: PluginRegistration):
"aitbc_version": plugin.aitbc_version, "aitbc_version": plugin.aitbc_version,
"plugin_type": plugin.plugin_type, "plugin_type": plugin.plugin_type,
"status": "active", "status": "active",
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"updated_at": datetime.now(datetime.UTC).isoformat(), "updated_at": datetime.now(timezone.utc).isoformat(),
"verified": False, "verified": False,
"featured": False, "featured": False,
"download_count": 0, "download_count": 0,
@@ -158,14 +158,14 @@ async def add_plugin_version(plugin_id: str, version: PluginVersion):
"release_date": version.release_date.isoformat(), "release_date": version.release_date.isoformat(),
"downloads": 0, "downloads": 0,
"security_scan_passed": False, "security_scan_passed": False,
"created_at": datetime.now(datetime.UTC).isoformat() "created_at": datetime.now(timezone.utc).isoformat()
} }
plugin_versions[plugin_id].append(version_record) plugin_versions[plugin_id].append(version_record)
# Update plugin's latest version # Update plugin's latest version
plugins[plugin_id]["latest_version"] = version.version plugins[plugin_id]["latest_version"] = version.version
plugins[plugin_id]["updated_at"] = datetime.now(datetime.UTC).isoformat() plugins[plugin_id]["updated_at"] = datetime.now(timezone.utc).isoformat()
# Sort versions by version number (semantic versioning) # Sort versions by version number (semantic versioning)
plugin_versions[plugin_id].sort(key=lambda x: x["version"], reverse=True) plugin_versions[plugin_id].sort(key=lambda x: x["version"], reverse=True)
@@ -272,7 +272,7 @@ async def download_plugin(plugin_id: str, version: str):
# Record download # Record download
download_record = { download_record = {
"version": version, "version": version,
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"ip_address": "client_ip", # In production, get actual IP "ip_address": "client_ip", # In production, get actual IP
"user_agent": "user_agent" # In production, get actual user agent "user_agent": "user_agent" # In production, get actual user agent
} }
@@ -284,7 +284,7 @@ async def download_plugin(plugin_id: str, version: str):
# Update analytics # Update analytics
if plugin_id not in analytics: if plugin_id not in analytics:
analytics[plugin_id] = {"downloads": [], "views": [], "ratings": []} analytics[plugin_id] = {"downloads": [], "views": [], "ratings": []}
analytics[plugin_id]["downloads"].append(datetime.now(datetime.UTC).timestamp()) analytics[plugin_id]["downloads"].append(datetime.now(timezone.utc).timestamp())
# Update plugin download count # Update plugin download count
plugins[plugin_id]["download_count"] += 1 plugins[plugin_id]["download_count"] += 1
@@ -319,7 +319,7 @@ async def create_security_scan(plugin_id: str, scan: SecurityScan):
"vulnerabilities": scan.vulnerabilities, "vulnerabilities": scan.vulnerabilities,
"risk_score": scan.risk_score, "risk_score": scan.risk_score,
"passed": scan.passed, "passed": scan.passed,
"created_at": datetime.now(datetime.UTC).isoformat() "created_at": datetime.now(timezone.utc).isoformat()
} }
# Update version security status # Update version security status
@@ -400,7 +400,7 @@ async def get_popular_plugins(limit: int = 10):
return { return {
"popular_plugins": popular_plugins, "popular_plugins": popular_plugins,
"limit": limit, "limit": limit,
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/analytics/recent") @app.get("/api/v1/analytics/recent")
@@ -411,7 +411,7 @@ async def get_recent_plugins(limit: int = 10):
return { return {
"recent_plugins": recent_plugins, "recent_plugins": recent_plugins,
"limit": limit, "limit": limit,
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/analytics/dashboard") @app.get("/api/v1/analytics/dashboard")
@@ -429,7 +429,7 @@ async def get_analytics_dashboard():
# Recent activity # Recent activity
recent_downloads = 0 recent_downloads = 0
today = datetime.now(datetime.UTC).date() today = datetime.now(timezone.utc).date()
for download_list in downloads.values(): for download_list in downloads.values():
recent_downloads += len([d for d in download_list recent_downloads += len([d for d in download_list
if datetime.fromisoformat(d["timestamp"]).date() == today]) if datetime.fromisoformat(d["timestamp"]).date() == today])
@@ -444,7 +444,7 @@ async def get_analytics_dashboard():
"security_scans": len(security_scans), "security_scans": len(security_scans),
"passed_scans": len([s for s in security_scans.values() if s["passed"]]) "passed_scans": len([s for s in security_scans.values() if s["passed"]])
}, },
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
# Background task for analytics processing # Background task for analytics processing
@@ -454,7 +454,7 @@ async def process_analytics():
await asyncio.sleep(3600) # Process every hour await asyncio.sleep(3600) # Process every hour
# Update daily statistics # Update daily statistics
current_date = datetime.now(datetime.UTC).date() current_date = datetime.now(timezone.utc).date()
for plugin_id, plugin_analytics in analytics.items(): for plugin_id, plugin_analytics in analytics.items():
daily_key = current_date.isoformat() daily_key = current_date.isoformat()

View File

@@ -5,7 +5,7 @@ import sys
import sys import sys
from pathlib import Path from pathlib import Path
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, PluginRegistration, PluginVersion, SecurityScan, plugins, plugin_versions, security_scans, analytics, downloads from main import app, PluginRegistration, PluginVersion, SecurityScan, plugins, plugin_versions, security_scans, analytics, downloads
@@ -74,7 +74,7 @@ def test_plugin_version_empty_changelog():
download_url="https://github.com/test/plugin/archive/v1.0.0.tar.gz", download_url="https://github.com/test/plugin/archive/v1.0.0.tar.gz",
checksum="abc123", checksum="abc123",
aitbc_compatibility=["1.0.0"], aitbc_compatibility=["1.0.0"],
release_date=datetime.now(datetime.UTC) release_date=datetime.now(timezone.utc)
) )
assert version.changelog == "" assert version.changelog == ""
@@ -86,7 +86,7 @@ def test_security_scan_empty_vulnerabilities():
scan_id="scan_123", scan_id="scan_123",
plugin_id="test_plugin", plugin_id="test_plugin",
version="1.0.0", version="1.0.0",
scan_date=datetime.now(datetime.UTC), scan_date=datetime.now(timezone.utc),
vulnerabilities=[], vulnerabilities=[],
risk_score="low", risk_score="low",
passed=True passed=True
@@ -104,7 +104,7 @@ def test_add_version_nonexistent_plugin():
download_url="https://github.com/test/plugin/archive/v1.0.0.tar.gz", download_url="https://github.com/test/plugin/archive/v1.0.0.tar.gz",
checksum="abc123", checksum="abc123",
aitbc_compatibility=["1.0.0"], aitbc_compatibility=["1.0.0"],
release_date=datetime.now(datetime.UTC) release_date=datetime.now(timezone.utc)
) )
response = client.post("/api/v1/plugins/nonexistent/versions", json=version.model_dump(mode='json')) response = client.post("/api/v1/plugins/nonexistent/versions", json=version.model_dump(mode='json'))
assert response.status_code == 404 assert response.status_code == 404
@@ -152,7 +152,7 @@ def test_security_scan_nonexistent_plugin():
scan_id="scan_123", scan_id="scan_123",
plugin_id="nonexistent", plugin_id="nonexistent",
version="1.0.0", version="1.0.0",
scan_date=datetime.now(datetime.UTC), scan_date=datetime.now(timezone.utc),
vulnerabilities=[], vulnerabilities=[],
risk_score="low", risk_score="low",
passed=True passed=True
@@ -187,7 +187,7 @@ def test_security_scan_nonexistent_version():
scan_id="scan_123", scan_id="scan_123",
plugin_id="test_plugin", plugin_id="test_plugin",
version="2.0.0", version="2.0.0",
scan_date=datetime.now(datetime.UTC), scan_date=datetime.now(timezone.utc),
vulnerabilities=[], vulnerabilities=[],
risk_score="low", risk_score="low",
passed=True passed=True
@@ -296,7 +296,7 @@ def test_security_scan_failed():
download_url="https://github.com/test/plugin/archive/v1.0.0.tar.gz", download_url="https://github.com/test/plugin/archive/v1.0.0.tar.gz",
checksum="abc123", checksum="abc123",
aitbc_compatibility=["1.0.0"], aitbc_compatibility=["1.0.0"],
release_date=datetime.now(datetime.UTC) release_date=datetime.now(timezone.utc)
) )
client.post("/api/v1/plugins/test_plugin/versions", json=version.model_dump(mode='json')) client.post("/api/v1/plugins/test_plugin/versions", json=version.model_dump(mode='json'))
@@ -305,7 +305,7 @@ def test_security_scan_failed():
scan_id="scan_123", scan_id="scan_123",
plugin_id="test_plugin", plugin_id="test_plugin",
version="1.0.0", version="1.0.0",
scan_date=datetime.now(datetime.UTC), scan_date=datetime.now(timezone.utc),
vulnerabilities=[{"severity": "high", "description": "Critical issue"}], vulnerabilities=[{"severity": "high", "description": "Critical issue"}],
risk_score="high", risk_score="high",
passed=False passed=False

View File

@@ -5,7 +5,7 @@ import sys
import sys import sys
from pathlib import Path from pathlib import Path
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, PluginRegistration, PluginVersion, SecurityScan, plugins, plugin_versions, security_scans, analytics, downloads from main import app, PluginRegistration, PluginVersion, SecurityScan, plugins, plugin_versions, security_scans, analytics, downloads
@@ -129,7 +129,7 @@ def test_add_plugin_version():
download_url="https://github.com/test/plugin/archive/v1.1.0.tar.gz", download_url="https://github.com/test/plugin/archive/v1.1.0.tar.gz",
checksum="def456", checksum="def456",
aitbc_compatibility=["1.0.0"], aitbc_compatibility=["1.0.0"],
release_date=datetime.now(datetime.UTC) release_date=datetime.now(timezone.utc)
) )
response = client.post("/api/v1/plugins/test_plugin/versions", json=version.model_dump(mode='json')) response = client.post("/api/v1/plugins/test_plugin/versions", json=version.model_dump(mode='json'))
assert response.status_code == 200 assert response.status_code == 200
@@ -166,7 +166,7 @@ def test_add_duplicate_version():
download_url="https://github.com/test/plugin/archive/v1.1.0.tar.gz", download_url="https://github.com/test/plugin/archive/v1.1.0.tar.gz",
checksum="def456", checksum="def456",
aitbc_compatibility=["1.0.0"], aitbc_compatibility=["1.0.0"],
release_date=datetime.now(datetime.UTC) release_date=datetime.now(timezone.utc)
) )
client.post("/api/v1/plugins/test_plugin/versions", json=version.model_dump(mode='json')) client.post("/api/v1/plugins/test_plugin/versions", json=version.model_dump(mode='json'))
@@ -280,7 +280,7 @@ def test_download_plugin():
download_url="https://github.com/test/plugin/archive/v1.0.0.tar.gz", download_url="https://github.com/test/plugin/archive/v1.0.0.tar.gz",
checksum="abc123", checksum="abc123",
aitbc_compatibility=["1.0.0"], aitbc_compatibility=["1.0.0"],
release_date=datetime.now(datetime.UTC) release_date=datetime.now(timezone.utc)
) )
client.post("/api/v1/plugins/test_plugin/versions", json=version.model_dump(mode='json')) client.post("/api/v1/plugins/test_plugin/versions", json=version.model_dump(mode='json'))
@@ -320,7 +320,7 @@ def test_create_security_scan():
download_url="https://github.com/test/plugin/archive/v1.0.0.tar.gz", download_url="https://github.com/test/plugin/archive/v1.0.0.tar.gz",
checksum="abc123", checksum="abc123",
aitbc_compatibility=["1.0.0"], aitbc_compatibility=["1.0.0"],
release_date=datetime.now(datetime.UTC) release_date=datetime.now(timezone.utc)
) )
client.post("/api/v1/plugins/test_plugin/versions", json=version.model_dump(mode='json')) client.post("/api/v1/plugins/test_plugin/versions", json=version.model_dump(mode='json'))
@@ -329,7 +329,7 @@ def test_create_security_scan():
scan_id="scan_123", scan_id="scan_123",
plugin_id="test_plugin", plugin_id="test_plugin",
version="1.0.0", version="1.0.0",
scan_date=datetime.now(datetime.UTC), scan_date=datetime.now(timezone.utc),
vulnerabilities=[], vulnerabilities=[],
risk_score="low", risk_score="low",
passed=True passed=True

View File

@@ -4,7 +4,7 @@ import pytest
import sys import sys
import sys import sys
from pathlib import Path from pathlib import Path
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, PluginRegistration, PluginVersion, SecurityScan from main import app, PluginRegistration, PluginVersion, SecurityScan
@@ -72,7 +72,7 @@ def test_plugin_version_model():
download_url="https://github.com/test/plugin/archive/v1.0.0.tar.gz", download_url="https://github.com/test/plugin/archive/v1.0.0.tar.gz",
checksum="abc123", checksum="abc123",
aitbc_compatibility=["1.0.0", "1.1.0"], aitbc_compatibility=["1.0.0", "1.1.0"],
release_date=datetime.now(datetime.UTC) release_date=datetime.now(timezone.utc)
) )
assert version.version == "1.0.0" assert version.version == "1.0.0"
assert version.changelog == "Initial release" assert version.changelog == "Initial release"
@@ -88,7 +88,7 @@ def test_security_scan_model():
scan_id="scan_123", scan_id="scan_123",
plugin_id="test_plugin", plugin_id="test_plugin",
version="1.0.0", version="1.0.0",
scan_date=datetime.now(datetime.UTC), scan_date=datetime.now(timezone.utc),
vulnerabilities=[{"severity": "low", "description": "Test"}], vulnerabilities=[{"severity": "low", "description": "Test"}],
risk_score="low", risk_score="low",
passed=True passed=True

View File

@@ -8,7 +8,7 @@ import json
import subprocess import subprocess
import tempfile import tempfile
import os import os
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from pathlib import Path from pathlib import Path
from typing import Dict, Any, List, Optional from typing import Dict, Any, List, Optional
from fastapi import FastAPI, HTTPException, UploadFile, File from fastapi import FastAPI, HTTPException, UploadFile, File
@@ -63,7 +63,7 @@ async def root():
return { return {
"service": "AITBC Plugin Security Service", "service": "AITBC Plugin Security Service",
"status": "running", "status": "running",
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"version": "1.0.0" "version": "1.0.0"
} }
@@ -80,7 +80,7 @@ async def health_check():
@app.post("/api/v1/security/scan") @app.post("/api/v1/security/scan")
async def initiate_security_scan(scan: SecurityScan): async def initiate_security_scan(scan: SecurityScan):
"""Initiate a security scan for a plugin""" """Initiate a security scan for a plugin"""
scan_id = f"scan_{int(datetime.now(datetime.UTC).timestamp())}" scan_id = f"scan_{int(datetime.now(timezone.utc).timestamp())}"
# Create scan record # Create scan record
scan_record = { scan_record = {
@@ -91,7 +91,7 @@ async def initiate_security_scan(scan: SecurityScan):
"scan_type": scan.scan_type, "scan_type": scan.scan_type,
"priority": scan.priority, "priority": scan.priority,
"status": "queued", "status": "queued",
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"started_at": None, "started_at": None,
"completed_at": None, "completed_at": None,
"duration": None, "duration": None,
@@ -182,7 +182,7 @@ async def list_vulnerabilities(severity: Optional[str] = None,
@app.post("/api/v1/security/policies") @app.post("/api/v1/security/policies")
async def create_security_policy(policy: Dict[str, Any]): async def create_security_policy(policy: Dict[str, Any]):
"""Create a new security policy""" """Create a new security policy"""
policy_id = f"policy_{int(datetime.now(datetime.UTC).timestamp())}" policy_id = f"policy_{int(datetime.now(timezone.utc).timestamp())}"
policy_record = { policy_record = {
"policy_id": policy_id, "policy_id": policy_id,
@@ -197,8 +197,8 @@ async def create_security_policy(policy: Dict[str, Any]):
}), }),
"plugin_types": policy.get("plugin_types", []), "plugin_types": policy.get("plugin_types", []),
"active": True, "active": True,
"created_at": datetime.now(datetime.UTC).isoformat(), "created_at": datetime.now(timezone.utc).isoformat(),
"updated_at": datetime.now(datetime.UTC).isoformat() "updated_at": datetime.now(timezone.utc).isoformat()
} }
security_policies[policy_id] = policy_record security_policies[policy_id] = policy_record
@@ -261,7 +261,7 @@ async def get_security_dashboard():
"""Get security dashboard data""" """Get security dashboard data"""
total_scans = len(scan_reports) total_scans = len(scan_reports)
recent_scans = [r for r in scan_reports.values() recent_scans = [r for r in scan_reports.values()
if datetime.fromisoformat(r["scan_date"]) > datetime.now(datetime.UTC) - timedelta(days=7)] if datetime.fromisoformat(r["scan_date"]) > datetime.now(timezone.utc) - timedelta(days=7)]
# Calculate statistics # Calculate statistics
scan_results = list(scan_reports.values()) scan_results = list(scan_reports.values())
@@ -294,7 +294,7 @@ async def get_security_dashboard():
"queue_size": len(scan_queue), "queue_size": len(scan_queue),
"active_policies": len([p for p in security_policies.values() if p["active"]]) "active_policies": len([p for p in security_policies.values() if p["active"]])
}, },
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
# Core security scanning functions # Core security scanning functions
@@ -305,15 +305,15 @@ async def process_scan_file(scan_id: str, file_path: str, filename: str):
for scan_record in scan_queue: for scan_record in scan_queue:
if scan_record["scan_id"] == scan_id: if scan_record["scan_id"] == scan_id:
scan_record["status"] = "running" scan_record["status"] = "running"
scan_record["started_at"] = datetime.now(datetime.UTC).isoformat() scan_record["started_at"] = datetime.now(timezone.utc).isoformat()
break break
start_time = datetime.now(datetime.UTC) start_time = datetime.now(timezone.utc)
# Perform security scan # Perform security scan
scan_result = await perform_security_scan(file_path, filename) scan_result = await perform_security_scan(file_path, filename)
end_time = datetime.now(datetime.UTC) end_time = datetime.now(timezone.utc)
duration = (end_time - start_time).total_seconds() duration = (end_time - start_time).total_seconds()
# Create security report # Create security report
@@ -360,7 +360,7 @@ async def process_scan_file(scan_id: str, file_path: str, filename: str):
for scan_record in scan_queue: for scan_record in scan_queue:
if scan_record["scan_id"] == scan_id: if scan_record["scan_id"] == scan_id:
scan_record["status"] = "failed" scan_record["status"] = "failed"
scan_record["completed_at"] = datetime.now(datetime.UTC).isoformat() scan_record["completed_at"] = datetime.now(timezone.utc).isoformat()
break break
async def perform_security_scan(file_path: str, filename: str) -> Dict[str, Any]: async def perform_security_scan(file_path: str, filename: str) -> Dict[str, Any]:
@@ -392,7 +392,7 @@ async def perform_security_scan(file_path: str, filename: str) -> Dict[str, Any]
"vulnerability_count": len(vulnerabilities), "vulnerability_count": len(vulnerabilities),
"severity_distribution": get_severity_distribution(vulnerabilities), "severity_distribution": get_severity_distribution(vulnerabilities),
"file_type": filename.split('.')[-1], "file_type": filename.split('.')[-1],
"scan_timestamp": datetime.now(datetime.UTC).isoformat() "scan_timestamp": datetime.now(timezone.utc).isoformat()
}) })
except Exception as e: except Exception as e:

View File

@@ -4,7 +4,7 @@ import pytest
import sys import sys
import sys import sys
from pathlib import Path from pathlib import Path
from datetime import datetime, UTC from datetime import datetime, timezone
from main import app, SecurityScan, Vulnerability, SecurityReport, calculate_overall_score, generate_recommendations, get_severity_distribution, estimate_scan_time from main import app, SecurityScan, Vulnerability, SecurityReport, calculate_overall_score, generate_recommendations, get_severity_distribution, estimate_scan_time
@@ -76,7 +76,7 @@ def test_security_report_model():
scan_id="scan_123", scan_id="scan_123",
plugin_id="plugin_123", plugin_id="plugin_123",
version="1.0.0", version="1.0.0",
scan_date=datetime.now(datetime.UTC), scan_date=datetime.now(timezone.utc),
scan_duration=120.5, scan_duration=120.5,
overall_score="passed", overall_score="passed",
vulnerabilities=[], vulnerabilities=[],

View File

@@ -1,7 +1,7 @@
"""Miner Registry Implementation""" """Miner Registry Implementation"""
from typing import List, Optional, Dict, Any from typing import List, Optional, Dict, Any
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from dataclasses import dataclass, field from dataclasses import dataclass, field
import asyncio import asyncio
@@ -22,8 +22,8 @@ class MinerInfo:
jobs_completed: int = 0 jobs_completed: int = 0
jobs_failed: int = 0 jobs_failed: int = 0
uptime_percent: float = 100.0 uptime_percent: float = 100.0
registered_at: datetime = field(default_factory=datetime.now(datetime.UTC)) registered_at: datetime = field(default_factory=datetime.now(timezone.utc))
last_heartbeat: datetime = field(default_factory=datetime.now(datetime.UTC)) last_heartbeat: datetime = field(default_factory=datetime.now(timezone.utc))
gpu_utilization: float = 0.0 gpu_utilization: float = 0.0
memory_used_gb: float = 0.0 memory_used_gb: float = 0.0
@@ -43,7 +43,7 @@ class PoolInfo:
total_hashrate: float = 0.0 total_hashrate: float = 0.0
jobs_completed_24h: int = 0 jobs_completed_24h: int = 0
earnings_24h: float = 0.0 earnings_24h: float = 0.0
created_at: datetime = field(default_factory=datetime.now(datetime.UTC)) created_at: datetime = field(default_factory=datetime.now(timezone.utc))
@dataclass @dataclass
@@ -55,7 +55,7 @@ class JobAssignment:
pool_id: str pool_id: str
model: str model: str
status: str = "assigned" status: str = "assigned"
assigned_at: datetime = field(default_factory=datetime.now(datetime.UTC)) assigned_at: datetime = field(default_factory=datetime.now(timezone.utc))
deadline: Optional[datetime] = None deadline: Optional[datetime] = None
completed_at: Optional[datetime] = None completed_at: Optional[datetime] = None
@@ -142,7 +142,7 @@ class MinerRegistry:
miner.current_jobs = current_jobs miner.current_jobs = current_jobs
miner.gpu_utilization = gpu_utilization miner.gpu_utilization = gpu_utilization
miner.memory_used_gb = memory_used_gb miner.memory_used_gb = memory_used_gb
miner.last_heartbeat = datetime.now(datetime.UTC) miner.last_heartbeat = datetime.now(timezone.utc)
async def update_capabilities(self, miner_id: str, capabilities: List[str]): async def update_capabilities(self, miner_id: str, capabilities: List[str]):
"""Update miner capabilities.""" """Update miner capabilities."""
@@ -271,7 +271,7 @@ class MinerRegistry:
if job_id in self._jobs: if job_id in self._jobs:
job = self._jobs[job_id] job = self._jobs[job_id]
job.status = status job.status = status
job.completed_at = datetime.now(datetime.UTC) job.completed_at = datetime.now(timezone.utc)
if miner_id in self._miners: if miner_id in self._miners:
miner = self._miners[miner_id] miner = self._miners[miner_id]
@@ -314,7 +314,7 @@ class MinerRegistry:
# Update job # Update job
job.miner_id = new_miner_id job.miner_id = new_miner_id
job.status = "assigned" job.status = "assigned"
job.assigned_at = datetime.now(datetime.UTC) job.assigned_at = datetime.now(timezone.utc)
# Update new miner # Update new miner
if new_miner_id in self._miners: if new_miner_id in self._miners:

View File

@@ -1,7 +1,7 @@
"""Health check routes for Pool Hub""" """Health check routes for Pool Hub"""
from fastapi import APIRouter from fastapi import APIRouter
from datetime import datetime, UTC from datetime import datetime, timezone
from sqlalchemy import text from sqlalchemy import text
router = APIRouter(tags=["health"]) router = APIRouter(tags=["health"])
@@ -13,7 +13,7 @@ async def health_check():
return { return {
"status": "ok", "status": "ok",
"service": "pool-hub", "service": "pool-hub",
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
} }
@@ -28,7 +28,7 @@ async def readiness_check():
return { return {
"ready": all_ready, "ready": all_ready,
"checks": checks, "checks": checks,
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
} }

View File

@@ -2,7 +2,7 @@
from fastapi import APIRouter, HTTPException, Depends, Query from fastapi import APIRouter, HTTPException, Depends, Query
from typing import List, Optional from typing import List, Optional
from datetime import datetime, UTC from datetime import datetime, timezone
from pydantic import BaseModel from pydantic import BaseModel
from ..registry import MinerRegistry from ..registry import MinerRegistry
@@ -86,7 +86,7 @@ async def assign_job(
job_id=job.job_id, job_id=job.job_id,
miner_id=best_miner.miner_id, miner_id=best_miner.miner_id,
pool_id=best_miner.pool_id, pool_id=best_miner.pool_id,
assigned_at=datetime.now(datetime.UTC), assigned_at=datetime.now(timezone.utc),
deadline=job.deadline deadline=job.deadline
) )

View File

@@ -2,7 +2,7 @@
from typing import List, Dict, Any, Optional from typing import List, Dict, Any, Optional
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
import math import math
@@ -74,7 +74,7 @@ class ScoringEngine:
success_rate = 100.0 # New miners start with perfect score success_rate = 100.0 # New miners start with perfect score
# Heartbeat freshness penalty # Heartbeat freshness penalty
heartbeat_age = (datetime.now(datetime.UTC) - miner.last_heartbeat).total_seconds() heartbeat_age = (datetime.now(timezone.utc) - miner.last_heartbeat).total_seconds()
if heartbeat_age > 300: # 5 minutes if heartbeat_age > 300: # 5 minutes
freshness_penalty = min(20, heartbeat_age / 60) freshness_penalty = min(20, heartbeat_age / 60)
else: else:
@@ -137,7 +137,7 @@ class ScoringEngine:
weight_total = 0 weight_total = 0
for record in history: for record in history:
age_days = (datetime.now(datetime.UTC) - record["timestamp"]).days age_days = (datetime.now(timezone.utc) - record["timestamp"]).days
weight = math.exp(-age_days / self.DECAY_HALF_LIFE_DAYS) weight = math.exp(-age_days / self.DECAY_HALF_LIFE_DAYS)
if record["success"]: if record["success"]:
@@ -153,7 +153,7 @@ class ScoringEngine:
def _get_hours_active(self, miner) -> float: def _get_hours_active(self, miner) -> float:
"""Get hours since miner registered.""" """Get hours since miner registered."""
delta = datetime.now(datetime.UTC) - miner.registered_at delta = datetime.now(timezone.utc) - miner.registered_at
return max(1, delta.total_seconds() / 3600) return max(1, delta.total_seconds() / 3600)
def _parse_memory(self, memory_str: str) -> float: def _parse_memory(self, memory_str: str) -> float:
@@ -204,7 +204,7 @@ class ScoringEngine:
self._history[miner_id] = [] self._history[miner_id] = []
self._history[miner_id].append({ self._history[miner_id].append({
"timestamp": datetime.now(datetime.UTC), "timestamp": datetime.now(timezone.utc),
"success": True, "success": True,
"metrics": metrics or {} "metrics": metrics or {}
}) })
@@ -219,7 +219,7 @@ class ScoringEngine:
self._history[miner_id] = [] self._history[miner_id] = []
self._history[miner_id].append({ self._history[miner_id].append({
"timestamp": datetime.now(datetime.UTC), "timestamp": datetime.now(timezone.utc),
"success": False, "success": False,
"error": error "error": error
}) })

View File

@@ -3,7 +3,7 @@ SLA and Billing API Endpoints for Pool-Hub
Provides endpoints for SLA metrics, capacity planning, and billing integration. Provides endpoints for SLA metrics, capacity planning, and billing integration.
""" """
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from typing import Dict, List, Optional, Any from typing import Dict, List, Optional, Any
from decimal import Decimal from decimal import Decimal
@@ -165,7 +165,7 @@ async def get_capacity_snapshots(
): ):
"""Get capacity planning snapshots""" """Get capacity planning snapshots"""
try: try:
cutoff = datetime.now(datetime.UTC) - timedelta(hours=hours) cutoff = datetime.now(timezone.utc) - timedelta(hours=hours)
stmt = ( stmt = (
db.query(CapacitySnapshot) db.query(CapacitySnapshot)
.filter(CapacitySnapshot.timestamp >= cutoff) .filter(CapacitySnapshot.timestamp >= cutoff)
@@ -236,7 +236,7 @@ async def configure_capacity_alerts(
return { return {
"status": "configured", "status": "configured",
"alert_config": alert_config, "alert_config": alert_config,
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
} }
except Exception as e: except Exception as e:
logger.error(f"Error configuring capacity alerts: {e}") logger.error(f"Error configuring capacity alerts: {e}")
@@ -270,7 +270,7 @@ async def sync_billing_usage(
try: try:
if request.miner_id: if request.miner_id:
# Sync specific miner # Sync specific miner
end_date = datetime.now(datetime.UTC) end_date = datetime.now(timezone.utc)
start_date = end_date - timedelta(hours=request.hours_back) start_date = end_date - timedelta(hours=request.hours_back)
result = await billing_integration.sync_miner_usage( result = await billing_integration.sync_miner_usage(
miner_id=request.miner_id, start_date=start_date, end_date=end_date miner_id=request.miner_id, start_date=start_date, end_date=end_date
@@ -350,7 +350,7 @@ async def get_sla_status(db: Session = Depends(get_db)):
"status": status, "status": status,
"active_violations": len(active_violations), "active_violations": len(active_violations),
"recent_metrics_count": len(recent_metrics), "recent_metrics_count": len(recent_metrics),
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
} }
except Exception as e: except Exception as e:
logger.error(f"Error getting SLA status: {e}") logger.error(f"Error getting SLA status: {e}")

View File

@@ -40,7 +40,7 @@ class Miner(Base):
miner_id: Mapped[str] = mapped_column(String(64), primary_key=True) miner_id: Mapped[str] = mapped_column(String(64), primary_key=True)
api_key_hash: Mapped[str] = mapped_column(String(128), nullable=False) api_key_hash: Mapped[str] = mapped_column(String(128), nullable=False)
created_at: Mapped[dt.datetime] = mapped_column( created_at: Mapped[dt.datetime] = mapped_column(
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC) DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
) )
last_seen_at: Mapped[Optional[dt.datetime]] = mapped_column(DateTime(timezone=True)) last_seen_at: Mapped[Optional[dt.datetime]] = mapped_column(DateTime(timezone=True))
addr: Mapped[str] = mapped_column(String(256)) addr: Mapped[str] = mapped_column(String(256))
@@ -78,7 +78,7 @@ class MinerStatus(Base):
uptime_pct: Mapped[Optional[float]] = mapped_column(Float) # SLA metric uptime_pct: Mapped[Optional[float]] = mapped_column(Float) # SLA metric
last_heartbeat_at: Mapped[Optional[dt.datetime]] = mapped_column(DateTime(timezone=True)) last_heartbeat_at: Mapped[Optional[dt.datetime]] = mapped_column(DateTime(timezone=True))
updated_at: Mapped[dt.datetime] = mapped_column( updated_at: Mapped[dt.datetime] = mapped_column(
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC), onupdate=dt.datetime.now(datetime.UTC) DateTime(timezone=True), default=dt.datetime.now(timezone.utc), onupdate=dt.datetime.now(timezone.utc)
) )
miner: Mapped[Miner] = relationship(back_populates="status") miner: Mapped[Miner] = relationship(back_populates="status")
@@ -95,7 +95,7 @@ class MatchRequest(Base):
hints: Mapped[Dict[str, object]] = mapped_column(JSON, default=dict) hints: Mapped[Dict[str, object]] = mapped_column(JSON, default=dict)
top_k: Mapped[int] = mapped_column(Integer, default=1) top_k: Mapped[int] = mapped_column(Integer, default=1)
created_at: Mapped[dt.datetime] = mapped_column( created_at: Mapped[dt.datetime] = mapped_column(
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC) DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
) )
results: Mapped[List["MatchResult"]] = relationship( results: Mapped[List["MatchResult"]] = relationship(
@@ -119,7 +119,7 @@ class MatchResult(Base):
price: Mapped[Optional[float]] = mapped_column(Float) price: Mapped[Optional[float]] = mapped_column(Float)
created_at: Mapped[dt.datetime] = mapped_column( created_at: Mapped[dt.datetime] = mapped_column(
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC) DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
) )
request: Mapped[MatchRequest] = relationship(back_populates="results") request: Mapped[MatchRequest] = relationship(back_populates="results")
@@ -140,7 +140,7 @@ class Feedback(Base):
fail_code: Mapped[Optional[str]] = mapped_column(String(64)) fail_code: Mapped[Optional[str]] = mapped_column(String(64))
tokens_spent: Mapped[Optional[float]] = mapped_column(Float) tokens_spent: Mapped[Optional[float]] = mapped_column(Float)
created_at: Mapped[dt.datetime] = mapped_column( created_at: Mapped[dt.datetime] = mapped_column(
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC) DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
) )
miner: Mapped[Miner] = relationship(back_populates="feedback") miner: Mapped[Miner] = relationship(back_populates="feedback")
@@ -164,10 +164,10 @@ class ServiceConfig(Base):
capabilities: Mapped[List[str]] = mapped_column(JSON, default=list) capabilities: Mapped[List[str]] = mapped_column(JSON, default=list)
max_concurrent: Mapped[int] = mapped_column(Integer, default=1) max_concurrent: Mapped[int] = mapped_column(Integer, default=1)
created_at: Mapped[dt.datetime] = mapped_column( created_at: Mapped[dt.datetime] = mapped_column(
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC) DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
) )
updated_at: Mapped[dt.datetime] = mapped_column( updated_at: Mapped[dt.datetime] = mapped_column(
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC), onupdate=dt.datetime.now(datetime.UTC) DateTime(timezone=True), default=dt.datetime.now(timezone.utc), onupdate=dt.datetime.now(timezone.utc)
) )
# Add unique constraint for miner_id + service_type # Add unique constraint for miner_id + service_type
@@ -192,7 +192,7 @@ class SLAMetric(Base):
threshold: Mapped[float] = mapped_column(Float, nullable=False) threshold: Mapped[float] = mapped_column(Float, nullable=False)
is_violation: Mapped[bool] = mapped_column(Boolean, default=False) is_violation: Mapped[bool] = mapped_column(Boolean, default=False)
timestamp: Mapped[dt.datetime] = mapped_column( timestamp: Mapped[dt.datetime] = mapped_column(
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC) DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
) )
meta_data: Mapped[Dict[str, str]] = mapped_column(JSON, default=dict) meta_data: Mapped[Dict[str, str]] = mapped_column(JSON, default=dict)
@@ -217,7 +217,7 @@ class SLAViolation(Base):
violation_duration_ms: Mapped[Optional[int]] = mapped_column(Integer) violation_duration_ms: Mapped[Optional[int]] = mapped_column(Integer)
resolved_at: Mapped[Optional[dt.datetime]] = mapped_column(DateTime(timezone=True)) resolved_at: Mapped[Optional[dt.datetime]] = mapped_column(DateTime(timezone=True))
created_at: Mapped[dt.datetime] = mapped_column( created_at: Mapped[dt.datetime] = mapped_column(
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC) DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
) )
meta_data: Mapped[Dict[str, str]] = mapped_column(JSON, default=dict) meta_data: Mapped[Dict[str, str]] = mapped_column(JSON, default=dict)
@@ -241,6 +241,6 @@ class CapacitySnapshot(Base):
recommended_scaling: Mapped[str] = mapped_column(String(32), nullable=False) recommended_scaling: Mapped[str] = mapped_column(String(32), nullable=False)
scaling_reason: Mapped[str] = mapped_column(Text) scaling_reason: Mapped[str] = mapped_column(Text)
timestamp: Mapped[dt.datetime] = mapped_column( timestamp: Mapped[dt.datetime] = mapped_column(
DateTime(timezone=True), default=dt.datetime.now(datetime.UTC) DateTime(timezone=True), default=dt.datetime.now(timezone.utc)
) )
meta_data: Mapped[Dict[str, Any]] = mapped_column(JSON, default=dict) meta_data: Mapped[Dict[str, Any]] = mapped_column(JSON, default=dict)

View File

@@ -40,7 +40,7 @@ class FeedbackRepository:
latency_ms=latency_ms, latency_ms=latency_ms,
fail_code=fail_code, fail_code=fail_code,
tokens_spent=tokens_spent, tokens_spent=tokens_spent,
created_at=dt.datetime.now(datetime.UTC), created_at=dt.datetime.now(timezone.utc),
) )
self._session.add(feedback) self._session.add(feedback)
await self._session.flush() await self._session.flush()

View File

@@ -34,7 +34,7 @@ class MatchRepository:
requirements=requirements, requirements=requirements,
hints=hints or {}, hints=hints or {},
top_k=top_k, top_k=top_k,
created_at=dt.datetime.now(datetime.UTC), created_at=dt.datetime.now(timezone.utc),
) )
self._session.add(request) self._session.add(request)
await self._session.flush() await self._session.flush()
@@ -58,7 +58,7 @@ class MatchRepository:
publish: bool = True, publish: bool = True,
) -> List[MatchResult]: ) -> List[MatchResult]:
results: List[MatchResult] = [] results: List[MatchResult] = []
created_at = dt.datetime.now(datetime.UTC) created_at = dt.datetime.now(timezone.utc)
for candidate in candidates: for candidate in candidates:
result = MatchResult( result = MatchResult(
request_id=request_id, request_id=request_id,

View File

@@ -69,7 +69,7 @@ class MinerRepository:
miner.capabilities = capabilities miner.capabilities = capabilities
miner.region = region miner.region = region
miner.last_seen_at = dt.datetime.now(datetime.UTC) miner.last_seen_at = dt.datetime.now(timezone.utc)
await self._session.flush() await self._session.flush()
await self._sync_miner_to_redis(miner_id) await self._sync_miner_to_redis(miner_id)
@@ -97,7 +97,7 @@ class MinerRepository:
"avg_latency_ms": avg_latency_ms, "avg_latency_ms": avg_latency_ms,
"temp_c": temp_c, "temp_c": temp_c,
"mem_free_gb": mem_free_gb, "mem_free_gb": mem_free_gb,
"updated_at": dt.datetime.now(datetime.UTC), "updated_at": dt.datetime.now(timezone.utc),
}.items() }.items()
if v is not None if v is not None
} }
@@ -107,7 +107,7 @@ class MinerRepository:
miner = await self._session.get(Miner, miner_id) miner = await self._session.get(Miner, miner_id)
if miner: if miner:
miner.last_seen_at = dt.datetime.now(datetime.UTC) miner.last_seen_at = dt.datetime.now(timezone.utc)
await self._session.flush() await self._session.flush()
await self._sync_miner_to_redis(miner_id) await self._sync_miner_to_redis(miner_id)
@@ -115,7 +115,7 @@ class MinerRepository:
miner = await self._session.get(Miner, miner_id) miner = await self._session.get(Miner, miner_id)
if miner is None: if miner is None:
return return
miner.last_seen_at = dt.datetime.now(datetime.UTC) miner.last_seen_at = dt.datetime.now(timezone.utc)
await self._session.flush() await self._session.flush()
await self._sync_miner_to_redis(miner_id) await self._sync_miner_to_redis(miner_id)

View File

@@ -4,7 +4,7 @@ Integrates pool-hub usage data with coordinator-api's billing system.
""" """
import asyncio import asyncio
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from decimal import Decimal from decimal import Decimal
from typing import Dict, List, Optional, Any from typing import Dict, List, Optional, Any
@@ -76,7 +76,7 @@ class BillingIntegration:
"unit_price": float(unit_price), "unit_price": float(unit_price),
"total_amount": float(total_cost), "total_amount": float(total_cost),
"currency": "USD", "currency": "USD",
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"metadata": metadata or {}, "metadata": metadata or {},
} }
@@ -139,7 +139,7 @@ class BillingIntegration:
) -> Dict[str, Any]: ) -> Dict[str, Any]:
"""Sync usage data for all miners to coordinator-api billing""" """Sync usage data for all miners to coordinator-api billing"""
end_date = datetime.now(datetime.UTC) end_date = datetime.now(timezone.utc)
start_date = end_date - timedelta(hours=hours_back) start_date = end_date - timedelta(hours=hours_back)
# Get all miners # Get all miners

View File

@@ -4,7 +4,7 @@ Collects and tracks SLA metrics for miners including uptime, response time, job
""" """
import asyncio import asyncio
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from decimal import Decimal from decimal import Decimal
from typing import Dict, List, Optional, Any from typing import Dict, List, Optional, Any
@@ -57,7 +57,7 @@ class SLACollector:
metric_value=metric_value, metric_value=metric_value,
threshold=threshold, threshold=threshold,
is_violation=is_violation, is_violation=is_violation,
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
meta_data=metadata or {}, meta_data=metadata or {},
) )
@@ -90,7 +90,7 @@ class SLACollector:
# Calculate uptime based on last heartbeat # Calculate uptime based on last heartbeat
if miner_status.last_heartbeat_at: if miner_status.last_heartbeat_at:
time_since_heartbeat = ( time_since_heartbeat = (
datetime.now(datetime.UTC) - miner_status.last_heartbeat_at datetime.now(timezone.utc) - miner_status.last_heartbeat_at
).total_seconds() ).total_seconds()
# Consider miner down if no heartbeat for 5 minutes # Consider miner down if no heartbeat for 5 minutes
@@ -153,7 +153,7 @@ class SLACollector:
stmt = ( stmt = (
select(Feedback) select(Feedback)
.where(Feedback.miner_id == miner_id) .where(Feedback.miner_id == miner_id)
.where(Feedback.created_at >= datetime.now(datetime.UTC) - timedelta(days=7)) .where(Feedback.created_at >= datetime.now(timezone.utc) - timedelta(days=7))
.order_by(Feedback.created_at.desc()) .order_by(Feedback.created_at.desc())
.limit(100) .limit(100)
) )
@@ -206,7 +206,7 @@ class SLACollector:
forecast_capacity=total_miners, # Would be calculated from forecasting forecast_capacity=total_miners, # Would be calculated from forecasting
recommended_scaling="stable", recommended_scaling="stable",
scaling_reason="Capacity within normal range", scaling_reason="Capacity within normal range",
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
meta_data={"method": "real_time_collection"}, meta_data={"method": "real_time_collection"},
) )
@@ -266,7 +266,7 @@ class SLACollector:
stmt = ( stmt = (
select(func.count(SLAViolation.id)) select(func.count(SLAViolation.id))
.where(SLAViolation.resolved_at.is_(None)) .where(SLAViolation.resolved_at.is_(None))
.where(SLAViolation.created_at >= datetime.now(datetime.UTC) - timedelta(hours=1)) .where(SLAViolation.created_at >= datetime.now(timezone.utc) - timedelta(hours=1))
) )
results["violations_detected"] = self.db.execute(stmt).scalar() or 0 results["violations_detected"] = self.db.execute(stmt).scalar() or 0
@@ -282,7 +282,7 @@ class SLACollector:
) -> List[SLAMetric]: ) -> List[SLAMetric]:
"""Get SLA metrics for a miner or all miners""" """Get SLA metrics for a miner or all miners"""
cutoff = datetime.now(datetime.UTC) - timedelta(hours=hours) cutoff = datetime.now(timezone.utc) - timedelta(hours=hours)
stmt = select(SLAMetric).where(SLAMetric.timestamp >= cutoff) stmt = select(SLAMetric).where(SLAMetric.timestamp >= cutoff)
@@ -349,7 +349,7 @@ class SLACollector:
metric_value=metric_value, metric_value=metric_value,
threshold=threshold, threshold=threshold,
violation_duration_ms=None, # Will be updated when resolved violation_duration_ms=None, # Will be updated when resolved
created_at=datetime.now(datetime.UTC), created_at=datetime.now(timezone.utc),
meta_data=metadata or {}, meta_data=metadata or {},
) )

View File

@@ -4,7 +4,7 @@ Tests for Billing Integration Service
import sys import sys
import pytest import pytest
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from decimal import Decimal from decimal import Decimal
from unittest.mock import AsyncMock, patch from unittest.mock import AsyncMock, patch
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
@@ -84,7 +84,7 @@ async def test_record_usage_with_fallback_pricing(billing_integration: BillingIn
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_sync_miner_usage(billing_integration: BillingIntegration, sample_miner: Miner): async def test_sync_miner_usage(billing_integration: BillingIntegration, sample_miner: Miner):
"""Test syncing usage for a specific miner""" """Test syncing usage for a specific miner"""
end_date = datetime.now(datetime.UTC) end_date = datetime.now(timezone.utc)
start_date = end_date - timedelta(hours=24) start_date = end_date - timedelta(hours=24)
with patch("poolhub.services.billing_integration.httpx.AsyncClient") as mock_client: with patch("poolhub.services.billing_integration.httpx.AsyncClient") as mock_client:
@@ -123,7 +123,7 @@ async def test_sync_all_miners_usage(billing_integration: BillingIntegration, sa
def test_collect_miner_usage(billing_integration: BillingIntegration, sample_miner: Miner): def test_collect_miner_usage(billing_integration: BillingIntegration, sample_miner: Miner):
"""Test collecting usage data for a miner""" """Test collecting usage data for a miner"""
end_date = datetime.now(datetime.UTC) end_date = datetime.now(timezone.utc)
start_date = end_date - timedelta(hours=24) start_date = end_date - timedelta(hours=24)
usage_data = billing_integration.db.run_sync( usage_data = billing_integration.db.run_sync(
@@ -169,7 +169,7 @@ async def test_trigger_invoice_generation(billing_integration: BillingIntegratio
mock_client.return_value.__aenter__.return_value.post = AsyncMock(return_value=mock_response) mock_client.return_value.__aenter__.return_value.post = AsyncMock(return_value=mock_response)
end_date = datetime.now(datetime.UTC) end_date = datetime.now(timezone.utc)
start_date = end_date - timedelta(days=30) start_date = end_date - timedelta(days=30)
result = await billing_integration.trigger_invoice_generation( result = await billing_integration.trigger_invoice_generation(

View File

@@ -5,7 +5,7 @@ Tests the integration between pool-hub and coordinator-api's billing system.
import sys import sys
import pytest import pytest
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from decimal import Decimal from decimal import Decimal
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
@@ -70,7 +70,7 @@ def test_end_to_end_sla_to_billing_workflow(
assert len(metrics) > 0 assert len(metrics) > 0
# Step 3: Collect usage data for billing # Step 3: Collect usage data for billing
end_date = datetime.now(datetime.UTC) end_date = datetime.now(timezone.utc)
start_date = end_date - timedelta(hours=1) start_date = end_date - timedelta(hours=1)
usage_data = sla_collector.db.run_sync( usage_data = sla_collector.db.run_sync(
lambda sess: billing_integration._collect_miner_usage( lambda sess: billing_integration._collect_miner_usage(
@@ -126,7 +126,7 @@ def test_sla_violation_billing_correlation(
assert len(violations) > 0 assert len(violations) > 0
# Usage should still be recorded even with violations # Usage should still be recorded even with violations
end_date = datetime.now(datetime.UTC) end_date = datetime.now(timezone.utc)
start_date = end_date - timedelta(hours=1) start_date = end_date - timedelta(hours=1)
usage_data = sla_collector.db.run_sync( usage_data = sla_collector.db.run_sync(
lambda sess: billing_integration._collect_miner_usage( lambda sess: billing_integration._collect_miner_usage(
@@ -172,7 +172,7 @@ def test_billing_sync_with_coordinator_api(
"""Test billing sync with coordinator-api (mocked)""" """Test billing sync with coordinator-api (mocked)"""
from unittest.mock import AsyncMock, patch from unittest.mock import AsyncMock, patch
end_date = datetime.now(datetime.UTC) end_date = datetime.now(timezone.utc)
start_date = end_date - timedelta(hours=1) start_date = end_date - timedelta(hours=1)
with patch("poolhub.services.billing_integration.httpx.AsyncClient") as mock_client: with patch("poolhub.services.billing_integration.httpx.AsyncClient") as mock_client:

View File

@@ -4,7 +4,7 @@ Tests for SLA Collector Service
import sys import sys
import pytest import pytest
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from decimal import Decimal from decimal import Decimal
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
@@ -48,7 +48,7 @@ def sample_miner_status(db_session: Session, sample_miner: Miner) -> MinerStatus
avg_latency_ms=150, avg_latency_ms=150,
temp_c=65, temp_c=65,
mem_free_gb=32.0, mem_free_gb=32.0,
last_heartbeat_at=datetime.now(datetime.UTC), last_heartbeat_at=datetime.now(timezone.utc),
) )
db_session.add(status) db_session.add(status)
db_session.commit() db_session.commit()

View File

@@ -4,7 +4,7 @@ Tests for SLA API Endpoints
import sys import sys
import pytest import pytest
from datetime import datetime, UTC, timedelta from datetime import datetime, timezone, timedelta
from decimal import Decimal from decimal import Decimal
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
@@ -65,7 +65,7 @@ def sample_sla_metric(db_session: Session, sample_miner: Miner) -> SLAMetric:
metric_value=98.5, metric_value=98.5,
threshold=95.0, threshold=95.0,
is_violation=False, is_violation=False,
timestamp=datetime.now(datetime.UTC), timestamp=datetime.now(timezone.utc),
metadata={"test": "true"}, metadata={"test": "true"},
) )
db_session.add(metric) db_session.add(metric)
@@ -191,7 +191,7 @@ def test_record_usage(test_client: TestClient):
def test_generate_invoice(test_client: TestClient): def test_generate_invoice(test_client: TestClient):
"""Test triggering invoice generation""" """Test triggering invoice generation"""
end_date = datetime.now(datetime.UTC) end_date = datetime.now(timezone.utc)
start_date = end_date - timedelta(days=30) start_date = end_date - timedelta(days=30)
request_data = { request_data = {

View File

@@ -6,7 +6,7 @@ Handles order matching, trade execution, and settlement
import asyncio import asyncio
import json import json
from collections import defaultdict, deque from collections import defaultdict, deque
from datetime import datetime, UTC from datetime import datetime, timezone
from pathlib import Path from pathlib import Path
from typing import Dict, Any, List, Optional, Tuple from typing import Dict, Any, List, Optional, Tuple
from fastapi import FastAPI, HTTPException from fastapi import FastAPI, HTTPException
@@ -70,7 +70,7 @@ async def root():
return { return {
"service": "AITBC Trading Engine", "service": "AITBC Trading Engine",
"status": "running", "status": "running",
"timestamp": datetime.now(datetime.UTC).isoformat(), "timestamp": datetime.now(timezone.utc).isoformat(),
"version": "1.0.0" "version": "1.0.0"
} }
@@ -98,7 +98,7 @@ async def submit_order(order: Order):
"volume_24h": 0.0, "volume_24h": 0.0,
"high_24h": None, "high_24h": None,
"low_24h": None, "low_24h": None,
"created_at": datetime.now(datetime.UTC).isoformat() "created_at": datetime.now(timezone.utc).isoformat()
} }
# Store order # Store order
@@ -185,7 +185,7 @@ async def get_order_book(symbol: str, depth: int = 10):
"volume_24h": book["volume_24h"], "volume_24h": book["volume_24h"],
"high_24h": book["high_24h"], "high_24h": book["high_24h"],
"low_24h": book["low_24h"], "low_24h": book["low_24h"],
"timestamp": datetime.now(datetime.UTC).isoformat() "timestamp": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/trades") @app.get("/api/v1/trades")
@@ -216,7 +216,7 @@ async def get_ticker(symbol: str):
trades_24h = [t for t in trades.values() trades_24h = [t for t in trades.values()
if t["symbol"] == symbol and if t["symbol"] == symbol and
datetime.fromisoformat(t["timestamp"]) > datetime.fromisoformat(t["timestamp"]) >
datetime.now(datetime.UTC) - timedelta(hours=24)] datetime.now(timezone.utc) - timedelta(hours=24)]
if trades_24h: if trades_24h:
prices = [t["price"] for t in trades_24h] prices = [t["price"] for t in trades_24h]
@@ -276,7 +276,7 @@ async def cancel_order(order_id: str):
# Update order status # Update order status
order["status"] = "cancelled" order["status"] = "cancelled"
order["cancelled_at"] = datetime.now(datetime.UTC).isoformat() order["cancelled_at"] = datetime.now(timezone.utc).isoformat()
logger.info(f"Order cancelled: {order_id}") logger.info(f"Order cancelled: {order_id}")
@@ -295,7 +295,7 @@ async def get_market_data():
trades_24h = [t for t in trades.values() trades_24h = [t for t in trades.values()
if t["symbol"] == symbol and if t["symbol"] == symbol and
datetime.fromisoformat(t["timestamp"]) > datetime.fromisoformat(t["timestamp"]) >
datetime.now(datetime.UTC) - timedelta(hours=24)] datetime.now(timezone.utc) - timedelta(hours=24)]
market_summary[symbol] = { market_summary[symbol] = {
"last_price": book["last_price"], "last_price": book["last_price"],
@@ -310,7 +310,7 @@ async def get_market_data():
return { return {
"market_data": market_summary, "market_data": market_summary,
"total_symbols": len(market_summary), "total_symbols": len(market_summary),
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
@app.get("/api/v1/engine/stats") @app.get("/api/v1/engine/stats")
@@ -338,7 +338,7 @@ async def get_engine_stats():
"active_order_books": len(order_books), "active_order_books": len(order_books),
"uptime": "running" "uptime": "running"
}, },
"generated_at": datetime.now(datetime.UTC).isoformat() "generated_at": datetime.now(timezone.utc).isoformat()
} }
# Core trading engine logic # Core trading engine logic
@@ -457,7 +457,7 @@ async def execute_trade(order1: Dict, order2: Dict, price: float) -> Optional[Di
return None return None
# Create trade record # Create trade record
trade_id = f"trade_{int(datetime.now(datetime.UTC).timestamp())}_{len(trades)}" trade_id = f"trade_{int(datetime.now(timezone.utc).timestamp())}_{len(trades)}"
trade = { trade = {
"trade_id": trade_id, "trade_id": trade_id,
@@ -466,7 +466,7 @@ async def execute_trade(order1: Dict, order2: Dict, price: float) -> Optional[Di
"sell_order_id": order2["order_id"] if order2["side"] == "sell" else order1["order_id"], "sell_order_id": order2["order_id"] if order2["side"] == "sell" else order1["order_id"],
"quantity": trade_quantity, "quantity": trade_quantity,
"price": price, "price": price,
"timestamp": datetime.now(datetime.UTC).isoformat() "timestamp": datetime.now(timezone.utc).isoformat()
} }
trades[trade_id] = trade trades[trade_id] = trade
@@ -524,7 +524,7 @@ def update_market_data(symbol: str, trades_executed: List[Dict]):
trades_24h = [t for t in trades.values() trades_24h = [t for t in trades.values()
if t["symbol"] == symbol and if t["symbol"] == symbol and
datetime.fromisoformat(t["timestamp"]) > datetime.fromisoformat(t["timestamp"]) >
datetime.now(datetime.UTC) - timedelta(hours=24)] datetime.now(timezone.utc) - timedelta(hours=24)]
if trades_24h: if trades_24h:
prices = [t["price"] for t in trades_24h] prices = [t["price"] for t in trades_24h]
@@ -548,7 +548,7 @@ async def simulate_market_activity():
side = random.choice(["buy", "sell"]) side = random.choice(["buy", "sell"])
quantity = random.uniform(10, 1000) quantity = random.uniform(10, 1000)
order_id = f"sim_order_{int(datetime.now(datetime.UTC).timestamp())}" order_id = f"sim_order_{int(datetime.now(timezone.utc).timestamp())}"
order = Order( order = Order(
order_id=order_id, order_id=order_id,
symbol=symbol, symbol=symbol,
@@ -556,7 +556,7 @@ async def simulate_market_activity():
type="market", type="market",
quantity=quantity, quantity=quantity,
user_id="sim_user", user_id="sim_user",
timestamp=datetime.now(datetime.UTC) timestamp=datetime.now(timezone.utc)
) )
order_data = { order_data = {

Some files were not shown because too many files have changed in this diff Show More