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
.editorconfig
Normal file → Executable file
0
.editorconfig
Normal file → Executable file
0
.env.example
Normal file → Executable file
0
.env.example
Normal file → Executable file
0
.github/dependabot.yml
vendored
Normal file → Executable file
0
.github/dependabot.yml
vendored
Normal file → Executable file
505
.github/workflows/ci-cd.yml
vendored
Normal file
505
.github/workflows/ci-cd.yml
vendored
Normal file
@@ -0,0 +1,505 @@
|
||||
name: AITBC CI/CD Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop, feature/*, hotfix/* ]
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
release:
|
||||
types: [ published ]
|
||||
|
||||
env:
|
||||
PYTHON_VERSION: "3.13"
|
||||
NODE_VERSION: "18"
|
||||
|
||||
jobs:
|
||||
# Code Quality and Testing
|
||||
lint-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.11", "3.12", "3.13"]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Cache pip dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('**/requirements*.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-${{ matrix.python-version }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
pip install -r requirements-dev.txt
|
||||
pip install -r requirements-test.txt
|
||||
|
||||
- name: Lint Python code
|
||||
run: |
|
||||
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||
black --check .
|
||||
isort --check-only --diff .
|
||||
mypy . --ignore-missing-imports
|
||||
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
pytest tests/unit/ -v --cov=aitbc_cli --cov-report=xml --cov-report=html --cov-report=term
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
pytest tests/integration/ -v --tb=short
|
||||
|
||||
- name: Run performance tests
|
||||
run: |
|
||||
pytest tests/performance/ -v --tb=short
|
||||
|
||||
- name: Run security tests
|
||||
run: |
|
||||
pytest tests/security/ -v --tb=short
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
file: ./coverage.xml
|
||||
flags: unittests
|
||||
name: codecov-umbrella
|
||||
|
||||
# CLI Testing
|
||||
test-cli:
|
||||
runs-on: ubuntu-latest
|
||||
needs: lint-and-test
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.13"
|
||||
|
||||
- name: Install CLI
|
||||
run: |
|
||||
cd cli
|
||||
python -m pip install -e .
|
||||
|
||||
- name: Test CLI commands
|
||||
run: |
|
||||
cd cli
|
||||
python -m aitbc_cli.main --help
|
||||
python -m aitbc_cli.main wallet --help
|
||||
python -m aitbc_cli.main blockchain --help
|
||||
python -m aitbc_cli.main multisig --help
|
||||
python -m aitbc_cli.main genesis-protection --help
|
||||
python -m aitbc_cli.main transfer-control --help
|
||||
python -m aitbc_cli.main compliance --help
|
||||
python -m aitbc_cli.main exchange --help
|
||||
python -m aitbc_cli.main oracle --help
|
||||
python -m aitbc_cli.main market-maker --help
|
||||
|
||||
- name: Test CLI functionality
|
||||
run: |
|
||||
cd cli
|
||||
python -m aitbc_cli.main --test-mode multisig create --threshold 3 --owners "owner1,owner2,owner3"
|
||||
python -m aitbc_cli.main --test-mode transfer-control set-limit --wallet test_wallet --max-daily 1000
|
||||
|
||||
# Multi-Chain Service Testing
|
||||
test-services:
|
||||
runs-on: ubuntu-latest
|
||||
needs: lint-and-test
|
||||
|
||||
services:
|
||||
redis:
|
||||
image: redis:7
|
||||
ports:
|
||||
- 6379:6379
|
||||
postgres:
|
||||
image: postgres:15
|
||||
env:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: aitbc_test
|
||||
ports:
|
||||
- 5432:5432
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.13"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install -r requirements.txt
|
||||
pip install -r requirements-dev.txt
|
||||
pip install -r requirements-test.txt
|
||||
|
||||
- name: Test blockchain service
|
||||
run: |
|
||||
cd apps/blockchain-node
|
||||
python -m pytest tests/ -v -k "test_blockchain"
|
||||
|
||||
- name: Test coordinator service
|
||||
run: |
|
||||
cd apps/coordinator-api
|
||||
python -m pytest tests/ -v -k "test_coordinator"
|
||||
|
||||
- name: Test consensus service
|
||||
run: |
|
||||
cd apps/consensus-node
|
||||
python -m pytest tests/ -v -k "test_consensus"
|
||||
|
||||
- name: Test network service
|
||||
run: |
|
||||
cd apps/network-node
|
||||
python -m pytest tests/ -v -k "test_network"
|
||||
|
||||
- name: Test explorer service
|
||||
run: |
|
||||
cd apps/explorer
|
||||
python -m pytest tests/ -v -k "test_explorer"
|
||||
|
||||
# Production Services Testing
|
||||
test-production-services:
|
||||
runs-on: ubuntu-latest
|
||||
needs: lint-and-test
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.13"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install -r requirements.txt
|
||||
pip install -r requirements-dev.txt
|
||||
pip install -r requirements-test.txt
|
||||
|
||||
- name: Test exchange service
|
||||
run: |
|
||||
cd apps/exchange-integration
|
||||
python -m pytest tests/ -v -k "test_exchange"
|
||||
|
||||
- name: Test compliance service
|
||||
run: |
|
||||
cd apps/compliance-service
|
||||
python -m pytest tests/ -v -k "test_compliance"
|
||||
|
||||
- name: Test trading engine
|
||||
run: |
|
||||
cd apps/trading-engine
|
||||
python -m pytest tests/ -v -k "test_trading"
|
||||
|
||||
- name: Test plugin registry
|
||||
run: |
|
||||
cd apps/plugin-registry
|
||||
python -m pytest tests/ -v -k "test_plugin_registry"
|
||||
|
||||
- name: Test plugin marketplace
|
||||
run: |
|
||||
cd apps/plugin-marketplace
|
||||
python -m pytest tests/ -v -k "test_plugin_marketplace"
|
||||
|
||||
- name: Test global infrastructure
|
||||
run: |
|
||||
cd apps/global-infrastructure
|
||||
python -m pytest tests/ -v -k "test_global_infrastructure"
|
||||
|
||||
- name: Test AI agents
|
||||
run: |
|
||||
cd apps/global-ai-agents
|
||||
python -m pytest tests/ -v -k "test_ai_agents"
|
||||
|
||||
# Security Scanning
|
||||
security-scan:
|
||||
runs-on: ubuntu-latest
|
||||
needs: lint-and-test
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
scan-type: 'fs'
|
||||
scan-ref: '.'
|
||||
format: 'sarif'
|
||||
output: 'trivy-results.sarif'
|
||||
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: 'trivy-results.sarif'
|
||||
|
||||
- name: Run CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
with:
|
||||
languages: python
|
||||
|
||||
- name: Run Bandit security linter
|
||||
run: |
|
||||
pip install bandit
|
||||
bandit -r . -f json -o bandit-report.json
|
||||
bandit -r . -f text
|
||||
|
||||
- name: Run Safety check
|
||||
run: |
|
||||
pip install safety
|
||||
safety check --json --output safety-report.json
|
||||
|
||||
- name: Run semgrep security scan
|
||||
uses: semgrep/semgrep-action@v1
|
||||
with:
|
||||
config: >-
|
||||
p:security
|
||||
p:owertools
|
||||
|
||||
# Build and Package
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test-cli, test-services, test-production-services]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.13"
|
||||
|
||||
- name: Build CLI package
|
||||
run: |
|
||||
cd cli
|
||||
python -m build
|
||||
|
||||
- name: Build services packages
|
||||
run: |
|
||||
for service in apps/*/; do
|
||||
if [ -f "$service/pyproject.toml" ]; then
|
||||
cd "$service"
|
||||
python -m build
|
||||
cd - > /dev/null
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: build-artifacts
|
||||
path: |
|
||||
cli/dist/*
|
||||
apps/*/dist/*
|
||||
retention-days: 30
|
||||
|
||||
# Deployment to Staging
|
||||
deploy-staging:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
if: github.ref == 'refs/heads/develop'
|
||||
|
||||
environment: staging
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: build-artifacts
|
||||
|
||||
- name: Deploy CLI to staging
|
||||
run: |
|
||||
echo "Deploying CLI to staging environment"
|
||||
# Add actual deployment commands here
|
||||
|
||||
- name: Deploy services to staging
|
||||
run: |
|
||||
echo "Deploying services to staging environment"
|
||||
# Add actual deployment commands here
|
||||
|
||||
- name: Run smoke tests on staging
|
||||
run: |
|
||||
echo "Running smoke tests on staging"
|
||||
# Add smoke test commands here
|
||||
|
||||
# Deployment to Production
|
||||
deploy-production:
|
||||
runs-on: ubuntu-latest
|
||||
needs: deploy-staging
|
||||
if: github.event_name == 'release'
|
||||
|
||||
environment: production
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: build-artifacts
|
||||
|
||||
- name: Deploy CLI to production
|
||||
run: |
|
||||
echo "Deploying CLI to production environment"
|
||||
# Add actual deployment commands here
|
||||
|
||||
- name: Deploy services to production
|
||||
run: |
|
||||
echo "Deploying services to production environment"
|
||||
# Add actual deployment commands here
|
||||
|
||||
- name: Run health checks on production
|
||||
run: |
|
||||
echo "Running health checks on production"
|
||||
# Add health check commands here
|
||||
|
||||
- name: Notify deployment success
|
||||
run: |
|
||||
echo "Deployment to production completed successfully"
|
||||
|
||||
# Performance Testing
|
||||
performance-test:
|
||||
runs-on: ubuntu-latest
|
||||
needs: deploy-staging
|
||||
if: github.event_name == 'pull_request'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.13"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install -r requirements-test.txt
|
||||
pip install locust
|
||||
|
||||
- name: Run performance tests
|
||||
run: |
|
||||
cd tests/performance
|
||||
python -m pytest test_performance.py::TestPerformance::test_cli_performance -v
|
||||
python -m pytest test_performance.py::TestPerformance::test_concurrent_cli_operations -v
|
||||
|
||||
- name: Run load tests
|
||||
run: |
|
||||
cd tests/performance
|
||||
locust -f locustfile.py --headless -u 10 -r 1 -t 30s --host http://staging.aitbc.dev
|
||||
|
||||
# Documentation Generation
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: lint-and-test
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.13"
|
||||
|
||||
- name: Install documentation dependencies
|
||||
run: |
|
||||
pip install sphinx sphinx-rtd-theme myst-parser
|
||||
|
||||
- name: Generate documentation
|
||||
run: |
|
||||
cd docs
|
||||
make html
|
||||
|
||||
- name: Deploy documentation
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./docs/_build/html
|
||||
|
||||
# Release Management
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, security-scan]
|
||||
if: github.event_name == 'release'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: build-artifacts
|
||||
|
||||
- name: Create Release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: AITBC Release ${{ github.ref }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
|
||||
- name: Upload CLI Release Asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: cli/dist/*
|
||||
asset_name: aitbc-cli-${{ github.ref_name }}.tar.gz
|
||||
asset_content_type: application/gzip
|
||||
|
||||
- name: Upload Services Release Asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: apps/*/dist/*
|
||||
asset_name: aitbc-services-${{ github.ref_name }}.tar.gz
|
||||
asset_content_type: application/gzip
|
||||
|
||||
# Notification
|
||||
notify:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [lint-and-test, test-cli, test-services, test-production-services, security-scan]
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: Notify on success
|
||||
if: needs.lint-and-test.result == 'success' && needs.test-cli.result == 'success' && needs.test-services.result == 'success' && needs.test-production-services.result == 'success' && needs.security-scan.result == 'success'
|
||||
run: |
|
||||
echo "✅ All tests passed successfully!"
|
||||
# Add Slack/Discord notification here
|
||||
|
||||
- name: Notify on failure
|
||||
if: needs.lint-and-test.result == 'failure' || needs.test-cli.result == 'failure' || needs.test-services.result == 'failure' || needs.test-production-services.result == 'failure' || needs.security-scan.result == 'failure'
|
||||
run: |
|
||||
echo "❌ Some tests failed!"
|
||||
# Add Slack/Discord notification here
|
||||
0
.github/workflows/cli-level1-tests.yml
vendored
Normal file → Executable file
0
.github/workflows/cli-level1-tests.yml
vendored
Normal file → Executable file
0
.gitignore
vendored
Normal file → Executable file
0
.gitignore
vendored
Normal file → Executable file
102
.pre-commit-config.yaml
Normal file
102
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,102 @@
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.4.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-yaml
|
||||
- id: check-added-large-files
|
||||
- id: check-json
|
||||
- id: check-merge-conflict
|
||||
- id: debug-statements
|
||||
- id: check-docstring-first
|
||||
- id: check-executables-have-shebangs
|
||||
- id: check-toml
|
||||
- id: check-xml
|
||||
- id: check-case-conflict
|
||||
- id: check-ast
|
||||
- id: check-builddir
|
||||
- id: check-shebang-scripts
|
||||
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.3.0
|
||||
hooks:
|
||||
- id: black
|
||||
language_version: python3
|
||||
args: [--line-length=127]
|
||||
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.12.0
|
||||
hooks:
|
||||
- id: isort
|
||||
args: [--profile=black, --line-length=127]
|
||||
|
||||
- repo: https://github.com/pycqa/flake8
|
||||
rev: 6.0.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
args: [--max-line-length=127, --extend-ignore=E203,W503]
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.3.0
|
||||
hooks:
|
||||
- id: mypy
|
||||
additional_dependencies: [types-requests, types-python-dateutil]
|
||||
args: [--ignore-missing-imports]
|
||||
|
||||
- repo: https://github.com/PyCQA/bandit
|
||||
rev: 1.7.5
|
||||
hooks:
|
||||
- id: bandit
|
||||
args: [-r, ., -f, json, -o, bandit-report.json]
|
||||
pass_filenames: false
|
||||
|
||||
- repo: https://github.com/pycqa/pydocstyle
|
||||
rev: 6.3.0
|
||||
hooks:
|
||||
- id: pydocstyle
|
||||
args: [--convention=google]
|
||||
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v3.3.1
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py311-plus]
|
||||
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks-safety
|
||||
rev: v1.3.2
|
||||
hooks:
|
||||
- id: python-safety-dependencies-check
|
||||
files: requirements.*\.txt$
|
||||
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks-safety
|
||||
rev: v1.3.2
|
||||
hooks:
|
||||
- id: python-safety-check
|
||||
args: [--json, --output, safety-report.json]
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: pytest-check
|
||||
name: pytest-check
|
||||
entry: pytest
|
||||
language: system
|
||||
args: [tests/unit/, --tb=short, -q]
|
||||
pass_filenames: false
|
||||
always_run: true
|
||||
|
||||
- id: security-check
|
||||
name: security-check
|
||||
entry: pytest
|
||||
language: system
|
||||
args: [tests/security/, --tb=short, -q]
|
||||
pass_filenames: false
|
||||
always_run: true
|
||||
|
||||
- id: performance-check
|
||||
name: performance-check
|
||||
entry: pytest
|
||||
language: system
|
||||
args: [tests/performance/test_performance_lightweight.py::TestPerformance::test_cli_performance, --tb=short, -q]
|
||||
pass_filenames: false
|
||||
always_run: true
|
||||
66
Dockerfile
Normal file
66
Dockerfile
Normal file
@@ -0,0 +1,66 @@
|
||||
# Multi-stage build for AITBC CLI
|
||||
FROM python:3.13-slim as builder
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
gcc \
|
||||
g++ \
|
||||
make \
|
||||
libffi-dev \
|
||||
libssl-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy requirements
|
||||
COPY cli/requirements.txt .
|
||||
COPY cli/requirements-dev.txt .
|
||||
|
||||
# Install Python dependencies
|
||||
RUN pip install --no-cache-dir --upgrade pip && \
|
||||
pip install --no-cache-dir -r requirements.txt && \
|
||||
pip install --no-cache-dir -r requirements-dev.txt
|
||||
|
||||
# Copy CLI source code
|
||||
COPY cli/ .
|
||||
|
||||
# Install CLI in development mode
|
||||
RUN pip install -e .
|
||||
|
||||
# Production stage
|
||||
FROM python:3.13-slim as production
|
||||
|
||||
# Create non-root user
|
||||
RUN useradd --create-home --shell /bin/bash aitbc
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Install runtime dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy CLI from builder stage
|
||||
COPY --from=builder /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
|
||||
COPY --from=builder /usr/local/bin /usr/local/bin
|
||||
|
||||
# Create data directories
|
||||
RUN mkdir -p /home/aitbc/.aitbc && \
|
||||
chown -R aitbc:aitbc /home/aitbc
|
||||
|
||||
# Switch to non-root user
|
||||
USER aitbc
|
||||
|
||||
# Set environment variables
|
||||
ENV PATH=/home/aitbc/.local/bin:$PATH
|
||||
ENV PYTHONPATH=/app
|
||||
ENV AITBC_DATA_DIR=/home/aitbc/.aitbc
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD python -m aitbc_cli.main --version || exit 1
|
||||
|
||||
# Default command
|
||||
CMD ["python", "-m", "aitbc_cli.main", "--help"]
|
||||
0
SECURITY.md
Normal file → Executable file
0
SECURITY.md
Normal file → Executable file
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
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user