* 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:
219 lines
6.6 KiB
TypeScript
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>
|
|
)
|
|
}
|