Skip to content

fix: handle oracle syncing state in explorer#36

Open
aledefra wants to merge 1 commit into
developfrom
codex/syncing-oracles-tag-explorer
Open

fix: handle oracle syncing state in explorer#36
aledefra wants to merge 1 commit into
developfrom
codex/syncing-oracles-tag-explorer

Conversation

@aledefra
Copy link
Copy Markdown
Collaborator

@aledefra aledefra commented Feb 28, 2026

Summary

  • handle /node_epochs_range syncing responses (e.g. "No epochs found for the given node") without throwing
  • add shared oracle sync detection and a SyncingOraclesTag aligned with dapp style
  • show syncing state in node performance and PoA rewards while oracle data is catching up
  • fallback to /node_last_epoch for node metadata when range data is temporarily empty
  • align node availability typings to real oracle API payloads

Validation

  • npm run lint
  • npm run build

Copilot AI review requested due to automatic review settings February 28, 2026 21:49
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 improves the explorer’s resilience and UX when the Oracles API is still syncing, by detecting “syncing/no-epochs” states, avoiding hard failures, and surfacing a consistent syncing indicator in key UI cards.

Changes:

  • Add shared helpers to detect Oracles syncing / “no epochs found” responses.
  • Adjust Oracles API fetching and node availability selection to tolerate syncing/empty ranges and fall back to last-epoch metadata.
  • Display a “Syncing oracles” state in Node Performance and PoA rewards, and harden node metadata rendering against missing fields.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
typedefs/blockchain.ts Extends Oracles payload typings with sync/error metadata fields.
lib/oracles.ts Introduces shared sync/error detection helpers.
lib/api/oracles.ts Handles “No epochs found…” responses without throwing.
lib/actions.ts Adds fallback from range endpoint to last-epoch endpoint while syncing.
app/server-components/shared/SyncingOraclesTag.tsx Adds a shared syncing tag UI component.
app/server-components/main-cards/NodePerformanceCard.tsx Shows syncing state and guards against empty epoch arrays.
app/server-components/main-cards/NodeCard.tsx Adds safer rendering for potentially missing metadata fields.
app/server-components/main-cards/LicenseCard.tsx Updates node availability callback typing.
app/server-components/Nodes/NodeListGNDCard.tsx Updates node availability response typing usage.
app/server-components/Licenses/NodeSmallCard.tsx Updates node availability response typing usage.
app/server-components/Licenses/LicenseRewardsPoA.tsx Shows syncing state when rewards are not yet computable due to syncing.
app/server-components/LicensePage/LicensePageNodePerformanceCardWrapper.tsx Updates node availability callback typing usage.
app/server-components/LicensePage/LicensePageNodeCardWrapper.tsx Updates node availability callback typing usage.
app/node/[nodeAddr]/page.tsx Updates node availability response typing usage.

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

Comment thread lib/api/oracles.ts
Comment on lines 48 to +55
if ('error' in data.result) {
if (hasNoEpochsFoundError(data.result.error)) {
return {
...data.result,
epochs: 'epochs' in data.result && Array.isArray(data.result.epochs) ? data.result.epochs : [],
epochs_vals: 'epochs_vals' in data.result && Array.isArray(data.result.epochs_vals) ? data.result.epochs_vals : [],
} as T;
}
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

The special-case branch for No epochs found... returns data.result cast as T, but data.result can be just { error: string } (no node metadata fields). This makes getNodeLastEpoch/getNodeEpochsRange appear to return a full OraclesAvailabilityResult while potentially omitting required properties, leading to downstream runtime errors. Consider modeling this as a proper union return type (e.g., T | { error: string; epochs: number[]; epochs_vals: number[]; ...syncMeta }) or a dedicated “syncing/empty” result type and updating callers accordingly, rather than as T.

Copilot uses AI. Check for mistakes.
Comment on lines +131 to 136
{epochs
.slice(-10)
.reverse()
.map((epoch, index) => {
const availability = nodeResponse.epochs_vals.slice(-10)[index];
const availability = epochsVals.slice(-10)[index];

Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

In the mobile rendering, epochs are reversed but the availability values are still indexed from the non-reversed epochsVals.slice(-10). This can display mismatched availability percentages for a given epoch. Build a single list of {epoch, availability} pairs (or reverse both arrays consistently) before mapping so epoch/value stay aligned.

Copilot uses AI. Check for mistakes.
Comment on lines +19 to 21
const nodeResponse: types.OraclesAvailabilityResult = await getNodeLastEpoch(nodeAddress);

ratio1Addr = nodeResponse.node as types.R1Address;
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

getNodeLastEpoch() can now return an empty epochs_vals array for the handled "No epochs found..." case. This file later reads nodeResponse.epochs_vals[0] when building node.recent_history.last_epoch_avail, which will become undefined and lead to NaN% rendering in NodeListNodeCard. Add a guard/fallback (e.g., default to 0 or skip rendering until data exists).

Copilot uses AI. Check for mistakes.
Comment thread typedefs/blockchain.ts
Comment on lines 59 to +76
type OraclesAvailabilityResult = {
node: string;
node_alias: string;
node_eth_address: EthAddress;
epochs: number[];
epochs_vals: number[];
error?: string;
eth_signed_data: EthSignedData;
eth_signatures: EthAddress[];
eth_addresses: EthAddress[];
node_is_online: boolean;
node_is_oracle: boolean;
node_version: string;
node_last_seen_sec: number;
resources: Resources;
tags?: string[];
server_current_epoch?: number;
server_last_synced_epoch?: number;
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

OraclesAvailabilityResult now includes sync/error metadata (error, server_*_epoch), and the UI/actions code treats some node fields as potentially missing while syncing (e.g., resources, node_last_seen_sec, node_version). The type still marks these as required, which can mask real undefined cases (especially when _doGet returns an error/sync payload). Consider splitting this into a discriminated union (success vs syncing/error) or marking the affected node metadata fields optional to accurately reflect the payload and force callers to handle missing data explicitly.

Copilot uses AI. Check for mistakes.
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