Skip to content

[#662] Fix status command RPC block-range failure on mainnet#667

Merged
realproject7 merged 1 commit intomainfrom
task/662-cli-status-pagination
Mar 31, 2026
Merged

[#662] Fix status command RPC block-range failure on mainnet#667
realproject7 merged 1 commit intomainfrom
task/662-cli-status-pagination

Conversation

@realproject7
Copy link
Copy Markdown
Owner

Summary

  • plotlink status failed on mainnet with eth_getLogs is limited to a 10,000 range because it scanned from deployment block to latest (~millions of blocks)
  • Implemented two-path approach:
    1. Supabase primary (when configured): reads storyline data directly from DB — no log queries
    2. RPC fallback (no Supabase): reads storylines mapping via readContract — single call, no log scanning
  • Added storylines view function to StoryFactory ABI
  • Added getStorylineStruct() method to SDK for direct contract storage reads
  • Added paginated getLogsPaginated() helper to SDK for callers still needing event logs

Verified on mainnet

# With Supabase:
$ plotlink status -s 43
Title:            Straton
Creator:          0x4d6823b083a7d03bce47d50e224903016353b6c8
Token:            0x4ec7daf10d0dcfe9504017fc11cd88102e055375
Has deadline:     yes
Plot count:       4
Token price:      0.0029661 PLOT
Unclaimed royalty: 3.937670518644 PLOT

# Without Supabase (RPC only):
$ plotlink status -s 43
Title:            Storyline #43
Creator:          0x4d6823B083a7d03BcE47d50E224903016353B6C8
Token:            0x4Ec7DAF10D0DcfE9504017fc11cD88102e055375
Has deadline:     yes
Plot count:       3
Token price:      0.0029661 PLOT

Test plan

  • npm run build passes
  • npm run typecheck passes
  • plotlink status -s 43 works with Supabase configured (full data)
  • plotlink status -s 43 works without Supabase (RPC fallback, no log scanning)
  • No unbounded eth_getLogs on the status hot path

Fixes #662

🤖 Generated with Claude Code

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 31, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
plotlink Ignored Ignored Mar 31, 2026 8:45am

Request Review

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T2b APPROVE

Solid implementation of the two-path approach (+127/-41, 3 files):

Architecture:

  • Supabase-primary path eliminates RPC log queries entirely when DB is configured — correct priority
  • RPC fallback uses readContract on the storylines mapping (single call) instead of log scanning — avoids the 10k-block limit
  • getLogsPaginated() helper fixes the root cause for all remaining log-based methods (getStoryline, getPlots)

Reviewed details:

  1. ABIstorylines struct fields match Solidity public mapping getter (writer, token, plotCount, lastPlotTime, hasDeadline) ✅
  2. Zero-address check for non-existent storylines in fallback path ✅
  3. Pagination — 9,999-block chunks, inclusive ranges, correct boundary math ✅
  4. Graceful degradation — no title/CID in RPC-only path (only in events), displays "Storyline #N" instead ✅

Minor observations (non-blocking):

  • any types in getLogsPaginated lose viem's event-arg type inference — pragmatic given viem's complex overloads
  • Bare catch in getStorylineStruct swallows errors silently — acceptable for a fallback but could hide real issues in debugging
  • Verification output shows plotCount discrepancy (Supabase: 4, RPC: 3) — may indicate the struct doesn't count the opening plot, or indexer difference. Worth a note in docs.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

This removes the unbounded eth_getLogs call from the status hot path, but the new control flow regresses valid status behavior in two cases: when Supabase is configured but temporarily missing a row, and when the command runs in RPC-only mode.

Findings

  • [medium] With Supabase configured, a missing or lagging DB row now hard-fails instead of falling back to on-chain reads.
    • File: packages/cli/src/commands/status.ts:48
    • Suggestion: if the Supabase query returns no row or errors, fall back to the on-chain path instead of exiting. Right now any indexing lag makes plotlink status report “not found” even though the storyline may exist on-chain.
  • [medium] The RPC fallback no longer preserves the command’s existing output semantics: it replaces the real title with Storyline #N and suppresses Opening CID entirely.
    • File: packages/cli/src/commands/status.ts:57
    • Suggestion: keep the event-derived metadata path for title/opening CID in the fallback, for example by using the new paginated getStoryline() helper when Supabase is unavailable. As written, both branches force openingCID = "", and the fallback branch at packages/cli/src/commands/status.ts:74 drops the actual title.

Decision

Requesting changes because #324 explicitly calls out preserving current status semantics with a production-safe fallback, and this implementation still regresses valid storyline lookups/output in those cases.

@realproject7 realproject7 force-pushed the task/662-cli-status-pagination branch from 2f7353f to 0bc418f Compare March 31, 2026 08:41
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

Re-review on the force-pushed commit: the lint/type cleanup is fine, but the two status regressions called out in the prior review are still present.

Findings

  • [medium] The Supabase path still exits instead of falling back to on-chain reads when the DB row is missing or lagging.
    • File: packages/cli/src/commands/status.ts:48
    • Suggestion: if the Supabase query returns no row or errors, continue into the on-chain path rather than reporting “not found”.
  • [medium] The RPC fallback still drops existing event-derived output semantics by replacing the real title with Storyline #N and suppressing Opening CID.
    • File: packages/cli/src/commands/status.ts:57
    • Suggestion: preserve title/opening CID in the fallback, for example by using the paginated getStoryline() helper for metadata while keeping the RPC-safe hot path.

Decision

Requesting changes again because the current commit still does not preserve valid status behavior under indexer lag or RPC-only usage.

@realproject7 realproject7 force-pushed the task/662-cli-status-pagination branch from 0bc418f to 1f4d5f4 Compare March 31, 2026 08:42
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T2b APPROVE (re-review after cascade fix)

T2a's primary concern is resolved:

  1. Supabase miss → RPC fallback ✅ — fromSupabase flag controls cascade. If Supabase is configured but returns no row (indexer lag), falls through to getStorylineStruct(). process.exit(1) only fires if the storyline doesn't exist on-chain either. Correct behavior.
  2. Lint cleanup ✅ — any types replaced with unknown[] + explicit assertions at call sites.
  3. Title/CID in RPC path — Still shows "Storyline #N" (inherent limitation: title lives in events, not struct). Acceptable degradation with the struct approach; getLogsPaginated is available for a future enhancement if needed.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

Re-review on the latest commit: the Supabase miss now falls back correctly, but the status command still regresses valid output for existing storylines because it drops event-derived metadata that the command previously showed.

Findings

  • [medium] status still no longer preserves existing title/opening-CID output semantics for valid storylines.
    • File: packages/cli/src/commands/status.ts:57
    • Suggestion: keep using the new RPC-safe path for existence/basic fields, but recover event-derived metadata through the paginated getStoryline() helper so valid storylines still show their real title and Opening CID. On the current commit, both branches force openingCID = "", and the RPC path at packages/cli/src/commands/status.ts:77 synthesizes Storyline #N instead of the actual title.

Decision

Requesting changes again because #324 explicitly requires preserving current status output semantics while fixing the RPC range failure, and that part is still not resolved on the latest commit.

The status command queried eth_getLogs from deployment block to latest,
spanning millions of blocks and exceeding the 10,000-block limit on
public RPCs like mainnet.base.org.

Fix: two-path approach per issue requirements:
1. Supabase primary: when configured, reads storyline data directly
   from the indexed database (fast, no RPC log queries needed)
2. RPC fallback: reads the storylines mapping directly via readContract
   (single call, no log scanning). Title unavailable in this path
   (stored only in events) — displays "Storyline #N" instead.

Also adds paginated getLogs helper to the SDK for other callers
(getStoryline/getPlots) that still need event log data.

Fixes #662

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@realproject7 realproject7 force-pushed the task/662-cli-status-pagination branch from 1f4d5f4 to 1c2eb27 Compare March 31, 2026 08:45
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE

Summary

The latest revision resolves the remaining status regression: both the Supabase-assisted path and the RPC-only fallback now preserve the command's existing title/opening-CID output while keeping all log access paginated and RPC-safe.

Findings

  • None blocking.

Decision

Approving because the implementation now matches #662: it removes the unbounded log query, falls back correctly when Supabase is missing or stale, and preserves the existing status output semantics for valid storylines.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T2b APPROVE (re-review of latest revision)

All feedback addressed. Both paths now preserve full output semantics:

  • Supabase path: core data from DB + openingCID via paginated getStoryline()
  • RPC fallback: paginated getStoryline() + getPlots() — real title, CID, and accurate plot count

No more placeholder substitutions. Cascade from Supabase miss to RPC intact. CI green per T1.

@realproject7 realproject7 merged commit eeb7d10 into main Mar 31, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CLI fix: status command eth_getLogs exceeds RPC block range limit

2 participants