From 5622e18fba705d04d3dcd553c2420cf724855acc Mon Sep 17 00:00:00 2001 From: starksama <257340800+starksama@users.noreply.github.com> Date: Sat, 31 Jan 2026 17:51:39 +0800 Subject: [PATCH] feat: add 7d and 30d APY columns to markets list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add weeklySupplyApy, weeklyBorrowApy, monthlySupplyApy, monthlyBorrowApy to GraphQL query state - Update Market type to include new APY fields (nullable for graceful handling) - Add 4 new toggleable columns: 7d Supply, 7d Borrow, 30d Supply, 30d Borrow - All new columns are sortable with null values sorted to the end - Display "—" placeholder for null values (backup subgraph, new markets) - Subgraph data source returns null for these fields (not supported) Closes #349 --- src/data-sources/subgraph/market.ts | 5 ++ .../markets/components/column-visibility.ts | 16 ++++++ src/features/markets/components/constants.ts | 4 ++ .../components/table/market-table-body.tsx | 50 ++++++++++++++++++- .../components/table/markets-table.tsx | 36 +++++++++++++ src/graphql/morpho-api-queries.ts | 8 +++ src/hooks/useFilteredMarkets.ts | 4 ++ src/utils/types.ts | 6 +++ 8 files changed, 128 insertions(+), 1 deletion(-) diff --git a/src/data-sources/subgraph/market.ts b/src/data-sources/subgraph/market.ts index 3bbdb786..1f51e129 100644 --- a/src/data-sources/subgraph/market.ts +++ b/src/data-sources/subgraph/market.ts @@ -188,6 +188,11 @@ const transformSubgraphMarketToMarket = ( timestamp, apyAtTarget: 0, rateAtTarget: '0', + // Subgraph doesn't support weekly/monthly APY - return null + weeklySupplyApy: null, + weeklyBorrowApy: null, + monthlySupplyApy: null, + monthlyBorrowApy: null, }, oracleAddress, morphoBlue: { diff --git a/src/features/markets/components/column-visibility.ts b/src/features/markets/components/column-visibility.ts index cdf57637..d6cf8aed 100644 --- a/src/features/markets/components/column-visibility.ts +++ b/src/features/markets/components/column-visibility.ts @@ -9,6 +9,10 @@ export type ColumnVisibility = { rateAtTarget: boolean; trustedBy: boolean; utilizationRate: boolean; + weeklySupplyAPY: boolean; + weeklyBorrowAPY: boolean; + monthlySupplyAPY: boolean; + monthlyBorrowAPY: boolean; }; export const DEFAULT_COLUMN_VISIBILITY: ColumnVisibility = { @@ -20,6 +24,10 @@ export const DEFAULT_COLUMN_VISIBILITY: ColumnVisibility = { rateAtTarget: false, trustedBy: false, utilizationRate: false, + weeklySupplyAPY: false, + weeklyBorrowAPY: false, + monthlySupplyAPY: false, + monthlyBorrowAPY: false, }; export const COLUMN_LABELS: Record = { @@ -31,6 +39,10 @@ export const COLUMN_LABELS: Record = { rateAtTarget: 'Target Rate', trustedBy: 'Trusted By', utilizationRate: 'Utilization', + weeklySupplyAPY: '7d Supply APY', + weeklyBorrowAPY: '7d Borrow APY', + monthlySupplyAPY: '30d Supply APY', + monthlyBorrowAPY: '30d Borrow APY', }; export const COLUMN_DESCRIPTIONS: Record = { @@ -42,4 +54,8 @@ export const COLUMN_DESCRIPTIONS: Record = { rateAtTarget: 'Interest rate at target utilization', trustedBy: 'Highlights your trusted vaults that currently supply this market', utilizationRate: 'Percentage of supplied assets currently borrowed', + weeklySupplyAPY: '7-day average supply APY', + weeklyBorrowAPY: '7-day average borrow APY', + monthlySupplyAPY: '30-day average supply APY', + monthlyBorrowAPY: '30-day average borrow APY', }; diff --git a/src/features/markets/components/constants.ts b/src/features/markets/components/constants.ts index 10acd846..d8f40472 100644 --- a/src/features/markets/components/constants.ts +++ b/src/features/markets/components/constants.ts @@ -12,6 +12,10 @@ export enum SortColumn { TrustedBy = 11, UtilizationRate = 12, Trend = 13, + WeeklySupplyAPY = 14, + WeeklyBorrowAPY = 15, + MonthlySupplyAPY = 16, + MonthlyBorrowAPY = 17, } // Gas cost to simplify tx flow: do not need to estimate gas for transactions diff --git a/src/features/markets/components/table/market-table-body.tsx b/src/features/markets/components/table/market-table-body.tsx index 05a7480b..9f683f3b 100644 --- a/src/features/markets/components/table/market-table-body.tsx +++ b/src/features/markets/components/table/market-table-body.tsx @@ -44,7 +44,11 @@ export function MarketTableBody({ currentEntries, expandedRowId, setExpandedRowI (columnVisibility.borrowAPY ? 1 : 0) + (columnVisibility.rateAtTarget ? 1 : 0) + (columnVisibility.trustedBy ? 1 : 0) + - (columnVisibility.utilizationRate ? 1 : 0); + (columnVisibility.utilizationRate ? 1 : 0) + + (columnVisibility.weeklySupplyAPY ? 1 : 0) + + (columnVisibility.weeklyBorrowAPY ? 1 : 0) + + (columnVisibility.monthlySupplyAPY ? 1 : 0) + + (columnVisibility.monthlyBorrowAPY ? 1 : 0); const getTrustedVaultsForMarket = (market: Market): TrustedVault[] => { if (!columnVisibility.trustedBy || !market.supplyingVaults?.length) { @@ -229,6 +233,50 @@ export function MarketTableBody({ currentEntries, expandedRowId, setExpandedRowI

