Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
📝 WalkthroughWalkthroughThe codebase now uses a prioritized fallback for fetching data: it tries the Morpho API first (if supported by the network), and if that fails, falls back to the Subgraph. This pattern is applied across all relevant hooks and contexts. Error handling and logging are improved, and some formatting tweaks were made. Changes
Sequence Diagram(s)sequenceDiagram
participant UI
participant Hook
participant MorphoAPI
participant Subgraph
UI->>Hook: Request data (e.g., market, positions)
alt Morpho API supported
Hook->>MorphoAPI: Fetch data
alt MorphoAPI success
MorphoAPI-->>Hook: Return data
else MorphoAPI fails
Hook->>Subgraph: Fetch data
Subgraph-->>Hook: Return data
end
else Morpho API not supported
Hook->>Subgraph: Fetch data
Subgraph-->>Hook: Return data
end
Hook-->>UI: Return final data
Possibly related PRs
Poem
✨ Finishing Touches
🧪 Generate Unit Tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 5
🔭 Outside diff range comments (1)
src/hooks/useMarketData.ts (1)
60-73: Snapshot numbers need string conversion
Market.state.*is typed asstring. Assigning BigInt / bigint-like values straight fromsnapshotwill break JSON serialisation and can crash React rendering in some browsers.- supplyAssets: snapshot.totalSupplyAssets, - supplyShares: snapshot.totalSupplyShares, - borrowAssets: snapshot.totalBorrowAssets, - borrowShares: snapshot.totalBorrowShares, - liquidityAssets: snapshot.liquidityAssets, + supplyAssets: snapshot.totalSupplyAssets.toString(), + supplyShares: snapshot.totalSupplyShares.toString(), + borrowAssets: snapshot.totalBorrowAssets.toString(), + borrowShares: snapshot.totalBorrowShares.toString(), + liquidityAssets: snapshot.liquidityAssets.toString(),
♻️ Duplicate comments (1)
src/hooks/useMarketBorrows.ts (1)
30-50: Same duplication note as inuseMarketSuppliesThe fetch-with-fallback code is identical. Re-use a shared helper to avoid drift.
🧹 Nitpick comments (7)
src/config/dataSources.ts (1)
32-43: Duplicate switch-statements – extract a constant instead
supportsMorphoApi,getMarketDataSource, andgetHistoricalDataSourceall hard-code the same network list. Keeping them in sync is error-prone.- switch (network) { - case SupportedNetworks.Mainnet: - case SupportedNetworks.Base: - return true; - default: - return false; - } + const MORPHO_API_NETWORKS = new Set([ + SupportedNetworks.Mainnet, + SupportedNetworks.Base, + ]); + return MORPHO_API_NETWORKS.has(network);This removes repetition and makes later extensions single-source.
app/market/[chainId]/[marketid]/content.tsx (1)
134-137: Redundant.catch
handleRefreshAllalready catches and logs; the extra.catchhere never fires unless the call itself throws synchronously. That can’t happen. Dropping it simplifies the wrapper.- void handleRefreshAll().catch((error) => { - console.error('Failed to refresh data:', error); - }); + void handleRefreshAll();src/hooks/useMarketSupplies.ts (1)
30-47: Extract the fallback pattern into a shared utilThe Morpho-first / Subgraph-fallback block appears in every new hook. Copy-pasted logic is harder to keep in sync (retry count, logging, etc.). Consider a helper like
await fetchWithFallback({primary, fallback})to DRY things up.src/hooks/useMarketData.ts (1)
37-47: GuardsupportsMorphoApionceYou already wrap the Morpho call in a
try, so an unsupported network is not exceptional. Instead of anif+tryyou could:try { if (supportsMorphoApi(network)) { finalMarket = await fetchMorphoMarket(uniqueKey, network); } } catch { /* ... */ }Simpler flow, one less indentation level.
src/hooks/useUserPosition.ts (1)
88-109: Factor out duplicated fallback codeThe Morpho→Subgraph fallback logic is repeated three times in this hook alone. A small helper returning
Promise<T | null>would shrink this file and make future changes (timeout, retry) one-liner updates.src/contexts/MarketsContext.tsx (1)
189-197: Consider making the refresh interval configurable.The 5-minute interval is reasonable but could be made configurable for different deployment scenarios.
+ // Could be passed as prop or from config + const REFRESH_INTERVAL_MS = 5 * 60 * 1000; + // Set up refresh interval const refreshInterval = setInterval( () => { void fetchMarkets(true).catch(console.error); }, - 5 * 60 * 1000, + REFRESH_INTERVAL_MS, ); // Refresh every 5 minutessrc/hooks/useUserPositions.ts (1)
193-216: Consider extracting the fallback pattern to a shared utility.Since this Morpho-first, Subgraph-fallback pattern is used across multiple hooks, consider creating a generic utility function.
Would you like me to create a generic fallback utility that can be reused across all these hooks?
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
app/market/[chainId]/[marketid]/content.tsx(2 hunks)src/config/dataSources.ts(1 hunks)src/contexts/MarketsContext.tsx(6 hunks)src/hooks/useLiquidations.ts(2 hunks)src/hooks/useMarketBorrows.ts(2 hunks)src/hooks/useMarketData.ts(4 hunks)src/hooks/useMarketHistoricalData.ts(2 hunks)src/hooks/useMarketLiquidations.ts(2 hunks)src/hooks/useMarketSupplies.ts(2 hunks)src/hooks/useUserPosition.ts(2 hunks)src/hooks/useUserPositions.ts(4 hunks)src/hooks/useUserTransactions.ts(4 hunks)src/utils/tokens.ts(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (8)
app/market/[chainId]/[marketid]/content.tsx (1)
src/utils/external.ts (1)
getMarketURL(3-6)
src/config/dataSources.ts (1)
src/utils/networks.ts (1)
SupportedNetworks(52-52)
src/hooks/useMarketBorrows.ts (4)
src/utils/types.ts (1)
MarketActivityTransaction(378-384)src/config/dataSources.ts (1)
supportsMorphoApi(35-43)src/data-sources/morpho-api/market-borrows.ts (1)
fetchMorphoMarketBorrows(32-64)src/data-sources/subgraph/market-borrows.ts (1)
fetchSubgraphMarketBorrows(31-84)
src/hooks/useMarketLiquidations.ts (4)
src/utils/types.ts (1)
MarketLiquidationTransaction(387-395)src/config/dataSources.ts (1)
supportsMorphoApi(35-43)src/data-sources/morpho-api/market-liquidations.ts (1)
fetchMorphoMarketLiquidations(31-68)src/data-sources/subgraph/market-liquidations.ts (1)
fetchSubgraphMarketLiquidations(41-91)
src/hooks/useLiquidations.ts (3)
src/config/dataSources.ts (1)
supportsMorphoApi(35-43)src/data-sources/morpho-api/liquidations.ts (1)
fetchMorphoApiLiquidatedMarketKeys(56-119)src/data-sources/subgraph/liquidations.ts (1)
fetchSubgraphLiquidatedMarketKeys(20-76)
src/hooks/useMarketData.ts (3)
src/config/dataSources.ts (1)
supportsMorphoApi(35-43)src/data-sources/morpho-api/market.ts (1)
fetchMorphoMarket(45-57)src/data-sources/subgraph/market.ts (1)
fetchSubgraphMarket(296-326)
src/hooks/useMarketSupplies.ts (4)
src/utils/types.ts (1)
MarketActivityTransaction(378-384)src/config/dataSources.ts (1)
supportsMorphoApi(35-43)src/data-sources/morpho-api/market-supplies.ts (1)
fetchMorphoMarketSupplies(33-73)src/data-sources/subgraph/market-supplies.ts (1)
fetchSubgraphMarketSupplies(33-96)
src/hooks/useUserTransactions.ts (4)
src/config/dataSources.ts (1)
supportsMorphoApi(35-43)src/utils/types.ts (1)
UserTransaction(29-41)src/data-sources/morpho-api/transactions.ts (1)
fetchMorphoTransactions(14-68)src/data-sources/subgraph/transactions.ts (1)
fetchSubgraphTransactions(125-208)
🔇 Additional comments (4)
src/utils/tokens.ts (1)
466-468: Trailing comma change is finePure formatting – no impact on code paths.
src/contexts/MarketsContext.tsx (2)
93-119: Good fallback implementation!The two-step fallback pattern with detailed logging provides resilience and transparency.
81-81: Verify Unichain support in data sources.Ensure that Unichain is properly supported in either Morpho API or Subgraph before adding it to the fetch list.
#!/bin/bash # Check if Unichain is supported in supportsMorphoApi function ast-grep --pattern 'supportsMorphoApi = $_($$$) => { $$$ }' # Check for Unichain references in data source configurations rg -A 5 "Unichain" src/config/ src/data-sources/src/hooks/useUserPositions.ts (1)
108-134: Nice abstraction of the fallback pattern!The
fetchMarketDatahelper cleanly encapsulates the Morpho-first, Subgraph-fallback pattern.
| // If Morpho API failed or not supported, try Subgraph | ||
| if (!historicalData) { | ||
| try { | ||
| console.log(`Attempting to fetch historical data via Subgraph for ${uniqueKey}`); | ||
| historicalData = await fetchSubgraphMarketHistoricalData(uniqueKey, network, options); | ||
| } catch (subgraphError) { | ||
| console.error(`Failed to fetch historical data via Subgraph:`, subgraphError); | ||
| historicalData = null; | ||
| } | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Same silent-failure pattern as liquidations hook
If both sources fail we swallow the exception, error is unset, and consumers think data is just empty. Please propagate the last error (or aggregate both). Returning null vs empty structure also forces extra guarding code later.
Replicate the fix shown in useMarketLiquidations.
🤖 Prompt for AI Agents
In src/hooks/useMarketHistoricalData.ts around lines 50 to 59, the code silently
swallows errors when both Morpho API and Subgraph fetches fail, leaving the
error unset and causing consumers to misinterpret the data as simply empty.
Modify the code to propagate the last caught error (or combine errors if both
fail) instead of setting historicalData to null, ensuring the error state is
properly communicated to consumers, similar to the fix applied in
useMarketLiquidations.
| // Try Morpho API first if supported | ||
| if (supportsMorphoApi(network)) { | ||
| try { | ||
| console.log(`Attempting to fetch liquidated markets via Morpho API for ${network}`); | ||
| networkLiquidatedKeys = await fetchMorphoApiLiquidatedMarketKeys(network); | ||
| } catch (morphoError) { | ||
| console.error(`Failed to fetch liquidated markets via Morpho API:`, morphoError); | ||
| // Continue to Subgraph fallback | ||
| networkLiquidatedKeys = new Set(); | ||
| } | ||
| } else { | ||
| console.warn(`No valid data source found for network ${network} for liquidations.`); | ||
| networkLiquidatedKeys = new Set<string>(); // Assume none if no source | ||
| networkLiquidatedKeys = new Set(); | ||
| } | ||
|
|
||
| // If Morpho API failed or not supported, try Subgraph | ||
| if (networkLiquidatedKeys.size === 0) { | ||
| try { | ||
| console.log(`Attempting to fetch liquidated markets via Subgraph for ${network}`); | ||
| networkLiquidatedKeys = await fetchSubgraphLiquidatedMarketKeys(network); | ||
| } catch (subgraphError) { | ||
| console.error(`Failed to fetch liquidated markets via Subgraph:`, subgraphError); | ||
| throw subgraphError; // Throw to be caught by outer catch | ||
| } | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Uninitialised variable risk
let networkLiquidatedKeys: Set<string>; is declared but may stay undefined if both data sources throw.
Using const networkLiquidatedKeys = new Set<string>(); at declaration avoids the extra else { new Set() } and the possible undefined dereference later.
🤖 Prompt for AI Agents
In src/hooks/useLiquidations.ts around lines 36 to 59, the variable
networkLiquidatedKeys is declared without initialization and may remain
undefined if both Morpho API and Subgraph fetches fail, risking undefined
dereference. To fix this, initialize networkLiquidatedKeys as an empty
Set<string> at declaration using const, then update it as needed. This removes
the need for else blocks assigning new Sets and ensures networkLiquidatedKeys is
always defined.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/data-sources/morpho-api/transactions.ts (1)
61-67: Return typed errors instead of string fall-backs
errmay beunknown. Converting toErrorhere keeps type safety and preserves stack traces.- return { - items: [], - pageInfo: { count: 0, countTotal: 0 }, - error: err instanceof Error ? err.message : 'Unknown Morpho API error occurred', - }; + const message = + err instanceof Error ? err.message : JSON.stringify(err); + return { + items: [], + pageInfo: { count: 0, countTotal: 0 }, + error: message, + };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/config/dataSources.ts(1 hunks)src/data-sources/morpho-api/transactions.ts(1 hunks)src/hooks/useUserTransactions.ts(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/config/dataSources.ts
- src/hooks/useUserTransactions.ts
| // disable cuz it's too long | ||
| // if (filters.marketUniqueKeys && filters.marketUniqueKeys.length > 0) { | ||
| // whereClause.marketUniqueKey_in = filters.marketUniqueKeys; | ||
| // } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Ignoring marketUniqueKeys drops an expected filter
filters.marketUniqueKeys is still accepted by callers but silently discarded.
Down-stream code that relies on this filter will now process extra markets, which can blow up payload size and break UI assumptions.
Options:
-// disable cuz it's too long
-// if (filters.marketUniqueKeys && filters.marketUniqueKeys.length > 0) {
-// whereClause.marketUniqueKey_in = filters.marketUniqueKeys;
-// }
+// Morpho API rejects very long `IN` arrays (~5 KB limit). Chunk and merge.
+if (filters.marketUniqueKeys?.length) {
+ const CHUNK = 50;
+ const chunks = [];
+ for (let i = 0; i < filters.marketUniqueKeys.length; i += CHUNK) {
+ chunks.push({ ...whereClause, marketUniqueKey_in: filters.marketUniqueKeys.slice(i, i + CHUNK) });
+ }
+ return mergeResponses(
+ await Promise.all(chunks.map((w) => query(w)))
+ );
+}If the size limit is the real reason, chunking or a server-side alias is safer than dropping the filter.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // disable cuz it's too long | |
| // if (filters.marketUniqueKeys && filters.marketUniqueKeys.length > 0) { | |
| // whereClause.marketUniqueKey_in = filters.marketUniqueKeys; | |
| // } | |
| // Morpho API rejects very long `IN` arrays (~5 KB limit). Chunk and merge. | |
| if (filters.marketUniqueKeys?.length) { | |
| const CHUNK = 50; | |
| const chunks = []; | |
| for (let i = 0; i < filters.marketUniqueKeys.length; i += CHUNK) { | |
| chunks.push({ | |
| ...whereClause, | |
| marketUniqueKey_in: filters.marketUniqueKeys.slice(i, i + CHUNK), | |
| }); | |
| } | |
| return mergeResponses( | |
| await Promise.all(chunks.map((w) => query(w))) | |
| ); | |
| } |
🤖 Prompt for AI Agents
In src/data-sources/morpho-api/transactions.ts around lines 24 to 27, the code
currently ignores the filters.marketUniqueKeys filter by commenting it out,
which causes unexpected behavior downstream. To fix this, re-enable the filter
logic for marketUniqueKeys and implement a solution to handle large arrays
safely, such as chunking the filter values into smaller batches or using a
server-side alias to limit the size, ensuring the filter is applied without
causing payload or UI issues.
Summary by CodeRabbit
New Features
Bug Fixes
Refactor