Your DeFi Risk Console
A React + Vite dashboard that tracks Aave loans, Morpho Blue market positions, Morpho Midnight fixed-rate loans, and Morpho vault deposits from a wallet address and computes portfolio and risk metrics.
- Use a single wallet address as input.
- Fetch live position data from public blockchain indexers.
- Show all detected Aave loans and Morpho positions for a wallet.
- Compute practical monitoring metrics (HF, LTV, liquidation, leverage, carry/net APY).
- Notify of meaningful changes to health factors via Telegram bot, grouped into one message per wallet when multiple loans alert in the same poll
- Partial auto-repay bot maintains loan within a target HF range
- Wallet-only input UX.
- Wallet details auto-fetch on load when valid.
- Last successfully loaded wallet is saved in browser
localStorageand auto-used on reload when query params are absent. - The summary card eye toggle can blur sensitive dashboard values, including top-level totals, position balances, vault amounts, USD metrics, and monetary history charts. The privacy preference is saved in browser
localStorage. - Manual
Refreshbutton to reload the current dashboard data on demand. - Automatic refresh every 120 seconds after a wallet is loaded.
- Multi-market support:
- Aave V3:
proto_mainnet_v3,proto_lido_v3 - Morpho Blue: isolated markets (fetched from Morpho GraphQL API)
- Morpho Midnight: fixed-rate, fixed-term borrow positions (fetched from the Morpho Midnight REST API), shown as
midnight_<COLLATERAL>_<LOAN>_<maturity date>. Debt is the amount owed at maturity, which is what Midnight's liquidation check uses, so HF and liquidation prices match the protocol. Accrued interest spreads the fixed interest (amount owed at maturity minus the principal received) in equal daily amounts from position open to maturity. Lend positions are not shown, and the watchdog does not rescue Midnight loans. - Morpho Vaults: vault deposits such as
Steakhouse Reservoir USDC
- Aave V3:
- Support for multiple loans/borrowed assets plus supply-only vault deposits.
- Top-level portfolio metrics roll up all detected positions:
- Loan-risk metrics stay loan-only (average health factor, borrow power used, repay coverage)
- Asset/carry metrics include Morpho vault deposits (total assets, net worth, supply APY, net earnings, estimated daily net earnings, net APY)
- Morpho Blue market collateral is treated as risk collateral only and does not earn the market supply APY
- Hover or focus any top-level metric to see a one-sentence calculation note.
- Fully paid-off / dust positions with effectively zero USD exposure are filtered out.
- Portfolio average HF color bands:
HF > 2.2: normal operation (green)HF 1.8–2.2: no new leverage, monitor closelyHF 1.5–1.8: reduce debt or add collateralHF < 1.5: mandatory deleveraging (red)
- Auto-fetched collateral/borrow amounts and market metadata.
- Price enrichment with CoinGecko, including symbol aliases for wrapped assets such as
cbBTC. - Dashboard analytics:
- Health Factor liquidation price
- Liquidation price (primary-collateral approximation)
- LTV, leverage, borrow headroom
- Carry / Net APY summary, including loan net earnings offset by Morpho vault net income and gross annual borrow cost
- Top portfolio card
Accrued interestmetric that sums all outstanding loans'Accrued Int.values when upstream APIs provide them - Loan table
Accrued Int.column for borrowed positions when provided by the upstream protocol API (currently populated for Morpho Blue positions when available, and for Morpho Midnight positions) - Separate Morpho vault table with deposited asset amount, USD value, net APY, and shares
- Aave interest-rate model chart for the selected borrowed asset, including current utilization and the reserve kink
- Borrow APR history chart for the selected borrowed asset, tracked server-side with 180-day retention
- Top-level portfolio history tabs for asset/debt snapshots, debt-weighted Borrow APR history with a 7-day moving average, and combined daily borrow interest with a 7-day moving average across all open loan positions
- Repay coverage based on wallet balances that match borrowed assets
- Monitoring checklist + sensitivity cards
- React 19
- TypeScript
- Vite
- Tailwind CSS
- shadcn/ui-style components
- Lucide icons
- Node.js 18+
- Yarn (classic)
Create .env in project root.
# Required for reliable multi-market Graph access (especially proto_lido_v3)
VITE_THE_GRAPH_API_KEY=your_the_graph_api_key
# Optional but recommended to avoid CoinGecko rate limits
VITE_COINGECKO_API_KEY=your_coingecko_demo_api_keyNotes:
- Without
VITE_THE_GRAPH_API_KEY, some markets may fail to load depending on endpoint availability. - CoinGecko pricing still works without
VITE_COINGECKO_API_KEY, but may be rate-limited.
- Install dependencies:
yarn install --frozen-lockfile-
Add
.env(see above). -
Start development server:
yarn dev- Optional but recommended for the utilization curve, borrow APR history, wallet balance lookups, and alert settings API:
yarn dev:server-
Open the local URL shown by Vite (usually
http://localhost:5173). -
Optional: prefill wallet from query string:
http://localhost:5173/?wallet=0xYourEthereumAddress
Supported query params: wallet, address, walletAddress.
If no supported query param is provided, the app falls back to the last wallet saved in browser storage.
yarn dev # start frontend dev server
yarn dev:server # start backend monitor server
yarn dev:all # start both frontend and server
yarn typecheck # TypeScript checks (frontend + core package + server package)
yarn lint # ESLint
yarn format # Prettier format
yarn test # Server watchdog/config test suite
yarn test:contracts # Foundry smart contract tests (packages/rescue-contract)
yarn build # production frontend build
yarn build:server # production server build (includes @aave-monitor/core via TS project references)
yarn preview # preview production buildServer test suite details:
- Location:
packages/server/test/*.test.ts - Runner: Node built-in test runner via
tsx --test - Current coverage focus: watchdog execution/cooldown behavior, watchdog config migration/merge logic, and Telegram command sync behavior
packages/serverusestsconfig.typecheck.jsonfor CI/local typechecks so@aave-monitor/coreresolves from source without requiring a prebuiltdist/
Run the unified app (dashboard UI + API server) with:
docker compose up --buildThe app is available at http://localhost:3001 (both UI and API served from the same Express server).
Notes:
- Server runtime env vars (for example
TELEGRAM_BOT_TOKEN) are loaded from the root.envviaenv_file.
This project is configured to deploy automatically to GitHub Pages from main using GitHub Actions.
Files involved:
.github/workflows/deploy-pages.ymlvite.config.ts(usesVITE_BASE_PATHso asset URLs work under/<repo>/)
Setup steps:
- Push this repo to GitHub.
- In GitHub, open
Settings -> Pages. - Set
SourcetoGitHub Actions. - Add repository secrets (if needed) in
Settings -> Secrets and variables -> Actions:VITE_THE_GRAPH_API_KEY(recommended/usually required)VITE_COINGECKO_API_KEY(optional)
After each push to main, the workflow builds the app and publishes dist to GitHub Pages.
A backend monitoring service can poll your positions and send Telegram alerts when health factor zones change (e.g. Safe → Comfort → Watch → Alert → Action → Critical). When multiple loans for the same wallet trigger during a poll, they are grouped into one Telegram message instead of being sent separately. See docs/telegram-setup.md for full setup instructions.
On server startup, Telegram command metadata is synced with setMyCommands, so the in-app slash-command menu matches the backend command handlers.
The Telegram /status command includes a loan-focused portfolio summary with average health factor, Net APY, total collateral, total debt, portfolio borrow power used, and repay coverage (USD and %), plus each loan's current borrow rate and utilization percentage.
Loan-specific Telegram alerts, reminders, recoveries, all-clear messages, and watchdog notices include the current borrow rate percentage for that loan.
Watchdog dry-run/live notices and action logs include the authoritative projected HF from the rescue contract preview.
Each /status loan row uses the human-readable market name, so Morpho positions display labels like morpho_cbBTC_USDC instead of raw market IDs.
The /status footer shows Last updated with both an absolute timestamp and relative time (e.g. 3 minutes ago).
Reminder alerts include a human-readable elapsed duration label (e.g. 2h 40m ago).
Paid-off / zero-value positions are excluded from both dashboard and Telegram status output.
Legacy configs that only persisted five zones are automatically hydrated back to the default six-zone model (safe, comfort, watch, alert, action, critical) when loaded.
Quick start:
- Create a Telegram bot via @BotFather and get the bot token.
- Add
TELEGRAM_BOT_TOKEN=<your token>to the project root.env. - Run
yarn dev:serverto start the monitor. - Use the bell icon in the dashboard to configure alerts.
- If monitor status appears stale, trigger an immediate refresh with
POST /api/status/refresh(see docs).
Detailed user manual: docs/watchdog-user-manual.md.
Deployment/ops runbook: docs/rescue-v1-ops.md.
The watchdog monitors loan health and can execute an atomic on-chain rescue when HF drops below threshold. It computes a debt repay amount and submits a single rescue(...) transaction to the rescue contract, which repays the loan's borrowed stablecoin (e.g. USDC/USDT) from the wallet. It can also run an optional layer-0 pre-rescue step that withdraws debt-token liquidity from a configured Morpho ERC-4626 vault into the monitored wallet before the layer-1 rescue threshold is crossed.
- Runs after each monitor poll, evaluating all loans
- Monitor polling runs when at least one wallet is enabled (Telegram can stay disabled)
- Dry-run mode by default (notifies what would happen, no on-chain transactions)
- Live mode requires
WATCHDOG_EXECUTOR_PRIVATE_KEYon the server (WATCHDOG_PRIVATE_KEYstill works as a fallback alias) - Live mode requires allowance for the debt token (e.g. USDC) to be pulled by the rescue contract
- For Morpho Blue deploys, generate exact
MORPHO_*market env vars from a market URL or unique key withyarn morpho:market-env <market-url-or-unique-key>to avoid loan/collateral/oracle/IRM mismatches. - A single Morpho rescue contract can support multiple Morpho markets for the same monitored wallet/executor pair. Enable each supported market on-chain with
setSupportedMarket(...), typically from Etherscan Write Contract signed by the owner wallet. - Optional pre-rescue uses
MorphoVaultWithdrawV1: enable each supported Morpho vault withsetSupportedVault(...), approve vault shares from the monitored wallet tovaultWithdrawContract, and configurepreRescueTriggerHF > triggerHF. - Pre-rescue vault withdrawals use a hardcoded 500 debt-token minimum plus a 500 debt-token buffer over the exact wallet shortfall, so the watchdog avoids submitting dust-sized vault withdrawals.
- API:
GET /api/watchdog/statusfor status and recent action log - Telegram:
/watchdogcommand for status and recent actions - Config: watchdog and utilization sections in
GET/PUT /api/config - Dashboard UI: bell settings panel includes rescue contracts, HF thresholds, rescue-asset cap, deadline, gas cap, and pre-rescue vault withdrawal settings
- User enters an Ethereum wallet address, provides it via query string (
wallet,address, orwalletAddress), or reloads with the last saved wallet from browser storage. - App queries Aave subgraph data for supported markets.
- Aave reserves are grouped into loan positions per market; Morpho market loans and Morpho vault deposits are fetched from Morpho's GraphQL API, and Morpho Midnight fixed-rate loans from
https://api.morpho.org/v0/midnight. - Token prices are fetched from CoinGecko for Aave assets, while Morpho positions use API-provided pricing or USD back-calculation for borrowed assets and vault deposits. Morpho market borrow/supply rates are aligned to Morpho's interface default 1-day average APY by preferring Morpho's
avgBorrowApy/avgSupplyApyfields instead of the instantaneous spot rate. - Portfolio-level aggregate metrics are computed across all active positions, with loan-risk metrics kept separate from supply-only vault assets.
- Detailed risk metrics are computed and rendered for the selected loan, while Morpho vaults render in a separate table.
- The backend monitor records borrow/supply rate samples to a SQLite database (
packages/server/data/rates.db) every 15 minutes during its poll cycle. The dashboard fetches rate history from the/api/rates/historyendpoint, including the top-level combined Borrow APR tab that debt-weights samples across all open loan positions and overlays a trailing 7-day simple moving average; it falls back to browserlocalStoragewhen the backend has no data yet. Morpho borrow interest snapshots are served from/api/interest/historyand aggregated into the top-level Daily Interest tab with a trailing 7-day simple moving average.
- Liquidation price is shown as a primary-collateral approximation for multi-collateral positions.
- Coverage depends on the supported market list and indexer availability.
- Metrics are simplified monitoring estimates, not a substitute for protocol-native risk engines.
- Borrow APR and daily borrow-interest history are forward-looking: the server begins recording from the first poll after deployment, so newly monitored wallets start with empty charts.
- GitHub Pages deployments require proper repository secrets if API keys are needed at build time.