{`${(item.state.utilization * 100).toFixed(2)}%`}

)} + {columnVisibility.weeklySupplyAPY && ( + +

+ {item.state.weeklySupplyApy != null ? : '—'} +

+
+ )} + {columnVisibility.weeklyBorrowAPY && ( + +

+ {item.state.weeklyBorrowApy != null ? : '—'} +

+
+ )} + {columnVisibility.monthlySupplyAPY && ( + +

+ {item.state.monthlySupplyApy != null ? : '—'} +

+
+ )} + {columnVisibility.monthlyBorrowAPY && ( + +

+ {item.state.monthlyBorrowApy != null ? : '—'} +

+
+ )} diff --git a/src/features/markets/components/table/markets-table.tsx b/src/features/markets/components/table/markets-table.tsx index c8c77722..e0c99ae3 100644 --- a/src/features/markets/components/table/markets-table.tsx +++ b/src/features/markets/components/table/markets-table.tsx @@ -239,6 +239,42 @@ function MarketsTable({ currentPage, setCurrentPage, className, tableClassName, targetColumn={SortColumn.UtilizationRate} /> )} + {columnVisibility.weeklySupplyAPY && ( + + )} + {columnVisibility.weeklyBorrowAPY && ( + + )} + {columnVisibility.monthlySupplyAPY && ( + + )} + {columnVisibility.monthlyBorrowAPY && ( + + )} { [SortColumn.TrustedBy]: '', [SortColumn.UtilizationRate]: 'state.utilization', [SortColumn.Trend]: '', // Trend is a filter mode, not a sort + [SortColumn.WeeklySupplyAPY]: 'state.weeklySupplyApy', + [SortColumn.WeeklyBorrowAPY]: 'state.weeklyBorrowApy', + [SortColumn.MonthlySupplyAPY]: 'state.monthlySupplyApy', + [SortColumn.MonthlyBorrowAPY]: 'state.monthlyBorrowApy', }; const propertyPath = sortPropertyMap[preferences.sortColumn]; diff --git a/src/utils/types.ts b/src/utils/types.ts index 77b76348..fd3654a9 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -321,6 +321,12 @@ export type Market = { apyAtTarget: number; rateAtTarget: string; + + // Weekly and monthly APY averages (may be null for new markets or backup subgraph) + weeklySupplyApy: number | null; + weeklyBorrowApy: number | null; + monthlySupplyApy: number | null; + monthlyBorrowApy: number | null; }; realizedBadDebt: { underlying: string;