Location
core/src/exchanges/polymarket/websocket.ts:224
Code
private async connectUserChannel(creds: PolymarketUserChannelCreds): Promise<void> {
const WebSocket = (await import('ws')).default;
const url = 'wss://ws-subscriptions-clob.polymarket.com/ws/user';
this.userWs = new WebSocket(url);
this.userWs.on('open', () => {
console.log('[polymarket-ws] user channel connected');
this.sendUserSubscription(creds);
// ...
});
Risk
connectUserChannel creates a WebSocket without any connection timeout. The function itself is async but doesn't return a promise that settles on open — instead it fires-and-forgets. If the Polymarket user channel endpoint hangs, the authenticated user channel silently never establishes, and user-channel events (fills, position updates) are never received with no error surfaced.
Affected Methods
PolymarketWebSocket.connectUserChannel() — called for credentialed users
- All user-channel event callbacks (fill notifications, position updates)
Suggested Fix
Wrap the connection in a promise with a timeout and reject on both error and timeout:
await new Promise<void>((resolve, reject) => {
const timeout = setTimeout(() => {
this.userWs?.terminate();
reject(new Error('Polymarket user WS connection timeout'));
}, 15_000);
this.userWs!.on('open', () => { clearTimeout(timeout); resolve(); });
this.userWs!.on('error', (err) => { clearTimeout(timeout); reject(err); });
});
Found by automated missing timeout audit
Location
core/src/exchanges/polymarket/websocket.ts:224Code
Risk
connectUserChannelcreates a WebSocket without any connection timeout. The function itself isasyncbut doesn't return a promise that settles onopen— instead it fires-and-forgets. If the Polymarket user channel endpoint hangs, the authenticated user channel silently never establishes, and user-channel events (fills, position updates) are never received with no error surfaced.Affected Methods
PolymarketWebSocket.connectUserChannel()— called for credentialed usersSuggested Fix
Wrap the connection in a promise with a timeout and
rejecton botherrorand timeout:Found by automated missing timeout audit