Skip to content

fix: source round length and lock state on-chain in the round tracker#735

Merged
rickstaa merged 3 commits into
mainfrom
fix/round-status-onchain
Jul 21, 2026
Merged

fix: source round length and lock state on-chain in the round tracker#735
rickstaa merged 3 commits into
mainfrom
fix/round-status-onchain

Conversation

@rickstaa

@rickstaa rickstaa commented Jul 21, 2026

Copy link
Copy Markdown
Member

Summary

Follow-up to #731. That PR moved the round timing (round id, start block, current block, initialized) to the RoundsManager contract, but RoundStatus still read roundLength and the lock state from the subgraph — so the tracker remained a mixed source.

This finishes the job: the round tracker is now sourced entirely from one on-chain snapshot.

What changed

  • /api/current-round now also returns roundLength (RoundsManager.roundLength) and locked (RoundsManager.currentRoundLocked), alongside the existing timing reads, in the same cached call (s-maxage=60).
  • RoundStatus reads roundLength and locked from useCurrentRoundData instead of protocol:
    • isRoundLocked now comes straight from currentRoundLocked() rather than re-deriving blocksRemaining <= lockPeriod client-side. The subgraph had to store lockPeriod and defer the comparison to the client because, being event-driven, it can't keep a per-block boolean fresh; reading the getter directly removes that indirection and is authoritative.
    • The progress ring, "blocks remaining", and lock badge are now fully on-chain and consistent (single snapshot, no cross-source skew at round boundaries).
  • The spinner now only waits on the on-chain round data, so the tracker still renders during a full subgraph outage. The subgraph-only stat rows (Fees, Rewards, Total Supply, Supply Change) are hidden in that case; when the subgraph is merely behind (present but stale) everything renders as before.

Notes

  • Behavior/refresh cadence is unchanged: same s-maxage=60 endpoint, polled every 10s by SWR. locked and the round timing now refresh from the same atomic snapshot.
  • Aggregations that have no cheap on-chain equivalent (fees volume, rewards claimed, supply change) intentionally stay on the subgraph.

Testing

  • pnpm typecheck + pnpm lint pass; pre-commit hooks pass.

Summary by CodeRabbit

  • New Features

    • Round status now displays lock state and round length using the latest round information.
    • Progress indicators and remaining-block counts are more accurate.
  • Bug Fixes

    • Round status can load and display available information even when protocol details are temporarily unavailable.
    • Fee, reward, and supply details are safely hidden until the required protocol information is ready.

RoundStatus still mixed sources after #731: round timing came from the
RoundsManager via /current-round, but roundLength and the lock state came from
the subgraph (protocol.roundLength / protocol.lockPeriod). The lock state was
re-derived client-side (blocksRemaining <= lockPeriod) because the subgraph,
being event-driven, can't keep a per-block boolean fresh.

Extend /api/current-round to also return roundLength and locked (from
RoundsManager.roundLength and currentRoundLocked), and read both from
useCurrentRoundData. The lock state now comes straight from currentRoundLocked
— one authoritative snapshot instead of re-deriving it — and the round tracker
(ring, blocks remaining, lock badge) is fully on-chain and consistent.

The spinner now only waits on the on-chain round data, so the tracker renders
even when the subgraph is fully down; the subgraph-only stats (fees, rewards,
supply) are hidden in that case.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Copilot AI review requested due to automatic review settings July 21, 2026 07:43
@rickstaa
rickstaa requested a review from ECWireless as a code owner July 21, 2026 07:43
@vercel

vercel Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
explorer-arbitrum-one Ready Ready Preview, Comment Jul 21, 2026 8:28am

Request Review

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@rickstaa, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 44 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4ff86c5c-b082-488b-bf17-ccae1c8db938

📥 Commits

Reviewing files that changed from the base of the PR and between 98ec731 and fd707ce.

📒 Files selected for processing (1)
  • components/RoundStatus/index.tsx
📝 Walkthrough

Walkthrough

The current-round API now returns contract-derived lock and round-length data. RoundStatus uses these fields for progress, remaining blocks, and lock state, while rendering initialized UI without protocol and conditionally showing protocol-dependent metrics.

Changes

Current round state

Layer / File(s) Summary
Expose contract round state
lib/api/types/get-current-round.ts, pages/api/current-round.tsx
CurrentRoundInfo and the current-round API now include locked and roundLength values read from contract state.
Render round status from API state
components/RoundStatus/index.tsx
Round timing and progress use currentRoundInfo.roundLength, lock status uses currentRoundInfo.locked, and protocol-dependent metrics render only when protocol is available.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: ecwireless

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: moving round length and lock-state sourcing on-chain in the round tracker.
Description check ✅ Passed The description covers summary, key changes, notes, and testing, with enough context for reviewers despite missing some template sections.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/round-status-onchain

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR completes the shift of the round tracker to a single on-chain source by extending /api/current-round to include roundLength and locked from RoundsManager, and updating RoundStatus to use that data instead of the subgraph for timing/lock-related UI.

Changes:

  • Extend /api/current-round response to include locked (currentRoundLocked) and roundLength (roundLength) from RoundsManager.
  • Update CurrentRoundInfo type to include locked and roundLength.
  • Update RoundStatus to compute progress/remaining blocks and lock badge from useCurrentRoundData, and to render even when the subgraph protocol data is unavailable (hiding subgraph-only stat rows in that case).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
