2023-04-27 05:11:20 -07:00
import { Disclosure , Transition } from '@headlessui/react'
2023-07-04 21:40:47 -07:00
import { ChevronDownIcon , ChevronRightIcon } from '@heroicons/react/20/solid'
2023-04-27 05:11:20 -07:00
import { useTranslation } from 'next-i18next'
2023-08-17 11:02:59 -07:00
import { useViewport } from '../../../hooks/useViewport'
import { breakpoints } from '../../../utils/theme'
import { LinkButton } from '../../shared/Button'
import ContentBox from '../../shared/ContentBox'
2023-04-27 05:11:20 -07:00
import Tooltip from '@components/shared/Tooltip'
import { Bank , toUiDecimals } from '@blockworks-foundation/mango-v4'
import { NextRouter , useRouter } from 'next/router'
2023-07-27 04:24:04 -07:00
import {
SortableColumnHeader ,
Table ,
Td ,
Th ,
TrBody ,
TrHead ,
} from '@components/shared/TableElements'
2023-04-27 05:11:20 -07:00
import useMangoGroup from 'hooks/useMangoGroup'
import FormatNumericValue from '@components/shared/FormatNumericValue'
import BankAmountWithValue from '@components/shared/BankAmountWithValue'
2023-07-27 22:04:38 -07:00
import useBanksWithBalances from 'hooks/useBanksWithBalances'
2023-04-27 05:11:20 -07:00
import Decimal from 'decimal.js'
2023-07-27 04:24:04 -07:00
import { useCallback } from 'react'
import { useSortableData } from 'hooks/useSortableData'
2023-10-10 18:28:27 -07:00
import TableTokenName from '@components/shared/TableTokenName'
2023-11-01 18:21:35 -07:00
import { formatTokenSymbol } from 'utils/tokens'
2023-04-27 05:11:20 -07:00
2023-05-02 18:00:32 -07:00
export const goToTokenPage = ( token : string , router : NextRouter ) = > {
const query = { . . . router . query , [ 'token' ] : token }
router . push ( { pathname : router.pathname , query } )
}
2023-05-02 10:47:26 -07:00
const TokenOverviewTable = ( ) = > {
2023-04-27 05:11:20 -07:00
const { t } = useTranslation ( [ 'common' , 'token' ] )
const { group } = useMangoGroup ( )
const { width } = useViewport ( )
const showTableView = width ? width > breakpoints.md : false
const router = useRouter ( )
const banks = useBanksWithBalances ( )
2023-07-27 22:04:38 -07:00
const formattedTableData = useCallback ( ( ) = > {
const formatted = [ ]
for ( const b of banks ) {
const bank : Bank = b . bank
const deposits = bank . uiDeposits ( )
2023-07-31 19:26:08 -07:00
const depositsValue = deposits * bank . uiPrice
2023-07-27 22:04:38 -07:00
const borrows = bank . uiBorrows ( )
2023-07-31 19:26:08 -07:00
const borrowsValue = borrows * bank . uiPrice
2023-07-27 22:04:38 -07:00
const availableVaultBalance = group
? group . getTokenVaultBalanceByMintUi ( bank . mint ) -
deposits * bank . minVaultToDepositsRatio
: 0
const available = Decimal . max (
0 ,
availableVaultBalance . toFixed ( bank . mintDecimals ) ,
)
2023-07-31 19:26:08 -07:00
const availableValue = available . toNumber ( ) * bank . uiPrice
2023-07-27 22:04:38 -07:00
const feesEarned = toUiDecimals (
bank . collectedFeesNative ,
bank . mintDecimals ,
)
2023-07-31 19:26:08 -07:00
const feeValue = feesEarned * bank . uiPrice
2023-07-27 22:04:38 -07:00
const utilization =
bank . uiDeposits ( ) > 0 ? ( bank . uiBorrows ( ) / bank . uiDeposits ( ) ) * 100 : 0
2023-07-27 04:24:04 -07:00
2023-07-27 22:04:38 -07:00
const depositRate = bank . getDepositRateUi ( )
const borrowRate = bank . getBorrowRateUi ( )
const symbol = bank . name
2023-07-27 04:24:04 -07:00
2023-07-27 22:04:38 -07:00
const data = {
available ,
2023-07-31 19:26:08 -07:00
availableValue ,
2023-07-27 22:04:38 -07:00
bank ,
borrowRate ,
2023-07-31 19:26:08 -07:00
borrows ,
borrowsValue ,
2023-07-27 22:04:38 -07:00
depositRate ,
2023-07-31 19:26:08 -07:00
deposits ,
depositsValue ,
2023-07-27 22:04:38 -07:00
feesEarned ,
2023-07-31 19:26:08 -07:00
feeValue ,
2023-07-27 22:04:38 -07:00
symbol ,
utilization ,
2023-07-27 04:24:04 -07:00
}
2023-07-27 22:04:38 -07:00
formatted . push ( data )
}
2023-08-10 21:09:00 -07:00
return formatted . sort (
( a , b ) = > b . deposits * b . bank . uiPrice - a . deposits * a . bank . uiPrice ,
)
2023-07-27 22:04:38 -07:00
} , [ banks , group ] )
2023-07-27 04:24:04 -07:00
const {
items : tableData ,
requestSort ,
sortConfig ,
2023-07-27 22:04:38 -07:00
} = useSortableData ( formattedTableData ( ) )
2023-07-27 04:24:04 -07:00
return (
2023-04-27 05:11:20 -07:00
< ContentBox hideBorder hidePadding >
{ showTableView ? (
< div className = "thin-scroll overflow-x-auto" >
< Table >
< thead >
< TrHead >
2023-07-27 04:24:04 -07:00
< Th className = "text-left" >
< SortableColumnHeader
sortKey = "symbol"
sort = { ( ) = > requestSort ( 'symbol' ) }
sortConfig = { sortConfig }
title = { t ( 'token' ) }
/ >
< / Th >
< Th >
< div className = "flex justify-end" >
< SortableColumnHeader
2023-07-31 19:26:08 -07:00
sortKey = "depositsValue"
sort = { ( ) = > requestSort ( 'depositsValue' ) }
2023-07-27 04:24:04 -07:00
sortConfig = { sortConfig }
title = { t ( 'total-deposits' ) }
/ >
< / div >
< / Th >
< Th >
< div className = "flex justify-end" >
< SortableColumnHeader
2023-07-31 19:26:08 -07:00
sortKey = "borrowsValue"
sort = { ( ) = > requestSort ( 'borrowsValue' ) }
2023-07-27 04:24:04 -07:00
sortConfig = { sortConfig }
title = { t ( 'total-borrows' ) }
/ >
< / div >
< / Th >
2023-04-27 05:11:20 -07:00
< Th className = "text-right" >
< div className = "flex justify-end" >
2023-10-04 16:04:51 -07:00
< Tooltip content = { t ( 'tooltip-available' , { token : '' } ) } >
2023-07-27 04:24:04 -07:00
< SortableColumnHeader
2023-07-31 19:26:08 -07:00
sortKey = "availableValue"
sort = { ( ) = > requestSort ( 'availableValue' ) }
2023-07-27 04:24:04 -07:00
sortConfig = { sortConfig }
title = { t ( 'available' ) }
titleClass = "tooltip-underline"
/ >
2023-04-27 05:11:20 -07:00
< / Tooltip >
< / div >
< / Th >
< Th >
< div className = "flex justify-end" >
< Tooltip content = { t ( 'token:fees-tooltip' ) } >
2023-07-27 04:24:04 -07:00
< SortableColumnHeader
2023-07-31 19:26:08 -07:00
sortKey = "feeValue"
sort = { ( ) = > requestSort ( 'feeValue' ) }
2023-07-27 04:24:04 -07:00
sortConfig = { sortConfig }
title = { t ( 'fees' ) }
titleClass = "tooltip-underline"
/ >
2023-04-27 05:11:20 -07:00
< / Tooltip >
< / div >
< / Th >
< Th >
< 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." >
2023-07-27 04:24:04 -07:00
< SortableColumnHeader
sortKey = "depositRate"
sort = { ( ) = > requestSort ( 'depositRate' ) }
sortConfig = { sortConfig }
title = { t ( 'rates' ) }
titleClass = "tooltip-underline"
/ >
2023-04-27 05:11:20 -07:00
< / Tooltip >
< / div >
< / Th >
< Th >
< div className = "flex justify-end" >
< Tooltip content = "The percentage of deposits that have been lent out" >
2023-07-27 04:24:04 -07:00
< SortableColumnHeader
sortKey = "utilization"
sort = { ( ) = > requestSort ( 'utilization' ) }
sortConfig = { sortConfig }
title = { t ( 'utilization' ) }
titleClass = "tooltip-underline"
/ >
2023-04-27 05:11:20 -07:00
< / Tooltip >
< / div >
< / Th >
< Th / >
< / TrHead >
< / thead >
< tbody >
2023-07-27 04:24:04 -07:00
{ tableData . map ( ( data ) = > {
const {
available ,
bank ,
borrows ,
borrowRate ,
deposits ,
depositRate ,
feesEarned ,
symbol ,
utilization ,
} = data
2023-04-27 05:11:20 -07:00
return (
< TrBody
2023-05-02 18:03:06 -07:00
className = "default-transition md:hover:cursor-pointer md:hover:bg-th-bkg-2"
2023-07-27 04:24:04 -07:00
key = { symbol }
2023-04-27 05:11:20 -07:00
onClick = { ( ) = >
2023-06-27 08:00:48 -07:00
goToTokenPage ( bank . name . split ( ' ' ) [ 0 ] , router )
2023-04-27 05:11:20 -07:00
}
>
< Td >
2023-10-10 18:28:27 -07:00
< TableTokenName bank = { bank } symbol = { symbol } / >
2023-04-27 05:11:20 -07:00
< / Td >
< Td >
< div className = "flex flex-col text-right" >
< BankAmountWithValue
amount = { deposits . toFixed ( 4 ) }
bank = { bank }
fixDecimals = { false }
stacked
/ >
< / div >
< / Td >
< Td >
< div className = "flex flex-col text-right" >
< BankAmountWithValue
amount = { borrows . toFixed ( 4 ) }
bank = { bank }
fixDecimals = { false }
stacked
/ >
< / div >
< / Td >
< Td >
< div className = "flex flex-col text-right" >
< BankAmountWithValue
amount = { available }
bank = { bank }
fixDecimals = { false }
stacked
/ >
< / div >
< / Td >
< Td >
< div className = "flex flex-col text-right" >
< BankAmountWithValue
amount = { feesEarned }
bank = { bank }
fixDecimals = { false }
stacked
/ >
< / div >
< / Td >
< Td >
< div className = "flex justify-end space-x-1.5" >
< p className = "text-th-up" >
< FormatNumericValue
2023-07-27 04:24:04 -07:00
value = { depositRate }
2023-04-27 05:11:20 -07:00
decimals = { 2 }
/ >
%
< / p >
< span className = "text-th-fgd-4" > | < / span >
< p className = "text-th-down" >
2023-07-27 04:24:04 -07:00
< FormatNumericValue value = { borrowRate } decimals = { 2 } / >
2023-04-27 05:11:20 -07:00
%
< / p >
< / div >
< / Td >
< Td >
< div className = "flex flex-col text-right" >
2023-07-27 04:24:04 -07:00
< p > { utilization . toFixed ( 1 ) } % < / p >
2023-04-27 05:11:20 -07:00
< / div >
< / Td >
< Td >
< div className = "flex justify-end" >
< ChevronRightIcon className = "h-5 w-5 text-th-fgd-3" / >
< / div >
< / Td >
< / TrBody >
)
} ) }
< / tbody >
< / Table >
< / div >
) : (
< div className = "border-b border-th-bkg-3" >
2023-07-27 04:24:04 -07:00
{ tableData . map ( ( data , i ) = > {
const {
available ,
bank ,
borrows ,
borrowRate ,
deposits ,
depositRate ,
feesEarned ,
symbol ,
utilization ,
} = data
2023-04-27 05:11:20 -07:00
return (
2023-07-27 04:24:04 -07:00
< Disclosure key = { symbol } >
2023-04-27 05:11:20 -07:00
{ ( { open } ) = > (
< >
< Disclosure.Button
className = { ` w-full border-t border-th-bkg-3 p-4 text-left focus:outline-none ${
i === 0 ? 'border-t-0' : ''
} ` }
>
< div className = "flex items-center justify-between" >
2023-10-10 18:28:27 -07:00
< TableTokenName bank = { bank } symbol = { symbol } / >
2023-04-27 05:11:20 -07:00
< ChevronDownIcon
className = { ` ${
open ? 'rotate-180' : 'rotate-360'
} h - 6 w - 6 flex - shrink - 0 text - th - fgd - 3 ` }
/ >
< / div >
< / Disclosure.Button >
< Transition
enter = "transition ease-in duration-200"
enterFrom = "opacity-0"
enterTo = "opacity-100"
>
< Disclosure.Panel >
2023-08-17 16:47:11 -07:00
< div className = "mx-4 grid grid-cols-2 gap-4 border-t border-th-bkg-3 pb-4 pt-4" >
2023-04-27 05:11:20 -07:00
< div className = "col-span-1" >
< p className = "mb-0.5 text-xs" >
{ t ( 'total-deposits' ) }
< / p >
< BankAmountWithValue
amount = { deposits . toFixed ( 4 ) }
bank = { bank }
fixDecimals = { false }
/ >
< / div >
< div className = "col-span-1" >
< p className = "mb-0.5 text-xs" >
{ t ( 'total-borrows' ) }
< / p >
< BankAmountWithValue
amount = { borrows . toFixed ( 4 ) }
bank = { bank }
fixDecimals = { false }
/ >
< / div >
< div className = "col-span-1" >
< Tooltip content = "The amount available to borrow" >
< p className = "tooltip-underline text-xs" >
{ t ( 'available' ) }
< / p >
< / Tooltip >
< BankAmountWithValue
amount = { available }
bank = { bank }
fixDecimals = { false }
/ >
< / div >
< div className = "col-span-1" >
< Tooltip content = { t ( 'token:fees-tooltip' ) } >
< p className = "tooltip-underline text-xs" >
{ t ( 'fees' ) }
< / p >
< / Tooltip >
< BankAmountWithValue
amount = { feesEarned }
bank = { bank }
fixDecimals = { false }
/ >
< / div >
< div className = "col-span-1" >
< p className = "text-xs" > { t ( 'rates' ) } < / p >
< p className = "space-x-2" >
< span className = "font-mono text-th-up" >
< FormatNumericValue
2023-07-27 04:24:04 -07:00
value = { depositRate }
2023-04-27 05:11:20 -07:00
decimals = { 2 }
/ >
%
< / span >
< span className = "font-normal text-th-fgd-4" >
|
< / span >
< span className = "font-mono text-th-down" >
< FormatNumericValue
2023-07-27 04:24:04 -07:00
value = { borrowRate }
2023-04-27 05:11:20 -07:00
decimals = { 2 }
/ >
%
< / span >
< / p >
< / div >
< div className = "col-span-1" >
< p className = "text-xs" > { t ( 'utilization' ) } < / p >
< p className = "font-mono text-th-fgd-1" >
2023-08-05 05:32:18 -07:00
{ utilization . toFixed ( 1 ) } %
2023-04-27 05:11:20 -07:00
< / p >
< / div >
< div className = "col-span-1" >
< LinkButton
className = "flex items-center"
onClick = { ( ) = >
2023-06-27 08:00:48 -07:00
goToTokenPage ( bank . name . split ( ' ' ) [ 0 ] , router )
2023-04-27 05:11:20 -07:00
}
>
2023-11-01 18:21:35 -07:00
{ t ( 'token:token-stats' , {
token : formatTokenSymbol ( bank . name ) ,
} ) }
2023-04-27 05:11:20 -07:00
< ChevronRightIcon className = "ml-2 h-5 w-5" / >
< / LinkButton >
< / div >
< / div >
< / Disclosure.Panel >
< / Transition >
< / >
) }
< / Disclosure >
)
} ) }
< / div >
) }
< / ContentBox >
2023-07-27 04:24:04 -07:00
)
2023-04-27 05:11:20 -07:00
}
2023-05-02 10:47:26 -07:00
export default TokenOverviewTable