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")
|
@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")
|
metrics_registry.increment("rpc_get_balance_total")
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
with session_scope() as session:
|
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