From 66ae58dff8d400c530b7ff03400fa5ca2731ee95 Mon Sep 17 00:00:00 2001 From: Rick Staa Date: Tue, 21 Jul 2026 09:42:30 +0200 Subject: [PATCH 1/3] fix: source round length and lock state on-chain in the round tracker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- components/RoundStatus/index.tsx | 394 +++++++++++++++-------------- lib/api/types/get-current-round.ts | 2 + pages/api/current-round.tsx | 57 +++-- 3 files changed, 237 insertions(+), 216 deletions(-) diff --git a/components/RoundStatus/index.tsx b/components/RoundStatus/index.tsx index aeaba3b5..066a0cf5 100644 --- a/components/RoundStatus/index.tsx +++ b/components/RoundStatus/index.tsx @@ -37,14 +37,16 @@ const Index = ({ const currentRoundInfo = useCurrentRoundData(); + // Round timing/lock come entirely from the RoundsManager (via /current-round), + // so the tracker stays consistent and live even when the subgraph is behind. const blocksRemaining = useMemo( () => - currentRoundInfo?.initialized && protocol - ? +protocol.roundLength - - (+Number(currentRoundInfo.currentL1Block) - - +Number(currentRoundInfo.startBlock)) + currentRoundInfo?.initialized + ? currentRoundInfo.roundLength - + (Number(currentRoundInfo.currentL1Block) - + Number(currentRoundInfo.startBlock)) : 0, - [protocol, currentRoundInfo] + [currentRoundInfo] ); const timeRemaining = useMemo( () => AVERAGE_L1_BLOCK_TIME * blocksRemaining, @@ -61,19 +63,13 @@ const Index = ({ const percentage = useMemo( () => - protocol - ? (blocksSinceCurrentRoundStart / +protocol.roundLength) * 100 + currentRoundInfo?.roundLength + ? (blocksSinceCurrentRoundStart / currentRoundInfo.roundLength) * 100 : 0, - [blocksSinceCurrentRoundStart, protocol] + [blocksSinceCurrentRoundStart, currentRoundInfo] ); - const isRoundLocked = useMemo( - () => - protocol && currentRoundInfo - ? blocksRemaining <= Number(protocol?.lockPeriod) - : false, - [protocol, blocksRemaining, currentRoundInfo] - ); + const isRoundLocked = currentRoundInfo?.locked ?? false; const rewardTokensClaimed = useMemo( () => @@ -178,7 +174,7 @@ const Index = ({ marginTop: "$2", }} > - {!currentRoundInfo || !protocol ? ( + {!currentRoundInfo ? ( - of {protocol.roundLength} blocks + of {currentRoundInfo.roundLength} blocks @@ -259,212 +255,218 @@ const Index = ({ begins. - - The amount of fees that have been paid out in the current - round. Equivalent to{" "} - {formatUSD(protocol?.currentRound?.volumeUSD, { - precision: 0, - abbreviate: true, - })}{" "} - at recent prices of ETH. - - } - > - - - - Fees - - - - - - - - {formatETH(protocol?.currentRound?.volumeETH, { - precision: 2, - })} - - - - - The amount of rewards which have been claimed by orchestrators - in the current round. - - } - > - - + + The amount of fees that have been paid out in the current + round. Equivalent to{" "} + {formatUSD(protocol?.currentRound?.volumeUSD, { + precision: 0, + abbreviate: true, + })}{" "} + at recent prices of ETH. + + } > - - Rewards - - - - - + + + Fees + + + + + - - {rewards} - - - - - The current total supply of LPT.} - > - + {formatETH(protocol?.currentRound?.volumeETH, { + precision: 2, + })} + + + + + The amount of rewards which have been claimed by + orchestrators in the current round. + + } > + + + Rewards + + + + + + - Total Supply + {rewards} - - - - - - {totalSupply !== null - ? formatLPT(totalSupply, { - precision: 0, - abbreviate: true, - }) - : "--"} - - - - Total supply change over the past 365 days.} - > - + - The current total supply of LPT.} > - - Supply Change (1Y) - - - - - + + + Total Supply + + + + + - + {totalSupply !== null + ? formatLPT(totalSupply, { + precision: 0, + abbreviate: true, + }) + : "--"} + + + + Total supply change over the past 365 days. + } > - {isSupplyChangeLoading ? ( - - ) : supplyChangeData?.supplyChange != null ? ( - formatPercent(supplyChangeData.supplyChange, { - precision: 2, - }) - ) : ( - "--" - )} - - - - + + + + Supply Change (1Y) + + + + + + + + {isSupplyChangeLoading ? ( + + ) : supplyChangeData?.supplyChange != null ? ( + formatPercent(supplyChangeData.supplyChange, { + precision: 2, + }) + ) : ( + "--" + )} + + + + + + )} ) : ( Date: Tue, 21 Jul 2026 10:10:22 +0200 Subject: [PATCH 2/3] chore: drop redundant comment in RoundStatus Co-Authored-By: Claude Opus 4.8 (1M context) --- components/RoundStatus/index.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/RoundStatus/index.tsx b/components/RoundStatus/index.tsx index 066a0cf5..7dde0d60 100644 --- a/components/RoundStatus/index.tsx +++ b/components/RoundStatus/index.tsx @@ -37,8 +37,6 @@ const Index = ({ const currentRoundInfo = useCurrentRoundData(); - // Round timing/lock come entirely from the RoundsManager (via /current-round), - // so the tracker stays consistent and live even when the subgraph is behind. const blocksRemaining = useMemo( () => currentRoundInfo?.initialized From fd707ce23df4d73001fbee20ae2630a23651076c Mon Sep 17 00:00:00 2001 From: Rick Staa Date: Tue, 21 Jul 2026 10:25:37 +0200 Subject: [PATCH 3/3] 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) --- components/RoundStatus/index.tsx | 88 +++++++++++++++++--------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/components/RoundStatus/index.tsx b/components/RoundStatus/index.tsx index 7dde0d60..a8ab84d6 100644 --- a/components/RoundStatus/index.tsx +++ b/components/RoundStatus/index.tsx @@ -120,50 +120,54 @@ const Index = ({ {currentRoundInfo?.id ? `#${currentRoundInfo.id}` : ""} - - {!isRoundLocked - ? "The current round is ongoing and orchestrators can currently update their parameters." - : "The current round is locked, which means that orchestrator parameters cannot be updated until the next round begins."} - - } - > - - - {!isRoundLocked ? "Initialized " : "Locked "} - - - {isRoundLocked ? ( - - ) : ( - + ) : ( + + {!isRoundLocked + ? "The current round is ongoing and orchestrators can currently update their parameters." + : "The current round is locked, which means that orchestrator parameters cannot be updated until the next round begins."} + + } + > + + - )} - - + > + {!isRoundLocked ? "Initialized " : "Locked "} + + + {isRoundLocked ? ( + + ) : ( + + )} + + + )}