diff --git a/components/F2/UserDashboard.tsx b/components/F2/UserDashboard.tsx
index 785509b4a..ebf8525c8 100644
--- a/components/F2/UserDashboard.tsx
+++ b/components/F2/UserDashboard.tsx
@@ -163,12 +163,13 @@ export const MonthlyRewards = ({
}
-const NumberItem = ({ noDataFallback = '-', href = '', footer = undefined, isLoading = false, value = 0, price = undefined, label = '', isUsd = false, precision = 0 }) => {
+const NumberItem = ({ noDataFallback = '-', href = '', footer = undefined, isLoading = false, value = 0, price = undefined, label = '', isUsd = false, precision = 0, isPerc = false }) => {
return
{
isLoading ? :
{!value ? noDataFallback : value > 100000 ? smartShortNumber(value, 2, isUsd) : preciseCommify(value, precision, isUsd)}{!!price && !!value ? ` (${smartShortNumber(value * price, 2, true)})` : ''}
+ {!!value && isPerc ? "%" : null}
}
{
@@ -183,9 +184,9 @@ const NumberItem = ({ noDataFallback = '-', href = '', footer = undefined, isLoa
}
-export const NumberCard = ({ imageSrc = '', noDataFallback = undefined, href = undefined, footer = undefined, isLoading = false, value = 0, label = '', price = undefined, isUsd = false, precision = 0 }) => {
+export const NumberCard = ({ imageSrc = '', noDataFallback = undefined, href = undefined, footer = undefined, isLoading = false, value = 0, label = '', price = undefined, isUsd = false, precision = 0, isPerc = false }) => {
return
-
+
}
diff --git a/components/F2/liquidations/firm-positions.tsx b/components/F2/liquidations/firm-positions.tsx
index 0c9f43869..bca3d834e 100644
--- a/components/F2/liquidations/firm-positions.tsx
+++ b/components/F2/liquidations/firm-positions.tsx
@@ -12,7 +12,7 @@ import { SkeletonBlob } from "@app/components/common/Skeleton";
import { SmallTextLoader } from "@app/components/common/Loaders/SmallTextLoader";
import { FirmPositionsTable } from "../Infos/FirmPositionsTable";
-const groupPositionsBy = (positions: any[], groupBy: string, attributeToSum: string) => {
+export const groupPositionsBy = (positions: any[], groupBy: string, attributeToSum: string) => {
return Object.entries(
positions.reduce((prev, curr) => {
return { ...prev, [curr[groupBy]]: (prev[curr[groupBy]] || 0) + curr[attributeToSum] };
diff --git a/components/Transparency/TransparencyTabs.tsx b/components/Transparency/TransparencyTabs.tsx
index 780af7f4c..a457d8624 100644
--- a/components/Transparency/TransparencyTabs.tsx
+++ b/components/Transparency/TransparencyTabs.tsx
@@ -2,10 +2,10 @@ import { useAppTheme } from '@app/hooks/useAppTheme';
import { Tabs, TabList, Tab, VStack, Text, HStack, Image } from '@chakra-ui/react'
import Link from '../common/Link';
-type TabsType = 'overview' | 'treasury' | 'veNfts' | 'liquidity' | 'inv' | 'dola' | 'dbr' | 'multisigs' | 'interest-model' | 'feds' | 'stabilizer' | 'dao' | 'shortfalls' | 'bad-debts';
+type TabsType = 'overview' | 'keymetrics' | 'treasury' | 'veNfts' | 'liquidity' | 'inv' | 'dola' | 'dbr' | 'multisigs' | 'interest-model' | 'feds' | 'stabilizer' | 'dao' | 'shortfalls' | 'bad-debts';
const TABS = [
- // { page: 'overview', label: 'Overview' },
+ { page: 'keymetrics', label: 'Key Metrics' },
{ page: 'treasury', label: 'Treasury' },
{ page: 'veNfts', label: 'veNfts' },
{ page: 'liquidity', label: 'Liquidity' },
diff --git a/next.config.js b/next.config.js
index 768650404..5e4501788 100644
--- a/next.config.js
+++ b/next.config.js
@@ -119,8 +119,8 @@ const redirects = async () => {
},
{
source: '/transparency',
- destination: '/transparency/overview',
- permanent: true,
+ destination: '/transparency/keymetrics',
+ permanent: false,
},
{
source: '/banking',
diff --git a/pages/firm/[market].tsx b/pages/firm/[market].tsx
index bf8ff3ca2..408bdeb0c 100644
--- a/pages/firm/[market].tsx
+++ b/pages/firm/[market].tsx
@@ -21,7 +21,7 @@ import { FirmRewardWrapper } from '@app/components/F2/rewards/FirmRewardWrapper'
import { CvxCrvPreferences } from '@app/components/F2/rewards/CvxCrvPreferences'
import { DailyLimitCountdown } from '@app/components/common/Countdown'
import Container from '@app/components/common/Container'
-import { InfoMessage } from '@app/components/common/Messages'
+import { InfoMessage, WarningMessage } from '@app/components/common/Messages'
import { shortenNumber } from '@app/util/markets'
import { preciseCommify } from '@app/util/misc'
import { WorthEvoChartWrapper } from '@app/components/F2/WorthEvoChartContainer'
@@ -136,7 +136,7 @@ export const F2MarketPage = ({ market }: { market: string }) => {
{
- isMultisig && {
}
+export const DolaBadDebtRepaymentProgressBar = ({
+ progress,
+}: {
+ progress: number
+}) => {
+ const [isSmallerThan] = useMediaQuery('(max-width: 1150px)');
+ return
+
+ {!isSmallerThan && 0%}
+
+ {progress > 0 && !isSmallerThan && {shortenNumber(progress, 2)}%}
+ {
+ !isSmallerThan ?
+
+ :
+
+ {shortenNumber(progress, 2)}%
+
+
+ }
+
+ {!isSmallerThan! && 100%}
+
+
+}
+
const transactionsColumns = [
{
field: 'symbol',
@@ -353,8 +379,7 @@ export const BadDebtPage = () => {
const { prices } = usePrices();
const [selected, setSelected] = useState('all');
const isAllCase = selected === 'all';
- const isDolaCase = selected.toLowerCase().includes('dola');
- const [isSmallerThan] = useMediaQuery('(max-width: 1150px)')
+ const isDolaCase = selected.toLowerCase().includes('dola');
const dolaPrice = !!prices ? prices['dola-usd']?.usd : 1;
const totalDirectRepaymentsForTable = totalRepaymentKeys.map(key => {
@@ -452,24 +477,7 @@ export const BadDebtPage = () => {
-
-
- {!isSmallerThan && 0%}
-
- {dolaBadDebtRepaidProgress > 0 && !isSmallerThan && {shortenNumber(dolaBadDebtRepaidProgress, 2)}%}
- {
- !isSmallerThan ?
-
- :
-
- {shortenNumber(dolaBadDebtRepaidProgress, 2)}%
-
-
- }
-
- {!isSmallerThan! && 100%}
-
-
+
{
barProps={{ eventName: 'Repayment' }}
areaProps={{ id: 'bad-debt-chart', showRangeBtns: true, defaultRange: '1Y', rangesToInclude: ['All', 'YTD', '1Y', '6M', '3M', '7D'], yLabel: 'DOLA bad debt', useRecharts: true, fillInByDayInterval: 1, simplifyData: false, showEvents: true, showEventsLabels: true, domainYpadding: 1000000, showMaxY: false, showTooltips: true, autoMinY: true, mainColor: 'info', allowZoom: true }}
/>
-
{
- return
+export const DolaBackingLegend = (props) => {
+ return
{
LEGEND_ITEMS.map((item, index) => {
return
@@ -52,23 +52,16 @@ const Legend = () => {
})
}
-
+
}
-export const DolaDiagram = () => {
- const { themeStyles } = useAppTheme();
- const { dolaSupplies } = useDAO();
- const { markets, isLoading } = useDBRMarkets();
- const { fedOverviews, isLoading: isLoadingOverview } = useFedOverview();
- const { data, isLoading: isLoadingRepayments } = useRepayments();
- const { prices } = usePrices(['velodrome-finance']);
-
- const fedsPieChartData = fedOverviews.map(f => {
+export const fedsDataToPieChart = (fedOverviews: any[], colors) => {
+ return fedOverviews.map(f => {
const name = f.type === 'AMM' ?
`${f.name} ` + (f.subBalances.reduce((acc, curr) => acc ? acc + '-' + curr.symbol : curr.symbol, '') + ' LP')
: f.name;
const balance = ['FiRM', 'Frontier'].includes(f.protocol) ? f.borrows : f.supply;
- const color = ['Frontier', 'Fuse'].includes(f.protocol) ? themeStyles.colors.error : f.protocol === 'FiRM' ? themeStyles.colors.success : themeStyles.colors.info;
+ const color = ['Frontier', 'Fuse'].includes(f.protocol) ? colors.error : f.protocol === 'FiRM' ? colors.success : colors.info;
return {
...f,
token: { symbol: name },
@@ -81,6 +74,17 @@ export const DolaDiagram = () => {
textColor: color,
}
}).filter(d => d.sliceValue > 0);
+}
+
+export const DolaDiagram = () => {
+ const { themeStyles } = useAppTheme();
+ const { dolaSupplies } = useDAO();
+ const { markets, isLoading } = useDBRMarkets();
+ const { fedOverviews, isLoading: isLoadingOverview } = useFedOverview();
+ const { data, isLoading: isLoadingRepayments } = useRepayments();
+ const { prices } = usePrices(['velodrome-finance']);
+
+ const fedsPieChartData = fedsDataToPieChart(fedOverviews, themeStyles?.colors);
const firmPieChartData = markets.map(f => {
return {
@@ -164,7 +168,7 @@ export const DolaDiagram = () => {
}
/>
-
+
void,
+ value: boolean,
+ label?: string
+}) =>
+
+ {label}
+
+ setter(!value)} isChecked={value} id={id} />
+
+
+const above100UsdFilter = (item) => item.balance * (item.price || item.usdPrice) >= 100;
+
+export const KeymetricsPage = () => {
+ const { themeName, themeStyles } = useAppTheme();
+ const { prices, isLoading: isLoadingPrices } = usePricesV2(true);
+ const { price: dolaPrice, isLoading: isDolaPriceLoading } = useDOLAPrice();
+ const { positions, userPositions, isLoading: isLoadingPositions } = useFirmUsers();
+ const { treasury, anchorReserves, multisigs, isLoading: isLoadingDao } = useDAO();
+ const { fedOverviews, isLoading: isLoadingOverview } = useFedOverview();
+ const { data: currentCirculatingSupply } = useCustomSWR(`/api/dola/circulating-supply`);
+ const { data: invCirculatingSupply } = useCustomSWR(`/api/inv/circulating-supply`);
+ const invMarketCap = prices["inverse-finance"]?.usd * invCirculatingSupply;
+ const [excludeOwnTokens, setExcludeOwnTokens] = useState(false);
+
+ const totalMultisigs = multisigs?.map(m => {
+ return { label: m.shortName, balance: getFundsTotalUsd(m.funds.filter(above100UsdFilter), prices, 'balance'), onlyUsdValue: true, usdPrice: 1, drill: m.funds }
+ });
+
+ const totalHoldings = [
+ { label: 'Treasury Contract', balance: getFundsTotalUsd(treasury, prices, 'balance'), onlyUsdValue: true, usdPrice: 1, drill: treasury },
+ { label: 'Frontier Reserves', balance: getFundsTotalUsd(anchorReserves, prices, 'balance'), onlyUsdValue: true, usdPrice: 1, drill: anchorReserves },
+ { label: 'veNFTs', balance: getFundsTotalUsd(multisigs?.map(m => m.funds.filter(fund => !!fund.token.veNftId)), prices, 'balance'), onlyUsdValue: true, usdPrice: 1, drill: totalMultisigs },
+ { label: 'Multisigs (excl. veNFTs)', balance: getFundsTotalUsd(multisigs?.map(m => m.funds.filter(fund => !fund.token.veNftId)), prices, 'balance'), onlyUsdValue: true, usdPrice: 1, drill: totalMultisigs },
+ ];
+
+ const totalHoldingsExcludeOwnTokens = [
+ { label: 'Treasury Contract', balance: getFundsTotalUsd(treasury.filter(t => !OWN_TOKENS.includes(t.token.symbol)), prices, 'balance'), onlyUsdValue: true, usdPrice: 1, drill: treasury },
+ { label: 'Frontier Reserves', balance: getFundsTotalUsd(anchorReserves, prices, 'balance'), usdPrice: 1, drill: anchorReserves },
+ { label: 'veNFTs', balance: getFundsTotalUsd(multisigs?.map(m => m.funds.filter(fund => !!fund.token.veNftId)), prices, 'balance'), onlyUsdValue: true, usdPrice: 1, drill: totalMultisigs },
+ { label: 'Multisigs (excl. veNFTs)', balance: getFundsTotalUsd(multisigs?.map(m => m.funds.filter(fund => !fund.token.veNftId).filter(t => !OWN_TOKENS.includes(t.token.symbol))), prices, 'balance'), onlyUsdValue: true, usdPrice: 1, drill: totalMultisigs },
+ ];
+
+ const pieSize = 300;
+
+ const totalTvl = positions.reduce((prev, curr) => prev + (curr.deposits * curr.market.price), 0);
+ const totalDebt = positions.reduce((prev, curr) => prev + curr.debt, 0);
+ const nbUsers = userPositions.length;
+ const nbBorrowers = userPositions.filter(p => p.debt > 0).length;
+ const nbStakers = userPositions.filter(p => p.stakedInv > 0).length;
+
+ const positionsWithDebt = positions.filter(p => p.debt > 0);
+ const positionsWithDeposits = positions.filter(p => p.deposits > 0);
+ const groupMarketsByDeposits = groupPositionsBy(positionsWithDeposits, 'marketName', 'tvl');
+ const groupMarketsByDebt = groupPositionsBy(positionsWithDebt, 'marketName', 'debt');
+
+ const isLoading = isLoadingDao || isLoadingPrices || isDolaPriceLoading || isLoadingPositions;
+ const mainFontSize = { base: '16px', sm: '20px', md: '26px' };
+ const dashboardCardTitleProps = { w: 'fit-content', position: 'static', fontSize: mainFontSize, fontWeight: 'extrabold' };
+ const dashboardCardProps = { direction: 'column', mx: '0', w: { base: '100vw', sm: '95vw', lg: '600px' }, borderRadius: { base: '0', sm: '8' } };
+
+ const fedsPieChartData = fedsDataToPieChart(fedOverviews, themeStyles?.colors);
+
+ const dolaBackingProps = {
+ dataKey: "sliceValue",
+ nameKey: "sliceName",
+ activeFill: 'keep',
+ asStable: true,
+ type: 'balance',
+ useRecharts: true,
+ isLoading,
+ w: 'full',
+ leftSideMaxW: '300px',
+ chartProps: { activeFill: 'keep', centralFill: themeStyles.colors.mainTextColor, isUsd: false }
+ };
+
+ return (
+
+
+ Inverse Finance - Transparency Treasury
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default KeymetricsPage
diff --git a/variables/menus.ts b/variables/menus.ts
index b814a3b96..190e56186 100644
--- a/variables/menus.ts
+++ b/variables/menus.ts
@@ -100,12 +100,12 @@ export const MENUS = {
},
{
label: 'Transparency',
- href: '/transparency/treasury',
+ href: '/transparency/keymetrics',
submenus: [
- // {
- // href: '/transparency/overview',
- // label: 'Overview',
- // },
+ {
+ href: '/transparency/keymetrics',
+ label: 'Key Metrics',
+ },
{
href: '/transparency/treasury',
label: 'Treasury',