From d82c5fd14e82707c055105d54b4f37ad63cad0df Mon Sep 17 00:00:00 2001 From: direkturcrypto Date: Fri, 27 Mar 2026 13:47:22 +0700 Subject: [PATCH] fix: add axios interceptor for proxy + dual proxy test (fetch + axios) The CLOB client uses axios internally. Previous setup only set axios.defaults which doesn't work if the CLOB client or axios creates its own instance. Fix: add axios request interceptor that forces proxy agent on every request to polymarket.com domains. Also add separate axios-based proxy test alongside fetch test to catch cases where fetch works but axios doesn't route through proxy. Co-Authored-By: Claude Opus 4.6 --- src/utils/proxy.js | 61 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/src/utils/proxy.js b/src/utils/proxy.js index a38fb3e..2520214 100644 --- a/src/utils/proxy.js +++ b/src/utils/proxy.js @@ -39,6 +39,18 @@ export async function setupAxiosProxy() { axios.defaults.proxy = false; axios.defaults.httpAgent = axiosAgent; axios.defaults.httpsAgent = axiosAgent; + + // Add request interceptor to force proxy agent on every request + // This catches cases where axios.create() instances ignore defaults + axios.interceptors.request.use((cfg) => { + if (cfg.url && cfg.url.includes('polymarket.com')) { + cfg.httpsAgent = axiosAgent; + cfg.httpAgent = axiosAgent; + cfg.proxy = false; + } + return cfg; + }); + logger.info(`Axios proxy configured → ${maskProxyUrl(config.proxyUrl)}`); } catch (err) { logger.error(`Failed to configure axios proxy: ${err.message}`); @@ -115,12 +127,12 @@ export async function testProxy() { // Show both IPs so user can verify which IP Polymarket sees await checkOutboundIP(); + // ── Test 1: fetch (undici) ────────────────────────────────────────── try { if (!fetchDispatcher) { throw new Error('Proxy dispatcher not initialized'); } - // Test with a simple GET to the CLOB time endpoint via proxied fetch const resp = await fetch(`${config.clobHost}/time`, { dispatcher: fetchDispatcher, signal: AbortSignal.timeout(15000), @@ -146,13 +158,54 @@ export async function testProxy() { throw new Error(`HTTP ${resp.status} ${resp.statusText}`); } - logger.success(`Proxy test passed — connected via ${maskProxyUrl(config.proxyUrl)}`); - return true; + logger.success(`Proxy test (fetch) passed`); } catch (err) { - logger.error(`Proxy test FAILED: ${err.message}`); + logger.error(`Proxy test (fetch) FAILED: ${err.message}`); logger.error('Check PROXY_URL in .env. Bot cannot reach Polymarket without a working proxy.'); return false; } + + // ── Test 2: axios (same transport as CLOB client) ──────────────────── + try { + if (!axiosAgent) { + throw new Error('Axios proxy agent not initialized'); + } + + const axiosModule = await import('axios'); + const axios = axiosModule.default || axiosModule; + const axiosResp = await axios.get(`${config.clobHost}/time`, { + httpsAgent: axiosAgent, + proxy: false, + timeout: 15000, + }); + + logger.success(`Proxy test (axios) passed`); + } catch (err) { + const status = err?.response?.status; + const data = err?.response?.data; + + if (status === 403) { + const body = typeof data === 'string' ? data : JSON.stringify(data || ''); + const isGeoblock = body.includes('restricted') || body.includes('region') || body.includes('geoblock'); + if (isGeoblock) { + logger.error('═══════════════════════════════════════════════════'); + logger.error('GEOBLOCKED (axios) — Polymarket CLOB rejected your proxy IP!'); + logger.error('Your proxy IP is in a restricted region.'); + logger.error('The CLOB client uses axios — this test confirms proxy routing.'); + logger.error('Change PROXY_URL in .env to a proxy in an allowed region.'); + logger.error('═══════════════════════════════════════════════════'); + } else { + logger.error(`CLOB returned 403 via axios: ${body.substring(0, 200)}`); + } + return false; + } + + logger.error(`Proxy test (axios) FAILED: ${err.message}`); + return false; + } + + logger.success(`All proxy tests passed — connected via ${maskProxyUrl(config.proxyUrl)}`); + return true; } /**