[#329] Index MCV2_Bond mint/burn trades for storyline tokens#334
[#329] Index MCV2_Bond mint/burn trades for storyline tokens#334realproject7 merged 2 commits intomainfrom
Conversation
- Migration: trade_history table with (tx_hash, log_index) uniqueness - Database types: added trade_history to Database interface - ABI: added Minted/Burned event definitions from MCV2_Bond.sol - Cron route: /api/cron/trade-history scans MCV2_Bond events for known storyline tokens only, with own cursor (id=2) and CRON_SECRET fail-closed auth - Direct indexer: /api/index/trade accepts txHash+tokenAddress, decodes mint/burn events and upserts to trade_history - TradingWidget: fire-and-forget POST to trade indexer after successful mint/burn for instant chart updates - Price per token computed as reserveAmount/tokenAmount - Total supply read at trade block number Fixes #329 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: REQUEST CHANGES
Summary
The trade-history shape is reasonable, but the cron cursor design is currently incompatible with the existing schema. As written, the new cron route cannot persist or advance its own cursor.
Findings
- [high]
trade-historycron usesbackfill_cursor.id = 2, but the existing table schema explicitly enforcescheck (id = 1).- File:
src/app/api/cron/trade-history/route.ts:11 - Suggestion: Either migrate
backfill_cursorto support multiple ids, or create a separate cursor table for trade history. Right nowinsert({ id: 2, ... })atsrc/app/api/cron/trade-history/route.ts:47and laterupdate(...).eq("id", 2)can never succeed againstsupabase/migrations/00003_backfill_cursor.sql, so the cron route will rescan from block 0 on every run and never maintain state.
- File:
Decision
Request changes. The cron data layer is not functional until its cursor storage can actually persist id = 2.
project7-interns
left a comment
There was a problem hiding this comment.
T2b APPROVE
Verified against acceptance criteria and contract source:
Migration: trade_history with unique (tx_hash, log_index) idempotency, numeric types for price precision, indexes on (token_address, block_timestamp) and storyline_id ✅
Cron: Own cursor (ID=2), verifyCron fails closed in production, loads known storyline tokens from DB and skips unknown events, block timestamp caching ✅
ABI: Minted/Burned event signatures match MCV2_Bond.sol upstream — indexed token+account, non-indexed tokenAmount+reserveAmount/refundAmount+beneficiary ✅
Price: reserveAmount / tokenAmount (both 18 decimals for WETH/PLOT reserve) with correct field per event type (reserveAmount for Minted, refundAmount for Burned) ✅
Direct indexer: Upserts with conflict handling, storyline lookup by token_address, no auth needed (write-only fire-and-forget) ✅
TradingWidget: Fire-and-forget POST after successful mint/burn, .catch(() => {}) suppresses errors ✅
Non-blocking note: cron errors increment errors count but cursor still advances past failed blocks (same pattern as original backfill before #322). Consider logging to backfill_failures for consistency if trade indexing reliability matters.
Drop check(id=1) constraint on backfill_cursor so the trade-history cron can use its own cursor row (id=2). Seeds the new row. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: APPROVE
Summary
The follow-up fixes the cursor-schema incompatibility by migrating backfill_cursor to support multiple ids and seeding the trade-history cursor row. The trade-history data layer now matches issue #329’s intended design.
Findings
- [low] The prior blocker is resolved:
backfill_cursorno longer enforcesid = 1, and the migration seedsid = 2for the trade-history cron.- File:
supabase/migrations/00017_backfill_cursor_multi.sql:1 - Suggestion: None.
- File:
Decision
Approve. The cron cursor can now persist independently, the direct indexer and migration stay within scope, and local npm run build plus npm run typecheck both pass.
Summary
trade_historytable with(tx_hash, log_index)unique constraint + indexes/api/cron/trade-history): Scans MCV2_Bond Minted/Burned events for known storyline tokens only; own cursor (id=2); CRON_SECRET fail-closed in production/api/index/trade): AcceptstxHash+tokenAddress, decodes events, upserts immediatelyMinted/Burnedevent definitions from MCV2_Bond.soltrade_historyto Database interfacePrice per token computed as
reserveAmount / tokenAmount. Total supply read at trade block number.Fixes #329
Test plan
npm run buildpassesnpm run typecheckpasses