Skip to content

feat: add vault share price chart and adapter caps support#532

Merged
antoncoding merged 5 commits into
masterfrom
feat/vault-apy
May 19, 2026
Merged

feat: add vault share price chart and adapter caps support#532
antoncoding merged 5 commits into
masterfrom
feat/vault-apy

Conversation

@antoncoding
Copy link
Copy Markdown
Owner

@antoncoding antoncoding commented May 19, 2026

Summary by CodeRabbit

  • New Features

    • Vault share-price chart with configurable timeframe and live/update states
    • Improved multi-adapter support with capacity-aware display and visible "Caps" badge
    • 3-month period option added across earnings/positions and analytics
    • Better adapter labeling with safe generic fallback when metadata is missing
  • UX Changes

    • Period selector unified and available as a shared control; adapter overview no longer exposes an inline period control
  • Documentation

    • Validation guidelines updated for multi-adapter behavior and label handling

Review Change Stack

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 19, 2026

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

Project Deployment Actions Updated (UTC)
monarch Ready Ready Preview, Comment May 19, 2026 5:47pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ae3f5dba-b79b-4197-a898-b157a4433a8b

📥 Commits

Reviewing files that changed from the base of the PR and between f007c64 and c74e917.

📒 Files selected for processing (1)
  • src/features/market-detail/components/charts/chart-utils.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/features/market-detail/components/charts/chart-utils.tsx

📝 Walkthrough

Walkthrough

PR adds historical vault share-price charts, makes adapterType optional and derives aliases from active adapters, tracks positive-cap metrics, introduces a 3-month period, centralizes period controls, and refactors vault/autovault pages to render multi-adapter details and analytics controls.

Changes

Share Price Charts, Adapter Caps Awareness, and Period Control Refactor

