sticky headers on banks dashboard

This commit is contained in:
saml33 2023-11-07 11:49:12 +11:00
parent 218e1c6923
commit 44294a3e61
2 changed files with 291 additions and 256 deletions

View File

@ -122,7 +122,7 @@ const Layout = ({ children }: { children: ReactNode }) => {
</div>
{/* note: overflow-x-hidden below prevents position sticky from working in activity feed */}
<div
className={`w-full overflow-x-hidden transition-all duration-${sideBarAnimationDuration} ease-in-out ${
className={`w-full transition-all duration-${sideBarAnimationDuration} ease-in-out ${
isCollapsed ? 'md:pl-[64px]' : 'pl-[200px]'
}`}
>

View File

@ -32,6 +32,7 @@ import DashboardSuggestedValues from '@components/modals/DashboardSuggestedValue
import { USDC_MINT } from 'utils/constants'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import useBanks from 'hooks/useBanks'
dayjs.extend(relativeTime)
@ -55,9 +56,34 @@ export async function getStaticProps({ locale }: { locale: string }) {
const Dashboard: NextPage = () => {
const { group } = useMangoGroup()
const connection = mangoStore((s) => s.connection)
const { banks } = useBanks()
const [isOpenSuggestionModal, setIsOpenSuggestionModal] = useState(false)
const [priceImpacts, setPriceImapcts] = useState<PriceImpact[]>([])
const [stickyIndex, setStickyIndex] = useState(-1)
const handleScroll = useCallback(() => {
for (let i = 0; i < banks.length; i++) {
const element = document.getElementById(`parent-item-${i}`)
if (element) {
const rect = element.getBoundingClientRect()
if (rect.top <= 0) {
setStickyIndex(i)
}
}
}
}, [banks])
useEffect(() => {
if (banks.length) {
window.addEventListener('scroll', handleScroll)
return () => {
window.removeEventListener('scroll', handleScroll)
}
}
}, [banks])
useEffect(() => {
const handleGetPriceImapcts = async () => {
@ -114,28 +140,35 @@ const Dashboard: NextPage = () => {
</div>
<h3 className="mb-3 mt-6 text-base text-th-fgd-3">Banks</h3>
<div className="border-b border-th-bkg-3">
{Array.from(group.banksMapByMint)
.sort((a, b) => a[0].localeCompare(b[0]))
.map(([mintAddress, banks]) =>
banks.map((bank) => {
const mintInfo = group.mintInfosMapByMint.get(
bank.mint.toString(),
)
{banks
.sort((a, b) => a.name.localeCompare(b.name))
.map((bank, i) => {
const mintInfo = group.mintInfosMapByMint.get(
bank.mint.toString(),
)
const formattedBankValues = getFormattedBankValues(
group,
bank,
)
const formattedBankValues = getFormattedBankValues(
group,
bank,
)
return (
<Disclosure key={bank.publicKey.toString()}>
{({ open }) => (
<>
return (
<Disclosure key={bank.publicKey.toString()}>
{({ open }) => (
<>
<div
className={`w-full border-t border-th-bkg-3 p-4 md:hover:bg-th-bkg-4 ${
open
? i === stickyIndex
? 'sticky top-0 bg-th-bkg-4'
: 'bg-th-bkg-4'
: ''
}`}
id={`parent-item-${i}`}
>
<Disclosure.Button
className="flex w-full items-center justify-between"
aria-label="panel"
className={`flex w-full items-center justify-between border-t border-th-bkg-3 p-4 md:hover:bg-th-bkg-4 ${
open ? 'bg-th-bkg-4' : ''
}`}
>
<div className="flex items-center">
<TokenLogo bank={bank} />
@ -149,243 +182,245 @@ const Dashboard: NextPage = () => {
} h-5 w-5 text-th-fgd-3`}
/>
</Disclosure.Button>
<Disclosure.Panel>
<KeyValuePair
label="Mint"
value={
<ExplorerLink address={mintAddress} />
}
/>
<KeyValuePair
label="Bank"
value={
<ExplorerLink
address={formattedBankValues.publicKey.toString()}
anchorData
/>
}
/>
<KeyValuePair
label="MintInfo"
value={
<ExplorerLink
address={mintInfo!.publicKey.toString()}
anchorData
/>
}
/>
<KeyValuePair
label="Vault"
value={
<ExplorerLink
address={formattedBankValues.vault}
anchorData
/>
}
/>
<KeyValuePair
label="Oracle"
value={
bank.oracleProvider ==
OracleProvider.Switchboard ? (
<a
href={`https://app.switchboard.xyz/solana/mainnet-beta/feed/${bank.oracle.toString()}`}
className={`flex items-center break-all text-th-fgd-2 hover:text-th-fgd-3`}
target="_blank"
rel="noreferrer"
>
{bank.oracle.toString()}
<ArrowTopRightOnSquareIcon className="ml-2 h-5 w-5 whitespace-nowrap" />
</a>
) : (
<ExplorerLink
address={formattedBankValues.oracle}
/>
)
}
/>
<KeyValuePair
label="Token Index"
value={formattedBankValues.tokenIndex}
/>
<KeyValuePair
label="Mint Decimals"
value={formattedBankValues.mintDecimals}
/>
<KeyValuePair
label="Oracle Price"
value={`$${bank.uiPrice}`}
/>
<KeyValuePair
label="Stable Price"
value={`$${formattedBankValues.stablePrice}`}
/>
<KeyValuePair
label="Last stable price updated"
value={
formattedBankValues.lastStablePriceUpdated
}
/>
<KeyValuePair
label="Stable Price: delay interval"
value={`${formattedBankValues.stablePriceModel.delayIntervalSeconds}s`}
/>
<KeyValuePair
label="Stable Price: growth limits"
value={`${formattedBankValues.stablePriceGrowthLimitsDelay}% delay / ${formattedBankValues.stablePriceGrowthLimitsStable}% stable`}
/>
<VaultData bank={bank} />
<KeyValuePair
label="Loan Fee Rate"
value={`${formattedBankValues.loanFeeRate} bps`}
/>
<KeyValuePair
label="Loan origination fee rate"
value={`${formattedBankValues.loanOriginationFeeRate} bps`}
/>
<KeyValuePair
label="Collected fees native"
value={`${formattedBankValues.collectedFeesNative} ($${formattedBankValues.collectedFeesNativePrice})`}
/>
<KeyValuePair
label="Dust"
value={formattedBankValues.dust}
/>
<KeyValuePair
label="Deposits"
value={`${formattedBankValues.deposits} ($${formattedBankValues.depositsPrice})`}
/>
<KeyValuePair
label="Borrows"
value={`${formattedBankValues.borrows} ($${formattedBankValues.borrowsPrice})`}
/>
<KeyValuePair
label="Reduce Only"
value={`${
bank.reduceOnly
} (Are deposits reduce only - ${bank.areDepositsReduceOnly()}, Are borrows reduce only - ${bank.areBorrowsReduceOnly()})`}
/>
<KeyValuePair
label="Avg Utilization"
value={`${formattedBankValues.avgUtilization}%`}
/>
<KeyValuePair
label="Maint Asset/Liab Weight"
value={`${formattedBankValues.maintAssetWeight} /
${formattedBankValues.maintLiabWeight}`}
/>
<KeyValuePair
label="Init Asset/Liab Weight"
value={`${formattedBankValues.initAssetWeight} /
${formattedBankValues.initLiabWeight}`}
/>
<KeyValuePair
label="Scaled Init Asset/Liab Weight"
value={`${formattedBankValues.scaledInitAssetWeight} / ${formattedBankValues.scaledInitLiabWeight}`}
/>
<KeyValuePair
label="Deposit weight scale start quote"
value={`$${formattedBankValues.depositWeightScaleStartQuote}`}
/>
<KeyValuePair
label="Borrow weight scale start quote"
value={`$${formattedBankValues.borrowWeightScaleStartQuote}`}
/>
<KeyValuePair
label="Rate params"
value={
<span className="text-right">
{`${formattedBankValues.rate0}% @ ${formattedBankValues.util0}% util, `}
{`${formattedBankValues.rate1}% @ ${formattedBankValues.util1}% util, `}
{`${formattedBankValues.maxRate}% @ 100% util`}
</span>
}
/>
<KeyValuePair
label="Adjustment factor"
value={`${formattedBankValues.adjustmentFactor}%`}
/>
<KeyValuePair
label="Deposit rate"
value={`${formattedBankValues.depositRate}%`}
/>
<KeyValuePair
label="Borrow rate"
value={`${formattedBankValues.borrowRate}%`}
/>
<KeyValuePair
label="Last index update"
value={formattedBankValues.lastIndexUpdate}
/>
<KeyValuePair
label="Last rates updated"
value={formattedBankValues.lastRatesUpdate}
/>
<KeyValuePair
label="Oracle: Conf Filter"
value={`${
formattedBankValues.oracleConfFilter
}% (Last known confidence ${bank._oracleLastKnownDeviation
?.div(bank.price)
.mul(I80F48.fromNumber(100))
.toNumber()
.toFixed(2)}%)`}
/>
<KeyValuePair
label="Oracle: Max Staleness"
value={`${bank.oracleConfig.maxStalenessSlots} slots (Last updated slot ${bank._oracleLastUpdatedSlot})`}
/>
<KeyValuePair
label="Group Insurance Fund"
value={`${mintInfo!.groupInsuranceFund}`}
/>
<KeyValuePair
label="Min vault to deposits ratio"
value={`${formattedBankValues.minVaultToDepositsRatio}%`}
/>
<KeyValuePair
label={`Net borrows in window (next window starts ${dayjs().to(
dayjs().add(
bank.getTimeToNextBorrowLimitWindowStartsTs(),
'second',
),
)})`}
value={`$${formattedBankValues.minVaultToDepositsRatio} / $${formattedBankValues.netBorrowLimitPerWindowQuote}`}
/>
<KeyValuePair
label="Liquidation fee"
value={`${formattedBankValues.liquidationFee}%`}
/>
{bank.mint.toBase58() !== USDC_MINT && (
<div className="mb-4 mt-2 flex">
<Button
className=" ml-auto"
onClick={() =>
setIsOpenSuggestionModal(true)
}
</div>
<Disclosure.Panel>
<KeyValuePair
label="Mint"
value={
<ExplorerLink
address={bank.mint.toString()}
/>
}
/>
<KeyValuePair
label="Bank"
value={
<ExplorerLink
address={formattedBankValues.publicKey.toString()}
anchorData
/>
}
/>
<KeyValuePair
label="MintInfo"
value={
<ExplorerLink
address={mintInfo!.publicKey.toString()}
anchorData
/>
}
/>
<KeyValuePair
label="Vault"
value={
<ExplorerLink
address={formattedBankValues.vault}
anchorData
/>
}
/>
<KeyValuePair
label="Oracle"
value={
bank.oracleProvider ==
OracleProvider.Switchboard ? (
<a
href={`https://app.switchboard.xyz/solana/mainnet-beta/feed/${bank.oracle.toString()}`}
className={`flex items-center break-all text-th-fgd-2 hover:text-th-fgd-3`}
target="_blank"
rel="noreferrer"
>
Check suggested values
{isOpenSuggestionModal && (
<DashboardSuggestedValues
priceImpacts={priceImpacts}
group={group}
bank={bank}
isOpen={isOpenSuggestionModal}
onClose={() =>
setIsOpenSuggestionModal(false)
}
></DashboardSuggestedValues>
)}
</Button>
</div>
)}
</Disclosure.Panel>
</>
)}
</Disclosure>
)
}),
)}
{bank.oracle.toString()}
<ArrowTopRightOnSquareIcon className="ml-2 h-5 w-5 whitespace-nowrap" />
</a>
) : (
<ExplorerLink
address={formattedBankValues.oracle}
/>
)
}
/>
<KeyValuePair
label="Token Index"
value={formattedBankValues.tokenIndex}
/>
<KeyValuePair
label="Mint Decimals"
value={formattedBankValues.mintDecimals}
/>
<KeyValuePair
label="Oracle Price"
value={`$${bank.uiPrice}`}
/>
<KeyValuePair
label="Stable Price"
value={`$${formattedBankValues.stablePrice}`}
/>
<KeyValuePair
label="Last stable price updated"
value={
formattedBankValues.lastStablePriceUpdated
}
/>
<KeyValuePair
label="Stable Price: delay interval"
value={`${formattedBankValues.stablePriceModel.delayIntervalSeconds}s`}
/>
<KeyValuePair
label="Stable Price: growth limits"
value={`${formattedBankValues.stablePriceGrowthLimitsDelay}% delay / ${formattedBankValues.stablePriceGrowthLimitsStable}% stable`}
/>
<VaultData bank={bank} />
<KeyValuePair
label="Loan Fee Rate"
value={`${formattedBankValues.loanFeeRate} bps`}
/>
<KeyValuePair
label="Loan origination fee rate"
value={`${formattedBankValues.loanOriginationFeeRate} bps`}
/>
<KeyValuePair
label="Collected fees native"
value={`${formattedBankValues.collectedFeesNative} ($${formattedBankValues.collectedFeesNativePrice})`}
/>
<KeyValuePair
label="Dust"
value={formattedBankValues.dust}
/>
<KeyValuePair
label="Deposits"
value={`${formattedBankValues.deposits} ($${formattedBankValues.depositsPrice})`}
/>
<KeyValuePair
label="Borrows"
value={`${formattedBankValues.borrows} ($${formattedBankValues.borrowsPrice})`}
/>
<KeyValuePair
label="Reduce Only"
value={`${
bank.reduceOnly
} (Are deposits reduce only - ${bank.areDepositsReduceOnly()}, Are borrows reduce only - ${bank.areBorrowsReduceOnly()})`}
/>
<KeyValuePair
label="Avg Utilization"
value={`${formattedBankValues.avgUtilization}%`}
/>
<KeyValuePair
label="Maint Asset/Liab Weight"
value={`${formattedBankValues.maintAssetWeight} /
${formattedBankValues.maintLiabWeight}`}
/>
<KeyValuePair
label="Init Asset/Liab Weight"
value={`${formattedBankValues.initAssetWeight} /
${formattedBankValues.initLiabWeight}`}
/>
<KeyValuePair
label="Scaled Init Asset/Liab Weight"
value={`${formattedBankValues.scaledInitAssetWeight} / ${formattedBankValues.scaledInitLiabWeight}`}
/>
<KeyValuePair
label="Deposit weight scale start quote"
value={`$${formattedBankValues.depositWeightScaleStartQuote}`}
/>
<KeyValuePair
label="Borrow weight scale start quote"
value={`$${formattedBankValues.borrowWeightScaleStartQuote}`}
/>
<KeyValuePair
label="Rate params"
value={
<span className="text-right">
{`${formattedBankValues.rate0}% @ ${formattedBankValues.util0}% util, `}
{`${formattedBankValues.rate1}% @ ${formattedBankValues.util1}% util, `}
{`${formattedBankValues.maxRate}% @ 100% util`}
</span>
}
/>
<KeyValuePair
label="Adjustment factor"
value={`${formattedBankValues.adjustmentFactor}%`}
/>
<KeyValuePair
label="Deposit rate"
value={`${formattedBankValues.depositRate}%`}
/>
<KeyValuePair
label="Borrow rate"
value={`${formattedBankValues.borrowRate}%`}
/>
<KeyValuePair
label="Last index update"
value={formattedBankValues.lastIndexUpdate}
/>
<KeyValuePair
label="Last rates updated"
value={formattedBankValues.lastRatesUpdate}
/>
<KeyValuePair
label="Oracle: Conf Filter"
value={`${
formattedBankValues.oracleConfFilter
}% (Last known confidence ${bank._oracleLastKnownDeviation
?.div(bank.price)
.mul(I80F48.fromNumber(100))
.toNumber()
.toFixed(2)}%)`}
/>
<KeyValuePair
label="Oracle: Max Staleness"
value={`${bank.oracleConfig.maxStalenessSlots} slots (Last updated slot ${bank._oracleLastUpdatedSlot})`}
/>
<KeyValuePair
label="Group Insurance Fund"
value={`${mintInfo!.groupInsuranceFund}`}
/>
<KeyValuePair
label="Min vault to deposits ratio"
value={`${formattedBankValues.minVaultToDepositsRatio}%`}
/>
<KeyValuePair
label={`Net borrows in window (next window starts ${dayjs().to(
dayjs().add(
bank.getTimeToNextBorrowLimitWindowStartsTs(),
'second',
),
)})`}
value={`$${formattedBankValues.minVaultToDepositsRatio} / $${formattedBankValues.netBorrowLimitPerWindowQuote}`}
/>
<KeyValuePair
label="Liquidation fee"
value={`${formattedBankValues.liquidationFee}%`}
/>
{bank.mint.toBase58() !== USDC_MINT && (
<div className="mb-4 mt-2 flex">
<Button
className=" ml-auto"
onClick={() =>
setIsOpenSuggestionModal(true)
}
>
Check suggested values
{isOpenSuggestionModal && (
<DashboardSuggestedValues
priceImpacts={priceImpacts}
group={group}
bank={bank}
isOpen={isOpenSuggestionModal}
onClose={() =>
setIsOpenSuggestionModal(false)
}
></DashboardSuggestedValues>
)}
</Button>
</div>
)}
</Disclosure.Panel>
</>
)}
</Disclosure>
)
})}
</div>
<h3 className="mb-3 mt-6 text-base text-th-fgd-3">