Refactor balances table (#590)
* env: update env.example after last sync * tidy: refactored AccountBalancesTable * fix: updated isCard to hideCard
This commit is contained in:
parent
fb2915ba37
commit
0c7f39a6a7
@ -4,8 +4,6 @@ NEXT_PUBLIC_CHAIN_ID=devnet
|
||||
NEXT_PUBLIC_RPC=https://rpc.devnet.osmosis.zone/
|
||||
NEXT_PUBLIC_GQL=https://devnet-osmosis-gql.marsprotocol.io/graphql
|
||||
NEXT_PUBLIC_REST=https://lcd.devnet.osmosis.zone/
|
||||
NEXT_PUBLIC_ZAPPER=osmo1yhh8mhthj5jn5c6ty59z3tpsk554qxmlkrkcderw6jls0pcg8zxsdjdj94
|
||||
NEXT_PUBLIC_PARAMS=osmo1aye5qcer5n52crrkaf35jprsad2807q6kg3eeeu7k79h4slxfausfqhc9y
|
||||
|
||||
|
||||
# MAINNET #
|
||||
@ -14,8 +12,6 @@ NEXT_PUBLIC_CHAIN_ID=osmosis-1
|
||||
NEXT_PUBLIC_RPC=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-rpc-front/
|
||||
NEXT_PUBLIC_GQL=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-hive-front/graphql
|
||||
NEXT_PUBLIC_REST=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-lcd-front/
|
||||
NEXT_PUBLIC_ZAPPER=osmo17qwvc70pzc9mudr8t02t3pl74hhqsgwnskl734p4hug3s8mkerdqzduf7c
|
||||
NEXT_PUBLIC_PARAMS=osmo1nlmdxt9ctql2jr47qd4fpgzg84cjswxyw6q99u4y4u4q6c2f5ksq7ysent
|
||||
|
||||
|
||||
# COMMON #
|
||||
@ -28,6 +24,8 @@ NEXT_PUBLIC_CREDIT_MANAGER=osmo1f2m24wktq0sw3c0lexlg7fv4kngwyttvzws3a3r3al9ld2s2
|
||||
NEXT_PUBLIC_INCENTIVES=osmo1nkahswfr8shg8rlxqwup0vgahp0dk4x8w6tkv3rra8rratnut36sk22vrm
|
||||
NEXT_PUBLIC_SWAPPER=osmo1wee0z8c7tcawyl647eapqs4a88q8jpa7ddy6nn2nrs7t47p2zhxswetwla
|
||||
NEXT_PUBLIC_PYTH=osmo13ge29x4e2s63a8ytz2px8gurtyznmue4a69n5275692v3qn3ks8q7cwck7
|
||||
NEXT_PUBLIC_ZAPPER=osmo17qwvc70pzc9mudr8t02t3pl74hhqsgwnskl734p4hug3s8mkerdqzduf7c
|
||||
NEXT_PUBLIC_PARAMS=osmo1nlmdxt9ctql2jr47qd4fpgzg84cjswxyw6q99u4y4u4q6c2f5ksq7ysent
|
||||
NEXT_PUBLIC_PYTH_ENDPOINT=https://hermes.pyth.network/api
|
||||
NEXT_PUBLIC_MAINNET_REST=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-rpc-front/
|
||||
NEXT_PUBLIC_CANDLES_ENDPOINT=https://osmosis-candles.marsprotocol.io/
|
||||
|
28
src/components/Account/AccountBalancesTable/Columns/Apy.tsx
Normal file
28
src/components/Account/AccountBalancesTable/Columns/Apy.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import AssetRate from 'components/Asset/AssetRate'
|
||||
import { byDenom } from 'utils/array'
|
||||
|
||||
export const APY_META = { accessorKey: 'apy', header: 'APY' }
|
||||
|
||||
interface Props {
|
||||
apy: number
|
||||
markets: Market[]
|
||||
denom: string
|
||||
type: 'deposits' | 'borrowing' | 'lending' | 'vault'
|
||||
}
|
||||
|
||||
export default function Apr(props: Props) {
|
||||
const { markets, type, denom, apy } = props
|
||||
|
||||
if (type === 'deposits') return <p className='w-full text-xs text-right number'>–</p>
|
||||
const isEnabled = markets.find(byDenom(denom))?.borrowEnabled ?? false
|
||||
|
||||
return (
|
||||
<AssetRate
|
||||
className='justify-end text-xs'
|
||||
rate={apy}
|
||||
isEnabled={type !== 'lending' || isEnabled}
|
||||
type='apy'
|
||||
orientation='ltr'
|
||||
/>
|
||||
)
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
import Text from 'components/Text'
|
||||
export const ASSET_META = { accessorKey: 'symbol', header: 'Asset', id: 'symbol' }
|
||||
|
||||
interface Props {
|
||||
symbol: string
|
||||
type: 'deposits' | 'borrowing' | 'lending' | 'vault'
|
||||
}
|
||||
|
||||
export const borderColor = (type: Props['type']): string =>
|
||||
type === 'borrowing' ? 'border-loss' : 'border-profit'
|
||||
|
||||
export default function Asset(props: Props) {
|
||||
const { symbol, type } = props
|
||||
return (
|
||||
<Text size='xs'>
|
||||
{symbol}
|
||||
{type === 'borrowing' && <span className='ml-1 text-loss'>(debt)</span>}
|
||||
{type === 'lending' && <span className='ml-1 text-profit'>(lent)</span>}
|
||||
{type === 'vault' && <span className='ml-1 text-profit'>(farm)</span>}
|
||||
</Text>
|
||||
)
|
||||
}
|
60
src/components/Account/AccountBalancesTable/Columns/Size.tsx
Normal file
60
src/components/Account/AccountBalancesTable/Columns/Size.tsx
Normal file
@ -0,0 +1,60 @@
|
||||
import { Row } from '@tanstack/react-table'
|
||||
import classNames from 'classnames'
|
||||
|
||||
import { getAmountChangeColor } from 'components/Account/AccountBalancesTable/functions'
|
||||
import { FormattedNumber } from 'components/FormattedNumber'
|
||||
import { MAX_AMOUNT_DECIMALS, MIN_AMOUNT } from 'constants/math'
|
||||
import { formatAmountToPrecision } from 'utils/formatters'
|
||||
|
||||
export const SIZE_META = { accessorKey: 'size', header: 'Size' }
|
||||
|
||||
interface Props {
|
||||
size: number
|
||||
amountChange: BigNumber
|
||||
denom: string
|
||||
type: 'deposits' | 'borrowing' | 'lending' | 'vault'
|
||||
}
|
||||
|
||||
export const sizeSortingFn = (a: Row<AccountBalanceRow>, b: Row<AccountBalanceRow>): number => {
|
||||
const isVaultA = a.original.type === 'vault'
|
||||
const isVaultB = b.original.type === 'vault'
|
||||
|
||||
const sizeA = isVaultA ? 0 : a.original.size
|
||||
const sizeB = isVaultB ? 0 : b.original.size
|
||||
|
||||
return sizeA - sizeB
|
||||
}
|
||||
|
||||
export default function Size(props: Props) {
|
||||
const { amountChange, type, size } = props
|
||||
|
||||
if (type === 'vault') return <p className='text-xs text-right number'>–</p>
|
||||
|
||||
const color = getAmountChangeColor(type, amountChange)
|
||||
const className = classNames('text-xs text-right', color)
|
||||
|
||||
if (size >= 1)
|
||||
return (
|
||||
<FormattedNumber
|
||||
className={className}
|
||||
amount={size}
|
||||
options={{ abbreviated: true, maxDecimals: MAX_AMOUNT_DECIMALS }}
|
||||
animate
|
||||
/>
|
||||
)
|
||||
|
||||
const formattedAmount = formatAmountToPrecision(size, MAX_AMOUNT_DECIMALS)
|
||||
const lowAmount = formattedAmount === 0 ? 0 : Math.max(formattedAmount, MIN_AMOUNT)
|
||||
return (
|
||||
<FormattedNumber
|
||||
className={className}
|
||||
smallerThanThreshold={formattedAmount !== 0 && formattedAmount < MIN_AMOUNT}
|
||||
amount={lowAmount}
|
||||
options={{
|
||||
maxDecimals: MAX_AMOUNT_DECIMALS,
|
||||
minDecimals: 0,
|
||||
}}
|
||||
animate
|
||||
/>
|
||||
)
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
import { Row } from '@tanstack/react-table'
|
||||
import classNames from 'classnames'
|
||||
|
||||
import { getAmountChangeColor } from 'components/Account/AccountBalancesTable/functions'
|
||||
import DisplayCurrency from 'components/DisplayCurrency'
|
||||
import { ORACLE_DENOM } from 'constants/oracle'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
export const VALUE_META = { accessorKey: 'value', header: 'Value' }
|
||||
|
||||
interface Props {
|
||||
amountChange: BigNumber
|
||||
value: string
|
||||
type: 'deposits' | 'borrowing' | 'lending' | 'vault'
|
||||
}
|
||||
|
||||
export const valueSortingFn = (a: Row<AccountBalanceRow>, b: Row<AccountBalanceRow>): number => {
|
||||
const valueA = BN(a.original.value)
|
||||
const valueB = BN(b.original.value)
|
||||
return valueA.minus(valueB).toNumber()
|
||||
}
|
||||
|
||||
export default function Value(props: Props) {
|
||||
const { amountChange, type, value } = props
|
||||
const color = getAmountChangeColor(type, amountChange)
|
||||
const coin = new BNCoin({
|
||||
denom: ORACLE_DENOM,
|
||||
amount: value,
|
||||
})
|
||||
|
||||
return <DisplayCurrency coin={coin} className={classNames('text-xs text-right', color)} />
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
import { ColumnDef } from '@tanstack/react-table'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import Apy, { APY_META } from 'components/Account/AccountBalancesTable/Columns/Apy'
|
||||
import Asset, { ASSET_META } from 'components/Account/AccountBalancesTable/Columns/Asset'
|
||||
import Size, {
|
||||
SIZE_META,
|
||||
sizeSortingFn,
|
||||
} from 'components/Account/AccountBalancesTable/Columns/Size'
|
||||
import Value, {
|
||||
VALUE_META,
|
||||
valueSortingFn,
|
||||
} from 'components/Account/AccountBalancesTable/Columns/Value'
|
||||
import useMarketAssets from 'hooks/useMarketAssets'
|
||||
|
||||
export default function useAccountBalancesColumns() {
|
||||
const { data: markets } = useMarketAssets()
|
||||
|
||||
return useMemo<ColumnDef<AccountBalanceRow>[]>(() => {
|
||||
return [
|
||||
{
|
||||
...ASSET_META,
|
||||
cell: ({ row }) => <Asset type={row.original.type} symbol={row.original.symbol} />,
|
||||
},
|
||||
{
|
||||
...VALUE_META,
|
||||
cell: ({ row }) => (
|
||||
<Value
|
||||
amountChange={row.original.amountChange}
|
||||
value={row.original.value}
|
||||
type={row.original.type}
|
||||
/>
|
||||
),
|
||||
|
||||
sortingFn: valueSortingFn,
|
||||
},
|
||||
{
|
||||
...SIZE_META,
|
||||
cell: ({ row }) => (
|
||||
<Size
|
||||
size={row.original.size}
|
||||
amountChange={row.original.amountChange}
|
||||
denom={row.original.denom}
|
||||
type={row.original.type}
|
||||
/>
|
||||
),
|
||||
sortingFn: sizeSortingFn,
|
||||
},
|
||||
{
|
||||
...APY_META,
|
||||
cell: ({ row }) => (
|
||||
<Apy
|
||||
apy={row.original.apy}
|
||||
markets={markets}
|
||||
denom={row.original.denom}
|
||||
type={row.original.type}
|
||||
/>
|
||||
),
|
||||
},
|
||||
]
|
||||
}, [markets])
|
||||
}
|
@ -1,51 +1,31 @@
|
||||
import {
|
||||
ColumnDef,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getSortedRowModel,
|
||||
SortingState,
|
||||
useReactTable,
|
||||
} from '@tanstack/react-table'
|
||||
import classNames from 'classnames'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
|
||||
import { getAmountChangeColor } from 'components/Account/AccountBalancesTable/functions'
|
||||
import useAccountBalancesColumns from 'components/Account/AccountBalancesTable/Columns/useAccountBalancesColumns'
|
||||
import useAccountBalanceData from 'components/Account/AccountBalancesTable/useAccountBalanceData'
|
||||
import AccountFundFullPage from 'components/Account/AccountFund/AccountFundFullPage'
|
||||
import AssetRate from 'components/Asset/AssetRate'
|
||||
import ActionButton from 'components/Button/ActionButton'
|
||||
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 { MAX_AMOUNT_DECIMALS, MIN_AMOUNT } from 'constants/math'
|
||||
import { ORACLE_DENOM } from 'constants/oracle'
|
||||
import Card from 'components/Card'
|
||||
import Table from 'components/Table'
|
||||
import ConditionalWrapper from 'hocs/ConditionalWrapper'
|
||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||
import useMarketAssets from 'hooks/useMarketAssets'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { getAssetByDenom } from 'utils/assets'
|
||||
import { demagnify, formatAmountToPrecision } from 'utils/formatters'
|
||||
import { getPage, getRoute } from 'utils/route'
|
||||
|
||||
interface Props {
|
||||
account: Account
|
||||
lendingData: LendingMarketTableData[]
|
||||
borrowingData: BorrowMarketTableData[]
|
||||
hideCard?: boolean
|
||||
tableBodyClassName?: string
|
||||
}
|
||||
|
||||
export default function Index(props: Props) {
|
||||
const { account, lendingData, borrowingData, tableBodyClassName } = props
|
||||
const { data: markets } = useMarketAssets()
|
||||
export default function AccountBalancesTable(props: Props) {
|
||||
const { account, lendingData, borrowingData, tableBodyClassName, hideCard } = props
|
||||
const currentAccount = useCurrentAccount()
|
||||
const navigate = useNavigate()
|
||||
const { pathname } = useLocation()
|
||||
const address = useStore((s) => s.address)
|
||||
const [sorting, setSorting] = useState<SortingState>([])
|
||||
const updatedAccount = useStore((s) => s.updatedAccount)
|
||||
const accountBalanceData = useAccountBalanceData({
|
||||
account,
|
||||
@ -54,206 +34,51 @@ export default function Index(props: Props) {
|
||||
borrowingData,
|
||||
})
|
||||
|
||||
const columns = useMemo<ColumnDef<AccountBalanceRow>[]>(
|
||||
() => [
|
||||
{
|
||||
header: 'Asset',
|
||||
accessorKey: 'symbol',
|
||||
id: 'symbol',
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<Text size='xs'>
|
||||
{row.original.symbol}
|
||||
{row.original.type === 'borrowing' && <span className='ml-1 text-loss'>(debt)</span>}
|
||||
{row.original.type === 'lending' && <span className='ml-1 text-profit'>(lent)</span>}
|
||||
{row.original.type === 'vault' && <span className='ml-1 text-profit'>(farm)</span>}
|
||||
</Text>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
header: 'Value',
|
||||
accessorKey: 'value',
|
||||
id: 'value',
|
||||
cell: ({ row }) => {
|
||||
const color = getAmountChangeColor(row.original.type, row.original.amountChange)
|
||||
const coin = new BNCoin({
|
||||
denom: ORACLE_DENOM,
|
||||
amount: row.original.value.toString(),
|
||||
})
|
||||
return <DisplayCurrency coin={coin} className={classNames('text-xs text-right', color)} />
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'size',
|
||||
accessorKey: 'size',
|
||||
header: 'Size',
|
||||
cell: ({ row }) => {
|
||||
const asset = getAssetByDenom(row.original.denom)
|
||||
|
||||
if (row.original.type === 'vault' || !asset)
|
||||
return <p className='text-xs text-right number'>–</p>
|
||||
|
||||
const color = getAmountChangeColor(row.original.type, row.original.amountChange)
|
||||
const className = classNames('text-xs text-right', color)
|
||||
const amount = demagnify(
|
||||
row.original.amount,
|
||||
getAssetByDenom(row.original.denom) ?? ASSETS[0],
|
||||
)
|
||||
if (amount >= 1)
|
||||
return (
|
||||
<FormattedNumber
|
||||
className={className}
|
||||
amount={amount}
|
||||
options={{ abbreviated: true, maxDecimals: MAX_AMOUNT_DECIMALS }}
|
||||
animate
|
||||
/>
|
||||
)
|
||||
|
||||
const formattedAmount = formatAmountToPrecision(amount, MAX_AMOUNT_DECIMALS)
|
||||
const lowAmount = formattedAmount === 0 ? 0 : Math.max(formattedAmount, MIN_AMOUNT)
|
||||
return (
|
||||
<FormattedNumber
|
||||
className={className}
|
||||
smallerThanThreshold={formattedAmount !== 0 && formattedAmount < MIN_AMOUNT}
|
||||
amount={lowAmount}
|
||||
options={{
|
||||
maxDecimals: MAX_AMOUNT_DECIMALS,
|
||||
minDecimals: 0,
|
||||
}}
|
||||
animate
|
||||
/>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'apy',
|
||||
accessorKey: 'apy',
|
||||
header: 'APY',
|
||||
cell: ({ row }) => {
|
||||
if (row.original.type === 'deposits')
|
||||
return <p className='w-full text-xs text-right number'>–</p>
|
||||
const isEnabled = markets.find(byDenom(row.original.denom))?.borrowEnabled ?? false
|
||||
return (
|
||||
<AssetRate
|
||||
className='justify-end text-xs'
|
||||
rate={row.original.apy}
|
||||
isEnabled={row.original.type !== 'lending' || isEnabled}
|
||||
type='apy'
|
||||
orientation='ltr'
|
||||
/>
|
||||
)
|
||||
},
|
||||
},
|
||||
],
|
||||
[markets],
|
||||
)
|
||||
|
||||
const table = useReactTable({
|
||||
data: accountBalanceData,
|
||||
columns,
|
||||
state: {
|
||||
sorting,
|
||||
},
|
||||
onSortingChange: setSorting,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
})
|
||||
const columns = useAccountBalancesColumns()
|
||||
|
||||
if (accountBalanceData.length === 0)
|
||||
return (
|
||||
<div className='w-full p-4'>
|
||||
<ActionButton
|
||||
className='w-full'
|
||||
text='Fund this Account'
|
||||
color='tertiary'
|
||||
onClick={() => {
|
||||
if (currentAccount?.id !== account.id) {
|
||||
navigate(getRoute(getPage(pathname), address, account.id))
|
||||
}
|
||||
useStore.setState({
|
||||
focusComponent: {
|
||||
component: <AccountFundFullPage />,
|
||||
onClose: () => {
|
||||
useStore.setState({ getStartedModal: true })
|
||||
<ConditionalWrapper
|
||||
condition={!hideCard}
|
||||
wrapper={(children) => (
|
||||
<Card className='w-full' title='Balances'>
|
||||
{children}
|
||||
</Card>
|
||||
)}
|
||||
>
|
||||
<div className='w-full p-4'>
|
||||
<ActionButton
|
||||
className='w-full'
|
||||
text='Fund this Account'
|
||||
color='tertiary'
|
||||
onClick={() => {
|
||||
if (currentAccount?.id !== account.id) {
|
||||
navigate(getRoute(getPage(pathname), address, account.id))
|
||||
}
|
||||
useStore.setState({
|
||||
focusComponent: {
|
||||
component: <AccountFundFullPage />,
|
||||
onClose: () => {
|
||||
useStore.setState({ getStartedModal: true })
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</ConditionalWrapper>
|
||||
)
|
||||
|
||||
return (
|
||||
<table className='w-full'>
|
||||
<thead className='border-b border-white/10'>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<tr key={headerGroup.id}>
|
||||
{headerGroup.headers.map((header) => {
|
||||
return (
|
||||
<th
|
||||
key={header.id}
|
||||
onClick={header.column.getToggleSortingHandler()}
|
||||
className={classNames(
|
||||
'p-2',
|
||||
header.column.getCanSort() && 'hover:cursor-pointer',
|
||||
header.id === 'symbol' ? 'text-left' : 'text-right',
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
'flex',
|
||||
header.id === 'symbol' ? 'justify-start' : 'justify-end',
|
||||
'align-center',
|
||||
)}
|
||||
>
|
||||
<span className='w-6 h-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/70'
|
||||
>
|
||||
{flexRender(header.column.columnDef.header, header.getContext())}
|
||||
</Text>
|
||||
</div>
|
||||
</th>
|
||||
)
|
||||
})}
|
||||
</tr>
|
||||
))}
|
||||
</thead>
|
||||
<tbody className={tableBodyClassName}>
|
||||
{table.getRowModel().rows.map((row) => {
|
||||
return (
|
||||
<tr key={row.id} className=' text-white/60'>
|
||||
{row.getVisibleCells().map((cell) => {
|
||||
const borderClass =
|
||||
cell.row.original.type === 'borrowing' ? 'border-loss' : 'border-profit'
|
||||
return (
|
||||
<td
|
||||
key={cell.id}
|
||||
className={classNames(
|
||||
cell.column.id === 'symbol' ? `border-l ${borderClass}` : 'text-right',
|
||||
'p-2',
|
||||
cell.column.id === 'size' && 'min-w-20 pl-0',
|
||||
)}
|
||||
>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</td>
|
||||
)
|
||||
})}
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
<Table
|
||||
title='Balances'
|
||||
isBalancesTable={true}
|
||||
columns={columns}
|
||||
data={accountBalanceData}
|
||||
tableBodyClassName={classNames(tableBodyClassName, 'text-white/60')}
|
||||
initialSorting={[]}
|
||||
spacingClassName='p-2'
|
||||
hideCard={hideCard}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -180,6 +180,7 @@ function AccountDetails(props: Props) {
|
||||
account={account}
|
||||
borrowingData={borrowAssetsData}
|
||||
lendingData={lendingAssetsData}
|
||||
hideCard
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
|
@ -130,6 +130,7 @@ export default function AccountSummary(props: Props) {
|
||||
account={props.account}
|
||||
borrowingData={borrowAssetsData}
|
||||
lendingData={lendingAssetsData}
|
||||
hideCard
|
||||
/>
|
||||
) : null,
|
||||
isOpen: accountSummaryTabs[1],
|
||||
|
@ -10,8 +10,7 @@ import DepositCap, {
|
||||
import MaxLTV, { LTV_MAX_META } from 'components/Earn/Farm/Table/Columns/MaxLTV'
|
||||
import Name, { NAME_META } from 'components/Earn/Farm/Table/Columns/Name'
|
||||
import TVL, { TVL_META } from 'components/Earn/Farm/Table/Columns/TVL'
|
||||
|
||||
import { DETAILS_META } from './Details'
|
||||
import { DETAILS_META } from 'components/Earn/Farm/Table/Columns/Details'
|
||||
|
||||
interface Props {
|
||||
isLoading: boolean
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Suspense, useMemo } from 'react'
|
||||
|
||||
import { NAME_META } from 'components/Earn/Farm/Table/Columns/Name'
|
||||
import useAvailableColumns from 'components/Earn/Farm/Table/Columns/useAvailableColumns'
|
||||
import Table from 'components/Table'
|
||||
import { ENV } from 'constants/env'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
@ -8,8 +9,6 @@ import { TESTNET_VAULTS_META_DATA, VAULTS_META_DATA } from 'constants/vaults'
|
||||
import useVaults from 'hooks/useVaults'
|
||||
import { NETWORK } from 'types/enums/network'
|
||||
|
||||
import useAvailableColumns from './Table/Columns/useAvailableColumns'
|
||||
|
||||
const title = 'Available HLS Vaults'
|
||||
|
||||
function Content() {
|
||||
|
@ -29,6 +29,7 @@ function Content(props: Props) {
|
||||
account={account}
|
||||
borrowingData={borrowAssets}
|
||||
lendingData={lendingAssets}
|
||||
hideCard
|
||||
/>
|
||||
</Skeleton>
|
||||
)
|
||||
|
@ -7,6 +7,12 @@ interface Props<T> {
|
||||
renderExpanded?: (row: TanstackRow<T>, table: TanstackTable<T>) => JSX.Element
|
||||
rowClassName?: string
|
||||
rowClickHandler?: () => void
|
||||
spacingClassName?: string
|
||||
isBalancesTable?: boolean
|
||||
}
|
||||
|
||||
function getBorderColor(row: AccountBalanceRow) {
|
||||
return row.type === 'borrowing' ? 'border-loss' : 'border-profit'
|
||||
}
|
||||
|
||||
export default function Row<T>(props: Props<T>) {
|
||||
@ -27,8 +33,20 @@ export default function Row<T>(props: Props<T>) {
|
||||
}}
|
||||
>
|
||||
{props.row.getVisibleCells().map((cell) => {
|
||||
const isSymbolOrName = cell.column.id === 'symbol' || cell.column.id === 'name'
|
||||
const borderClasses =
|
||||
props.isBalancesTable && isSymbolOrName
|
||||
? classNames('border-l', getBorderColor(cell.row.original as AccountBalanceRow))
|
||||
: ''
|
||||
return (
|
||||
<td key={cell.id} className={'p-4 text-right'}>
|
||||
<td
|
||||
key={cell.id}
|
||||
className={classNames(
|
||||
isSymbolOrName ? 'text-left' : 'text-right',
|
||||
props.spacingClassName ?? 'p-4',
|
||||
borderClasses,
|
||||
)}
|
||||
>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</td>
|
||||
)
|
||||
|
@ -15,6 +15,7 @@ import Card from 'components/Card'
|
||||
import { SortAsc, SortDesc, SortNone } from 'components/Icons'
|
||||
import Row from 'components/Table/Row'
|
||||
import Text from 'components/Text'
|
||||
import ConditionalWrapper from 'hocs/ConditionalWrapper'
|
||||
|
||||
interface Props<T> {
|
||||
title: string
|
||||
@ -22,6 +23,10 @@ interface Props<T> {
|
||||
data: T[]
|
||||
initialSorting: SortingState
|
||||
renderExpanded?: (row: TanstackRow<T>, table: TanstackTable<T>) => JSX.Element
|
||||
tableBodyClassName?: string
|
||||
spacingClassName?: string
|
||||
isBalancesTable?: boolean
|
||||
hideCard?: boolean
|
||||
}
|
||||
|
||||
export default function Table<T>(props: Props<T>) {
|
||||
@ -39,9 +44,19 @@ export default function Table<T>(props: Props<T>) {
|
||||
})
|
||||
|
||||
return (
|
||||
<Card className='w-full h-fit bg-white/5' title={props.title}>
|
||||
<table className='w-full'>
|
||||
<thead className='bg-black/20'>
|
||||
<ConditionalWrapper
|
||||
condition={!props.hideCard}
|
||||
wrapper={(children) => (
|
||||
<Card
|
||||
className={classNames('w-full', !props.isBalancesTable && 'h-fit bg-white/5')}
|
||||
title={props.title}
|
||||
>
|
||||
{children}
|
||||
</Card>
|
||||
)}
|
||||
>
|
||||
<table className={classNames('w-full', props?.tableBodyClassName)}>
|
||||
<thead className='border-b bg-black/20 border-white/10'>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<tr key={headerGroup.id}>
|
||||
{headerGroup.headers.map((header) => {
|
||||
@ -50,7 +65,7 @@ export default function Table<T>(props: Props<T>) {
|
||||
key={header.id}
|
||||
onClick={header.column.getToggleSortingHandler()}
|
||||
className={classNames(
|
||||
'px-4 py-3',
|
||||
props.spacingClassName ?? 'px-4 py-3',
|
||||
header.column.getCanSort() && 'hover:cursor-pointer',
|
||||
header.id === 'symbol' || header.id === 'name' ? 'text-left' : 'text-right',
|
||||
)}
|
||||
@ -75,8 +90,8 @@ export default function Table<T>(props: Props<T>) {
|
||||
</span>
|
||||
<Text
|
||||
tag='span'
|
||||
size='xs'
|
||||
className='flex items-center font-normal text-white/40'
|
||||
size='sm'
|
||||
className='flex items-center font-normal text-white/70'
|
||||
>
|
||||
{flexRender(header.column.columnDef.header, header.getContext())}
|
||||
</Text>
|
||||
@ -89,10 +104,17 @@ export default function Table<T>(props: Props<T>) {
|
||||
</thead>
|
||||
<tbody>
|
||||
{table.getRowModel().rows.map((row) => (
|
||||
<Row key={row.id} row={row} table={table} renderExpanded={props.renderExpanded} />
|
||||
<Row
|
||||
key={row.id}
|
||||
row={row}
|
||||
table={table}
|
||||
renderExpanded={props.renderExpanded}
|
||||
spacingClassName={props.spacingClassName}
|
||||
isBalancesTable={props.isBalancesTable}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</Card>
|
||||
</ConditionalWrapper>
|
||||
)
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import AccountBalancesTable from 'components/Account/AccountBalancesTable'
|
||||
import Card from 'components/Card'
|
||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||
@ -19,13 +18,11 @@ export default function AccountDetailsCard() {
|
||||
|
||||
if (account)
|
||||
return (
|
||||
<Card className='h-fit' title='Balances'>
|
||||
<AccountBalancesTable
|
||||
account={account}
|
||||
borrowingData={borrowAssetsData}
|
||||
lendingData={lendingAssetsData}
|
||||
tableBodyClassName='gradient-card-content'
|
||||
/>
|
||||
</Card>
|
||||
<AccountBalancesTable
|
||||
account={account}
|
||||
borrowingData={borrowAssetsData}
|
||||
lendingData={lendingAssetsData}
|
||||
tableBodyClassName='gradient-card-content'
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -10,8 +10,7 @@ import {
|
||||
import { byDenom } from 'utils/array'
|
||||
import { getAssetByDenom } from 'utils/assets'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
import { convertApyToApr } from './parsers'
|
||||
import { convertApyToApr } from 'utils/parsers'
|
||||
|
||||
export const calculateAccountBalanceValue = (
|
||||
account: Account | AccountChange,
|
||||
|
Loading…
Reference in New Issue
Block a user