Merge branch 'main' into feature/close-account-modal
This commit is contained in:
commit
be7aa47a09
|
@ -1,31 +1,15 @@
|
|||
import SheenLoader from '@components/shared/SheenLoader'
|
||||
import mangoStore, { TokenStatsItem } from '@store/mangoStore'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { useMemo } from 'react'
|
||||
import dayjs from 'dayjs'
|
||||
import { numberCompacter } from 'utils/numbers'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import TotalDepositBorrowCharts from './TotalDepositBorrowCharts'
|
||||
// import { useTranslation } from 'next-i18next'
|
||||
// import { PerpMarket } from '@blockworks-foundation/mango-v4'
|
||||
const DetailedAreaChart = dynamic(
|
||||
() => import('@components/shared/DetailedAreaChart'),
|
||||
{ ssr: false }
|
||||
)
|
||||
|
||||
interface TotalValueItem {
|
||||
date: string
|
||||
borrowValue: number
|
||||
depositValue: number
|
||||
}
|
||||
|
||||
const MangoStats = () => {
|
||||
const { t } = useTranslation(['common', 'token', 'trade'])
|
||||
// const { t } = useTranslation(['common', 'token', 'trade'])
|
||||
const tokenStats = mangoStore((s) => s.tokenStats.data)
|
||||
const loadingStats = mangoStore((s) => s.tokenStats.loading)
|
||||
// const perpStats = mangoStore((s) => s.perpStats.data)
|
||||
// const loadingPerpStats = mangoStore((s) => s.perpStats.loading)
|
||||
// const perpMarkets = mangoStore((s) => s.perpMarkets)
|
||||
const { group } = useMangoGroup()
|
||||
|
||||
// const totalFeeValues = useMemo(() => {
|
||||
// if (!perpStats.length) return []
|
||||
|
@ -72,111 +56,12 @@ const MangoStats = () => {
|
|||
// }, 0)
|
||||
// }, [perpMarkets])
|
||||
|
||||
const totalDepositBorrowValues = useMemo(() => {
|
||||
if (!tokenStats) return []
|
||||
const values: TotalValueItem[] = tokenStats.reduce(
|
||||
(a: TotalValueItem[], c: TokenStatsItem) => {
|
||||
const hasDate = a.find((d: TotalValueItem) => d.date === c.date_hour)
|
||||
if (!hasDate) {
|
||||
a.push({
|
||||
date: c.date_hour,
|
||||
depositValue: Math.floor(c.total_deposits * c.price),
|
||||
borrowValue: Math.floor(c.total_borrows * c.price),
|
||||
})
|
||||
} else {
|
||||
hasDate.depositValue =
|
||||
hasDate.depositValue + Math.floor(c.total_deposits * c.price)
|
||||
hasDate.borrowValue =
|
||||
hasDate.borrowValue + Math.floor(c.total_borrows * c.price)
|
||||
}
|
||||
return a
|
||||
},
|
||||
[]
|
||||
)
|
||||
return values.reverse()
|
||||
}, [tokenStats])
|
||||
|
||||
const banks = useMemo(() => {
|
||||
if (group) {
|
||||
const rawBanks = Array.from(group?.banksMapByName, ([key, value]) => ({
|
||||
key,
|
||||
value,
|
||||
}))
|
||||
return rawBanks
|
||||
}
|
||||
return []
|
||||
}, [group])
|
||||
|
||||
const [currentTotalDepositValue, currentTotalBorrowValue] = useMemo(() => {
|
||||
if (banks.length) {
|
||||
return [
|
||||
banks.reduce(
|
||||
(a, c) => a + c.value[0].uiPrice * c.value[0].uiDeposits(),
|
||||
0
|
||||
),
|
||||
banks.reduce(
|
||||
(a, c) => a + c.value[0].uiPrice * c.value[0].uiBorrows(),
|
||||
0
|
||||
),
|
||||
]
|
||||
}
|
||||
return [0, 0]
|
||||
}, [banks])
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-2">
|
||||
{loadingStats ? (
|
||||
<div className="col-span-2 border-b border-th-bkg-3 py-4 px-6 md:col-span-1">
|
||||
<SheenLoader className="flex flex-1">
|
||||
<div className="h-96 w-full rounded-lg bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
</div>
|
||||
) : totalDepositBorrowValues.length ? (
|
||||
<div className="col-span-2 border-b border-th-bkg-3 py-4 px-6 md:col-span-1">
|
||||
<DetailedAreaChart
|
||||
data={totalDepositBorrowValues.concat([
|
||||
{
|
||||
date: dayjs().toISOString(),
|
||||
depositValue: Math.floor(currentTotalDepositValue),
|
||||
borrowValue: Math.floor(currentTotalBorrowValue),
|
||||
},
|
||||
])}
|
||||
daysToShow={'999'}
|
||||
heightClass="h-64"
|
||||
prefix="$"
|
||||
tickFormat={(x) => `$${numberCompacter.format(x)}`}
|
||||
title={t('total-deposit-value')}
|
||||
xKey="date"
|
||||
yKey={'depositValue'}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
{loadingStats ? (
|
||||
<div className="col-span-2 border-b border-th-bkg-3 py-4 px-6 md:col-span-1 md:border-l md:pl-6">
|
||||
<SheenLoader className="flex flex-1">
|
||||
<div className="h-96 w-full rounded-lg bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
</div>
|
||||
) : totalDepositBorrowValues.length ? (
|
||||
<div className="col-span-2 border-b border-th-bkg-3 py-4 px-6 md:col-span-1 md:border-l md:pl-6">
|
||||
<DetailedAreaChart
|
||||
data={totalDepositBorrowValues.concat([
|
||||
{
|
||||
date: dayjs().toISOString(),
|
||||
borrowValue: Math.floor(currentTotalBorrowValue),
|
||||
depositValue: Math.floor(currentTotalDepositValue),
|
||||
},
|
||||
])}
|
||||
daysToShow={'999'}
|
||||
heightClass="h-64"
|
||||
prefix="$"
|
||||
tickFormat={(x) => `$${numberCompacter.format(x)}`}
|
||||
title={t('total-borrow-value')}
|
||||
xKey="date"
|
||||
yKey={'borrowValue'}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
<TotalDepositBorrowCharts
|
||||
tokenStats={tokenStats}
|
||||
loadingStats={loadingStats}
|
||||
/>
|
||||
{/* uncomment below when perps launch */}
|
||||
|
||||
{/* {loadingPerpStats ? (
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
import SheenLoader from '@components/shared/SheenLoader'
|
||||
import { TokenStatsItem } from '@store/mangoStore'
|
||||
import useMangoGroup from 'hooks/useMangoGroup'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { useMemo, useState } from 'react'
|
||||
import dayjs from 'dayjs'
|
||||
import { numberCompacter } from 'utils/numbers'
|
||||
const DetailedAreaChart = dynamic(
|
||||
() => import('@components/shared/DetailedAreaChart'),
|
||||
{ ssr: false }
|
||||
)
|
||||
|
||||
interface TotalValueItem {
|
||||
date: string
|
||||
borrowValue: number
|
||||
depositValue: number
|
||||
}
|
||||
|
||||
const TotalDepositBorrowCharts = ({
|
||||
tokenStats,
|
||||
loadingStats,
|
||||
}: {
|
||||
tokenStats: TokenStatsItem[] | null
|
||||
loadingStats: boolean
|
||||
}) => {
|
||||
const { t } = useTranslation(['common', 'token', 'trade'])
|
||||
const [borrowDaysToShow, setBorrowDaysToShow] = useState('30')
|
||||
const [depositDaysToShow, setDepositDaysToShow] = useState('30')
|
||||
const { group } = useMangoGroup()
|
||||
|
||||
const totalDepositBorrowValues = useMemo(() => {
|
||||
if (!tokenStats) return []
|
||||
const values: TotalValueItem[] = tokenStats.reduce(
|
||||
(a: TotalValueItem[], c: TokenStatsItem) => {
|
||||
const hasDate = a.find((d: TotalValueItem) => d.date === c.date_hour)
|
||||
if (!hasDate) {
|
||||
a.push({
|
||||
date: c.date_hour,
|
||||
depositValue: Math.floor(c.total_deposits * c.price),
|
||||
borrowValue: Math.floor(c.total_borrows * c.price),
|
||||
})
|
||||
} else {
|
||||
hasDate.depositValue =
|
||||
hasDate.depositValue + Math.floor(c.total_deposits * c.price)
|
||||
hasDate.borrowValue =
|
||||
hasDate.borrowValue + Math.floor(c.total_borrows * c.price)
|
||||
}
|
||||
return a
|
||||
},
|
||||
[]
|
||||
)
|
||||
return values.reverse()
|
||||
}, [tokenStats])
|
||||
|
||||
const filteredBorrowValues = useMemo(() => {
|
||||
if (!totalDepositBorrowValues) return []
|
||||
if (borrowDaysToShow !== '30') {
|
||||
const seconds = Number(borrowDaysToShow) * 86400
|
||||
const data = totalDepositBorrowValues.filter((d) => {
|
||||
const dataTime = new Date(d.date).getTime() / 1000
|
||||
const now = new Date().getTime() / 1000
|
||||
const limit = now - seconds
|
||||
return dataTime >= limit
|
||||
})
|
||||
return data
|
||||
}
|
||||
return totalDepositBorrowValues
|
||||
}, [totalDepositBorrowValues, borrowDaysToShow])
|
||||
|
||||
const filteredDepositValues = useMemo(() => {
|
||||
if (!totalDepositBorrowValues) return []
|
||||
if (depositDaysToShow !== '30') {
|
||||
const seconds = Number(depositDaysToShow) * 86400
|
||||
const data = totalDepositBorrowValues.filter((d) => {
|
||||
const dataTime = new Date(d.date).getTime() / 1000
|
||||
const now = new Date().getTime() / 1000
|
||||
const limit = now - seconds
|
||||
return dataTime >= limit
|
||||
})
|
||||
return data
|
||||
}
|
||||
return totalDepositBorrowValues
|
||||
}, [totalDepositBorrowValues, depositDaysToShow])
|
||||
|
||||
const banks = useMemo(() => {
|
||||
if (group) {
|
||||
const rawBanks = Array.from(group?.banksMapByName, ([key, value]) => ({
|
||||
key,
|
||||
value,
|
||||
}))
|
||||
return rawBanks
|
||||
}
|
||||
return []
|
||||
}, [group])
|
||||
|
||||
const [currentTotalDepositValue, currentTotalBorrowValue] = useMemo(() => {
|
||||
if (banks.length) {
|
||||
return [
|
||||
banks.reduce(
|
||||
(a, c) => a + c.value[0].uiPrice * c.value[0].uiDeposits(),
|
||||
0
|
||||
),
|
||||
banks.reduce(
|
||||
(a, c) => a + c.value[0].uiPrice * c.value[0].uiBorrows(),
|
||||
0
|
||||
),
|
||||
]
|
||||
}
|
||||
return [0, 0]
|
||||
}, [banks])
|
||||
|
||||
return loadingStats ? (
|
||||
<>
|
||||
<div className="col-span-2 border-b border-th-bkg-3 py-4 px-6 md:col-span-1">
|
||||
<SheenLoader className="flex flex-1">
|
||||
<div className="h-96 w-full rounded-lg bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
</div>
|
||||
<div className="col-span-2 border-b border-th-bkg-3 py-4 px-6 md:col-span-1 md:border-l md:pl-6">
|
||||
<SheenLoader className="flex flex-1">
|
||||
<div className="h-96 w-full rounded-lg bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
</div>
|
||||
</>
|
||||
) : totalDepositBorrowValues.length ? (
|
||||
<>
|
||||
<div className="col-span-2 border-b border-th-bkg-3 py-4 px-6 md:col-span-1">
|
||||
<DetailedAreaChart
|
||||
data={filteredDepositValues.concat([
|
||||
{
|
||||
date: dayjs().toISOString(),
|
||||
depositValue: Math.floor(currentTotalDepositValue),
|
||||
borrowValue: Math.floor(currentTotalBorrowValue),
|
||||
},
|
||||
])}
|
||||
daysToShow={depositDaysToShow}
|
||||
setDaysToShow={setDepositDaysToShow}
|
||||
heightClass="h-64"
|
||||
prefix="$"
|
||||
tickFormat={(x) => `$${numberCompacter.format(x)}`}
|
||||
title={t('total-deposit-value')}
|
||||
xKey="date"
|
||||
yKey={'depositValue'}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-2 border-b border-th-bkg-3 py-4 px-6 md:col-span-1 md:border-l md:pl-6">
|
||||
<DetailedAreaChart
|
||||
data={filteredBorrowValues.concat([
|
||||
{
|
||||
date: dayjs().toISOString(),
|
||||
borrowValue: Math.floor(currentTotalBorrowValue),
|
||||
depositValue: Math.floor(currentTotalDepositValue),
|
||||
},
|
||||
])}
|
||||
daysToShow={borrowDaysToShow}
|
||||
setDaysToShow={setBorrowDaysToShow}
|
||||
heightClass="h-64"
|
||||
prefix="$"
|
||||
tickFormat={(x) => `$${numberCompacter.format(x)}`}
|
||||
title={t('total-borrow-value')}
|
||||
xKey="date"
|
||||
yKey={'borrowValue'}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
) : null
|
||||
}
|
||||
|
||||
export default TotalDepositBorrowCharts
|
|
@ -8,6 +8,7 @@ import useMangoGroup from 'hooks/useMangoGroup'
|
|||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import {
|
||||
formatDecimal,
|
||||
formatFixedDecimals,
|
||||
getDecimalCount,
|
||||
numberFormat,
|
||||
|
@ -66,8 +67,8 @@ const PerpPositions = () => {
|
|||
<Th className="text-right">{t('trade:size')}</Th>
|
||||
<Th className="text-right">{t('trade:notional')}</Th>
|
||||
<Th className="text-right">{t('trade:entry-price')}</Th>
|
||||
<Th className="text-right">Redeemable PnL</Th>
|
||||
<Th className="text-right">Realized PnL</Th>
|
||||
<Th className="text-right">Unsettled PnL</Th>
|
||||
<Th className="text-right">PnL</Th>
|
||||
</TrHead>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -86,7 +87,11 @@ const PerpPositions = () => {
|
|||
|
||||
if (!basePosition) return null
|
||||
|
||||
const unsettledPnl = position.getEquityUi(group, market)
|
||||
const unsettledPnl = position.getUnsettledPnlUi(group, market)
|
||||
const cummulativePnl = position.cumulativePnlOverPositionLifetimeUi(
|
||||
group,
|
||||
market
|
||||
)
|
||||
|
||||
return (
|
||||
<TrBody key={`${position.marketIndex}`} className="my-1 p-2">
|
||||
|
@ -96,7 +101,7 @@ const PerpPositions = () => {
|
|||
<Td className="text-right">
|
||||
<PerpSideBadge basePosition={basePosition} />
|
||||
</Td>
|
||||
<Td className="text-right">
|
||||
<Td className="text-right font-mono">
|
||||
<p className="flex justify-end">
|
||||
{isSelectedMarket ? (
|
||||
<LinkButton
|
||||
|
@ -123,20 +128,15 @@ const PerpPositions = () => {
|
|||
)}
|
||||
</div>
|
||||
</Td>
|
||||
<Td className={`text-right font-mono`}>
|
||||
<div>{formatDecimal(unsettledPnl, market.baseDecimals)}</div>
|
||||
</Td>
|
||||
<Td
|
||||
className={`text-right font-mono ${
|
||||
unsettledPnl > 0 ? 'text-th-up' : 'text-th-down'
|
||||
cummulativePnl > 0 ? 'text-th-up' : 'text-th-down'
|
||||
}`}
|
||||
>
|
||||
<div>{formatFixedDecimals(unsettledPnl, true)}</div>
|
||||
</Td>
|
||||
<Td className="text-right">
|
||||
<div>
|
||||
$
|
||||
{/* {numberFormat.format(
|
||||
position.perpSpotTransfers.toNumber()
|
||||
)} */}
|
||||
</div>
|
||||
<div>{formatFixedDecimals(cummulativePnl, true)}</div>
|
||||
</Td>
|
||||
</TrBody>
|
||||
)
|
||||
|
|
|
@ -204,7 +204,7 @@ const UnsettledTrades = ({
|
|||
</Td>
|
||||
<Td className="text-right font-mono">
|
||||
{formatDecimal(
|
||||
position.getEquityUi(group, market),
|
||||
position.getUnsettledPnlUi(group, market),
|
||||
market.baseDecimals
|
||||
)}
|
||||
</Td>
|
||||
|
|
|
@ -7,8 +7,8 @@ const useUnsettledPerpPositions = () => {
|
|||
|
||||
return perpPositions.filter((p) => {
|
||||
const market = group?.getPerpMarketByMarketIndex(p.marketIndex)
|
||||
if (!market) return false
|
||||
return p.getPnl(market).toNumber() > 0
|
||||
if (!market || !group) return false
|
||||
return p.getUnsettledPnlUi(group, market) !== 0
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -441,17 +441,29 @@ const Dashboard: NextPage = () => {
|
|||
/>
|
||||
<KeyValuePair
|
||||
label="Maint Asset/Liab Weight"
|
||||
value={`${perpMarket.maintAssetWeight.toFixed(
|
||||
value={`${perpMarket.maintBaseAssetWeight.toFixed(
|
||||
4
|
||||
)}/
|
||||
${perpMarket.maintLiabWeight.toFixed(4)}`}
|
||||
${perpMarket.maintBaseLiabWeight.toFixed(4)}`}
|
||||
/>
|
||||
<KeyValuePair
|
||||
label="Init Asset/Liab Weight"
|
||||
value={`${perpMarket.initAssetWeight.toFixed(
|
||||
value={`${perpMarket.initBaseAssetWeight.toFixed(
|
||||
4
|
||||
)}/
|
||||
${perpMarket.initLiabWeight.toFixed(4)}`}
|
||||
${perpMarket.initBaseLiabWeight.toFixed(4)}`}
|
||||
/>
|
||||
<KeyValuePair
|
||||
label="Maint PNL Asset weight"
|
||||
value={`${perpMarket.maintPnlAssetWeight.toFixed(
|
||||
4
|
||||
)}`}
|
||||
/>
|
||||
<KeyValuePair
|
||||
label="Init PNL Asset weight"
|
||||
value={`${perpMarket.initPnlAssetWeight.toFixed(
|
||||
4
|
||||
)}`}
|
||||
/>
|
||||
<KeyValuePair
|
||||
label="Liquidation Fee"
|
||||
|
@ -500,10 +512,6 @@ const Dashboard: NextPage = () => {
|
|||
label="Oracle: Max Staleness"
|
||||
value={`${perpMarket.oracleConfig.maxStalenessSlots} slots`}
|
||||
/>
|
||||
<KeyValuePair
|
||||
label="Trusted Market"
|
||||
value={`${perpMarket.trustedMarket}`}
|
||||
/>
|
||||
<KeyValuePair
|
||||
label="Group Insurance Fund"
|
||||
value={`${perpMarket.groupInsuranceFund}`}
|
||||
|
|
|
@ -60,7 +60,7 @@ export const COLORS: any = {
|
|||
Olive: '#acaa8b',
|
||||
},
|
||||
UP: {
|
||||
'Mango Classic': '#A6CD03',
|
||||
'Mango Classic': '#89B92A',
|
||||
Dark: '#4aa13a',
|
||||
Light: '#60bf4f',
|
||||
'High Contrast': '#50f434',
|
||||
|
|
|
@ -35,17 +35,17 @@ module.exports = {
|
|||
},
|
||||
link: { DEFAULT: 'hsl(33, 100%, 57%)', hover: 'hsl(33, 100%, 52%)' },
|
||||
down: {
|
||||
DEFAULT: 'hsl(4, 93%, 60%)',
|
||||
DEFAULT: 'hsl(4, 63%, 55%)',
|
||||
dark: 'hsl(4, 93%, 55%)',
|
||||
muted: 'hsl(4, 53%, 55%)',
|
||||
muted: 'hsl(4, 43%, 38%)',
|
||||
},
|
||||
up: {
|
||||
DEFAULT: 'hsl(72, 97%, 41%)',
|
||||
dark: 'hsl(72, 97%, 36%)',
|
||||
muted: 'hsl(72, 57%, 36%)',
|
||||
DEFAULT: 'hsl(77, 63%, 40%)',
|
||||
dark: 'hsl(85, 50%, 36%)',
|
||||
muted: 'hsl(84, 40%, 32%)',
|
||||
},
|
||||
error: 'hsl(4, 93%, 60%)',
|
||||
success: 'hsl(72, 97%, 41%)',
|
||||
success: 'hsl(82, 97%, 41%)',
|
||||
warning: 'hsl(33, 100%, 57%)',
|
||||
'bkg-1': 'hsl(256, 18%, 12%)',
|
||||
'bkg-2': 'hsl(256, 18%, 17%)',
|
||||
|
@ -110,8 +110,8 @@ module.exports = {
|
|||
link: { DEFAULT: 'hsl(45, 86%, 62%)', hover: 'hsl(45, 86%, 57%)' },
|
||||
down: {
|
||||
DEFAULT: 'hsl(358, 55%, 50%)',
|
||||
dark: 'hsl(0, 59%, 53%)',
|
||||
muted: 'hsl(0, 45%, 26%)',
|
||||
dark: 'hsl(0, 45%, 26%)',
|
||||
muted: 'hsl(0, 45%, 30%)',
|
||||
},
|
||||
up: {
|
||||
DEFAULT: 'hsl(111, 47%, 43%)',
|
||||
|
|
Loading…
Reference in New Issue