# Ponder LM Indexing - Backend Metrics Implementation **Branch:** feat/ponder-lm-indexing **Commit:** 3ec9bfb **Date:** 2026-02-16 ## Summary Successfully implemented backend indexing for three key protocol metrics: 1. **ETH Reserve Growth (7d)** ✅ 2. **Floor Price per KRK** ✅ 3. **Trading Fees (7d)** ⚠️ Infrastructure ready, awaiting implementation ## Changes Made ### 1. Schema Updates (`ponder.schema.ts`) #### Extended `stats` Table Added fields to track new metrics: ```typescript // 7-day ETH reserve growth metrics ethReserve7dAgo: bigint (nullable) ethReserveGrowthBps: int (nullable) // basis points // 7-day trading fees earned feesEarned7dEth: bigint (default 0n) feesEarned7dKrk: bigint (default 0n) feesLastUpdated: bigint (nullable) // Floor price metrics floorTick: int (nullable) floorPriceWei: bigint (nullable) // wei per KRK currentPriceWei: bigint (nullable) floorDistanceBps: int (nullable) // distance from floor in bps ``` #### New Tables - **`ethReserveHistory`**: Tracks ETH balance over time for 7-day growth calculations - `id` (string): block_logIndex format - `timestamp` (bigint): event timestamp - `ethBalance` (bigint): ETH reserve at that time - **`feeHistory`**: Infrastructure for fee tracking (ready for Collect events) - `id` (string): block_logIndex format - `timestamp` (bigint): event timestamp - `ethFees` (bigint): ETH fees collected - `krkFees` (bigint): KRK fees collected ### 2. Handler Updates (`src/lm.ts`) #### New Helper Functions - **`priceFromTick(tick: number): bigint`** - Calculates price in wei per KRK from Uniswap V3 tick - Uses formula: `price = 1.0001^tick` - Accounts for WETH as token0 in the pool - Returns wei-denominated price for precision - **`calculateBps(newValue: bigint, oldValue: bigint): number`** - Calculates basis points difference: `(new - old) / old * 10000` - Used for growth percentages and distance metrics #### Updated Event Handlers **`EthScarcity` and `EthAbundance` Handlers:** 1. **Record ETH Reserve History** - Insert ethBalance into `ethReserveHistory` table - Enables time-series analysis 2. **Calculate 7-Day Growth** - Look back 7 days in `ethReserveHistory` - Find oldest record within window - Calculate growth in basis points - Updates: `ethReserve7dAgo`, `ethReserveGrowthBps` 3. **Calculate Floor Price** - Uses `vwapTick` from event as floor tick - Converts to wei per KRK using `priceFromTick()` - Updates: `floorTick`, `floorPriceWei` 4. **Calculate Current Price** - Uses `currentTick` from event - Converts to wei per KRK - Updates: `currentPriceWei` 5. **Calculate Floor Distance** - Computes distance from floor in basis points - Formula: `(currentPrice - floorPrice) / floorPrice * 10000` - Updates: `floorDistanceBps` **`Recentered` Handler:** - Cleaned up: removed direct ETH balance reading - Now relies on EthScarcity/EthAbundance events for balance data - Maintains counter updates for recenter tracking ## Fee Tracking Status ### Current State: Infrastructure Ready ⚠️ The fee tracking infrastructure is in place but **not yet populated** with data: - `feeHistory` table exists in schema - `feesEarned7dEth` and `feesEarned7dKrk` fields default to `0n` - `feesLastUpdated` field available ### Implementation Options Documented two approaches in code: #### Option 1: Uniswap V3 Pool Collect Events (Recommended) **Pros:** - Accurate fee data directly from pool - Clean separation of concerns **Cons:** - Requires adding UniswapV3Pool contract to `ponder.config.ts` - **Forces a full re-sync from startBlock** (significant downtime) **Implementation Steps:** 1. Add pool contract to `ponder.config.ts`: ```typescript UniswapV3Pool: { abi: UniswapV3PoolAbi, chain: NETWORK, address: '', startBlock: selectedNetwork.contracts.startBlock, } ``` 2. Add handler for `Collect(address owner, int24 tickLower, int24 tickUpper, uint128 amount0, uint128 amount1)` 3. Filter for LM contract as owner 4. Record to `feeHistory` table 5. Calculate 7-day rolling totals #### Option 2: Derive from ETH Balance Changes **Pros:** - No config changes needed - No resync required **Cons:** - Less accurate (hard to isolate fees from other balance changes) - More complex logic - Potential edge cases ### Recommendation **Wait for next planned resync** or **maintenance window** to implement Option 1 (Collect events). This provides the most accurate and maintainable solution. ## Verification All success criteria met: ✅ **Schema compiles** (valid TypeScript) ```bash npm run build # ✓ Wrote ponder-env.d.ts ``` ✅ **New fields added to stats** - ethReserve7dAgo, ethReserveGrowthBps - feesEarned7dEth, feesEarned7dKrk, feesLastUpdated - floorTick, floorPriceWei, currentPriceWei, floorDistanceBps ✅ **EthScarcity/EthAbundance handlers updated** - Record history to `ethReserveHistory` - Calculate 7-day growth - Calculate floor and current prices - Calculate floor distance ✅ **Fee tracking infrastructure** - `feeHistory` table created - Fee fields in stats table - Documentation for implementation approaches ✅ **Git commit with --no-verify** ```bash git log -1 --oneline # 3ec9bfb feat(ponder): add ETH reserve growth, floor price, and fee tracking metrics ``` ✅ **Linting passes** ```bash npm run lint # (no errors) ``` ## Testing Recommendations 1. **Deploy to staging** and verify: - `ethReserveHistory` table populates on Scarcity/Abundance events - 7-day growth calculates correctly after 7 days of data - Floor price calculations match expected values - Current price tracks tick movements 2. **API Integration:** - Query `stats` table for dashboard metrics - Use `ethReserveHistory` for time-series charts - Monitor for null values in first 7 days (expected) 3. **Future Fee Implementation:** - Plan maintenance window for resync - Test Collect event handler on local fork first - Verify fee calculations match pool data ## Technical Notes ### Price Calculation Details - **Formula:** `price = 1.0001^tick` - **Token Order:** WETH (0x4200...0006) < KRK (0xff196f...) → WETH is token0 - **Conversion:** Price in KRK/WETH → invert to get wei per KRK - **Precision:** Uses `BigInt` for wei-level accuracy, floating point only for tick math ### 7-Day Lookback Strategy - **Simple approach:** Query `ethReserveHistory` for oldest record ≥ 7 days ago - **Performance:** Acceptable given low event volume (~50-200 recenters/week) - **Edge case:** Returns `null` if less than 7 days of history exists ### Data Consistency - Both EthScarcity and EthAbundance handlers implement identical logic - Ensures consistent metrics regardless of recenter direction - History records use `block_logIndex` format for unique IDs ## Files Modified - `/home/debian/harb/services/ponder/ponder.schema.ts` (+50 lines) - `/home/debian/harb/services/ponder/src/lm.ts` (+139 lines, -32 lines) **Total:** +157 lines, comprehensive implementation with documentation. --- **Status:** ✅ Ready for staging deployment **Next Steps:** Monitor metrics in staging, plan fee implementation during next maintenance window