Skip to content

LP dashboard

Goal: the liquidity side of a trading app — where the fees are, whether a pool is honest, what range to take, and how open positions are doing.

GET /lp/overview?chain=5042 — fees paid to LPs in 24 hours, the best real yield (≥ 25 traders, not suspect), liquidity added and removed, volume, TVL and providers over pools with ≥ $10k TVL, the six hottest pools by fees (hot) and the three biggest net inflows (inflow). One call, memoised 30 s.

const { pools, total, hidden } = await fetch(`${A}/lp/pools?chain=5042&sort=fee_tvl&interval=24h&limit=50`).then((r) => r.json());

Columns: pair (token0 / token1 with logos and impostor flags), venue (dex), fee tier (feeBps), TVL, volume and fees for the interval, feeTvlPct, aprPct, traders (wallets24h), LP net flow (lpAdd24h − lpRemove24h), providers, age (createdTs), score.

  • Sorts: fee_tvl · vol_24h · vol_1h · tvl · fees_24h · first_seen · lp_net_24h · trades_24h · score.
  • Filters: quote=USDC (anchor), dex=uniswap_v4, search=argus, minTvl=, small=1 (under $10k), flagged=1 (show suspect pools, greyed).
  • hidden is how many rows the filters removed — show it; users ask.
  • lpAccess: "hooked" means a V4 hook can refuse adds. Do not offer a mint button on those.

GET /lp/pools/{pool}?chain=5042 returns the row plus:

  • hourly — 7 days of volume, trades and price for the chart.
  • topLps — providers over 7 days with net dollars.
  • health — the score, its six parts and reasons in plain English.
  • launch — who launched it, the launcher’s share of all liquidity ever added, and when it last pulled.
  • mint — what a wallet needs to add liquidity: manager, pool key, Permit2, tick spacing, native flag.

GET /lp/pools/{pool}/positions?chain=5042&limit=20 lists the open positions in the pool, largest first, valued live. GET /lp/events?chain=5042&pool={pool}&minUsd=1000 is the add/remove tape.

const plan = await fetch(`${A}/lp/plan?chain=5042&token=${addr}&amountUsd=1000&days=7`).then((r) => r.json());

bands.profiles gives tight, balanced and wide ranges from the token’s own volatility with the share of the last seven days inside each; sims[] backtests each against holding — fees, impermanent loss, exits, net versus hold, capital efficiency. Draw bands.histogram (hours the price spent in each bucket) behind the ranges. young: true means fewer than two days of candles: say so instead of drawing bands. For a user-drawn range call GET /lp/simulate with lower and upper.

GET /lp/positions?chain=5042&owner={wallet}&status=open — each position with valueUsd, uncollectedUsd, inRange, edgePct (distance to the nearest edge), pnlUsd and ageHours; summary for the header. GET /lp/position/{chain}/{manager}/{id} opens one with its events and a hold-instead comparison. Closed positions page with status=closed&limit=25&offset=25, newest first, and pool= keeps one pool.

Alerts: POST /lp/watch { chain, wallet } turns on out-of-range, fee-bar and drain alerts and returns a Telegram deep link; GET /lp/watch?chain=&wallet= is the inbox.

GET /lp/leaderboard?chain=5042&sort=profit&limit=48 — providers by profit (all time, or profit_7d / profit_30d), win rate, fees, EV, age, invested, monthly profit or last activity, with inclusive filters (minPositions, minWinRate, minEv, lastActiveDays, …) and the last seven days of profit per wallet for a sparkline. Wallets whose profit came from the token’s price rather than fees are left out and counted in hidden; all=1 keeps them.

GET /lp/wallet/{address}?chain=5042 is the page behind a leaderboard row: the same figures for that wallet whether it is ranked or not (summary), one row per UTC day on which a position ended with the profit and the fees that landed on it (history: draw it as bars with a running total, or as a calendar), and the pools it provided to. unscored says how many of its positions the figures leave out and why.

GET /lp/pools/{pool}/lps?chain=5042 ranks a pool’s providers by what they made there (profit, fees, positions, average age, win rate), where the pool’s topLps ranks them by how much they moved.

Overview and screener every 30 s, pool page every 30 s, positions every 60 s. All are cached server-side at those intervals, so faster polling returns the same bytes.