Claude/polymarket trading bot o r ioe#233
Conversation
- main.py: Entry point with FastAPI server and trading loop - bot/state.py: Thread-safe shared state (paused, mode, risk limits) - bot/execution.py: Wrapper around py-clob-client for order execution - bot/strategy.py: Placeholder for directional trading signals - bot_requirements.txt: Dependencies including FastAPI and uvicorn - BOT_README.md: Setup instructions for Codespaces and Railway Features: - HTTP API for phone-based control via curl - Paper/live trading modes - Risk limits (max order size, max exposure) - Bearer token authentication - Starts paused and in paper mode for safety
- GET /ui serves a single-page control panel - Token stored in localStorage after first login - Auto-refreshes status every 5 seconds - Mobile-first responsive design - Controls: pause/resume, paper/live mode, risk limits - Emergency cancel all orders button - Buttons disabled when action not applicable - Dark theme with clear status badges
- Validate API secret is valid base64 - Check for accidental quotes in environment variables - Test API credentials by calling get_api_keys endpoint - Log clearer error message when credentials don't match wallet
| result = self.client.get_midpoint(token_id) | ||
| if result and hasattr(result, 'mid'): | ||
| return float(result.mid) | ||
| return None |
There was a problem hiding this comment.
Dictionary accessed as object attributes always returns None
The get_midpoint method checks hasattr(result, 'mid') but the py-clob-client's get_midpoint() returns a dictionary (raw JSON from resp.json()), not an object with attributes. Dictionaries in Python don't have attribute access, so hasattr() always returns False, causing this method to always return None. The same pattern affects get_collateral_balance() and get_token_balance() which check hasattr(result, 'balance'). The correct approach would use dictionary key access like result.get('mid') or 'mid' in result. This completely breaks the bot's ability to fetch market prices and account balances.
Additional Locations (2)
| logger.info("=== CLOB Client Initialization ===") | ||
| logger.info(f"Host: {host}") | ||
| logger.info(f"POLY_PRIVATE_KEY: {'SET' if private_key else 'MISSING'} (len={len(private_key)})") | ||
| logger.info(f"POLY_API_KEY: {'SET' if api_key else 'MISSING'} (len={len(api_key)}, starts={api_key[:8] if len(api_key) > 8 else 'N/A'}...)") |
There was a problem hiding this comment.
API key prefix logged exposes partial credential
The initialization code logs the first 8 characters of POLY_API_KEY to application logs with the message starts={api_key[:8]}.... The comment claims this is "without exposing secrets" but partial API keys are sensitive information that can help attackers narrow down valid credentials. Logs are often accessible to multiple team members, stored in log aggregation services, or exposed in error reports. Credential prefixes should never be logged.
| # Update exposure tracking | ||
| order_value = price * size | ||
| if side.upper() == "BUY": | ||
| state.add_exposure(token_id, order_value) |
There was a problem hiding this comment.
SELL orders never reduce exposure tracking
The reduce_exposure method is defined in bot/state.py but is never called anywhere in the codebase. When place_order executes a SELL order, it does not reduce the tracked exposure. This means exposure only ever increases (on BUY orders), causing the tracked exposure to accumulate over time. Eventually, all markets will appear to have reached their max_exposure_per_market limit, blocking legitimate BUY orders even when actual positions have been sold. The bot would effectively stop trading after enough BUY/SELL cycles.
Overview
Description
Testing instructions
Types of changes
Notes
Status
[WIP]if necessary (changes not yet made).Note
Introduces a complete directional trading bot for Polymarket with an HTTP control plane and basic web UI.
main.pyFastAPI server with auth-protected endpoints (/status,/pause,/resume,/mode/{paper|live},/risk,/markets,/cancel-all) and/uiweb panel; starts background trading loopbot/execution.pyexecution engine wrappingpy-clob-clientfor order placement/cancellation, midpoints/order book, and balance queries with env-based initializationbot/state.py(paused/mode, risk limits, uptime, last actions, exposure tracking)bot/strategy.pyscaffold for signal generation/validation and market summariesBOT_README.mdwith setup/deployment (Codespaces/Railway) and updatesrequirements.txt/bot_requirements.txtfor FastAPI/uvicorn/pydanticWritten by Cursor Bugbot for commit fcb9d3d. This will update automatically on new commits. Configure here.