chore: update file permissions to executable across repository
- Change file mode from 644 to 755 for all project files - Add chain_id parameter to get_balance RPC endpoint with default "ait-devnet" - Rename Miner.extra_meta_data to extra_metadata for consistency
This commit is contained in:
0
apps/EXPLORER_MERGE_SUMMARY.md
Normal file → Executable file
0
apps/EXPLORER_MERGE_SUMMARY.md
Normal file → Executable file
0
apps/blockchain-explorer/README.md
Normal file → Executable file
0
apps/blockchain-explorer/README.md
Normal file → Executable file
0
apps/blockchain-explorer/assets/index.js
Normal file → Executable file
0
apps/blockchain-explorer/assets/index.js
Normal file → Executable file
0
apps/blockchain-explorer/assets/style.css
Normal file → Executable file
0
apps/blockchain-explorer/assets/style.css
Normal file → Executable file
0
apps/blockchain-explorer/index.html
Normal file → Executable file
0
apps/blockchain-explorer/index.html
Normal file → Executable file
0
apps/blockchain-explorer/main.py
Normal file → Executable file
0
apps/blockchain-explorer/main.py
Normal file → Executable file
0
apps/blockchain-explorer/nginx.conf
Normal file → Executable file
0
apps/blockchain-explorer/nginx.conf
Normal file → Executable file
0
apps/blockchain-explorer/requirements.txt
Normal file → Executable file
0
apps/blockchain-explorer/requirements.txt
Normal file → Executable file
0
apps/blockchain-node/.env.example
Normal file → Executable file
0
apps/blockchain-node/.env.example
Normal file → Executable file
0
apps/blockchain-node/README.md
Normal file → Executable file
0
apps/blockchain-node/README.md
Normal file → Executable file
0
apps/blockchain-node/alembic.ini
Normal file → Executable file
0
apps/blockchain-node/alembic.ini
Normal file → Executable file
0
apps/blockchain-node/create_genesis.py
Normal file → Executable file
0
apps/blockchain-node/create_genesis.py
Normal file → Executable file
0
apps/blockchain-node/data/devnet/genesis.json
Normal file → Executable file
0
apps/blockchain-node/data/devnet/genesis.json
Normal file → Executable file
0
apps/blockchain-node/docs/SCHEMA.md
Normal file → Executable file
0
apps/blockchain-node/docs/SCHEMA.md
Normal file → Executable file
0
apps/blockchain-node/init_genesis.py
Normal file → Executable file
0
apps/blockchain-node/init_genesis.py
Normal file → Executable file
0
apps/blockchain-node/migrations/README
Normal file → Executable file
0
apps/blockchain-node/migrations/README
Normal file → Executable file
0
apps/blockchain-node/migrations/env.py
Normal file → Executable file
0
apps/blockchain-node/migrations/env.py
Normal file → Executable file
0
apps/blockchain-node/migrations/script.py.mako
Normal file → Executable file
0
apps/blockchain-node/migrations/script.py.mako
Normal file → Executable file
0
apps/blockchain-node/migrations/versions/50fb6691025c_add_chain_id.py
Normal file → Executable file
0
apps/blockchain-node/migrations/versions/50fb6691025c_add_chain_id.py
Normal file → Executable file
0
apps/blockchain-node/migrations/versions/80bc0020bde2_add_block_relationships.py
Normal file → Executable file
0
apps/blockchain-node/migrations/versions/80bc0020bde2_add_block_relationships.py
Normal file → Executable file
0
apps/blockchain-node/migrations/versions/e31f486f1484_baseline.py
Normal file → Executable file
0
apps/blockchain-node/migrations/versions/e31f486f1484_baseline.py
Normal file → Executable file
0
apps/blockchain-node/migrations/versions/fix_transaction_block_foreign_key.py
Normal file → Executable file
0
apps/blockchain-node/migrations/versions/fix_transaction_block_foreign_key.py
Normal file → Executable file
0
apps/blockchain-node/observability/README.md
Normal file → Executable file
0
apps/blockchain-node/observability/README.md
Normal file → Executable file
0
apps/blockchain-node/observability/alerts.yml
Normal file → Executable file
0
apps/blockchain-node/observability/alerts.yml
Normal file → Executable file
0
apps/blockchain-node/observability/generated_dashboards/blockchain-node-overview.json
Normal file → Executable file
0
apps/blockchain-node/observability/generated_dashboards/blockchain-node-overview.json
Normal file → Executable file
0
apps/blockchain-node/observability/generated_dashboards/coordinator-overview.json
Normal file → Executable file
0
apps/blockchain-node/observability/generated_dashboards/coordinator-overview.json
Normal file → Executable file
0
apps/blockchain-node/observability/gossip-recording-rules.yml
Normal file → Executable file
0
apps/blockchain-node/observability/gossip-recording-rules.yml
Normal file → Executable file
0
apps/blockchain-node/observability/grafana-dashboard.json
Normal file → Executable file
0
apps/blockchain-node/observability/grafana-dashboard.json
Normal file → Executable file
0
apps/blockchain-node/observability/prometheus.yml
Normal file → Executable file
0
apps/blockchain-node/observability/prometheus.yml
Normal file → Executable file
0
apps/blockchain-node/poetry.lock
generated
Normal file → Executable file
0
apps/blockchain-node/poetry.lock
generated
Normal file → Executable file
0
apps/blockchain-node/pyproject.toml
Normal file → Executable file
0
apps/blockchain-node/pyproject.toml
Normal file → Executable file
0
apps/blockchain-node/requirements.txt
Normal file → Executable file
0
apps/blockchain-node/requirements.txt
Normal file → Executable file
0
apps/blockchain-node/scripts/apply_bootstrap_genesis.sh
Normal file → Executable file
0
apps/blockchain-node/scripts/apply_bootstrap_genesis.sh
Normal file → Executable file
0
apps/blockchain-node/scripts/assign_proposer.py
Normal file → Executable file
0
apps/blockchain-node/scripts/assign_proposer.py
Normal file → Executable file
0
apps/blockchain-node/scripts/create_bootstrap_genesis.py
Normal file → Executable file
0
apps/blockchain-node/scripts/create_bootstrap_genesis.py
Normal file → Executable file
0
apps/blockchain-node/scripts/keygen.py
Normal file → Executable file
0
apps/blockchain-node/scripts/keygen.py
Normal file → Executable file
0
apps/blockchain-node/scripts/load_genesis.py
Normal file → Executable file
0
apps/blockchain-node/scripts/load_genesis.py
Normal file → Executable file
0
apps/blockchain-node/scripts/make_genesis.py
Normal file → Executable file
0
apps/blockchain-node/scripts/make_genesis.py
Normal file → Executable file
0
apps/blockchain-node/scripts/mock_coordinator.py
Normal file → Executable file
0
apps/blockchain-node/scripts/mock_coordinator.py
Normal file → Executable file
0
apps/blockchain-node/scripts/start_mock_blockchain.sh
Normal file → Executable file
0
apps/blockchain-node/scripts/start_mock_blockchain.sh
Normal file → Executable file
0
apps/blockchain-node/scripts/ws_load_test.py
Normal file → Executable file
0
apps/blockchain-node/scripts/ws_load_test.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/__init__.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/__init__.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/app.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/app.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/config.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/config.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/consensus/__init__.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/consensus/__init__.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/consensus/poa.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/consensus/poa.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/consensus/poa.py.orig
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/consensus/poa.py.orig
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/consensus/poa.py.rej
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/consensus/poa.py.rej
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/contracts/agent_wallet_security.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/contracts/agent_wallet_security.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/contracts/guardian_config_fixed.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/contracts/guardian_config_fixed.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/contracts/guardian_contract.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/contracts/guardian_contract.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/contracts/persistent_spending_tracker.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/contracts/persistent_spending_tracker.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/database.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/database.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/gossip/__init__.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/gossip/__init__.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/gossip/broker.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/gossip/broker.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/gossip/relay.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/gossip/relay.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/logger.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/logger.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/main.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/main.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/mempool.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/mempool.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/metrics.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/metrics.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/models.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/models.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/observability/__init__.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/observability/__init__.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/observability/dashboards.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/observability/dashboards.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/observability/exporters.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/observability/exporters.py
Normal file → Executable file
2
apps/blockchain-node/src/aitbc_chain/rpc/router.py
Normal file → Executable file
2
apps/blockchain-node/src/aitbc_chain/rpc/router.py
Normal file → Executable file
@@ -300,7 +300,7 @@ async def get_receipts(limit: int = 20, offset: int = 0) -> Dict[str, Any]:
|
||||
|
||||
|
||||
@router.get("/getBalance/{address}", summary="Get account balance")
|
||||
async def get_balance(address: str) -> Dict[str, Any]:
|
||||
async def get_balance(address: str, chain_id: str = "ait-devnet") -> Dict[str, Any]:
|
||||
metrics_registry.increment("rpc_get_balance_total")
|
||||
start = time.perf_counter()
|
||||
with session_scope() as session:
|
||||
|
||||
0
apps/blockchain-node/src/aitbc_chain/rpc/websocket.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/rpc/websocket.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/sync.py
Normal file → Executable file
0
apps/blockchain-node/src/aitbc_chain/sync.py
Normal file → Executable file
0
apps/blockchain-node/tests/conftest.py
Normal file → Executable file
0
apps/blockchain-node/tests/conftest.py
Normal file → Executable file
0
apps/blockchain-node/tests/test_gossip_broadcast.py
Normal file → Executable file
0
apps/blockchain-node/tests/test_gossip_broadcast.py
Normal file → Executable file
0
apps/blockchain-node/tests/test_mempool.py
Normal file → Executable file
0
apps/blockchain-node/tests/test_mempool.py
Normal file → Executable file
0
apps/blockchain-node/tests/test_models.py
Normal file → Executable file
0
apps/blockchain-node/tests/test_models.py
Normal file → Executable file
0
apps/blockchain-node/tests/test_observability_dashboards.py
Normal file → Executable file
0
apps/blockchain-node/tests/test_observability_dashboards.py
Normal file → Executable file
0
apps/blockchain-node/tests/test_sync.py
Normal file → Executable file
0
apps/blockchain-node/tests/test_sync.py
Normal file → Executable file
0
apps/blockchain-node/tests/test_websocket.py
Normal file → Executable file
0
apps/blockchain-node/tests/test_websocket.py
Normal file → Executable file
431
apps/compliance-service/main.py
Executable file
431
apps/compliance-service/main.py
Executable file
@@ -0,0 +1,431 @@
|
||||
"""
|
||||
Production Compliance Service for AITBC
|
||||
Handles KYC/AML, regulatory compliance, and monitoring
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
from typing import Dict, Any, List, Optional
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
app = FastAPI(
|
||||
title="AITBC Compliance Service",
|
||||
description="Regulatory compliance and monitoring for AITBC operations",
|
||||
version="1.0.0"
|
||||
)
|
||||
|
||||
# Data models
|
||||
class KYCRequest(BaseModel):
|
||||
user_id: str
|
||||
name: str
|
||||
email: str
|
||||
document_type: str
|
||||
document_number: str
|
||||
address: Dict[str, str]
|
||||
|
||||
class ComplianceReport(BaseModel):
|
||||
report_type: str
|
||||
description: str
|
||||
severity: str # low, medium, high, critical
|
||||
details: Dict[str, Any]
|
||||
|
||||
class TransactionMonitoring(BaseModel):
|
||||
transaction_id: str
|
||||
user_id: str
|
||||
amount: float
|
||||
currency: str
|
||||
counterparty: str
|
||||
timestamp: datetime
|
||||
|
||||
# In-memory storage (in production, use database)
|
||||
kyc_records: Dict[str, Dict] = {}
|
||||
compliance_reports: Dict[str, Dict] = {}
|
||||
suspicious_transactions: Dict[str, Dict] = {}
|
||||
compliance_rules: Dict[str, Dict] = {}
|
||||
risk_scores: Dict[str, Dict] = {}
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
return {
|
||||
"service": "AITBC Compliance Service",
|
||||
"status": "running",
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"version": "1.0.0"
|
||||
}
|
||||
|
||||
@app.get("/health")
|
||||
async def health_check():
|
||||
return {
|
||||
"status": "healthy",
|
||||
"kyc_records": len(kyc_records),
|
||||
"compliance_reports": len(compliance_reports),
|
||||
"suspicious_transactions": len(suspicious_transactions),
|
||||
"active_rules": len(compliance_rules)
|
||||
}
|
||||
|
||||
@app.post("/api/v1/kyc/submit")
|
||||
async def submit_kyc(kyc_request: KYCRequest):
|
||||
"""Submit KYC verification request"""
|
||||
if kyc_request.user_id in kyc_records:
|
||||
raise HTTPException(status_code=400, detail="KYC already submitted for this user")
|
||||
|
||||
# Create KYC record
|
||||
kyc_record = {
|
||||
"user_id": kyc_request.user_id,
|
||||
"name": kyc_request.name,
|
||||
"email": kyc_request.email,
|
||||
"document_type": kyc_request.document_type,
|
||||
"document_number": kyc_request.document_number,
|
||||
"address": kyc_request.address,
|
||||
"status": "pending",
|
||||
"submitted_at": datetime.utcnow().isoformat(),
|
||||
"reviewed_at": None,
|
||||
"approved_at": None,
|
||||
"risk_score": "medium",
|
||||
"notes": []
|
||||
}
|
||||
|
||||
kyc_records[kyc_request.user_id] = kyc_record
|
||||
|
||||
# Simulate KYC verification process
|
||||
await asyncio.sleep(2) # Simulate verification delay
|
||||
|
||||
# Auto-approve for demo (in production, this would involve actual verification)
|
||||
kyc_record["status"] = "approved"
|
||||
kyc_record["reviewed_at"] = datetime.utcnow().isoformat()
|
||||
kyc_record["approved_at"] = datetime.utcnow().isoformat()
|
||||
kyc_record["risk_score"] = "low"
|
||||
|
||||
logger.info(f"KYC approved for user: {kyc_request.user_id}")
|
||||
|
||||
return {
|
||||
"user_id": kyc_request.user_id,
|
||||
"status": kyc_record["status"],
|
||||
"risk_score": kyc_record["risk_score"],
|
||||
"approved_at": kyc_record["approved_at"]
|
||||
}
|
||||
|
||||
@app.get("/api/v1/kyc/{user_id}")
|
||||
async def get_kyc_status(user_id: str):
|
||||
"""Get KYC status for a user"""
|
||||
if user_id not in kyc_records:
|
||||
raise HTTPException(status_code=404, detail="KYC record not found")
|
||||
|
||||
return kyc_records[user_id]
|
||||
|
||||
@app.get("/api/v1/kyc")
|
||||
async def list_kyc_records():
|
||||
"""List all KYC records"""
|
||||
return {
|
||||
"kyc_records": list(kyc_records.values()),
|
||||
"total_records": len(kyc_records),
|
||||
"approved": len([r for r in kyc_records.values() if r["status"] == "approved"]),
|
||||
"pending": len([r for r in kyc_records.values() if r["status"] == "pending"]),
|
||||
"rejected": len([r for r in kyc_records.values() if r["status"] == "rejected"])
|
||||
}
|
||||
|
||||
@app.post("/api/v1/compliance/report")
|
||||
async def create_compliance_report(report: ComplianceReport):
|
||||
"""Create a compliance report"""
|
||||
report_id = f"report_{int(datetime.utcnow().timestamp())}"
|
||||
|
||||
compliance_record = {
|
||||
"report_id": report_id,
|
||||
"report_type": report.report_type,
|
||||
"description": report.description,
|
||||
"severity": report.severity,
|
||||
"details": report.details,
|
||||
"status": "open",
|
||||
"created_at": datetime.utcnow().isoformat(),
|
||||
"assigned_to": None,
|
||||
"resolved_at": None,
|
||||
"resolution": None
|
||||
}
|
||||
|
||||
compliance_reports[report_id] = compliance_record
|
||||
|
||||
logger.info(f"Compliance report created: {report_id} - {report.report_type}")
|
||||
|
||||
return {
|
||||
"report_id": report_id,
|
||||
"status": "created",
|
||||
"severity": report.severity,
|
||||
"created_at": compliance_record["created_at"]
|
||||
}
|
||||
|
||||
@app.get("/api/v1/compliance/reports")
|
||||
async def list_compliance_reports():
|
||||
"""List all compliance reports"""
|
||||
return {
|
||||
"reports": list(compliance_reports.values()),
|
||||
"total_reports": len(compliance_reports),
|
||||
"open": len([r for r in compliance_reports.values() if r["status"] == "open"]),
|
||||
"resolved": len([r for r in compliance_reports.values() if r["status"] == "resolved"])
|
||||
}
|
||||
|
||||
@app.post("/api/v1/monitoring/transaction")
|
||||
async def monitor_transaction(transaction: TransactionMonitoring):
|
||||
"""Monitor transaction for compliance"""
|
||||
transaction_id = transaction.transaction_id
|
||||
|
||||
# Create transaction monitoring record
|
||||
monitoring_record = {
|
||||
"transaction_id": transaction_id,
|
||||
"user_id": transaction.user_id,
|
||||
"amount": transaction.amount,
|
||||
"currency": transaction.currency,
|
||||
"counterparty": transaction.counterparty,
|
||||
"timestamp": transaction.timestamp.isoformat(),
|
||||
"monitored_at": datetime.utcnow().isoformat(),
|
||||
"risk_score": calculate_transaction_risk(transaction),
|
||||
"flags": [],
|
||||
"status": "monitored"
|
||||
}
|
||||
|
||||
suspicious_transactions[transaction_id] = monitoring_record
|
||||
|
||||
# Check for suspicious patterns
|
||||
flags = check_suspicious_patterns(transaction)
|
||||
if flags:
|
||||
monitoring_record["flags"] = flags
|
||||
monitoring_record["status"] = "flagged"
|
||||
|
||||
# Create compliance report for suspicious transaction
|
||||
await create_suspicious_transaction_report(transaction, flags)
|
||||
|
||||
return {
|
||||
"transaction_id": transaction_id,
|
||||
"risk_score": monitoring_record["risk_score"],
|
||||
"flags": flags,
|
||||
"status": monitoring_record["status"]
|
||||
}
|
||||
|
||||
@app.get("/api/v1/monitoring/transactions")
|
||||
async def list_monitored_transactions():
|
||||
"""List all monitored transactions"""
|
||||
return {
|
||||
"transactions": list(suspicious_transactions.values()),
|
||||
"total_transactions": len(suspicious_transactions),
|
||||
"flagged": len([t for t in suspicious_transactions.values() if t["status"] == "flagged"]),
|
||||
"suspicious": len([t for t in suspicious_transactions.values() if t["risk_score"] == "high"])
|
||||
}
|
||||
|
||||
@app.post("/api/v1/rules/create")
|
||||
async def create_compliance_rule(rule_data: Dict[str, Any]):
|
||||
"""Create a new compliance rule"""
|
||||
rule_id = f"rule_{int(datetime.utcnow().timestamp())}"
|
||||
|
||||
rule = {
|
||||
"rule_id": rule_id,
|
||||
"name": rule_data.get("name"),
|
||||
"description": rule_data.get("description"),
|
||||
"type": rule_data.get("type"),
|
||||
"conditions": rule_data.get("conditions", {}),
|
||||
"actions": rule_data.get("actions", []),
|
||||
"severity": rule_data.get("severity", "medium"),
|
||||
"active": True,
|
||||
"created_at": datetime.utcnow().isoformat(),
|
||||
"trigger_count": 0
|
||||
}
|
||||
|
||||
compliance_rules[rule_id] = rule
|
||||
|
||||
logger.info(f"Compliance rule created: {rule_id} - {rule['name']}")
|
||||
|
||||
return {
|
||||
"rule_id": rule_id,
|
||||
"name": rule["name"],
|
||||
"status": "created",
|
||||
"active": rule["active"]
|
||||
}
|
||||
|
||||
@app.get("/api/v1/rules")
|
||||
async def list_compliance_rules():
|
||||
"""List all compliance rules"""
|
||||
return {
|
||||
"rules": list(compliance_rules.values()),
|
||||
"total_rules": len(compliance_rules),
|
||||
"active": len([r for r in compliance_rules.values() if r["active"]])
|
||||
}
|
||||
|
||||
@app.get("/api/v1/dashboard")
|
||||
async def compliance_dashboard():
|
||||
"""Get compliance dashboard data"""
|
||||
total_users = len(kyc_records)
|
||||
approved_users = len([r for r in kyc_records.values() if r["status"] == "approved"])
|
||||
pending_reviews = len([r for r in kyc_records.values() if r["status"] == "pending"])
|
||||
|
||||
total_reports = len(compliance_reports)
|
||||
open_reports = len([r for r in compliance_reports.values() if r["status"] == "open"])
|
||||
|
||||
total_transactions = len(suspicious_transactions)
|
||||
flagged_transactions = len([t for t in suspicious_transactions.values() if t["status"] == "flagged"])
|
||||
|
||||
return {
|
||||
"summary": {
|
||||
"total_users": total_users,
|
||||
"approved_users": approved_users,
|
||||
"pending_reviews": pending_reviews,
|
||||
"approval_rate": (approved_users / total_users * 100) if total_users > 0 else 0,
|
||||
"total_reports": total_reports,
|
||||
"open_reports": open_reports,
|
||||
"total_transactions": total_transactions,
|
||||
"flagged_transactions": flagged_transactions,
|
||||
"flag_rate": (flagged_transactions / total_transactions * 100) if total_transactions > 0 else 0
|
||||
},
|
||||
"risk_distribution": get_risk_distribution(),
|
||||
"recent_activity": get_recent_activity(),
|
||||
"generated_at": datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
# Helper functions
|
||||
def calculate_transaction_risk(transaction: TransactionMonitoring) -> str:
|
||||
"""Calculate risk score for a transaction"""
|
||||
risk_score = 0
|
||||
|
||||
# Amount-based risk
|
||||
if transaction.amount > 10000:
|
||||
risk_score += 3
|
||||
elif transaction.amount > 1000:
|
||||
risk_score += 2
|
||||
elif transaction.amount > 100:
|
||||
risk_score += 1
|
||||
|
||||
# Time-based risk (transactions outside business hours)
|
||||
hour = transaction.timestamp.hour
|
||||
if hour < 9 or hour > 17:
|
||||
risk_score += 1
|
||||
|
||||
# Convert to risk level
|
||||
if risk_score >= 4:
|
||||
return "high"
|
||||
elif risk_score >= 2:
|
||||
return "medium"
|
||||
else:
|
||||
return "low"
|
||||
|
||||
def check_suspicious_patterns(transaction: TransactionMonitoring) -> List[str]:
|
||||
"""Check for suspicious transaction patterns"""
|
||||
flags = []
|
||||
|
||||
# High value transaction
|
||||
if transaction.amount > 50000:
|
||||
flags.append("high_value_transaction")
|
||||
|
||||
# Rapid transactions (check if user has multiple transactions in short time)
|
||||
user_transactions = [t for t in suspicious_transactions.values()
|
||||
if t["user_id"] == transaction.user_id]
|
||||
|
||||
recent_transactions = [t for t in user_transactions
|
||||
if datetime.fromisoformat(t["monitored_at"]) >
|
||||
datetime.utcnow() - timedelta(hours=1)]
|
||||
|
||||
if len(recent_transactions) > 5:
|
||||
flags.append("rapid_transactions")
|
||||
|
||||
# Unusual counterparty
|
||||
if transaction.counterparty in ["high_risk_entity_1", "high_risk_entity_2"]:
|
||||
flags.append("high_risk_counterparty")
|
||||
|
||||
return flags
|
||||
|
||||
async def create_suspicious_transaction_report(transaction: TransactionMonitoring, flags: List[str]):
|
||||
"""Create compliance report for suspicious transaction"""
|
||||
report_data = ComplianceReport(
|
||||
report_type="suspicious_transaction",
|
||||
description=f"Suspicious transaction detected: {transaction.transaction_id}",
|
||||
severity="high",
|
||||
details={
|
||||
"transaction_id": transaction.transaction_id,
|
||||
"user_id": transaction.user_id,
|
||||
"amount": transaction.amount,
|
||||
"flags": flags,
|
||||
"timestamp": transaction.timestamp.isoformat()
|
||||
}
|
||||
)
|
||||
|
||||
await create_compliance_report(report_data)
|
||||
|
||||
def get_risk_distribution() -> Dict[str, int]:
|
||||
"""Get distribution of risk scores"""
|
||||
distribution = {"low": 0, "medium": 0, "high": 0}
|
||||
|
||||
for record in kyc_records.values():
|
||||
distribution[record["risk_score"]] = distribution.get(record["risk_score"], 0) + 1
|
||||
|
||||
for transaction in suspicious_transactions.values():
|
||||
distribution[transaction["risk_score"]] = distribution.get(transaction["risk_score"], 0) + 1
|
||||
|
||||
return distribution
|
||||
|
||||
def get_recent_activity() -> List[Dict]:
|
||||
"""Get recent compliance activity"""
|
||||
activities = []
|
||||
|
||||
# Recent KYC approvals
|
||||
recent_kyc = [r for r in kyc_records.values()
|
||||
if r.get("approved_at") and
|
||||
datetime.fromisoformat(r["approved_at"]) >
|
||||
datetime.utcnow() - timedelta(hours=24)]
|
||||
|
||||
for kyc in recent_kyc[:5]:
|
||||
activities.append({
|
||||
"type": "kyc_approved",
|
||||
"description": f"KYC approved for {kyc['name']}",
|
||||
"timestamp": kyc["approved_at"]
|
||||
})
|
||||
|
||||
# Recent compliance reports
|
||||
recent_reports = [r for r in compliance_reports.values()
|
||||
if datetime.fromisoformat(r["created_at"]) >
|
||||
datetime.utcnow() - timedelta(hours=24)]
|
||||
|
||||
for report in recent_reports[:5]:
|
||||
activities.append({
|
||||
"type": "compliance_report",
|
||||
"description": f"Report: {report['description']}",
|
||||
"timestamp": report["created_at"]
|
||||
})
|
||||
|
||||
# Sort by timestamp
|
||||
activities.sort(key=lambda x: x["timestamp"], reverse=True)
|
||||
|
||||
return activities[:10]
|
||||
|
||||
# Background task for periodic compliance checks
|
||||
async def periodic_compliance_checks():
|
||||
"""Background task for periodic compliance monitoring"""
|
||||
while True:
|
||||
await asyncio.sleep(300) # Check every 5 minutes
|
||||
|
||||
# Check for expired KYC records
|
||||
current_time = datetime.utcnow()
|
||||
for user_id, kyc_record in kyc_records.items():
|
||||
if kyc_record["status"] == "approved":
|
||||
approved_time = datetime.fromisoformat(kyc_record["approved_at"])
|
||||
if current_time - approved_time > timedelta(days=365):
|
||||
# Flag for re-verification
|
||||
kyc_record["status"] = "reverification_required"
|
||||
logger.info(f"KYC re-verification required for user: {user_id}")
|
||||
|
||||
@app.on_event("startup")
|
||||
async def startup_event():
|
||||
logger.info("Starting AITBC Compliance Service")
|
||||
# Start background compliance checks
|
||||
asyncio.create_task(periodic_compliance_checks())
|
||||
|
||||
@app.on_event("shutdown")
|
||||
async def shutdown_event():
|
||||
logger.info("Shutting down AITBC Compliance Service")
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8011, log_level="info")
|
||||
0
apps/coordinator-api/.env.example
Normal file → Executable file
0
apps/coordinator-api/.env.example
Normal file → Executable file
0
apps/coordinator-api/=
Normal file → Executable file
0
apps/coordinator-api/=
Normal file → Executable file
0
apps/coordinator-api/QUICK_WINS_SUMMARY.md
Normal file → Executable file
0
apps/coordinator-api/QUICK_WINS_SUMMARY.md
Normal file → Executable file
0
apps/coordinator-api/README.md
Normal file → Executable file
0
apps/coordinator-api/README.md
Normal file → Executable file
0
apps/coordinator-api/aitbc/api/v1/settlement.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/api/v1/settlement.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/logging.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/logging.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/settlement/__init__.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/settlement/__init__.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/settlement/bridges/__init__.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/settlement/bridges/__init__.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/settlement/bridges/base.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/settlement/bridges/base.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/settlement/bridges/layerzero.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/settlement/bridges/layerzero.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/settlement/hooks.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/settlement/hooks.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/settlement/manager.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/settlement/manager.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/settlement/storage.py
Normal file → Executable file
0
apps/coordinator-api/aitbc/settlement/storage.py
Normal file → Executable file
0
apps/coordinator-api/alembic/versions/2024_01_10_add_settlements_table.py
Normal file → Executable file
0
apps/coordinator-api/alembic/versions/2024_01_10_add_settlements_table.py
Normal file → Executable file
0
apps/coordinator-api/alembic/versions/add_cross_chain_reputation.py
Normal file → Executable file
0
apps/coordinator-api/alembic/versions/add_cross_chain_reputation.py
Normal file → Executable file
0
apps/coordinator-api/alembic/versions/add_developer_platform.py
Normal file → Executable file
0
apps/coordinator-api/alembic/versions/add_developer_platform.py
Normal file → Executable file
0
apps/coordinator-api/alembic/versions/add_dynamic_pricing_tables.py
Normal file → Executable file
0
apps/coordinator-api/alembic/versions/add_dynamic_pricing_tables.py
Normal file → Executable file
0
apps/coordinator-api/alembic/versions/add_global_marketplace.py
Normal file → Executable file
0
apps/coordinator-api/alembic/versions/add_global_marketplace.py
Normal file → Executable file
0
apps/coordinator-api/demo_client_miner_workflow.py
Normal file → Executable file
0
apps/coordinator-api/demo_client_miner_workflow.py
Normal file → Executable file
0
apps/coordinator-api/examples/agent_identity_sdk_example.py
Normal file → Executable file
0
apps/coordinator-api/examples/agent_identity_sdk_example.py
Normal file → Executable file
0
apps/coordinator-api/integration_test.py
Normal file → Executable file
0
apps/coordinator-api/integration_test.py
Normal file → Executable file
0
apps/coordinator-api/migrations/001_initial_schema.sql
Normal file → Executable file
0
apps/coordinator-api/migrations/001_initial_schema.sql
Normal file → Executable file
0
apps/coordinator-api/migrations/002_indexes.sql
Normal file → Executable file
0
apps/coordinator-api/migrations/002_indexes.sql
Normal file → Executable file
0
apps/coordinator-api/migrations/003_data_migration.py
Normal file → Executable file
0
apps/coordinator-api/migrations/003_data_migration.py
Normal file → Executable file
0
apps/coordinator-api/migrations/004_payments.sql
Normal file → Executable file
0
apps/coordinator-api/migrations/004_payments.sql
Normal file → Executable file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user