Automated Action b9798f0eaf Implement comprehensive crypto P2P trading platform
- Complete FastAPI application with JWT authentication
- SQLite database with SQLAlchemy ORM and Alembic migrations
- User registration/login with secure password hashing
- Multi-cryptocurrency wallet system with balance tracking
- Advertisement system for buy/sell listings with fund locking
- Order management with automatic payment integration
- Payment provider API integration with mock fallback
- Automatic crypto release after payment confirmation
- Health monitoring endpoint and CORS configuration
- Comprehensive API documentation with OpenAPI/Swagger
- Database models for users, wallets, ads, orders, and payments
- Complete CRUD operations for all entities
- Security features including fund locking and order expiration
- Detailed README with setup and usage instructions

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-26 14:48:18 +00:00

162 lines
8.0 KiB
Python

"""Initial migration
Revision ID: 001
Revises:
Create Date: 2024-01-01 00: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('username', sa.String(), nullable=False),
sa.Column('hashed_password', 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(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_users_email'), 'users', ['email'], unique=True)
op.create_index(op.f('ix_users_username'), 'users', ['username'], unique=True)
op.create_index(op.f('ix_users_id'), 'users', ['id'], unique=False)
# Create cryptocurrencies table
op.create_table(
'cryptocurrencies',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('symbol', sa.String(), nullable=False),
sa.Column('name', sa.String(), nullable=False),
sa.Column('is_active', sa.Boolean(), nullable=True),
sa.Column('min_trade_amount', sa.Float(), nullable=True),
sa.Column('max_trade_amount', sa.Float(), nullable=True),
sa.Column('precision', sa.Integer(), nullable=True),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_cryptocurrencies_symbol'), 'cryptocurrencies', ['symbol'], unique=True)
op.create_index(op.f('ix_cryptocurrencies_id'), 'cryptocurrencies', ['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('cryptocurrency_id', sa.Integer(), nullable=False),
sa.Column('available_balance', sa.Float(), nullable=True),
sa.Column('locked_balance', sa.Float(), nullable=True),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.ForeignKeyConstraint(['cryptocurrency_id'], ['cryptocurrencies.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_user_crypto', 'wallets', ['user_id', 'cryptocurrency_id'], unique=True)
op.create_index(op.f('ix_wallets_id'), 'wallets', ['id'], unique=False)
# Create advertisements table
op.create_table(
'advertisements',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('cryptocurrency_id', sa.Integer(), nullable=False),
sa.Column('ad_type', sa.Enum('buy', 'sell', name='adtype'), nullable=False),
sa.Column('price', sa.Float(), nullable=False),
sa.Column('min_order_amount', sa.Float(), nullable=False),
sa.Column('max_order_amount', sa.Float(), nullable=False),
sa.Column('available_amount', sa.Float(), nullable=False),
sa.Column('payment_methods', sa.String(), nullable=False),
sa.Column('terms_conditions', sa.Text(), nullable=True),
sa.Column('status', sa.Enum('active', 'inactive', 'completed', 'cancelled', name='adstatus'), nullable=True),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.ForeignKeyConstraint(['cryptocurrency_id'], ['cryptocurrencies.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_advertisements_id'), 'advertisements', ['id'], unique=False)
# Create orders table
op.create_table(
'orders',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('advertisement_id', sa.Integer(), nullable=False),
sa.Column('buyer_id', sa.Integer(), nullable=False),
sa.Column('seller_id', sa.Integer(), nullable=False),
sa.Column('cryptocurrency_id', sa.Integer(), nullable=False),
sa.Column('crypto_amount', sa.Float(), nullable=False),
sa.Column('fiat_amount', sa.Float(), nullable=False),
sa.Column('price', sa.Float(), nullable=False),
sa.Column('status', sa.Enum('pending', 'payment_pending', 'payment_confirmed', 'completed', 'cancelled', 'disputed', name='orderstatus'), nullable=True),
sa.Column('payment_account_number', sa.String(), nullable=True),
sa.Column('payment_reference', sa.String(), nullable=True),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.Column('expires_at', sa.DateTime(), nullable=True),
sa.Column('notes', sa.Text(), nullable=True),
sa.ForeignKeyConstraint(['advertisement_id'], ['advertisements.id'], ),
sa.ForeignKeyConstraint(['buyer_id'], ['users.id'], ),
sa.ForeignKeyConstraint(['cryptocurrency_id'], ['cryptocurrencies.id'], ),
sa.ForeignKeyConstraint(['seller_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_orders_id'), 'orders', ['id'], unique=False)
# Create payments table
op.create_table(
'payments',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('order_id', sa.Integer(), nullable=False),
sa.Column('account_number', sa.String(), nullable=False),
sa.Column('account_name', sa.String(), nullable=False),
sa.Column('bank_name', sa.String(), nullable=False),
sa.Column('amount', sa.Float(), nullable=False),
sa.Column('reference', sa.String(), nullable=False),
sa.Column('status', sa.Enum('pending', 'confirmed', 'failed', 'cancelled', name='paymentstatus'), nullable=True),
sa.Column('provider_transaction_id', sa.String(), nullable=True),
sa.Column('confirmed_at', sa.DateTime(), nullable=True),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=True),
sa.ForeignKeyConstraint(['order_id'], ['orders.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_payments_reference'), 'payments', ['reference'], unique=True)
op.create_index(op.f('ix_payments_id'), 'payments', ['id'], unique=False)
def downgrade() -> None:
op.drop_index(op.f('ix_payments_id'), table_name='payments')
op.drop_index(op.f('ix_payments_reference'), table_name='payments')
op.drop_table('payments')
op.drop_index(op.f('ix_orders_id'), table_name='orders')
op.drop_table('orders')
op.drop_index(op.f('ix_advertisements_id'), table_name='advertisements')
op.drop_table('advertisements')
op.drop_index(op.f('ix_wallets_id'), table_name='wallets')
op.drop_index('ix_user_crypto', table_name='wallets')
op.drop_table('wallets')
op.drop_index(op.f('ix_cryptocurrencies_id'), table_name='cryptocurrencies')
op.drop_index(op.f('ix_cryptocurrencies_symbol'), table_name='cryptocurrencies')
op.drop_table('cryptocurrencies')
op.drop_index(op.f('ix_users_id'), table_name='users')
op.drop_index(op.f('ix_users_username'), table_name='users')
op.drop_index(op.f('ix_users_email'), table_name='users')
op.drop_table('users')