📈 Crypto Simulator

Real-time multi-coin trading simulator with WebSocket price feed and QA chaos controls.

Overview

The Crypto Simulator provides a live multi-coin trading environment over WebSocket. Each user starts with a $10,000 USD balance and can buy and sell BTC, ETH, SOL, and DOGE in real time. Prices update every second using a market simulation engine with distinct patterns (bull flag, channel up, random walk).

The built-in QA Control Panel lets testers inject latency, simulate server crashes, send malformed WebSocket payloads, and force price directions — all without touching the server code.

REST Base Path
/api/crypto
WebSocket URL
ws://localhost:3000/ws/crypto
Auth Header (REST)
x-api-key: <your-key>
Starting Balance
$10,000.00 USD
Price data is simulated — prices change every second server-side. All trades execute at the current live price at the moment the WebSocket message is received.

Quick Start

  1. Connect to the WebSocket at ws://<host>/ws/crypto with your API key as a query param or in the first message.
  2. Receive live price ticks — the server broadcasts prices for all 4 coins every second.
  3. Send a BUY or SELL message to trade.
  4. Check your portfolio via the REST endpoint GET /api/crypto/profile.
# Get live prices (no auth required)
curl https://qacloud.dev/api/crypto/prices

# Get portfolio (auth required)
curl https://qacloud.dev/api/crypto/profile \
  -H "x-api-key: YOUR_KEY"
# WebSocket trade message (send after connecting)
{
  "action": "BUY",
  "symbol": "BTC",
  "amount": 0.01
}
# Force BTC to trend upward for 15 seconds
curl -X POST "https://qacloud.dev/api/crypto/inject?symbol=BTC&direction=up&duration=15" \
  -H "x-api-key: YOUR_KEY"

Supported Coins

BTC
Bitcoin
Start: ~$45,000
Ξ
ETH
Ethereum
Start: ~$2,800
SOL
Solana
Start: ~$180
Ð
DOGE
Dogecoin
Start: ~$0.18

Each coin has a minimum price floor and its own volatility coefficient. The price engine prevents any coin from dropping below its minimum price.

WebSocket Price Feed

Connect to ws://<host>/ws/crypto to receive live price broadcasts. The server emits a tick every second containing current prices for all coins.

Incoming Tick Message (server → client)

{
  "type": "tick",
  "prices": {
    "BTC": 46230.50,
    "ETH": 2847.12,
    "SOL": 182.44,
    "DOGE": 0.1923
  },
  "timestamp": 1715000000000
}

Authentication

Pass your API key as a query parameter when connecting: ws://<host>/ws/crypto?api_key=YOUR_KEY, or send it in the first message. Without a valid key, trades will fail but price ticks will still be received.

Trading via WebSocket

All buy/sell operations are sent as WebSocket messages. The server processes the trade at the current price and responds with the updated state.

Buy Order

{
  "action": "BUY",
  "symbol": "ETH",
  "amount": 0.5
}

Purchases amount units of the coin at the current price. Deducts the USD cost from your balance.

Sell Order

{
  "action": "SELL",
  "symbol": "ETH",
  "amount": 0.5
}

Sells amount units at the current price. Returns USD to your balance.

Trade Response

{
  "type": "trade_result",
  "success": true,
  "action": "BUY",
  "symbol": "ETH",
  "amount": 0.5,
  "price": 2847.12,
  "cost": 1423.56,
  "balance_usd": 8576.44,
  "coin_balance": 0.5
}
Sending a negative amount or a non-numeric value is a deliberate bug surface for QA testing. Try "amount": -500 or "amount": "five" via the QA Control Panel.

QA Control Panel

The Crypto Simulator includes a built-in QA Control Panel accessible from the app UI. It gives testers direct access to chaos scenarios without writing code.

🔧 Available Controls

  • High Latency Mode — introduces artificial delay on all WebSocket messages to simulate network lag. Tests client timeout handling.
  • Simulate Server Crash — closes the WebSocket connection abruptly. Verifies client reconnect logic.
  • Send Negative Amount — sends { action: "BUY", amount: -500 } to test negative value handling.
  • Send String Amount — sends { action: "BUY", amount: "five" } to test type validation.
  • Rapid Fire Orders — sends 10 BUY orders in rapid succession to simulate concurrency/race conditions.
  • Inject Price Direction — forces a coin to trend up or down for a configurable duration (1–60 seconds).

Price Patterns

The price engine cycles through three patterns every 50 ticks (~50 seconds). Each pattern applies a different movement algorithm to produce realistic chart shapes.

Bull Flag
Strong directional move for 25 ticks followed by a consolidation phase.
Channel Up
Oscillating price with a gradual upward trend using a sine-wave delta.
Random Walk
Slight bullish bias with random noise — the default baseline pattern.

When a price injection is active, the normal pattern is overridden with a strong directional delta toward the injected direction.

REST Endpoints

GET /api/crypto/prices Current prices for all coins — no auth required

