diff --git a/app/markets/components/MarketTableBody.tsx b/app/markets/components/MarketTableBody.tsx
index 0d30170a..ceea24ae 100644
--- a/app/markets/components/MarketTableBody.tsx
+++ b/app/markets/components/MarketTableBody.tsx
@@ -54,7 +54,8 @@ export function MarketTableBody({
(columnVisibility.supplyAPY ? 1 : 0) +
(columnVisibility.borrowAPY ? 1 : 0) +
(columnVisibility.rateAtTarget ? 1 : 0) +
- (columnVisibility.trustedBy ? 1 : 0);
+ (columnVisibility.trustedBy ? 1 : 0) +
+ (columnVisibility.utilizationRate ? 1 : 0);
const getTrustedVaultsForMarket = (market: Market): TrustedVault[] => {
if (!columnVisibility.trustedBy || !market.supplyingVaults?.length) {
@@ -216,6 +217,13 @@ export function MarketTableBody({
)}
+ {columnVisibility.utilizationRate && (
+
+
+ {`${(item.state.utilization * 100).toFixed(2)}%`}
+
+ |
+ )}
diff --git a/app/markets/components/columnVisibility.ts b/app/markets/components/columnVisibility.ts
index eba18bd4..cdf57637 100644
--- a/app/markets/components/columnVisibility.ts
+++ b/app/markets/components/columnVisibility.ts
@@ -8,6 +8,7 @@ export type ColumnVisibility = {
borrowAPY: boolean;
rateAtTarget: boolean;
trustedBy: boolean;
+ utilizationRate: boolean;
};
export const DEFAULT_COLUMN_VISIBILITY: ColumnVisibility = {
@@ -18,6 +19,7 @@ export const DEFAULT_COLUMN_VISIBILITY: ColumnVisibility = {
borrowAPY: false,
rateAtTarget: false,
trustedBy: false,
+ utilizationRate: false,
};
export const COLUMN_LABELS: Record = {
@@ -28,6 +30,7 @@ export const COLUMN_LABELS: Record = {
borrowAPY: 'Borrow APY',
rateAtTarget: 'Target Rate',
trustedBy: 'Trusted By',
+ utilizationRate: 'Utilization',
};
export const COLUMN_DESCRIPTIONS: Record = {
@@ -38,4 +41,5 @@ export const COLUMN_DESCRIPTIONS: Record = {
borrowAPY: 'Annual percentage rate for borrowers',
rateAtTarget: 'Interest rate at target utilization',
trustedBy: 'Highlights your trusted vaults that currently supply this market',
+ utilizationRate: 'Percentage of supplied assets currently borrowed',
};
diff --git a/app/markets/components/constants.ts b/app/markets/components/constants.ts
index 0d446665..7b313484 100644
--- a/app/markets/components/constants.ts
+++ b/app/markets/components/constants.ts
@@ -10,6 +10,7 @@ export enum SortColumn {
BorrowAPY = 9,
RateAtTarget = 10,
TrustedBy = 11,
+ UtilizationRate = 12,
}
// Gas cost to simplify tx flow: do not need to estimate gas for transactions
diff --git a/app/markets/components/markets.tsx b/app/markets/components/markets.tsx
index 24a0575e..0bfe2b33 100644
--- a/app/markets/components/markets.tsx
+++ b/app/markets/components/markets.tsx
@@ -341,6 +341,7 @@ export default function Markets({
[SortColumn.BorrowAPY]: 'state.borrowApy',
[SortColumn.RateAtTarget]: 'state.apyAtTarget',
[SortColumn.TrustedBy]: '',
+ [SortColumn.UtilizationRate]: 'state.utilization',
};
const propertyPath = sortPropertyMap[sortColumn];
if (propertyPath) {
diff --git a/app/markets/components/marketsTable.tsx b/app/markets/components/marketsTable.tsx
index ec6d21fd..4c04ef29 100644
--- a/app/markets/components/marketsTable.tsx
+++ b/app/markets/components/marketsTable.tsx
@@ -174,6 +174,15 @@ function MarketsTable({
targetColumn={SortColumn.RateAtTarget}
/>
)}
+ {columnVisibility.utilizationRate && (
+
+ )}
| Risk |
Indicators |
Actions |
diff --git a/app/markets/components/utils.ts b/app/markets/components/utils.ts
deleted file mode 100644
index 6786ba28..00000000
--- a/app/markets/components/utils.ts
+++ /dev/null
@@ -1,162 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unsafe-assignment */
-
-import { SupportedNetworks } from '@/utils/networks';
-import { parsePriceFeedVendors, PriceFeedVendors, getOracleType, OracleType } from '@/utils/oracle';
-import { ERC20Token } from '@/utils/tokens';
-import { Market } from '@/utils/types';
-import { SortColumn } from './constants';
-
-export const sortProperties = {
- [SortColumn.Starred]: 'uniqueKey',
- [SortColumn.LoanAsset]: 'loanAsset.name',
- [SortColumn.CollateralAsset]: 'collateralAsset.name',
- [SortColumn.LLTV]: 'lltv',
- [SortColumn.Supply]: 'state.supplyAssetsUsd',
- [SortColumn.Borrow]: 'state.borrowAssetsUsd',
- [SortColumn.SupplyAPY]: 'state.supplyApy',
- [SortColumn.Liquidity]: 'state.liquidityAssets',
- [SortColumn.BorrowAPY]: 'state.borrowApy',
- [SortColumn.RateAtTarget]: 'state.apyAtTarget',
- [SortColumn.TrustedBy]: 'uniqueKey',
-};
-
-export const getNestedProperty = (obj: Market, path: string | ((item: Market) => number)) => {
- if (typeof path === 'function') {
- return path(obj);
- }
-
- if (!path) {
- return undefined;
- }
-
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
- return path.split('.').reduce((acc, part) => acc && acc[part], obj as any);
-};
-
-const isSelectedAsset = (
- market: Market,
- selectedAssetKeys: string[],
- type: 'collateral' | 'loan',
-) => {
- return selectedAssetKeys.find((combinedKey) =>
- combinedKey
- .split('|')
- .includes(
- `${(type === 'collateral'
- ? market.collateralAsset
- : market.loanAsset
- ).address.toLowerCase()}-${market.morphoBlue.chain.id}`,
- ),
- );
-};
-
-// Define the type for USD Filters
-type UsdFilters = {
- minSupply: string;
- minBorrow: string;
-};
-
-export function applyFilterAndSort(
- markets: Market[],
- sortColumn: SortColumn,
- sortDirection: number,
- selectedNetwork: SupportedNetworks | null,
- showUnknown: boolean,
- showUnknownOracle: boolean,
- selectedCollaterals: string[],
- selectedLoanAssets: string[],
- selectedOracles: PriceFeedVendors[],
- staredIds: string[],
- findToken: (address: string, chainId: number) => ERC20Token | undefined,
- usdFilters: UsdFilters,
- hideSmallMarkets?: boolean,
-): Market[] {
- const parseUsdValue = (value: string | null | undefined): number | null => {
- if (value === null || value === undefined || value === '') return null;
- const num = parseFloat(value);
- return isNaN(num) ? null : num;
- };
-
- const minSupplyUsd = parseUsdValue(usdFilters.minSupply);
- const minBorrowUsd = parseUsdValue(usdFilters.minBorrow);
-
- return markets
- .filter((market) => {
- if (selectedNetwork !== null && market.morphoBlue.chain.id !== selectedNetwork) {
- return false;
- }
-
- // todo: might need async function to search for tokens from API.
- const collateralToken = findToken(market.collateralAsset.address, market.morphoBlue.chain.id);
- const loanToken = findToken(market.loanAsset.address, market.morphoBlue.chain.id);
-
- if (!showUnknown && (!collateralToken || !loanToken)) {
- return false;
- }
-
- if (!showUnknownOracle) {
- const info = market.oracle
- ? parsePriceFeedVendors(market.oracle.data, market.morphoBlue.chain.id)
- : null;
- const isCustom =
- getOracleType(market.oracle?.data, market.oracleAddress, market.morphoBlue.chain.id) ===
- OracleType.Custom;
- const isUnknown = isCustom || (info?.hasUnknown ?? false);
- if (!market.oracle || isUnknown) return false;
- }
-
- if (
- (selectedCollaterals.length > 0 &&
- !isSelectedAsset(market, selectedCollaterals, 'collateral')) ||
- (selectedLoanAssets.length > 0 && !isSelectedAsset(market, selectedLoanAssets, 'loan'))
- ) {
- return false;
- }
-
- if (selectedOracles.length > 0 && !!market.oracle) {
- const marketOracles = parsePriceFeedVendors(
- market.oracle.data,
- market.morphoBlue.chain.id,
- ).vendors;
- if (!marketOracles.some((oracle) => selectedOracles.includes(oracle))) {
- return false;
- }
- }
-
- // Add USD Filters - only apply if hideSmallMarkets is true (or undefined for backwards compatibility)
- if (hideSmallMarkets !== false) {
- const supplyUsd = parseUsdValue(market.state?.supplyAssetsUsd?.toString()); // Use optional chaining
- const borrowUsd = parseUsdValue(market.state?.borrowAssetsUsd?.toString()); // Use optional chaining
-
- if (minSupplyUsd !== null && (supplyUsd === null || supplyUsd < minSupplyUsd)) {
- return false;
- }
- if (minBorrowUsd !== null && (borrowUsd === null || borrowUsd < minBorrowUsd)) {
- return false;
- }
- }
- // End USD Filters
-
- return true;
- })
- .sort((a, b) => {
- let comparison = 0;
- if (sortColumn === SortColumn.Starred) {
- const aStared = staredIds.includes(a.uniqueKey);
- const bStared = staredIds.includes(b.uniqueKey);
- if (aStared && !bStared) return -1;
- if (!aStared && bStared) return 1;
- return 0;
- } else {
- const property = sortProperties[sortColumn];
- if (!property) {
- return 0;
- }
-
- const aValue = getNestedProperty(a, property);
- const bValue = getNestedProperty(b, property);
- comparison = aValue > bValue ? 1 : aValue < bValue ? -1 : 0;
- }
- return comparison * sortDirection;
- });
-}
diff --git a/src/components/common/MarketsTableWithSameLoanAsset.tsx b/src/components/common/MarketsTableWithSameLoanAsset.tsx
index d17bace3..38dcfa2b 100644
--- a/src/components/common/MarketsTableWithSameLoanAsset.tsx
+++ b/src/components/common/MarketsTableWithSameLoanAsset.tsx
@@ -73,6 +73,7 @@ enum SortColumn {
RateAtTarget = 6,
Risk = 7,
TrustedBy = 8,
+ UtilizationRate = 9,
}
function getTrustedVaultsForMarket(
@@ -533,6 +534,13 @@ function MarketRow({
|
)}
+ {columnVisibility.utilizationRate && (
+
+
+ {`${(market.state.utilization * 100).toFixed(2)}%`}
+
+ |
+ )}
|
@@ -778,6 +786,7 @@ export function MarketsTableWithSameLoanAsset({
[SortColumn.RateAtTarget]: 'state.apyAtTarget',
[SortColumn.Risk]: '', // No sorting for risk
[SortColumn.TrustedBy]: '',
+ [SortColumn.UtilizationRate]: 'state.utilization',
};
const propertyPath = sortPropertyMap[sortColumn];
@@ -826,7 +835,15 @@ export function MarketsTableWithSameLoanAsset({
const safePage = Math.min(Math.max(1, currentPage), totalPages);
const startIndex = (safePage - 1) * safePerPage;
const paginatedMarkets = processedMarkets.slice(startIndex, startIndex + safePerPage);
- const emptyStateColumns = (showSelectColumn ? 7 : 6) + (columnVisibility.trustedBy ? 1 : 0);
+ const emptyStateColumns = (showSelectColumn ? 7 : 6) +
+ (columnVisibility.trustedBy ? 1 : 0) +
+ (columnVisibility.totalSupply ? 1 : 0) +
+ (columnVisibility.totalBorrow ? 1 : 0) +
+ (columnVisibility.liquidity ? 1 : 0) +
+ (columnVisibility.supplyAPY ? 1 : 0) +
+ (columnVisibility.borrowAPY ? 1 : 0) +
+ (columnVisibility.rateAtTarget ? 1 : 0) +
+ (columnVisibility.utilizationRate ? 1 : 0);
React.useEffect(() => {
setCurrentPage(1);
@@ -1020,6 +1037,15 @@ export function MarketsTableWithSameLoanAsset({
onSort={handleSort}
/>
)}
+ {columnVisibility.utilizationRate && (
+
+ )}
Indicators |