Skip to main content

Welcome Contributors!

We welcome contributions to Opinix Trade! Whether you’re fixing bugs, adding features, improving documentation, or suggesting ideas, your help is appreciated.
This project is a real-time opinion trading platform where users can place bets on different events, similar to prediction markets.

Getting Started

1

Fork the repository

Fork Opinix Trade on GitHub to your account.
2

Clone your fork

git clone https://github.com/YOUR_USERNAME/opinix-trade.git
cd opinix-trade
3

Set up development environment

Follow the Development Setup guide to configure your local environment.
# Start infrastructure
docker-compose up -d

# Install dependencies
npm install

# Set up environment variables
cp packages/db/.env.example packages/db/.env
cp apps/client/.env.example apps/client/.env
cp packages/order-queue/.env.example packages/order-queue/.env

# Generate Prisma client
cd packages/db && npx prisma generate

# Run migrations
npx prisma migrate dev

# Build project
npm run build

# Start development servers
npm run dev
4

Create a branch

Create a feature branch for your changes:
git checkout -b feature/your-feature-name
Branch naming conventions:
  • feature/ - New features
  • fix/ - Bug fixes
  • docs/ - Documentation updates
  • refactor/ - Code refactoring
  • test/ - Adding tests
  • chore/ - Maintenance tasks

Development Workflow

1

Write code

Make your changes following the project’s code style.
2

Test locally

Ensure your changes work as expected:
# Start all services
npm run dev

# Test specific service
cd apps/client && npm run dev
cd apps/server && npm run dev
3

Lint your code

Run linting to check for code style issues:
npm run lint
Fix any linting errors before committing.
4

Format code

Format your code with Prettier:
npm run format

Code Style Guidelines

General Rules:
  • Use TypeScript for all new code
  • Avoid any type - use proper types
  • Use interfaces for object shapes
  • Export types when shared across files
// Good
interface Order {
  id: string;
  userId: string;
  eventId: string;
  quantity: number;
  price: number;
  side: 'YES' | 'NO';
}

async function placeOrder(order: Order): Promise<Order> {
  // Implementation
}

// Bad
async function placeOrder(order: any) {
  // Implementation
}
Variables & Functions:
  • Use camelCase
  • Descriptive names
  • Boolean variables start with is, has, should
// Good
const orderQueue = new Queue();
const isOrderValid = validateOrder(order);
const hasPermission = checkPermission(user);

// Bad
const q = new Queue();
const valid = validateOrder(order);
const perm = checkPermission(user);
Classes & Interfaces:
  • Use PascalCase
  • Interfaces don’t need I prefix
// Good
class OrderMatchingEngine {}
interface User {}

// Avoid
class order_matching_engine {}
interface IUser {}
Constants:
  • Use UPPER_SNAKE_CASE for true constants
const MAX_ORDER_SIZE = 1000;
const DEFAULT_CACHE_TTL = 60;
File naming:
  • Use kebab-case for files: order-matching.ts
  • Use PascalCase for component files: OrderBook.tsx
Project structure:
apps/
  client/          # Next.js frontend
  server/          # Express backend
packages/
  db/              # Database & Prisma
  order-queue/     # Order queue logic
  types/           # Shared types
  zod/             # Validation schemas
  logger/          # Logging utility
services/
  engine/          # Matching engine
  wss/             # WebSocket server
Always handle errors properly:
// Good - Proper error handling
try {
  const order = await placeOrder(orderData);
  logger.info('Order placed', { orderId: order.id });
  return order;
} catch (error) {
  logger.error('Failed to place order', { 
    error: error.message, 
    stack: error.stack,
    orderData 
  });
  throw new Error('Order placement failed');
}

// Bad - Silent failure
try {
  await placeOrder(orderData);
} catch (error) {
  // Silent
}
Prefer async/await over promises:
// Good
async function getUserOrders(userId: string) {
  const user = await prisma.user.findUnique({ 
    where: { id: userId } 
  });
  
  if (!user) throw new Error('User not found');
  
  return prisma.order.findMany({ 
    where: { userId } 
  });
}

