A real-time cryptocurrency exchange platform built with Laravel 12 and Vue 3, featuring automated order matching, real-time updates, and comprehensive wallet management.
This application implements a limit order matching engine for cryptocurrency trading. Users can place buy and sell orders for BTC and ETH, with automatic matching when compatible orders are found. The system handles order execution, fee calculation, balance management, and provides real-time updates via WebSocket broadcasting.
- Limit Order System: Place buy and sell orders with custom price and amount
- Automated Matching: Automatic order matching based on price-time priority
- Real-time Updates: Live orderbook and wallet updates via Laravel Echo and Pusher
- Wallet Management: Track USD balance and cryptocurrency assets (BTC, ETH)
- Order History: View open, filled, and cancelled orders
- Fee Calculation: Automatic 1.5% trading fee applied to buyers
- Multi-asset Support: Trade BTC and ETH with symbol-based filtering
- PHP 8.2+ with Laravel 12
- MySQL/PostgreSQL/SQLite database
- Laravel Sanctum for API authentication
- Laravel Queue for asynchronous order matching
- Laravel Broadcasting with Pusher for real-time events
- Pest for testing
- Vue 3 with Composition API
- Vue Router for navigation
- Pinia for state management
- Axios for HTTP requests
- Laravel Echo with Pusher JS for real-time updates
- Tailwind CSS v4 for styling
- Vite for asset bundling
git clone https://github.com/ajooda/limit-order-matching-system.git
cd limit-order-matchingcomposer installCopy the environment file and configure your settings:
cp .env.example .env
php artisan key:generateEdit .env and configure the following:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_database_name
DB_USERNAME=your_username
DB_PASSWORD=your_passwordBROADCAST_CONNECTION=pusher
PUSHER_APP_ID=your_app_id
PUSHER_APP_KEY=your_app_key
PUSHER_APP_SECRET=your_app_secret
PUSHER_APP_CLUSTER=your_cluster
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"Get your Pusher credentials from pusher.com/channels
QUEUE_CONNECTION=databasephp artisan migrateThe seeder creates test users with initial balances for testing:
php artisan db:seedThis creates the following test accounts (all passwords: password):
buyer1@test.com(Buyer A) - $10,000 USDbuyer2@test.com(Buyer B) - $10,000 USDseller1@test.com(Seller A) - $10,000 USD, 1.0 BTC, 2.0 ETHseller2@test.com(Seller B) - $0 USD, 1.0 ETH
npm installFor development:
npm run devFor production:
npm run buildStart all development servers with a single command:
composer devThis starts:
- Laravel development server (http://localhost:8000)
- Queue worker (for order matching)
- Vite dev server (for hot module replacement)
If you prefer to run services separately:
Terminal 1 - Laravel Server:
php artisan serveTerminal 2 - Queue Worker:
php artisan queue:workTerminal 3 - Vite Dev Server:
npm run devOpen your browser and navigate to:
http://localhost:8000
- Buy Order matches with Sell Order when:
sell.price <= buy.priceANDamounts are exactly equal - Sell Order matches with Buy Order when:
buy.price >= sell.priceANDamounts are exactly equal - Orders are sorted by: price (priority), then created_at, then id
- Trade Price: Uses the counter order's price (price-time priority)
- Fee: 1.5% of trade volume, charged to buyer
- Partial Fills: Not supported - amounts must match exactly
- users: User accounts with USD balance
- assets: Cryptocurrency holdings (BTC, ETH) per user
- orders: Buy/sell orders with status tracking
- trades: Executed trades linking buyer and seller orders
The application uses Laravel Echo with Pusher for real-time updates:
- Order Matched Events: Broadcast to
user.{userId}channel when orders match - Event Payload: Includes trade details, updated user balance, assets, and order statuses
- Frontend Listener: Automatically updates wallet, orderbook, and order status without page refresh
- Create a free account at pusher.com
- Create a new Channels app
- Copy your credentials to
.env - Ensure
VITE_PUSHER_APP_KEYandVITE_PUSHER_APP_CLUSTERare set for frontend
Essential commands:
composer install
php artisan migrate
php artisan queue:work
npm run devapp/
├── Domain/Exchange/ # Domain logic for exchange features
│ ├── DTO/ # Data Transfer Objects
│ └── Services/ # Business logic services
├── Enums/ # OrderSide, OrderStatus enums
├── Events/ # OrderMatchedEvent
├── Http/
│ ├── Controllers/Api/ # API controllers
│ ├── Requests/ # Form request validation
│ └── Resources/ # API resources
├── Jobs/ # MatchOrderJob
├── Models/ # Eloquent models
└── Support/ # Helper classes (Money, FeeCalculator)
resources/
├── js/
│ ├── api/ # API client functions
│ ├── components/exchange/ # Vue components
│ ├── pages/ # Vue pages
│ ├── router/ # Vue Router configuration
│ ├── stores/ # Pinia stores
│ └── echo.js # Laravel Echo setup
database/
├── migrations/ # Database migrations
├── factories/ # Model factories
└── seeders/ # Database seeders
Ensure the queue worker is running:
php artisan queue:work- Verify Pusher credentials in
.env - If testing on localhost, add
PUSHER_SSL_VERIFY=falseto.env - Ensure
VITE_PUSHER_APP_KEYis set (required for frontend) - Check browser console for connection errors
- Verify database credentials in
.env - Ensure database exists and server is running
- Run migrations:
php artisan migrate
This project is open-sourced software.