Automated Action ab87d3c506 Implement comprehensive cryptocurrency exchange platform
- Built complete CEX platform with FastAPI and Python
- JWT-based authentication system with secure password hashing
- Multi-currency crypto wallet support (BTC, ETH, USDT)
- Fiat account management (USD, EUR, GBP)
- Local transaction signing without external APIs
- Comprehensive transaction handling (send/receive/deposit/withdraw)
- SQLAlchemy models with Alembic migrations
- Security middleware (rate limiting, headers, logging)
- Input validation and sanitization
- Encrypted private key storage with PBKDF2
- Standardized codebase architecture with service layer pattern
- Complete API documentation with health endpoints
- Comprehensive README with setup instructions

Features:
- User registration and authentication
- Crypto wallet creation and management
- Secure transaction signing using local private keys
- Fiat deposit/withdrawal system
- Transaction history and tracking
- Rate limiting and security headers
- Input validation for all endpoints
- Error handling and logging
2025-06-20 23:08:04 +00:00

127 lines
6.5 KiB
Python

"""Initial migration
Revision ID: 001
Revises:
Create Date: 2025-06-20 12:00:00.000000
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '001'
down_revision = None
branch_labels = None
depends_on = None
def upgrade() -> None:
# Create users table
op.create_table('users',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('email', sa.String(), nullable=False),
sa.Column('hashed_password', sa.String(), nullable=False),
sa.Column('full_name', sa.String(), nullable=False),
sa.Column('is_active', sa.Boolean(), nullable=True),
sa.Column('is_verified', sa.Boolean(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('kyc_level', sa.Integer(), nullable=True),
sa.Column('phone_number', sa.String(), nullable=True),
sa.Column('country', sa.String(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_users_email'), 'users', ['email'], unique=True)
op.create_index(op.f('ix_users_id'), 'users', ['id'], unique=False)
# Create wallets table
op.create_table('wallets',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('currency', sa.String(), nullable=False),
sa.Column('address', sa.String(), nullable=False),
sa.Column('private_key_encrypted', sa.String(), nullable=False),
sa.Column('balance', sa.Float(), nullable=True),
sa.Column('is_active', sa.Boolean(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_wallets_address'), 'wallets', ['address'], unique=True)
op.create_index(op.f('ix_wallets_id'), 'wallets', ['id'], unique=False)
# Create fiat_accounts table
op.create_table('fiat_accounts',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('currency', sa.String(), nullable=False),
sa.Column('balance', sa.Float(), nullable=True),
sa.Column('is_active', sa.Boolean(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_fiat_accounts_id'), 'fiat_accounts', ['id'], unique=False)
# Create transactions table
op.create_table('transactions',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('from_wallet_id', sa.Integer(), nullable=True),
sa.Column('to_wallet_id', sa.Integer(), nullable=True),
sa.Column('transaction_hash', sa.String(), nullable=True),
sa.Column('amount', sa.Float(), nullable=False),
sa.Column('fee', sa.Float(), nullable=True),
sa.Column('currency', sa.String(), nullable=False),
sa.Column('transaction_type', sa.Enum('SEND', 'RECEIVE', 'DEPOSIT', 'WITHDRAWAL', name='transactiontype'), nullable=False),
sa.Column('status', sa.Enum('PENDING', 'CONFIRMED', 'FAILED', 'CANCELLED', name='transactionstatus'), nullable=True),
sa.Column('from_address', sa.String(), nullable=True),
sa.Column('to_address', sa.String(), nullable=False),
sa.Column('block_number', sa.Integer(), nullable=True),
sa.Column('confirmations', sa.Integer(), nullable=True),
sa.Column('notes', sa.Text(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
sa.ForeignKeyConstraint(['from_wallet_id'], ['wallets.id'], ),
sa.ForeignKeyConstraint(['to_wallet_id'], ['wallets.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_transactions_id'), 'transactions', ['id'], unique=False)
op.create_index(op.f('ix_transactions_transaction_hash'), 'transactions', ['transaction_hash'], unique=True)
# Create fiat_transactions table
op.create_table('fiat_transactions',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('account_id', sa.Integer(), nullable=False),
sa.Column('amount', sa.Float(), nullable=False),
sa.Column('currency', sa.String(), nullable=False),
sa.Column('transaction_type', sa.Enum('SEND', 'RECEIVE', 'DEPOSIT', 'WITHDRAWAL', name='transactiontype'), nullable=False),
sa.Column('status', sa.Enum('PENDING', 'CONFIRMED', 'FAILED', 'CANCELLED', name='transactionstatus'), nullable=True),
sa.Column('bank_reference', sa.String(), nullable=True),
sa.Column('payment_method', sa.String(), nullable=True),
sa.Column('notes', sa.Text(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
sa.ForeignKeyConstraint(['account_id'], ['fiat_accounts.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_fiat_transactions_id'), 'fiat_transactions', ['id'], unique=False)
def downgrade() -> None:
op.drop_index(op.f('ix_fiat_transactions_id'), table_name='fiat_transactions')
op.drop_table('fiat_transactions')
op.drop_index(op.f('ix_transactions_transaction_hash'), table_name='transactions')
op.drop_index(op.f('ix_transactions_id'), table_name='transactions')
op.drop_table('transactions')
op.drop_index(op.f('ix_fiat_accounts_id'), table_name='fiat_accounts')
op.drop_table('fiat_accounts')
op.drop_index(op.f('ix_wallets_id'), table_name='wallets')
op.drop_index(op.f('ix_wallets_address'), table_name='wallets')
op.drop_table('wallets')
op.drop_index(op.f('ix_users_id'), table_name='users')
op.drop_index(op.f('ix_users_email'), table_name='users')
op.drop_table('users')