Returns the current simulated price for all 4 coins plus the coin metadata (name, pair, icon).

{
  "prices": { "BTC": 46230.50, "ETH": 2847.12, ... },
  "coins": { "BTC": { "name": "Bitcoin", "pair": "BTC/USD", "icon": "₿" }, ... }
}

This endpoint does NOT require an API key — public read access.

GET /api/crypto/profile Portfolio snapshot for the authenticated user

Returns the user's USD balance, coin holdings, portfolio value (at current prices), total P&L, and last 50 trades.

{
  "balance_usd": 8576.44,
  "portfolio_value": 11423.56,
  "pnl_total": 1423.56,
  "holdings": [
    { "symbol": "BTC", "balance": 0.02, "price": 46230.50, "value": 924.61, "pnl": 24.61 }
  ],
  "orders": [...],
  "total_trades": 7
}
POST /api/crypto/inject Force a coin to trend in a direction for N seconds
Query ParamRequiredDescription
symbolrequiredBTC | ETH | SOL | DOGE
directionrequiredup | down
durationoptionalSeconds (1–60). Default: 10
{
  "symbol": "BTC",
  "direction": "up",
  "duration": 15,
  "message": "BTC will trend up for 15s",
  "endsAt": "2026-04-14T10:00:15.000Z"
}
POST /api/crypto/reset Reset trading account to $10,000 initial state

Wipes all trade history and coin holdings, resets USD balance to $10,000. Prices continue running — only the user's portfolio is reset.

WS ws://<host>/ws/crypto Live price feed + trade execution

Server → Client: Price tick every 1 second for all 4 coins.

Client → Server: Trade orders as JSON. Fields: action (BUY|SELL), symbol, amount.

QA Control: Send { "type": "qa_control", "action": "set_latency", "value": true } to enable high-latency mode.

Test Cases

TC-CRY-001 GET /prices returns 200 without auth PASS

Steps: Call GET /api/crypto/prices without any x-api-key header → expect 200 with prices object containing BTC, ETH, SOL, DOGE.

TC-CRY-002 BUY reduces USD balance correctly PASS

Steps: GET /profile → note balance_usd. Send WS BUY for ETH: 1.0 → GET /profile → verify new balance_usd = old_balance - (eth_price × 1.0).

TC-CRY-003 Negative amount BUY is handled gracefully FAIL

Steps: Send WS message { action: "BUY", symbol: "BTC", amount: -500 } → verify server does not execute trade and returns an error response (not a silent success or crash).

TC-CRY-004 String amount type is rejected FAIL

Steps: Send WS message { action: "BUY", symbol: "BTC", amount: "five" } → verify error response, no trade executed.

TC-CRY-005 Cannot buy more than USD balance allows FAIL

Steps: Calculate max BTC purchasable with $10,000. Attempt to buy 10x that amount → verify error response indicating insufficient funds.

TC-CRY-006 Price injection makes coin trend up PASS

Steps: Record BTC price. POST /inject?symbol=BTC&direction=up&duration=10. Monitor WS ticks for 10 seconds → verify prices are generally trending upward during injection period.

TC-CRY-007 Reset clears portfolio to initial state PASS

Steps: Buy some coins. POST /reset. GET /profile → verify balance_usd = 10000, all coin balances = 0, orders = [].

TC-CRY-008 P&L calculation is correct after buy and sell PASS

Steps: Buy 1 ETH. Wait for price to change. Sell 1 ETH. GET /profile → pnl_total should reflect the gain/loss from the round trip.

QA Tasks

1. WebSocket Reconnect Testing
Use the "Simulate Server Crash" QA control to close the connection. Verify the client automatically reconnects and resumes receiving price ticks without page reload.
2. High Latency Mode Impact
Enable high latency mode. Measure time between ticks. Attempt trades during high latency and verify they execute correctly with delayed responses (not dropped or duplicated).
3. Rapid Fire Race Conditions
Use the "Rapid Fire Orders" control to send 10 simultaneous BUY orders. Verify: (a) each order deducts the correct separate cost, (b) balance does not go negative, (c) no duplicate trade records.
4. Malformed Message Handling
Send each malformed payload type: negative amount, string amount, missing symbol, unknown action type. Document the server response for each case — error message vs silent failure vs crash.
5. Float Precision in P&L
Buy and sell small fractions (e.g. 0.001 BTC) multiple times. Check pnl_total for floating-point rounding errors. Does 10 round trips return exactly the starting capital?
6. Price Injection Coverage
Test inject for all 4 coins, both directions, and edge-case durations (1s, 60s, 61s — boundary). Verify 61s returns a capped 60s response.
7. Unauthenticated Access
Verify GET /prices works without auth (200). Verify GET /profile, POST /inject, POST /reset all return 401 without an API key.
8. Portfolio Value Accuracy
After buying multiple coins, query GET /prices and GET /profile simultaneously. Verify portfolio_value = sum of (coin_balance × current_price) for each holding, plus balance_usd.