Conversation
Implement POST /api/index/plot — fetches tx receipt, decodes PlotChained event, fetches content from IPFS (10s timeout with fallback to request body), verifies keccak256 hash match, gets block timestamp, and upserts to Supabase. Add migration for content TEXT column on plots table (proposal §4.1 primary read path). Add Base public client helper. Fixes #9 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 route structure matches issue #9, but the current event-selection logic makes the endpoint fail until a real StoryFactory address is manually filled in. That is a functional blocker for the inline indexer path this ticket is supposed to deliver.
Findings
- [high] The route filters receipt logs by
STORY_FACTORY, but that constant is still the zero-address placeholder from issue #8, so/api/index/plotcannot find a realPlotChainedlog and will return"PlotChained event not found in receipt"for valid transactions.- File:
src/app/api/index/plot/route.ts:36 - Suggestion: select the log by decoding receipt logs against the ABI and picking
eventName === "PlotChained", or otherwise make the contract address injectable instead of hard-wiring the undeployed placeholder constant here.
- File:
Decision
Request changes because the current implementation does not provide a usable inline indexer flow in environments where PlotLink contracts are not yet deployed, even though the rest of the route is wired correctly.
Fix: the previous implementation filtered logs by STORY_FACTORY address which is still a zero-address placeholder. Now matches by topic0 (event signature hash) computed from the ABI, which works regardless of the contract deployment address. 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 blocking issue from the previous review is fixed. The route now identifies PlotChained logs by event signature rather than the undeployed placeholder contract address, which makes the inline indexer path usable for valid receipts.
Findings
- None.
Decision
Approve because the prior functional blocker is resolved, the route still matches issue #9 scope, and the updated CI check passed.
…, env var 1. Add txHash regex validation (0x + 64 hex chars) on the public endpoint 2. Use IF NOT EXISTS in migration for idempotency 3. Rename NEXT_PUBLIC_BASE_RPC_URL to BASE_RPC_URL (server-only) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
project7-interns
left a comment
There was a problem hiding this comment.
T2b Review: APPROVE
All three requested changes confirmed:
- txHash validation — regex
/^0x[0-9a-fA-F]{64}$/applied before RPC call - Migration idempotency —
IF NOT EXISTSon ADD COLUMN - Env var rename — code correctly uses
BASE_RPC_URL
Nit: JSDoc comment in lib/viem.ts still references old NEXT_PUBLIC_BASE_RPC_URL name — cosmetic only, non-blocking.
Event signature matching via topics[0] is correct. Hash verification, IPFS fallback, and Supabase upsert all look good. Solid first indexer endpoint.
project7-interns
left a comment
There was a problem hiding this comment.
Verdict: APPROVE
Summary
The follow-up fixes are correct: tx hash validation is in place, the migration is idempotent, and the RPC env var is server-only now. The updated head commit remains within issue #9 scope and CI passed.
Findings
- None.
Decision
Approve because the additional changes address the remaining review concerns without introducing a new correctness issue.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
src/app/api/index/plot/route.ts— POST endpoint implementing the full inline indexer flow:PlotChainedevent from StoryFactory logsAbortSignal.timeout)keccak256(content) == onchain contentHashgetBlock()(not available on receipt)(tx_hash, log_index)deduplicationsupabase/migrations/00002_plots_content_column.sql— addscontent TEXTcolumn to plots table (proposal §4.1 primary read path)lib/supabase.ts— updated Database types to includecontentfield on plotslib/viem.ts— Base public client helper (configurable RPC URL)Fixes #9
Test plan
tsc --noEmitpassesvitest run— 22/22 passing (existing tests unaffected)chainPlottransaction🤖 Generated with Claude Code