Changelog¶
Project + documentation history. Newest first. Add a one-line bullet for every code or doc change worth surfacing.
Format: YYYY-MM-DD — <area> — <one-line summary>
Areas: feat, fix, refactor, test, docs, chore, security.
2026-07-08 — full-egress IP privacy¶
security— all network egress now shares one proxy agent (src/utils/proxyAgent.js): ethers RPC over HTTP (FetchRequest agent) and WebSocket (ws factory + agent), the Solana connection (httpAgent), and axios (alerts/price). Previously only axios was proxied, so the RPC connection — the bot's most continuous trace — leaked the real IP even with a proxy set. Verified live: withHTTPS_PROXYset, the RPC host is tunnelled through the proxy, not connected directly. One switch (SOCKS_PROXY/HTTPS_PROXY) covers everything; fail-closed if the agent dep is missing.security—PRICE_LOOKUP_ENABLEDnow defaults false (privacy-first): no CoinGecko holdings leak out of the box. It only affects cosmetic USD PnL in alerts, never triggers/automation.security— addedhttps-proxy-agentoptional dep (alongsidesocks-proxy-agent) for the HTTP-proxy agent path.test—proxyAgentsuite + updatedhttpClientsuite (shared-agent model). Suite: 199 passing.docs— safety.md §8a: RPC now proxied, CoinGecko off by default, "minimal setup for full IP privacy" (Tor in 3 steps).
2026-07-08 — security & privacy hardening¶
security— logs — no secret or key-bearing URL can reach the logs: newsrc/utils/redact.js(maskUrl/maskAddress/scrubSecrets) + a two-layer pino config (expanded key list incl. all*_RPC_*, + value-scrubbing serializers). Fixed a direct RPC-URL-with-API-key leak insolana.js. Verified live: 0 secret occurrences in logs/state.security— identity — wallet address is masked (0x1234…5678) before it ever enters the dashboard store//api/state/SSE, unlessDASHBOARD_SHOW_FULL_ADDRESS=true.security— dashboard — CSP (connect-src 'self'blocks exfiltration),X-Frame-Options: DENY,nosniff,no-referrer,no-storeon every response; configurableDASHBOARD_BIND(default 127.0.0.1) with a loud warning on non-loopback binds.security— startup preflight (src/security/preflight.js): refuses to start in production when.env/keystore are group/world-readable (warns in dev); warns on identity/egress exposure (no proxy, exposed dashboard, CoinGecko holdings leak, raw key).security— egress privacy — all outbound HTTP (Telegram/Discord/CoinGecko) routed through a shared client honoringSOCKS_PROXY(Tor, socks5h) /HTTPS_PROXY; fails closed if the proxy is configured but unavailable.PRICE_LOOKUP_ENABLED=falsedisables CoinGecko holdings leakage.DASHBOARD_PERSIST=falsedisables the plaintext trade log.security— deps — overrode vulnerablews(ethers transitive DoS) → 8.21.0 andform-data(CRLF) → 4.0.6. EVM-only install now audits 0 vulnerabilities; remaining advisories are all upstream in the optional Solana/Raydium SDK tree.test— addedredact,preflight,dashboardSecurity,httpClientsuites (34 new tests). Suite: 195 passing.-
docs— safety.md — new §8a Privacy & identity + rewritten §8 Logging. -
fix— triggerEngine/index.js — positions are retired after a permanent executor failure (markPermanentlyFailed): no more endless re-fire/alert loop on errors that can never succeed (e.g. "No LP tokens to remove"). Dashboard showsfailed-permanent; alert says the position will not re-fire. Regression test added. feat— alerts — Telegram/Discord messages rebuilt: per-channel rendering (Telegram HTML with escaping — labels with underscores no longer break parsing; Discord markdown), human trigger reasons (single-swap vs cumulative move, volume ratio, position age, emergency tx), received amounts with symbols, PNL, explorer links, dry-run labeling, and retry-vs-retired guidance on errors.feat— alerts/telegram —/statusnow actually replies with a live summary (mode, uptime, chain WS health, tx budget, every position with status/price/last-seen) instead of only logging. Built from the same store snapshot the dashboard uses.feat— dashboard — UI rebuilt for at-a-glance visibility: DRY-RUN/LIVE badge, stat tiles (positions, chain WS health, tx budget vs caps, slippage/gas caps), armed-trigger chips, per-position cards with live price, last-swap/session deltas, drop-from-peak meter showing proximity to the price-drop trigger, price sparkline with hover tooltip (240-point rolling buffer added to the store), and a clearer event feed distinguishing retrying vs retired errors. Coverage/docs panels collapsed by default. Operational view is now dependency-free (works offline); CDN libs only for the docs viewer with plain-text fallback.
2026-07-07¶
fix— config.js —poolAddresswas missing fromPositionSchema, so zod silently stripped it and the V3 price monitor was disabled for every V3 position even when configured exactly as documented. Found during live mainnet verification of the audit fixes; regression test added.fix— raydium.js — missingawaitonloadSolanaSigner(); the SDK was receiving a Promise asowner, breaking every live Solana removal.fix— evm.js + monitors — WS reconnect now emitsws-down/ws-reconnectedviaproviderEvents; PriceMonitor and EventMonitor re-establish their subscriptions on reconnect (previously the bot went silently blind after the first disconnect). Chain WS status surfaces on the dashboard.feat— triggerEngine.js — price drop/rise now also fire on cumulative moves (drop from trailing peak, rise from first observation), catching gradual dumps a per-swap delta never sees.feat— triggerEngine.js — max-age evaluated by a 30s timer sweep, so it fires even for pools with zero swap activity;engine.stop()added to shutdown.fix— gas.js — base fee read from the latest block (previous derivation double-counted ethers' getFeeData convention); the gas-cap guard is now live: executors abort pre-broadcast when base+priority exceedsMAX_GAS_GWEI(previously the fee was silently clamped and the guard could never trip, risking indefinitely-stuck transactions).tx.waitbounded byTX_DEADLINE_SEC.fix— priceMonitor.js — volume-spike baseline is now average volume per window-sized span (was per-swap mean), eliminating false fires on steady volume.feat— BSC/PancakeSwap wired end to end:bscchain inCHAINS/schema/position enum,BSC_RPC_*env vars, bscscan explorer URL, CoinGecko platform mapping, dex-first positionManager lookup.fix— executors — emergency removals bypass the rate limiter (dead-man's switch no longer strands positions beyondMAX_TX_PER_MINUTE); EVM signers wrapped inethers.NonceManagerfor concurrent removals; live mode preloads signers at boot.fix— executors/index.js — permanent errors (blacklist, not-owner, empty position, post-broadcast failures) abort the retry loop instead of re-running the whole removal (a retry after broadcast could misreport a confirmed removal as failed).fix— telegram.js — command backlog queued while the bot was down is discarded at startup (a stale/removeno longer executes on boot).fix— keystore.js — fails fast whenKEYSTORE_PASSWORDis unset and there is no TTY (previously hung forever on a readline prompt in Docker).fix— priceMonitor.js —priceUnitsnow decimals-adjusted (human token1-per-token0 ratio); removed a wastedpositions()RPC from the V3 monitor.fix— alerts — dry-run success alerts no longer rendertx/undefined; dry runs are labeled.chore— eslint 9 flat config added (npm run lintwas broken); CI workflow.github/workflows/test.yml(lint + tests); Dockerfile usesnpm ciwith the lockfile.test—tests/poc.findings.test.js: 6 proof-of-concept tests pinned the audit defects, then were flipped to regression tests (10 tests) when the fixes landed. Monitor resubscription + new gas/volume semantics covered in existing suites. Suite now 158 tests.docs— testing.md, CLAUDE.md — synced with new trigger semantics, gas-cap contract, WS resubscription invariant, BSC support.
2026-05-13¶
docs— Initial/docsdirectory created (README, getting-started, usage, architecture, testing, safety, extending, CHANGELOG).test— Keystore test suite now passes 9/9. Switched toencryptKeystoreJsonSyncfor correct ethers v6 API.feat— UniswapV2 honeypot pre-flight viaremoveLiquidity.staticCallsimulation (gap 1).feat— Raydium price decoder viaAmmRpcDatapre-computed prices (gap 2).feat— Raydium CPMM/CLMM dispatch + AMM v4 liquidity removal (gap 3).test— Coverage now at 100 tests, ~87% branch. Suites: config, rateLimit, triggerEngine, priceMonitor, eventMonitor, executorDispatch, executorV2, executorV3, executorRaydium, approvalManager, keystore, gas, slippage, pnl.fix— Telegram HTTP 400 on alert send. Caused by malformedTELEGRAM_CHAT_ID(leading colon). Stripped — delivery confirmed.
Template for future entries¶
## YYYY-MM-DD
- `feat` — <module> — short description.
- `fix` — <module> — short description.
- `docs` — <page touched> — short description.
Open-ended TODOs and known gaps live in docs/testing.md §3 and docs/architecture.md §7, not here. This file is for what happened, not what's pending.