import useMangoGroup from 'hooks/useMangoGroup' import type { NextPage } from 'next' import { serverSideTranslations } from 'next-i18next/serverSideTranslations' import { DashboardNavbar } from '.' import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements' import { PublicKey } from '@solana/web3.js' import { formatNumericValue } from 'utils/numbers' import { toUiDecimals } from '@blockworks-foundation/mango-v4' import { useMemo, useState } from 'react' import Select from '@components/forms/Select' import Input from '@components/forms/Input' import { LISTING_PRESETS, getMidPriceImpacts, } from '@blockworks-foundation/mango-v4-settings/lib/helpers/listingTools' export async function getStaticProps({ locale }: { locale: string }) { return { props: { ...(await serverSideTranslations(locale, [ 'account', 'close-account', 'common', 'notifications', 'onboarding', 'profile', 'search', 'settings', 'token', 'trade', ])), }, } } const formatValue = (val: string | number | PublicKey) => { if (val instanceof PublicKey || typeof val === 'object') { return val.toString() } if (typeof val === 'string') { if (val === 'ask') { return 'Sell' } if (val === 'bid') { return 'Buy' } return val } else { return formatNumericValue(val) } } const RiskDashboard: NextPage = () => { const { group } = useMangoGroup() const [currentFilter, setCurrentFilter] = useState< 'avg_price_impact' | 'p90' | 'p95' >('avg_price_impact') const [currentSearch, setCurrentSearch] = useState('') const filters = ['avg_price_impact', 'p90', 'p95'] const filterLabels = { avg_price_impact: 'Average Price Impact', p90: '90th Percentile', p95: '95th Percentile', } const heads = group ? [ ...new Set([ 'Token', 'Side', ...group.pis.map((x) => formatValue(x.target_amount)), 'Init/Main Weight', '~Current tier', 'Suggested tier', ]), ] : [] type FixedProperties = { symbol: string side: string } type DynamicProperties = { [key: string]: | { avg_price_impact: number p90: number p95: number target_amount: number } | string } type TransformedPis = FixedProperties & DynamicProperties const transformedPis = group?.pis .filter((x) => x.symbol.toLowerCase().includes(currentSearch.toLowerCase())) .reduce((acc, val) => { const currentItem = acc.find( (x) => x.symbol === val.symbol && x.side === val.side, ) if (currentItem) { currentItem['amount_' + val.target_amount] = { avg_price_impact: val.avg_price_impact_percent, p90: val.p90, p95: val.p95, target_amount: val.target_amount, } } else { const newItem = { symbol: val.symbol, side: val.side, ['amount_' + val.target_amount]: { avg_price_impact: val.avg_price_impact_percent, p90: val.p90, p95: val.p95, target_amount: val.target_amount, }, } acc.push(newItem) } return acc }, [] as TransformedPis[]) const symbolToSuggestedPresetName = useMemo( () => (group ? getMidPriceImpacts(group.pis) : []), [group], ) .filter((x) => x.avg_price_impact_percent < 1) .reduce( (acc, val, index, pisFiltred) => { const avaPreests = LISTING_PRESETS if (!acc[val.symbol]) { acc[val.symbol] = Object.values(avaPreests).find( (x) => x.preset_target_amount <= pisFiltred .filter((pis) => pis.symbol === val.symbol) .sort( (a, b) => b.avg_price_impact_percent - a.avg_price_impact_percent, )[0].target_amount, )?.preset_name || 'C' } return acc }, {} as { [symbol: string]: string }, ) return (
Slippage setCurrentSearch(e.target.value)} >
{x} | ))}
{formatValue(visibleValue)}
{isNumericValue && (
{(targetAmountVsBorrows ||
targetAmountVsDeposits) && (
)}
{(targetAmountVsAssetWeightScale ||
targetAmountVsLiabWeightScale) && (
)}
)}
|
)
})}
{isBid && collateralEnabled && `${ bank && formatValue( bank ?.scaledInitAssetWeight(bank.price) .toNumber(), ) } / ${ bank && formatValue(bank.maintAssetWeight.toNumber()) }`} {isAsk && borrowsEnabled && `${ bank && formatValue( bank?.scaledInitLiabWeight(bank.price).toNumber(), ) } / ${ bank && formatValue(bank.maintLiabWeight.toNumber()) }`} | {idx % 2 === 0 && bank ? Object.values(LISTING_PRESETS).find((x) => { return x.initLiabWeight.toFixed(1) === '1.8' ? x.initLiabWeight.toFixed(1) === bank?.initLiabWeight .toNumber() .toFixed(1) && x.reduceOnly === bank.reduceOnly : x.initLiabWeight.toFixed(1) === bank?.initLiabWeight.toNumber().toFixed(1) })?.preset_name || '' : ''} | {idx % 2 === 0 ? symbolToSuggestedPresetName[row.symbol] ? symbolToSuggestedPresetName[row.symbol] : 'C' : ''} |
---|
Annotation | Sell | Buy |
Red Text
|
{`liquidation fee < price impact && init or main asset weight > 0`}
|
{`liquidation fee < price impact && borrows enabled `}
|
{' '}
{/* Fixed width and height */}
|
{`target amount <= notional amount of current deposit`}
|
{`target amount <= notional amount of current borrows `}
|
{' '}
{/* Fixed width and height */}
|
{`target amount <= ui deposit weight scale start quote && main asset weight > 0`}
|
{`target amount <= ui borrows weight scale start quote && main asset weight > 0`}
|
---|