Developing a Liquidity Monitoring Bot
Uniswap v3 made liquidity management an active endeavor. An LP position in the $1800-$2200 ETH/USDC range worked great for a week — until the price moved outside the range and the position stopped earning fees, converting entirely to one asset. Without monitoring, this can go unnoticed for days. These are direct losses from missed commissions and impermanent loss.
What Really Needs to be Tracked in DEX Pools
Uniswap v3: Position Activity and Out-of-Range Events
Each Uniswap v3 position is defined by (tokenId, tickLower, tickUpper). The pool stores current tick — logarithmic price. As soon as currentTick < tickLower or currentTick > tickUpper — position is out-of-range, fees aren't accrued.
Swap event in the pool emits new tick. Bot subscribes to Swap via WebSocket (eth_subscribe("logs", {address: poolAddress, topics: [Swap.topic]})), decodes tick from event data and compares with tickLower/tickUpper of all tracked positions. Latency from event to notification — 100-500ms, sufficient for notifying LP.
Additionally useful to track Mint and Burn events — they show when large LPs enter or exit range, often preceding price movement.
Curve: Pool Disbalance and De-Peg Monitoring
In Curve StableSwap, a pool is considered balanced when asset shares are close to targets (usually equal). With strong disbalance (e.g., 90% USDT and 10% USDC in 3pool), swap slippage rises sharply, and effective APY for LP drops.
Metric to monitor: deviation of current balances from ideal. Call get_balances() + compare with total_supply() / N. If one asset occupies >70% — alert. This happened to 3pool during de-pegging events (USDC briefly traded at $0.87 on Curve in March 2023).
The Graph for Historical Data
To monitor pool TVL and volumes in real time, use The Graph subgraph for Uniswap v3 (subgraph id: 5zvR82QoaXYFyDEKLZ9t6v9adgnptxYpKpSbxtgVENFV). GraphQL query every 60 seconds returns pool.totalValueLockedUSD, pool.volumeUSD, pool.feesUSD. For large pools with >$10M TVL this is sufficient. For small pools with fast changes — direct WebSocket events are more reliable.
Bot Architecture
Typical monitoring system has three components:
| Component | Technology | Task |
|---|---|---|
| Event listener | ethers.js / viem WebSocket | Subscribe to on-chain events |
| State aggregator | Node.js / Python | Aggregate and compare with thresholds |
| Alert dispatcher | Telegram Bot API / PagerDuty | Send notifications |
Event listener subscribes via WebSocket to pools from config list. On event, decodes data via ABI and publishes to queue (Redis Pub/Sub or in-memory queue).
State aggregator reads queue, updates pool state (current tick, balances, TVL) and checks alert conditions. Also here — periodic polling (every 30-60 seconds) for metrics not emitted as events (e.g., accumulated fees via NonfungiblePositionManager.collect).
Alert dispatcher deduplicates alerts (one alert per 5 minutes per position), formats message and sends to Telegram or webhook. For production systems — PagerDuty with severity levels.
Calculating Accumulated Fees Without Transaction
Current accumulated LP position fees can be calculated off-chain without collect (which costs gas). Formula from Uniswap v3 whitepaper via feeGrowthInside:
fees0 = liquidity * (feeGrowthInside0 - feeGrowthInside0Last) / 2^128
fees1 = liquidity * (feeGrowthInside1 - feeGrowthInside1Last) / 2^128
feeGrowthInside calculated from pool data per ticks — this is static call, not transaction. Showing user accumulated fees in real time is useful for rebalancing decisions.
Stack and Integrations
viem (TypeScript) for on-chain interaction — typed calls, built-in ABI decoder, multicall support for batching. The Graph for historical data and aggregated metrics. Redis for state storage between restarts and deduplication. Telegram Bot API as primary notification channel.
For multi-chain monitoring (Ethereum + Arbitrum + Optimism) — parallel WebSocket connections to one aggregator. Uniswap v3 deployed on all three chains, pool addresses differ, but ABI is identical.
Work Process
Configuration (1 day). List of pools, positions, alert threshold values.
Development (3-5 days). Event listener + state aggregator + Telegram/webhook integration. Test on testnet (Sepolia with forked Uniswap v3 state via Foundry vm.createFork).
Deployment. VPS with minimum 2 CPU / 4GB RAM, dedicated full node or Alchemy/QuickNode WebSocket endpoint. Monitor bot via pm2 + health check endpoint.
Timeline Guidelines
Basic bot (one DEX, Telegram alerts): 3-5 days. Multi-chain system with historical metrics and dashboard: 2-3 weeks.







