Skip to content

fix: chart for inactive markets#491

Merged
antoncoding merged 4 commits into
masterfrom
fix/chart
Apr 2, 2026
Merged

fix: chart for inactive markets#491
antoncoding merged 4 commits into
masterfrom
fix/chart

Conversation

@antoncoding
Copy link
Copy Markdown
Owner

@antoncoding antoncoding commented Apr 2, 2026

Summary by CodeRabbit

  • New Features

    • Charts now display state read indicators to show data source origins.
    • Added configurable RPC fallback control for historical rate enrichment.
  • Improvements

    • Enhanced chart tooltips and layouts for improved data visualization.
    • Improved historical rate data accuracy with boundary state enrichment.
    • Better block number display formatting in charts.

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 2, 2026

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

Project Deployment Actions Updated (UTC)
monarch Ready Ready Preview, Comment Apr 2, 2026 10:55am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 2, 2026

Warning

Rate limit exceeded

@antoncoding has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 7 minutes and 37 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 7 minutes and 37 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 63959176-6d25-4187-916e-d38187f7a333

📥 Commits

Reviewing files that changed from the base of the PR and between 095c065 and db621a4.

📒 Files selected for processing (3)
  • src/features/market-detail/components/charts/rate-chart.tsx
  • src/features/market-detail/components/charts/volume-chart.tsx
  • src/hooks/useMarketHistoricalData.ts
📝 Walkthrough

Walkthrough

The PR adds an environment variable to conditionally disable RPC fallback when Morpho API fails, enhances useMarketHistoricalData to fetch boundary state points from on-chain data at target timestamps, and updates chart components to display state-read metadata alongside historical data.

Changes

Cohort / File(s) Summary
Configuration
.env.local.example
Added NEXT_PUBLIC_ENABLE_MARKET_RATE_RPC_FALLBACK environment variable (defaults to true) to control RPC fallback behavior.
Chart Utilities
src/features/market-detail/components/charts/chart-utils.tsx
Added "State Read" badge to tooltip header; exported getTimeSeriesXAxisProps() helper to provide numeric linear scale x-axis config for Recharts.
Chart Components
src/features/market-detail/components/charts/rate-chart.tsx, volume-chart.tsx
Integrated stateReadPoints from hook; built timestamp lookup maps; attached blockNumber and isStateRead fields to chart points; spread x-axis props from utility function.
Chart Header/Tooltip
src/features/market-detail/components/charts/supplier-positions-chart.tsx
Updated tooltip layout to horizontal flex row with timestamp/block on opposite sides; imported and applied getTimeSeriesXAxisProps().
Historical Data Hook
src/hooks/useMarketHistoricalData.ts
Added market and timeframe optional params; refactored to generate target timestamps from config, batch-fetch boundary states via RPC, merge results into stateReadPoints field; changed return shape to { historicalData, stateReadPoints }.
Rate Enrichment Utilities
src/utils/market-rate-enrichment.ts
Added HistoricalMarketBoundaryState type and fetchHistoricalMarketBoundaryState(s) functions; gated Morpho fallback on NEXT_PUBLIC_ENABLE_MARKET_RATE_RPC_FALLBACK; imported IRM utilities to derive rateAtTarget from borrow rate and utilization.

Sequence Diagram(s)

sequenceDiagram
    participant Chart as Chart Component
    participant Hook as useMarketHistoricalData
    participant Monarch as Monarch API
    participant Morpho as Morpho API
    participant RPC as Custom RPC
    participant BlockFetch as Block Timestamp Service

    Chart->>Hook: Call with market, timeframe, timeRange
    Hook->>Monarch: Fetch historical rates (if network supported)
    alt Monarch returns data
        Monarch-->>Hook: historicalData
    else Morpho fallback enabled
        Hook->>Morpho: Fetch rates
        Morpho-->>Hook: historicalData
    end
    
    alt market & timeframe provided
        Hook->>Hook: Generate target timestamps from config
        Hook->>BlockFetch: Resolve block numbers for targets
        BlockFetch-->>Hook: Block mapping
        Hook->>RPC: Batch fetch boundary market states
        RPC-->>Hook: Snapshots at blocks
        Hook->>Hook: Compute APYs, utilization, rateAtTarget
        Hook-->>Hook: stateReadPoints array
    end
    
    Hook-->>Chart: { historicalData, stateReadPoints }
    Chart->>Chart: Build timestamp lookup from stateReadPoints
    Chart->>Chart: Merge blockNumber & isStateRead into chart data
    Chart->>Chart: Render with "State Read" badges
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • #469: Modifies useMarketHistoricalData hook and chart components with overlapping data sourcing changes.
  • #483: Modifies market-rate-enrichment.ts implementation and enrichment fetch logic.
  • #359: Updates chart component layout and XAxis props in the same files.

Suggested labels

