mars-v2-frontend/src/components/Account/AccountBalancesTable.tsx
Bob van der Helm 697e83b7cb
Mp depostied vaults table (#271)
* added correct resolving of account positions

* solve rendering bug for lp amount

* bugfix: add slippage to minlpamount

* fix DisplayCurrency to accept only BNCoin

* bugfix: remove prices from store

* add basic depostied vaults table

* Farm: Added deposited table

* finish deposited table, remove featured vaults:
2023-06-29 12:55:47 +02:00

219 lines
6.6 KiB
TypeScript

import {
ColumnDef,
flexRender,
getCoreRowModel,
getSortedRowModel,
SortingState,
useReactTable,
} from '@tanstack/react-table'
import classNames from 'classnames'
import React from 'react'
import DisplayCurrency from 'components/DisplayCurrency'
import { FormattedNumber } from 'components/FormattedNumber'
import { SortAsc, SortDesc, SortNone } from 'components/Icons'
import Text from 'components/Text'
import { ASSETS } from 'constants/assets'
import useStore from 'store'
import { convertToDisplayAmount, demagnify } from 'utils/formatters'
import { BN } from 'utils/helpers'
import { BNCoin } from 'types/classes/BNCoin'
import usePrices from 'hooks/usePrices'
interface Props {
data: Account
}
export const AccountBalancesTable = (props: Props) => {
const displayCurrency = useStore((s) => s.displayCurrency)
const { data: prices } = usePrices()
const [sorting, setSorting] = React.useState<SortingState>([])
const balanceData = React.useMemo<AccountBalanceRow[]>(() => {
const accountDeposits = props.data?.deposits ?? []
const accountLends = props.data?.lends ?? []
const deposits = accountDeposits.map((deposit) => {
const asset = ASSETS.find((asset) => asset.denom === deposit.denom) ?? ASSETS[0]
const apy = 0
return {
type: 'deposit',
symbol: asset.symbol,
denom: deposit.denom,
amount: deposit.amount,
size: demagnify(deposit.amount, asset),
value: convertToDisplayAmount(
new BNCoin({ amount: deposit.amount, denom: deposit.denom }),
displayCurrency,
prices,
).toString(),
apy,
}
})
const lends = accountLends.map((lending) => {
const asset = ASSETS.find((asset) => asset.denom === lending.denom) ?? ASSETS[0]
const apy = 0
return {
type: 'lending',
symbol: asset.symbol,
denom: lending.denom,
amount: lending.amount,
size: demagnify(lending.amount, asset),
value: convertToDisplayAmount(
new BNCoin({ amount: lending.amount, denom: lending.denom }),
displayCurrency,
prices,
).toString(),
apy,
}
})
return [...deposits, ...lends]
}, [displayCurrency, prices, props.data?.deposits, props.data?.lends])
const columns = React.useMemo<ColumnDef<AccountBalanceRow>[]>(
() => [
{
header: 'Asset',
accessorKey: 'symbol',
id: 'symbol',
cell: ({ row }) => {
return (
<Text size='xs'>
{row.original.symbol}
{row.original.type === 'lending' && <span className='text-profit'>(Lent)</span>}
</Text>
)
},
},
{
header: 'Value',
accessorKey: 'value',
id: 'value',
cell: ({ row }) => {
const coin = new BNCoin({ denom: row.original.denom, amount: row.original.amount })
return <DisplayCurrency coin={coin} className='text-right text-xs' />
},
},
{
id: 'size',
accessorKey: 'size',
header: 'Size',
cell: ({ row }) => {
return (
<FormattedNumber
className='text-right text-xs'
amount={BN(
demagnify(
row.original.amount,
ASSETS.find((asset) => asset.denom === row.original.denom) ?? ASSETS[0],
),
)}
options={{ maxDecimals: 4 }}
/>
)
},
},
{
id: 'apy',
accessorKey: 'apy',
header: 'APY',
cell: ({ row }) => {
return (
<FormattedNumber
className='text-xs'
amount={BN(row.original.apy)}
options={{ maxDecimals: 2, minDecimals: 2, suffix: '%' }}
/>
)
},
},
],
[],
)
const table = useReactTable({
data: balanceData,
columns,
state: {
sorting,
},
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
})
return (
<table className='w-full'>
<thead className='border-b border-b-white/5'>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header, index) => {
return (
<th
key={header.id}
onClick={header.column.getToggleSortingHandler()}
className={classNames(
'p-2',
header.column.getCanSort() && 'cursor-pointer',
header.id === 'symbol' ? 'text-left' : 'text-right',
)}
>
<div
className={classNames(
'flex',
header.id === 'symbol' ? 'justify-start' : 'justify-end',
'align-center',
)}
>
<span className='h-6 w-6 text-white'>
{header.column.getCanSort()
? {
asc: <SortAsc />,
desc: <SortDesc />,
false: <SortNone />,
}[header.column.getIsSorted() as string] ?? null
: null}
</span>
<Text
tag='span'
size='sm'
className='flex items-center font-normal text-white/40'
>
{flexRender(header.column.columnDef.header, header.getContext())}
</Text>
</div>
</th>
)
})}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => {
return (
<tr key={row.id} className=' text-white/60'>
{row.getVisibleCells().map((cell) => {
const borderClass =
cell.row.original.type === 'deposit' ? 'border-profit' : 'border-loss'
return (
<td
key={cell.id}
className={classNames(
cell.column.id === 'symbol' ? `border-l ${borderClass}` : 'pl-4 text-right',
'p-2',
)}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
)
})}
</tr>
)
})}
</tbody>
</table>
)
}