Layer / File(s) Summary
Period type extension and vault capacity utilities
src/stores/usePositionsFilters.ts, src/hooks/usePositionsWithEarnings.ts, src/utils/vaultAllocation.ts
EarningsPeriod adds 'threemonth', getPeriodTimestamp handles 90-day offset, and hasPositiveVaultCap safely parses relative/absolute cap strings to detect positive capacity.
Vault adapter metadata optionality and capability tracking
src/contexts/VaultRegistryContext.tsx, src/data-sources/monarch-api/vaults.ts, src/hooks/useMorphoMarketAdapters.ts
adapterType becomes optional in VaultAdapterAlias. fetchMonarchVaultAdapterAliases derives aliases from active vault adapters and deduplicates via map. useMorphoMarketAdapters computes per-adapter cap metrics, deduplicates case-insensitively, derives configuredAdapters subset, and adds hasMultipleAdapters flag.
Vault V2 cap data structure and evaluation
src/hooks/useVaultV2Data.ts
CapData now includes adapterCaps array. Caps parsing collects all adapter caps, derives single adapterCap via positive-cap check, and updates needSetupCaps logic.
Share price data pipeline
src/graphql/vault-queries.ts, src/data-sources/morpho-api/vault-share-price-history.ts, src/hooks/useVaultSharePriceHistory.ts
New vaultV2SharePriceHistoryQuery fetches x/y timeseries. fetchMorphoVaultV2SharePriceHistory normalizes Morpho API points. useVaultSharePriceHistory hook fetches Morpho API history or falls back to batched RPC previewRedeem calls at computed block timestamps, returns series with source metadata.
Period label mappings and component utilities
src/features/position-detail/components/overview-tab.tsx, src/features/position-detail/position-view.tsx, src/features/positions/components/supplied-morpho-blue-grouped-table.tsx, src/features/positions/components/user-vaults-table.tsx, src/features/vault/components/vault-adapter-position-overview.tsx, src/features/market-detail/components/charts/chart-utils.tsx, src/utils/vaults.ts, src/components/common/period-selector.tsx
PERIOD_LABELS adds threemonth'3M' mapping across components. formatVaultAdapterType trims and falls back to 'Vault adapter' for missing/empty types. ChartTooltipContent uses structured payload typing with blockNumber metadata. PeriodSelector replaces PositionPeriodSelector, accepts optional options prop, exports EARNINGS_PERIOD_OPTIONS and PeriodSelectorOption.
Table and transaction history component updates
src/features/vault/components/vault-market-allocations-table.tsx, src/features/history/components/transaction-history-preview.tsx, src/features/positions/components/user-positions-chart.tsx
VaultMarketAllocationsTable removes mode-dependent sort and position-specific fields, displays liquidity directly in position mode. TransactionHistoryPreview accepts optional accounts prop, normalizes to transactionAccounts. UserPositionsChart accepts optional actions prop and forwards to TableContainerWithDescription.
Share price chart visualization
src/features/vault/components/vault-share-price-chart.tsx
New VaultSharePriceChart component reads timeframe/range from useMarketDetailChartState, fetches via useVaultSharePriceHistory, renders memoized Recharts AreaChart with computed Y-axis domain around starting share price, displays period control and "Updating" indicator, shows unavailable message when data unsupported/insufficient, renders footer with Start/End/Change values.
Vault header caps display and analytics period control
src/features/autovault/components/vault-detail/vault-header.tsx, src/features/vault/components/vault-analytics-period-control.tsx
VaultHeader accepts capsAdapters, renders "Caps: …" badge and "Active" markers for caps-configured adapters. New VaultAnalyticsPeriodControl uses PeriodSelector, wires VaultAnalyticsPeriod with timeframe/period bidirectional mappings.
Vault adapter position overview refactoring
src/features/vault/components/vault-adapter-position-overview.tsx
Removes PositionPeriodSelector UI and setPeriod callback, deferring period control to container.
Vault detail page refactor
src/features/vault/vault-view.tsx
Derives positionAdapters from configuredAdapters (fallback to adapters), passes both adapters and capsAdapters to VaultHeader. New VaultAdaptersPositionDetail renders per-adapter details with optional labels (shown only when multiple adapters). Wires useMarketDetailChartState to drive analyticsPeriod, renders VaultAnalyticsPeriodControl and VaultSharePriceChart, removes transaction-activity flow.
Autovault page refactor
src/features/autovault/vault-view.tsx
Derives positionAdapters, passes both adapters and capsAdapters to VaultHeader, inserts VaultSharePriceChart into render sequence, removes transaction-history preview.
Documentation and comments
docs/VALIDATIONS.md, src/hooks/useAddressLabel.ts
VALIDATIONS.md adds rules for cap-aware adapter selection, shared period controls, and adapter label derivation from confirmed metadata. useAddressLabel updates terminology from "recognized" to "confirmed" vault adapter.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • antoncoding/monarch#509: Updates VaultAdapterAlias.adapterType and Monarch vault adapter alias infrastructure related to adapter metadata/deduping.
  • antoncoding/monarch#524: Related adapter identity/type changes around VaultRegistryContext and adapter label handling.
  • antoncoding/monarch#531: Overlapping vault/autovault page refactors and transaction-history preview changes.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the two main features added: a vault share price chart and adapter caps support, which are reflected throughout the changeset.
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.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/vault-apy

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 feature request Specific feature ready to be implemented ui User interface labels May 19, 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: 6

🤖 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 `@src/data-sources/morpho-api/vault-share-price-history.ts`:
- Around line 65-79: The mapping that builds normalizedPoints currently trusts
point.x for timestamp; before returning each MorphoVaultSharePricePoint ensure
the timestamp is a valid finite number (e.g., coerce with Number(point.x) and
test with Number.isFinite) and drop points with non-finite timestamps; update
the map/filter pipeline around normalizeSharePrice(point.y) to also validate the
timestamp and only return objects with a finite timestamp so sortByTimestamp and
downstream chart math cannot receive invalid values.

In `@src/features/autovault/components/vault-detail/vault-header.tsx`:
- Around line 102-104: The current logic initializes capsAdapterRows with a
fallback to the single `adapter` value which can incorrectly indicate configured
caps and render “Active” badges; change the caps state to rely only on
`capsAdapters` (remove the fallback to `adapter`) so `capsAdapterRows =
capsAdapters`, then recompute `capsAdapterKeys = new Set(capsAdapterRows.map(row
=> row.adapter.toLowerCase()))` and keep `showCapsAdapter = adapterRows.length >
1 && capsAdapterRows.length > 0` so the UI only reflects actual `capsAdapters`
data; update any downstream usages that assumed the fallback to `adapter`
accordingly (symbols: capsAdapterRows, capsAdapters, adapter, capsAdapterKeys,
showCapsAdapter, adapterRows).

