2022-08-23 15:33:09 -07:00
import { Transition } from '@headlessui/react'
2022-09-06 21:36:35 -07:00
import {
ChevronDownIcon ,
2022-10-11 04:59:01 -07:00
ChevronRightIcon ,
2022-09-06 21:36:35 -07:00
QuestionMarkCircleIcon ,
} from '@heroicons/react/20/solid'
2022-08-23 15:33:09 -07:00
import { useTranslation } from 'next-i18next'
2022-10-28 14:46:38 -07:00
import Image from 'next/legacy/image'
2022-12-05 19:23:22 -08:00
import { Fragment , useEffect , useMemo , useState } from 'react'
2022-08-23 15:33:09 -07:00
import { useViewport } from '../../hooks/useViewport'
import { formatDecimal , formatFixedDecimals } from '../../utils/numbers'
import { breakpoints } from '../../utils/theme'
2022-10-11 04:59:01 -07:00
import { IconButton , LinkButton } from '../shared/Button'
2022-08-23 15:33:09 -07:00
import ContentBox from '../shared/ContentBox'
2022-09-24 05:28:11 -07:00
import Tooltip from '@components/shared/Tooltip'
2022-10-11 04:59:01 -07:00
import { Bank } from '@blockworks-foundation/mango-v4'
import { useRouter } from 'next/router'
2022-11-18 11:11:06 -08:00
import useJupiterMints from 'hooks/useJupiterMints'
2022-11-20 02:44:14 -08:00
import { Table , Td , Th , TrBody , TrHead } from '@components/shared/TableElements'
2022-11-20 12:32:38 -08:00
import useMangoGroup from 'hooks/useMangoGroup'
2022-12-20 00:16:05 -08:00
import mangoStore from '@store/mangoStore'
2022-08-23 15:33:09 -07:00
2022-10-11 04:59:01 -07:00
const TokenStats = ( ) = > {
const { t } = useTranslation ( [ 'common' , 'token' ] )
2023-01-03 14:20:00 -08:00
const actions = mangoStore . getState ( ) . actions
2022-12-11 02:08:50 -08:00
const initialStatsLoad = mangoStore ( ( s ) = > s . tokenStats . initialLoad )
2022-08-23 15:33:09 -07:00
const [ showTokenDetails , setShowTokenDetails ] = useState ( '' )
2022-11-20 12:32:38 -08:00
const { group } = useMangoGroup ( )
2022-11-18 11:11:06 -08:00
const { mangoTokens } = useJupiterMints ( )
2022-08-23 15:33:09 -07:00
const { width } = useViewport ( )
const showTableView = width ? width > breakpoints.md : false
2022-10-11 04:59:01 -07:00
const router = useRouter ( )
2022-12-05 19:23:22 -08:00
useEffect ( ( ) = > {
2022-12-11 02:08:50 -08:00
if ( group && ! initialStatsLoad ) {
2022-12-06 03:58:22 -08:00
actions . fetchTokenStats ( )
}
2022-12-05 19:23:22 -08:00
} , [ group ] )
2022-08-23 15:33:09 -07:00
const banks = useMemo ( ( ) = > {
if ( group ) {
const rawBanks = Array . from ( group ? . banksMapByName , ( [ key , value ] ) = > ( {
key ,
value ,
} ) )
2023-01-03 01:20:34 -08:00
return rawBanks . sort ( ( a , b ) = > a . key . localeCompare ( b . key ) )
2022-08-23 15:33:09 -07:00
}
return [ ]
} , [ group ] )
const handleShowTokenDetails = ( name : string ) = > {
showTokenDetails ? setShowTokenDetails ( '' ) : setShowTokenDetails ( name )
}
2022-10-11 04:59:01 -07:00
const goToTokenPage = ( bank : Bank ) = > {
router . push ( ` /token/ ${ bank . name } ` , undefined , { shallow : true } )
}
2022-08-23 15:33:09 -07:00
return (
2022-09-14 19:41:55 -07:00
< ContentBox hideBorder hidePadding >
2022-08-23 15:33:09 -07:00
{ showTableView ? (
2022-11-20 02:44:14 -08:00
< Table >
2022-08-23 15:33:09 -07:00
< thead >
2022-11-20 02:44:14 -08:00
< TrHead >
< Th className = "text-left" > { t ( 'token' ) } < / Th >
< Th className = "text-right" > { t ( 'total-deposits' ) } < / Th >
< Th className = "text-right" > { t ( 'total-borrows' ) } < / Th >
< Th >
2022-09-25 17:37:04 -07:00
< div className = "flex justify-end" >
< Tooltip content = "The deposit rate (green) will automatically be paid on positive balances and the borrow rate (red) will automatically be charged on negative balances." >
< span className = "tooltip-underline" > { t ( 'rates' ) } < / span >
< / Tooltip >
< / div >
2022-11-20 02:44:14 -08:00
< / Th >
< Th >
2022-09-25 17:37:04 -07:00
< div className = "flex justify-end" >
< Tooltip content = "The percentage of deposits that have been lent out." >
< span className = "tooltip-underline" >
{ t ( 'utilization' ) }
< / span >
< / Tooltip >
< / div >
2022-11-20 02:44:14 -08:00
< / Th >
< Th >
2022-10-11 04:59:01 -07:00
< div className = "flex justify-end text-right" >
2022-09-25 17:37:04 -07:00
< Tooltip content = { t ( 'asset-weight-desc' ) } >
< span className = "tooltip-underline" >
{ t ( 'asset-weight' ) }
< / span >
< / Tooltip >
< / div >
2022-11-20 02:44:14 -08:00
< / Th >
< Th >
2022-08-24 20:55:55 -07:00
< div className = "flex items-center justify-end" >
2022-09-18 23:26:42 -07:00
< span className = "text-right" > { t ( 'liability-weight' ) } < / span >
2022-08-23 15:33:09 -07:00
< / div >
2022-11-20 02:44:14 -08:00
< / Th >
< / TrHead >
2022-08-23 15:33:09 -07:00
< / thead >
< tbody >
2023-01-03 01:20:34 -08:00
{ banks . map ( ( { key , value } ) = > {
2023-01-03 00:33:30 -08:00
const bank = value [ 0 ]
2023-01-03 01:20:34 -08:00
2023-01-03 00:33:30 -08:00
let logoURI
if ( mangoTokens ? . length ) {
logoURI = mangoTokens . find (
( t ) = > t . address === bank . mint . toString ( )
) ? . logoURI
}
2023-01-08 16:40:15 -08:00
const deposits = bank . uiDeposits ( )
const borrows = bank . uiBorrows ( )
const price = bank . uiPrice
2023-01-03 01:20:34 -08:00
2023-01-03 00:33:30 -08:00
return (
2023-01-03 01:20:34 -08:00
< TrBody key = { key } >
< Td >
2023-01-03 00:33:30 -08:00
< div className = "flex items-center" >
< div className = "mr-2.5 flex flex-shrink-0 items-center" >
{ logoURI ? (
< Image alt = "" width = "24" height = "24" src = { logoURI } / >
) : (
2023-01-03 01:20:34 -08:00
< QuestionMarkCircleIcon className = "h-6 w-6 text-th-fgd-3" / >
2023-01-03 00:33:30 -08:00
) }
< / div >
2023-01-05 18:03:58 -08:00
< p className = "font-body tracking-wider" > { bank . name } < / p >
2022-08-23 15:33:09 -07:00
< / div >
2023-01-03 01:20:34 -08:00
< / Td >
< Td >
< div className = "flex flex-col text-right" >
2023-01-08 16:40:15 -08:00
< p > { formatFixedDecimals ( deposits ) } < / p >
2023-01-08 16:49:42 -08:00
< p className = "text-th-fgd-4" >
2023-01-08 17:50:46 -08:00
{ formatFixedDecimals ( deposits * price , true , true ) }
2023-01-08 16:40:15 -08:00
< / p >
2023-01-03 01:20:34 -08:00
< / div >
< / Td >
< Td >
< div className = "flex flex-col text-right" >
2023-01-08 16:40:15 -08:00
< p > { formatFixedDecimals ( borrows ) } < / p >
2023-01-08 16:49:42 -08:00
< p className = "text-th-fgd-4" >
2023-01-08 17:50:46 -08:00
{ formatFixedDecimals ( borrows * price , true , true ) }
2023-01-08 16:40:15 -08:00
< / p >
2023-01-03 01:20:34 -08:00
< / div >
< / Td >
< Td >
< div className = "flex justify-end space-x-2" >
< p className = "text-th-up" >
{ formatDecimal ( bank . getDepositRateUi ( ) , 2 , {
fixed : true ,
} ) }
%
< / p >
< span className = "text-th-fgd-4" > | < / span >
< p className = "text-th-down" >
{ formatDecimal ( bank . getBorrowRateUi ( ) , 2 , {
fixed : true ,
} ) }
%
< / p >
< / div >
< / Td >
< Td >
< div className = "flex flex-col text-right" >
< p >
{ bank . uiDeposits ( ) > 0
? formatDecimal (
( bank . uiBorrows ( ) / bank . uiDeposits ( ) ) * 100 ,
1 ,
{ fixed : true }
)
: '0.0' }
%
< / p >
< / div >
< / Td >
< Td >
< div className = "text-right" >
< p > { bank . initAssetWeight . toFixed ( 2 ) } < / p >
< / div >
< / Td >
< Td >
< div className = "text-right" >
< p > { bank . initLiabWeight . toFixed ( 2 ) } < / p >
< / div >
< / Td >
< Td >
< div className = "flex justify-end" >
2023-01-03 00:33:30 -08:00
< IconButton
2023-01-03 01:20:34 -08:00
onClick = { ( ) = > goToTokenPage ( bank ) }
size = "small"
2022-10-11 04:59:01 -07:00
>
2023-01-03 01:20:34 -08:00
< ChevronRightIcon className = "h-5 w-5" / >
2023-01-03 00:33:30 -08:00
< / IconButton >
2022-10-11 04:59:01 -07:00
< / div >
2023-01-03 01:20:34 -08:00
< / Td >
< / TrBody >
)
} ) }
< / tbody >
< / Table >
) : (
< div >
{ banks . map ( ( { key , value } ) = > {
const bank = value [ 0 ]
let logoURI
if ( mangoTokens ? . length ) {
logoURI = mangoTokens . find (
( t ) = > t . address === bank . mint . toString ( )
) ? . logoURI
}
2023-01-08 16:49:42 -08:00
const deposits = bank . uiDeposits ( )
const borrows = bank . uiBorrows ( )
const price = bank . uiPrice
2023-01-03 01:20:34 -08:00
return (
< div key = { key } className = "border-b border-th-bkg-3 px-6 py-4" >
< div className = "flex items-center justify-between" >
< div className = "flex items-center" >
< div className = "mr-2.5 flex flex-shrink-0 items-center" >
{ logoURI ? (
< Image alt = "" width = "24" height = "24" src = { logoURI } / >
) : (
< QuestionMarkCircleIcon className = "h-7 w-7 text-th-fgd-3" / >
) }
< / div >
< p className = "text-th-fgd-1" > { bank . name } < / p >
2022-08-23 15:33:09 -07:00
< / div >
2023-01-03 01:20:34 -08:00
< div className = "flex items-center space-x-4" >
< div >
2023-01-08 16:49:42 -08:00
< p className = "mb-0.5 text-right text-xs" >
2023-01-03 01:20:34 -08:00
{ t ( 'total-deposits' ) }
< / p >
< p className = "text-right font-mono text-th-fgd-1" >
2023-01-08 16:49:42 -08:00
{ formatFixedDecimals ( deposits ) }
< / p >
< p className = "text-right text-th-fgd-4" >
2023-01-08 17:50:46 -08:00
{ formatFixedDecimals ( deposits * price , true , true ) }
2023-01-03 01:20:34 -08:00
< / p >
2023-01-03 00:33:30 -08:00
< / div >
2023-01-03 01:20:34 -08:00
< div >
2023-01-08 16:49:42 -08:00
< p className = "mb-0.5 text-right text-xs" >
{ t ( 'total-borrows' ) }
< / p >
2023-01-03 01:20:34 -08:00
< p className = "text-right font-mono text-th-fgd-1" >
2023-01-08 16:49:42 -08:00
{ formatFixedDecimals ( borrows ) }
< / p >
< p className = "text-right text-th-fgd-4" >
2023-01-08 17:50:46 -08:00
{ formatFixedDecimals ( borrows * price , true , true ) }
2023-01-03 01:20:34 -08:00
< / p >
< / div >
< IconButton
onClick = { ( ) = > handleShowTokenDetails ( bank . name ) }
>
< ChevronDownIcon
className = { ` ${
showTokenDetails === bank . name
? 'rotate-180'
: 'rotate-360'
} h - 6 w - 6 flex - shrink - 0 text - th - fgd - 1 ` }
/ >
< / IconButton >
< / div >
2023-01-03 00:33:30 -08:00
< / div >
2023-01-03 01:20:34 -08:00
< Transition
appear = { true }
show = { showTokenDetails === bank . name }
as = { Fragment }
enter = "transition ease-in duration-200"
enterFrom = "opacity-0"
enterTo = "opacity-100"
leave = "transition ease-out"
leaveFrom = "opacity-100"
leaveTo = "opacity-0"
>
< div className = "mt-4 grid grid-cols-2 gap-4 border-t border-th-bkg-3 pt-4" >
< div className = "col-span-1" >
< p className = "text-xs text-th-fgd-3" > { t ( 'rates' ) } < / p >
< p className = "space-x-2" >
< span className = "font-mono text-th-up" >
{ formatDecimal ( bank . getDepositRate ( ) . toNumber ( ) , 2 ) } %
< / span >
< span className = "font-normal text-th-fgd-4" > | < / span >
< span className = "font-mono text-th-down" >
{ formatDecimal ( bank . getBorrowRate ( ) . toNumber ( ) , 2 ) } %
< / span >
< / p >
< / div >
< div className = "col-span-1" >
< p className = "text-xs text-th-fgd-3" >
{ t ( 'utilization' ) }
< / p >
< p className = "font-mono text-th-fgd-1" >
{ bank . uiDeposits ( ) > 0
? formatDecimal (
( bank . uiBorrows ( ) / bank . uiDeposits ( ) ) * 100 ,
1 ,
{ fixed : true }
)
: '0.0' }
%
< / p >
< / div >
< div className = "col-span-1" >
< p className = "text-xs text-th-fgd-3" >
{ t ( 'asset-weight' ) }
< / p >
< p className = "font-mono text-th-fgd-1" >
{ bank . initAssetWeight . toFixed ( 2 ) }
< / p >
< / div >
< div className = "col-span-1" >
< p className = "text-xs text-th-fgd-3" >
{ t ( 'liability-weight' ) }
< / p >
< p className = "font-mono text-th-fgd-1" >
{ bank . initLiabWeight . toFixed ( 2 ) }
< / p >
< / div >
< div className = "col-span-1" >
< LinkButton
className = "flex items-center"
onClick = { ( ) = > goToTokenPage ( bank ) }
>
{ t ( 'token:token-details' ) }
< ChevronRightIcon className = "ml-2 h-5 w-5" / >
< / LinkButton >
< / div >
< / div >
< / Transition >
< / div >
)
} ) }
2022-08-23 15:33:09 -07:00
< / div >
) }
< / ContentBox >
)
}
2022-10-11 04:59:01 -07:00
export default TokenStats