This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
yarn dev # start Vite dev server (localhost:5173)
yarn build # tsc -b && vite build (production)
yarn preview # preview production build
yarn typecheck # frontend + backend workspace TypeScript checks
yarn lint # eslint
yarn format # prettier --write
yarn format:check # prettier --check
yarn test # server watchdog/config tests (node:test via tsx)Always run typecheck, lint, and format before finishing changes. Also make sure you check
instructions in AGENTS.md if you haven't already.
Configured via .env in project root (prefixed with VITE_ for Vite exposure):
VITE_THE_GRAPH_API_KEY— required for multi-market subgraph accessVITE_COINGECKO_API_KEY— optional, avoids CoinGecko rate limitsVITE_R_DEPLOY— optional deploy APY rate (decimal, default 0.1125)VITE_BASE_PATH— used in vite.config.ts for GitHub Pages deploymentRPC_URL— Ethereum JSON-RPC endpoint used by backend for on-chain reads (defaulthttps://eth.llamarpc.com)WATCHDOG_PRIVATE_KEY— optional private key for watchdog live mode (atomic rescue); omit for dry-run onlyWATCHDOG_MIN_RESULTING_HF— optional override for minimum required post-rescue HFWATCHDOG_MAX_TOP_UP_WBTC— optional override for max WBTC top-up per rescue actionWATCHDOG_DEADLINE_SECONDS— optional override for rescue transaction deadline in secondsWATCHDOG_RESCUE_CONTRACT— optional override for rescue contract addressTELEGRAM_BOT_TOKEN— backend Telegram bot token (loaded from root.env)PORT— optional backend port (default3001)
Backend server notes:
packages/serverauto-loads the root.envon startup.packages/serveruses a TypeScript project reference topackages/aave-core;yarn workspace @aave-monitor/server buildbuilds the referenced core package first and consumes its emitted declarations instead of importing core source files directly.packages/servertypechecks throughpackages/server/tsconfig.typecheck.json, which resolves@aave-monitor/coreto source for CI/local checks without requiringpackages/aave-core/distto exist first.- Backend Graph/CoinGecko keys are read from
VITE_THE_GRAPH_API_KEYandVITE_COINGECKO_API_KEY(legacy non-VITE_names still work as fallback). POST /api/status/refreshforces an immediate monitor recomputation and returns fresh/api/statuspayload.GET /api/reserves/telemetry?market=<market>&asset=<address>&symbol=<optional>returns live on-chain reserve utilization and interest-rate-strategy parameters for the selected borrowed asset.- Telegram
/statusincludes portfolio average health factor, Net APY, total collateral, total debt, portfolio borrow power used, and collateral margin of safety (USD and %) alongside per-loan health factors. Telegram alerts include per-asset liquidation prices for each collateral asset. - Telegram
/statusincludesLast updatedwith absolute timestamp + relative time (e.g.3 minutes ago). - Telegram command metadata (
/status,/refresh,/watchdog,/help) is synced on server startup viasetMyCommands, so Telegram slash-command suggestions stay current. - Reminder alerts include a human-readable elapsed duration label (e.g.
2h 40m ago). - Fully paid-off / zero-value positions are filtered out of both dashboard data and Telegram status output.
- Watchdog user-facing docs live in
docs/watchdog-user-manual.md. - Watchdog uses an atomic on-chain rescue path: it computes required WBTC collateral top-up off-chain and submits a single
rescue(...)transaction to the configured rescue contract. - Watchdog is fully wired: monitor integration,
GET /api/watchdog/statusendpoint,/watchdogTelegram command, config viaGET/PUT /api/config, and dashboard settings controls for watchdog fields. zones[].maxHFaccepts JSONnullonPUT /api/configand is normalized toInfinity(important because JSON serialization turnsInfinityintonull).- Legacy configs that omit one or more zones are hydrated back to the full default six-zone set by name, so runtime,
/api/config, and the dashboard stay aligned. - Monitor runtime is driven by enabled wallets (not Telegram enablement), so watchdog polling can run without Telegram configured.
Frontend notes:
src/App.tsxstores the last successfully loaded wallet underlocalStorage['aave-monitor:last-wallet'].src/App.tsxalso stores borrow APR history per market/asset in browserlocalStorageunder theaave-monitor:borrow-apr-history:*prefix.- On page load, wallet resolution order is: query string (
wallet,address,walletAddress) first, then saved local storage wallet. - The portfolio card labeled
Collateral margin of safetyis based on wallet-held balances of tokens that also appear in the loan's supplied collateral set; it does not include unrelated wallet assets. - The utilization curve and borrow APR history charts depend on the Express API server for on-chain reserve telemetry. Without
yarn dev:server(or the unified Docker/server runtime), those charts fall back to an unavailable message.
This is a single-page React 19 + TypeScript + Vite app. Nearly all application logic lives in src/App.tsx (~1000 lines), which is a single large component containing:
- Type definitions —
RawUserReserve,AssetPosition,LoanPosition,FetchState - Data fetching — queries Aave subgraph (The Graph) for user reserves across supported markets (
proto_mainnet_v3,proto_lido_v3), fetches token prices from CoinGecko - Loan grouping — raw reserves are grouped into
LoanPositionobjects per borrowed asset per market - Metric computation — health factor, LTV, liquidation price, leverage, borrow headroom, carry/net APY, all computed inline
- Rendering — portfolio-level aggregates, tabbed per-loan details, sensitivity cards, monitoring checklist
Supporting files:
src/main.tsx— React entry pointsrc/styles.css— Tailwind CSS importssrc/components/ui/— shadcn/ui-style primitives (Button, Card, Badge, Input, Separator)src/lib/utils.ts—cn()utility (clsx + tailwind-merge)
Testing currently exists for backend watchdog/config behavior in packages/server/test/*.test.ts and runs with yarn test. There is still no routing, no state management library, and no API abstraction layer. The app is self-contained with external data coming from The Graph and CoinGecko APIs.
- GitHub Pages: automated via
.github/workflows/deploy-pages.ymlon push tomain - Docker Compose:
docker compose up --buildstarts the unified app onhttp://localhost:3001 - Docker: single unified image where Express serves both API and frontend static files
- hl:
git push production masterdeploys via hl with Procfile (web: node dist/index.js)