// Avoid
function getUserOrders(userId: string) {
  return prisma.user.findUnique({ where: { id: userId } })
    .then(user => {
      if (!user) throw new Error('User not found');
      return prisma.order.findMany({ where: { userId } });
    });
}

Areas to Contribute

Core Features

  • Portfolio management improvements
  • Advanced order types (stop-loss, etc.)
  • Social features (leaderboards, etc.)
  • Analytics dashboard

Performance

  • Order matching optimization
  • Database query optimization
  • Caching improvements
  • WebSocket efficiency

Testing

  • Unit tests
  • Integration tests
  • E2E tests
  • Load testing

Documentation

  • API documentation
  • Architecture guides
  • Tutorial content
  • Code comments

UI/UX

  • Design improvements
  • Mobile responsiveness
  • Accessibility
  • Dark mode enhancements

DevOps

  • CI/CD improvements
  • Docker optimization
  • Monitoring setup
  • Deployment automation

Project Architecture

Understanding the architecture helps you contribute effectively:Flow:
  1. Client - User places order via Next.js frontend
  2. Backend (Server) - Validates and accepts order
  3. Queue - Order added to Redis queue (BullMQ)
  4. Worker (Engine) - Processes order from queue
  5. Matching Logic - Updates order book with matching
  6. WebSocket - Broadcasts updates to all clients
  7. Database - Persists state to PostgreSQL
Key Components:
  • Order Book: In-memory structure for fast matching
  • Queue: Asynchronous order processing
  • WebSocket: Real-time updates
  • Database: Source of truth for all data
See the Architecture Overview for detailed diagrams.

Monorepo Structure

client/ - Next.js frontend
  • React components
  • NextAuth authentication
  • Real-time WebSocket integration
  • TanStack Query for data fetching
server/ - Express backend API
  • REST endpoints
  • JWT authentication
  • Order management
  • Event management
db/ - Database layer
  • Prisma schema
  • Database client
  • Migrations
order-queue/ - Queue management
  • BullMQ integration
  • Redis connection
  • Worker logic
types/ - Shared TypeScript typeszod/ - Validation schemaslogger/ - Logging utility
engine/ - Order matching engine
  • Core matching algorithm
  • Order book management
  • Price calculation
wss/ - WebSocket server
  • Real-time connections
  • Message broadcasting
  • Redis pub/sub

Testing

Add tests for new features:
// Example test structure
import { describe, it, expect } from 'vitest';
import { placeOrder } from './orders';

describe('Order Placement', () => {
  it('should place a valid order', async () => {
    const order = {
      userId: 'user123',
      eventId: 'event456',
      side: 'YES',
      quantity: 10,
      price: 5.5
    };

    const result = await placeOrder(order);

    expect(result).toBeDefined();
    expect(result.id).toBeTruthy();
    expect(result.userId).toBe(order.userId);
  });

  it('should reject invalid order', async () => {
    const order = {
      userId: 'user123',
      eventId: 'event456',
      side: 'INVALID',
      quantity: -10,
      price: 0
    };

    await expect(placeOrder(order)).rejects.toThrow();
  });
});

Database Changes

When modifying the database schema:
1

Update Prisma schema

Edit packages/db/prisma/schema.prisma:
model NewModel {
  id        String   @id @default(cuid())
  field     String
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}
2

Create migration

cd packages/db
npx prisma migrate dev --name add_new_model
3

Generate Prisma client

npx prisma generate
4

Update application code

Use the new schema in your application code.

Getting Help

GitHub Issues

Browse existing issues or create a new one

Discussions

Ask questions and discuss ideas

Documentation

Read the full documentation

Code of Conduct

Be respectful and inclusive

Recognition

All contributors are recognized in:
  • README.md contributors section
  • GitHub contributor graph
  • Release notes for significant contributions
We value all contributions, no matter how small. Every improvement helps make Opinix Trade better!

Next Steps

Development Setup

Set up your development environment

Architecture

Understand the system architecture

API Reference

Explore the API documentation

GitHub Repository

View the source code