In `@src/features/history/components/transaction-history-preview.tsx`:
- Around line 50-53: In sourceAccounts.flatMap in
transaction-history-preview.tsx the normalization only lowercases addresses but
doesn't trim whitespace, so use a trimmed lowercase value (e.g., compute
normalizedAccount from sourceAccount.trim().toLowerCase()) and then check the
falsy/seen Set using that trimmed value; update the variable used in subsequent
logic (normalizedAccount and any seen.add calls) to prevent padded strings from
slipping through.

In `@src/features/market-detail/components/charts/chart-utils.tsx`:
- Around line 159-171: The onClick and formatter handlers for the chart legend
currently coerce entry.dataKey even when it's undefined, which creates a literal
"undefined" key in the visibleLines state; update the onClick in the legend and
the formatter to guard that entry.dataKey is non-null/undefined before calling
String or using it as a key (return early from onClick if missing), and use the
guarded key when reading from visibleLines in formatter (e.g., compute const key
= entry.dataKey != null ? String(entry.dataKey) as keyof T : null and only
toggle or read state when key is not null) so you never create or reference the
"undefined" state key; apply changes to the functions referenced as onClick,
formatter, setVisibleLines, and visibleLines.

In `@src/features/positions/components/supplied-morpho-blue-grouped-table.tsx`:
- Line 388: Inconsistent label for the 'threemonth' period exists across
components; standardize it to a single format (use '3M') by updating the
'threemonth' mapping currently set in supplied-morpho-blue-grouped-table (and
user-vaults-table) and changing the occurrences in overview-tab and
position-view from '3mo' to '3M'; ideally extract this into a shared constant
(e.g., PERIOD_LABELS or a PERIODS enum with a 'threemonth' key) exported and
imported by the components to avoid future drift.

In `@src/hooks/useVaultSharePriceHistory.ts`:
- Around line 70-106: selectNearestMorphoPoints currently prevents reusing a
source point by tracking usedIndexes, which causes sparse early points to be
consumed and leaves later targets unmapped or stale; change the algorithm to
match each targetTimestamp to its nearest Morpho point independently (remove
usedIndexes, related checks, and usedIndexes.add) so a single source point may
be reused for multiple targets, still guarding for empty points and sorting the
resulting VaultSharePricePoint[] by targetTimestamp before returning; keep
function signature and field mapping (sharePrice, source:'morpho-api',
timestamp, targetTimestamp).
🪄 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: 65f695a1-f417-42e7-bc58-1f0017701c98

📥 Commits

Reviewing files that changed from the base of the PR and between 31157e2 and 8410f30.

📒 Files selected for processing (28)
  • docs/VALIDATIONS.md
  • src/contexts/VaultRegistryContext.tsx
  • src/data-sources/monarch-api/vaults.ts
  • src/data-sources/morpho-api/vault-share-price-history.ts
  • src/features/autovault/components/vault-detail/vault-header.tsx
  • src/features/autovault/vault-view.tsx
  • src/features/history/components/transaction-history-preview.tsx
  • src/features/market-detail/components/charts/chart-utils.tsx
  • src/features/position-detail/components/overview-tab.tsx
  • src/features/position-detail/components/position-period-selector.tsx
  • src/features/position-detail/position-view.tsx
  • src/features/positions/components/supplied-morpho-blue-grouped-table.tsx
  • src/features/positions/components/user-positions-chart.tsx
  • src/features/positions/components/user-vaults-table.tsx
  • src/features/vault/components/vault-adapter-position-overview.tsx
  • src/features/vault/components/vault-analytics-period-control.tsx
  • src/features/vault/components/vault-market-allocations-table.tsx
  • src/features/vault/components/vault-share-price-chart.tsx
  • src/features/vault/vault-view.tsx
  • src/graphql/vault-queries.ts
  • src/hooks/useAddressLabel.ts
  • src/hooks/useMorphoMarketAdapters.ts
  • src/hooks/usePositionsWithEarnings.ts
  • src/hooks/useVaultSharePriceHistory.ts
  • src/hooks/useVaultV2Data.ts
  • src/stores/usePositionsFilters.ts
  • src/utils/vaultAllocation.ts
  • src/utils/vaults.ts