bug, ui

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is vague and doesn't clearly describe the actual changes—it mentions 'inactive markets' but the PR primarily adds RPC fallback configuration, state-read tracking, and chart enhancements across multiple components. Consider a more specific title like 'feat: add RPC fallback for market rates and state-read tracking in charts' that captures the core changes.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/chart

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 and usage tips.

@coderabbitai coderabbitai Bot added bug Something isn't working ui User interface labels Apr 2, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/hooks/useMarketHistoricalData.ts`:
- Around line 256-260: The code currently drops unresolved timestamps by
filtering out nulls from the mapped array (filledPoints), which hides gaps;
instead preserve the full target grid and fail the rebuild when any slots remain
unresolved or boundaries are stale: replace the .map/.filter sequence with const
grid = targetTimestamps.map(t => pointsByTarget.get(t) ?? null) and then if
(grid.some(p => p === null) || !bracketsWindow(grid[0], grid[grid.length-1])) {
throw new Error("Historical samples do not bracket requested window"); } else
set historicalData = buildHistoricalDataFromSamplePoints(grid) (or adapt
buildHistoricalDataFromSamplePoints to accept nullable points) so the chart
keeps nulls or the function fails closed; reference: targetTimestamps,
pointsByTarget, filledPoints, buildHistoricalDataFromSamplePoints,
historicalData.

In `@src/utils/market-rate-enrichment.ts`:
- Around line 550-599: The loop over boundaryBlocks currently runs sequentially
and any thrown error bubbles to the outer try/catch causing an empty [] return;
change this to process boundaryBlocks with bounded parallelism (e.g., use a
concurrency limiter like p-limit or Promise.allSettled with slicing) and wrap
the per-block work (the body that calls fetchMarketsSnapshots,
fetchBoundaryBorrowRates, accrueSnapshotToTimestamp and pushes into
boundaryStates) in its own try/catch so failures for a single boundaryBlock are
logged and skipped rather than aborting the whole function; keep returning only
the successfully constructed HistoricalMarketBoundaryState items (i.e., the
collected boundaryStates) from the surrounding function.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 43c9429b-efeb-44cf-8f0f-13cc9f5566c0

📥 Commits

Reviewing files that changed from the base of the PR and between 7b37ded and 095c065.

📒 Files selected for processing (7)
  • .env.local.example
  • src/features/market-detail/components/charts/chart-utils.tsx
  • src/features/market-detail/components/charts/rate-chart.tsx
  • src/features/market-detail/components/charts/supplier-positions-chart.tsx
  • src/features/market-detail/components/charts/volume-chart.tsx
  • src/hooks/useMarketHistoricalData.ts
  • src/utils/market-rate-enrichment.ts

Comment on lines +256 to +260
const filledPoints = targetTimestamps
.map((targetTimestamp) => pointsByTarget.get(targetTimestamp) ?? null)
.filter((point): point is HistoricalSamplePoint => point !== null);

historicalData = filledPoints.length > 0 ? buildHistoricalDataFromSamplePoints(filledPoints) : null;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Don't collapse unresolved timestamps out of the rebuilt series.

If some target slots still miss after the RPC fill, filtering them out here makes the chart look continuous anyway—the X values disappear, so the line just interpolates across the hole. Keep the full target grid with null values, or fail the rebuild unless every slot is covered.

As per coding guidelines, "Fail closed when historical rate snapshots do not actually bracket requested window, including stale lastUpdate on either boundary".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useMarketHistoricalData.ts` around lines 256 - 260, The code
currently drops unresolved timestamps by filtering out nulls from the mapped
array (filledPoints), which hides gaps; instead preserve the full target grid
and fail the rebuild when any slots remain unresolved or boundaries are stale:
replace the .map/.filter sequence with const grid = targetTimestamps.map(t =>
pointsByTarget.get(t) ?? null) and then if (grid.some(p => p === null) ||
!bracketsWindow(grid[0], grid[grid.length-1])) { throw new Error("Historical
samples do not bracket requested window"); } else set historicalData =
buildHistoricalDataFromSamplePoints(grid) (or adapt
buildHistoricalDataFromSamplePoints to accept nullable points) so the chart
keeps nulls or the function fails closed; reference: targetTimestamps,
pointsByTarget, filledPoints, buildHistoricalDataFromSamplePoints,
historicalData.

Comment thread src/utils/market-rate-enrichment.ts
Copy link
Copy Markdown
Collaborator

@starksama starksama left a comment

Choose a reason for hiding this comment

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

LGTM. Main 7d cadence concern is addressed by reverting to the shared 4h interval. Remaining CodeRabbit note looks like optional robustness hardening, not something I’d block this PR on.

@antoncoding antoncoding merged commit 6e6b066 into master Apr 2, 2026
4 checks passed
@antoncoding antoncoding deleted the fix/chart branch April 2, 2026 10:55
This was referenced May 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working ui User interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants