Parent: #877
Depends on: #878
Scope
Daily cron job that records PLOT USD price, supply, and mcap for TWAP calculation.
Logic
- Fetch PLOT USD price via
getPlotUsdPrice() (existing in lib/usd-price.ts)
- Fetch circulating supply from MCV2 Bond or Mint Club SDK
- Compute mcap = price × supply
- Insert into
pl_daily_prices (date-unique — skip if today already has an entry)
Error handling: If getPlotUsdPrice() returns null (all 3 sources failed), skip the day's snapshot — do NOT insert a zero or stale value. The TWAP calculation at campaign end uses AVG() over available days, so a missing day is better than a wrong value. Log the failure for monitoring.
Endpoint
POST /api/cron/airdrop-price
Schedule: Once/day at midnight UTC (0 0 * * *)
Auth: CRON_SECRET header
TWAP Usage
At campaign end, the final milestone is determined by the 7-day TWAP:
AVG(mcap_usd) FROM pl_daily_prices WHERE recorded_at >= (end_date - 7 days)
Files
src/app/api/cron/airdrop-price/route.ts
Acceptance Criteria
Parent: #877
Depends on: #878
Scope
Daily cron job that records PLOT USD price, supply, and mcap for TWAP calculation.
Logic
getPlotUsdPrice()(existing inlib/usd-price.ts)pl_daily_prices(date-unique — skip if today already has an entry)Error handling: If
getPlotUsdPrice()returnsnull(all 3 sources failed), skip the day's snapshot — do NOT insert a zero or stale value. The TWAP calculation at campaign end usesAVG()over available days, so a missing day is better than a wrong value. Log the failure for monitoring.Endpoint
POST /api/cron/airdrop-priceSchedule: Once/day at midnight UTC (
0 0 * * *)Auth:
CRON_SECRETheaderTWAP Usage
At campaign end, the final milestone is determined by the 7-day TWAP:
AVG(mcap_usd) FROM pl_daily_prices WHERE recorded_at >= (end_date - 7 days)Files
src/app/api/cron/airdrop-price/route.tsAcceptance Criteria
getPlotUsdPrice()(no new price source)vercel.jsoncrons (see [Airdrop P4] Weekly stats snapshot cron + vercel.json #891)