Comment thread src/data-sources/morpho-api/vault-share-price-history.ts
Comment thread src/features/autovault/components/vault-detail/vault-header.tsx Outdated
Comment thread src/features/history/components/transaction-history-preview.tsx
Comment thread src/features/market-detail/components/charts/chart-utils.tsx Outdated
day: '1D',
week: '7D',
month: '30D',
threemonth: '3M',
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 | 🟡 Minor | ⚡ Quick win

Inconsistent period label format across the UI.

The threemonth period uses different label formats in different parts of the UI:

  • '3M' here and in user-vaults-table.tsx (Line 30)
  • '3mo' in overview-tab.tsx (Line 25) and position-view.tsx (Line 32)

Consider standardizing to one format for consistency.

🤖 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 `@src/features/positions/components/supplied-morpho-blue-grouped-table.tsx` at
line 388, Inconsistent label for the 'threemonth' period exists across
components; standardize it to a single format (use '3M') by updating the
'threemonth' mapping currently set in supplied-morpho-blue-grouped-table (and
user-vaults-table) and changing the occurrences in overview-tab and
position-view from '3mo' to '3M'; ideally extract this into a shared constant
(e.g., PERIOD_LABELS or a PERIODS enum with a 'threemonth' key) exported and
imported by the components to avoid future drift.

Comment thread src/hooks/useVaultSharePriceHistory.ts
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a vault share price history chart and refactors vault adapter management to support multiple active adapters. Key changes include the addition of a shared analytics period control, a new share price history data source (Morpho API with RPC fallback), and updated logic for identifying and displaying configured adapters based on vault caps. Feedback focuses on handling edge cases in share price calculations (e.g., zero baseline), potential performance optimizations for data point selection, and ensuring RPC batch sizes are tuned for rate limits.

const baseline = chartData[0].sharePrice;
const dataMin = Math.min(...values);
const dataMax = Math.max(...values);
const minimumGrowth = Math.max(Math.abs(baseline) * SHARE_PRICE_DOMAIN_GROWTH_BY_TIMEFRAME[timeframe], Number.EPSILON);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The minimumGrowth calculation could potentially be zero if baseline is 0. While Number.EPSILON is used as a fallback, consider if this is the intended behavior for vaults with a share price of 0 or if a more robust minimum should be defined.

Comment on lines +140 to +143
const changePercent =
firstPoint && lastPoint && firstPoint.sharePrice > 0
? ((lastPoint.sharePrice - firstPoint.sharePrice) / firstPoint.sharePrice) * 100
: 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.

medium

The changePercent calculation assumes firstPoint.sharePrice > 0. If firstPoint.sharePrice is 0, this will be null. Ensure that the UI handles null correctly, which it seems to do, but consider if a different calculation is needed for 0-value share prices.

});
}

return selected.sort((left, right) => left.targetTimestamp - right.targetTimestamp);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The selectNearestMorphoPoints function uses an O(N*M) approach. While acceptable for small datasets, if the number of points grows significantly, consider optimizing this to O(N log M) using binary search.