pages/api/current-round.tsx Adds on-chain reads for currentRoundLocked and roundLength to the current round API response.
lib/api/types/get-current-round.ts Extends CurrentRoundInfo with locked and roundLength.
components/RoundStatus/index.tsx Switches round progress/lock UI to on-chain fields and allows rendering during subgraph outages.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +26 to +30
const [
id,
startBlock,
initialized,
locked,
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
components/RoundStatus/index.tsx (1)

40-70: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

No test coverage for the migrated timing/lock calculations.

blocksRemaining, percentage, and isRoundLocked all switched from subgraph-derived (protocol.*) to on-chain (currentRoundInfo.*) sources — a meaningful behavior change with no accompanying tests in this changeset for the new calculation paths or the loading/lock states.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/RoundStatus/index.tsx` around lines 40 - 70, Add tests for the
RoundStatus timing and lock calculations covering on-chain currentRoundInfo
values, including blocksRemaining, percentage, and isRoundLocked. Include
uninitialized/loading data and locked/unlocked states, and verify the rendered
output reflects each calculation path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@components/RoundStatus/index.tsx`:
- Around line 62-70: Update the isRoundLocked state used by the header badge and
tooltip in RoundStatus to preserve an explicit loading state while
currentRoundInfo is unavailable, rather than defaulting to false. Render a
neutral loading or skeleton indicator for that state, and keep the existing
locked/unlocked labels and icons once currentRoundInfo has resolved.

---

Outside diff comments:
In `@components/RoundStatus/index.tsx`:
- Around line 40-70: Add tests for the RoundStatus timing and lock calculations
covering on-chain currentRoundInfo values, including blocksRemaining,
percentage, and isRoundLocked. Include uninitialized/loading data and
locked/unlocked states, and verify the rendered output reflects each calculation
path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: de6ba784-fa7c-4355-b8b3-5ff15cf15cdb

📥 Commits

Reviewing files that changed from the base of the PR and between 29fd3cc and 98ec731.

📒 Files selected for processing (3)
  • components/RoundStatus/index.tsx
  • lib/api/types/get-current-round.ts
  • pages/api/current-round.tsx

Comment thread components/RoundStatus/index.tsx
isRoundLocked falls back to false before currentRoundInfo resolves, so the
header badge asserted "Initialized" while the round data was still loading.
Render a skeleton until currentRoundInfo is available, matching the spinner in
the content area below.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@rickstaa
rickstaa merged commit f0213aa into main Jul 21, 2026
8 of 9 checks passed
@rickstaa
rickstaa deleted the fix/round-status-onchain branch July 21, 2026 08:30
moudi-network pushed a commit to moudi-network/explorer that referenced this pull request Jul 24, 2026
…livepeer#735)

* fix: source round length and lock state on-chain in the round tracker

RoundStatus still mixed sources after livepeer#731: round timing came from the
RoundsManager via /current-round, but roundLength and the lock state came from
the subgraph (protocol.roundLength / protocol.lockPeriod). The lock state was
re-derived client-side (blocksRemaining <= lockPeriod) because the subgraph,
being event-driven, can't keep a per-block boolean fresh.

Extend /api/current-round to also return roundLength and locked (from
RoundsManager.roundLength and currentRoundLocked), and read both from
useCurrentRoundData. The lock state now comes straight from currentRoundLocked
— one authoritative snapshot instead of re-deriving it — and the round tracker
(ring, blocks remaining, lock badge) is fully on-chain and consistent.

The spinner now only waits on the on-chain round data, so the tracker renders
even when the subgraph is fully down; the subgraph-only stats (fees, rewards,
supply) are hidden in that case.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

* chore: drop redundant comment in RoundStatus

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

* fix: show a loading skeleton for the round lock badge

isRoundLocked falls back to false before currentRoundInfo resolves, so the
header badge asserted "Initialized" while the round data was still loading.
Render a skeleton until currentRoundInfo is available, matching the spinner in
the content area below.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
moudi-network pushed a commit to moudi-network/explorer that referenced this pull request Jul 24, 2026
…livepeer#735)

* fix: source round length and lock state on-chain in the round tracker

RoundStatus still mixed sources after livepeer#731: round timing came from the
RoundsManager via /current-round, but roundLength and the lock state came from
the subgraph (protocol.roundLength / protocol.lockPeriod). The lock state was
re-derived client-side (blocksRemaining <= lockPeriod) because the subgraph,
being event-driven, can't keep a per-block boolean fresh.

Extend /api/current-round to also return roundLength and locked (from
RoundsManager.roundLength and currentRoundLocked), and read both from
useCurrentRoundData. The lock state now comes straight from currentRoundLocked
— one authoritative snapshot instead of re-deriving it — and the round tracker
(ring, blocks remaining, lock badge) is fully on-chain and consistent.

The spinner now only waits on the on-chain round data, so the tracker renders
even when the subgraph is fully down; the subgraph-only stats (fees, rewards,
supply) are hidden in that case.


* chore: drop redundant comment in RoundStatus


* fix: show a loading skeleton for the round lock badge

isRoundLocked falls back to false before currentRoundInfo resolves, so the
header badge asserted "Initialized" while the round data was still loading.
Render a skeleton until currentRoundInfo is available, matching the spinner in
the content area below.


---------
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.

2 participants