Comment on lines +233 to +239
for (let i = 0; i < blocksWithTimestamps.length; i += PARALLEL_BATCH_SIZE) {
const batch = blocksWithTimestamps.slice(i, i + PARALLEL_BATCH_SIZE);
const batchResults = await Promise.all(
batch.map((block) => fetchSharePricePoint(client, vaultAddress, oneShareUnit, assetDecimals, block)),
);
points.push(...batchResults.filter((point): point is VaultSharePricePoint => point !== 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.

medium

The parallel batch processing for RPC calls is a good optimization. This aligns with the repository's preference for addressing performance bottlenecks via batched data fetching at the data layer rather than adding UI state complexity. Ensure that PARALLEL_BATCH_SIZE is tuned appropriately for the RPC provider's rate limits to avoid 429 errors.

References
  1. Address performance bottlenecks via batched data fetching at the data layer rather than adding UI state complexity.

@antoncoding antoncoding changed the title feat: vault display feat: add vault share price chart and adapter caps support May 19, 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.

♻️ Duplicate comments (1)
src/features/market-detail/components/charts/chart-utils.tsx (1)

159-168: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Avoid adding unknown legend keys into state.

onClick still toggles any stringified dataKey, so non-member keys can be inserted into visibleLines. Guard membership before writing state.

Suggested fix
     onClick: (entry: { dataKey?: unknown }) => {
       if (entry.dataKey == null) {
         return;
       }

       const dataKey = String(entry.dataKey) as keyof T;
-      setVisibleLines((prev) => ({
-        ...prev,
-        [dataKey]: !prev[dataKey],
-      }));
+      setVisibleLines((prev) => {
+        if (!(dataKey in prev)) return prev;
+        return {
+          ...prev,
+          [dataKey]: !prev[dataKey],
+        };
+      });
     },
     formatter: (value: string, entry: { dataKey?: unknown }) => {
       const dataKey = entry.dataKey == null ? null : (String(entry.dataKey) as keyof T);

       return (
         <span
           className="text-xs"
           style={{
-            color: dataKey === null || visibleLines[dataKey] ? 'var(--color-text-secondary)' : '`#666`',
+            color:
+              dataKey === null || !(dataKey in visibleLines) || visibleLines[dataKey]
+                ? 'var(--color-text-secondary)'
+                : '`#666`',
           }}
         >

Also applies to: 170-178

🤖 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 `@src/features/market-detail/components/charts/chart-utils.tsx` around lines
159 - 168, The onClick handler toggles any stringified dataKey into
visibleLines, allowing unknown legend keys to be inserted; update the onClick(s)
to first verify membership before updating state (e.g., check that dataKey
exists in the current visibleLines object or use
Object.prototype.hasOwnProperty.call(prev, dataKey) / dataKey in prev) and
return early if it isn’t present, then call setVisibleLines to toggle only known
keys (apply the same guard to the other occurrence around the setVisibleLines
usage).
🤖 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.

Duplicate comments:
In `@src/features/market-detail/components/charts/chart-utils.tsx`:
- Around line 159-168: The onClick handler toggles any stringified dataKey into
visibleLines, allowing unknown legend keys to be inserted; update the onClick(s)
to first verify membership before updating state (e.g., check that dataKey
exists in the current visibleLines object or use
Object.prototype.hasOwnProperty.call(prev, dataKey) / dataKey in prev) and
return early if it isn’t present, then call setVisibleLines to toggle only known
keys (apply the same guard to the other occurrence around the setVisibleLines
usage).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4264dcc3-4765-4b34-8552-d570352c8b79

📥 Commits

Reviewing files that changed from the base of the PR and between 8410f30 and f007c64.

📒 Files selected for processing (11)
  • src/components/common/period-selector.tsx
  • src/data-sources/morpho-api/vault-share-price-history.ts
  • src/features/autovault/components/vault-detail/vault-header.tsx
  • src/features/history/components/transaction-history-preview.tsx
  • src/features/market-detail/components/charts/chart-utils.tsx
  • src/features/position-detail/components/overview-tab.tsx
  • src/features/position-detail/position-view.tsx
  • src/features/vault/components/vault-adapter-position-overview.tsx
  • src/features/vault/components/vault-analytics-period-control.tsx
  • src/features/vault/vault-view.tsx
  • src/hooks/useVaultSharePriceHistory.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/features/position-detail/components/overview-tab.tsx
  • src/features/vault/components/vault-adapter-position-overview.tsx
  • src/features/history/components/transaction-history-preview.tsx
  • src/features/autovault/components/vault-detail/vault-header.tsx
  • src/data-sources/morpho-api/vault-share-price-history.ts
  • src/hooks/useVaultSharePriceHistory.ts
  • src/features/vault/vault-view.tsx

@antoncoding antoncoding merged commit ee03975 into master May 19, 2026
4 checks passed
@antoncoding antoncoding deleted the feat/vault-apy branch May 19, 2026 17:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature request Specific feature ready to be implemented ui User interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant