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_RPC=https://rpc.devnet.osmosis.zone/
|
||||||
NEXT_PUBLIC_GQL=https://devnet-osmosis-gql.marsprotocol.io/graphql
|
NEXT_PUBLIC_GQL=https://devnet-osmosis-gql.marsprotocol.io/graphql
|
||||||
NEXT_PUBLIC_REST=https://lcd.devnet.osmosis.zone/
|
NEXT_PUBLIC_REST=https://lcd.devnet.osmosis.zone/
|
||||||
NEXT_PUBLIC_ZAPPER=osmo1yhh8mhthj5jn5c6ty59z3tpsk554qxmlkrkcderw6jls0pcg8zxsdjdj94
|
|
||||||
NEXT_PUBLIC_PARAMS=osmo1aye5qcer5n52crrkaf35jprsad2807q6kg3eeeu7k79h4slxfausfqhc9y
|
|
||||||
|
|
||||||
|
|
||||||
# MAINNET #
|
# 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_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_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_REST=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-lcd-front/
|
||||||
NEXT_PUBLIC_ZAPPER=osmo17qwvc70pzc9mudr8t02t3pl74hhqsgwnskl734p4hug3s8mkerdqzduf7c
|
|
||||||
NEXT_PUBLIC_PARAMS=osmo1nlmdxt9ctql2jr47qd4fpgzg84cjswxyw6q99u4y4u4q6c2f5ksq7ysent
|
|
||||||
|
|
||||||
|
|
||||||
# COMMON #
|
# COMMON #
|
||||||
@ -28,6 +24,8 @@ NEXT_PUBLIC_CREDIT_MANAGER=osmo1f2m24wktq0sw3c0lexlg7fv4kngwyttvzws3a3r3al9ld2s2
|
|||||||
NEXT_PUBLIC_INCENTIVES=osmo1nkahswfr8shg8rlxqwup0vgahp0dk4x8w6tkv3rra8rratnut36sk22vrm
|
NEXT_PUBLIC_INCENTIVES=osmo1nkahswfr8shg8rlxqwup0vgahp0dk4x8w6tkv3rra8rratnut36sk22vrm
|
||||||
NEXT_PUBLIC_SWAPPER=osmo1wee0z8c7tcawyl647eapqs4a88q8jpa7ddy6nn2nrs7t47p2zhxswetwla
|
NEXT_PUBLIC_SWAPPER=osmo1wee0z8c7tcawyl647eapqs4a88q8jpa7ddy6nn2nrs7t47p2zhxswetwla
|
||||||
NEXT_PUBLIC_PYTH=osmo13ge29x4e2s63a8ytz2px8gurtyznmue4a69n5275692v3qn3ks8q7cwck7
|
NEXT_PUBLIC_PYTH=osmo13ge29x4e2s63a8ytz2px8gurtyznmue4a69n5275692v3qn3ks8q7cwck7
|
||||||
|
NEXT_PUBLIC_ZAPPER=osmo17qwvc70pzc9mudr8t02t3pl74hhqsgwnskl734p4hug3s8mkerdqzduf7c
|
||||||
|
NEXT_PUBLIC_PARAMS=osmo1nlmdxt9ctql2jr47qd4fpgzg84cjswxyw6q99u4y4u4q6c2f5ksq7ysent
|
||||||
NEXT_PUBLIC_PYTH_ENDPOINT=https://hermes.pyth.network/api
|
NEXT_PUBLIC_PYTH_ENDPOINT=https://hermes.pyth.network/api
|
||||||
NEXT_PUBLIC_MAINNET_REST=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-rpc-front/
|
NEXT_PUBLIC_MAINNET_REST=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-rpc-front/
|
||||||
NEXT_PUBLIC_CANDLES_ENDPOINT=https://osmosis-candles.marsprotocol.io/
|
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 classNames from 'classnames'
|
||||||
import { useMemo, useState } from 'react'
|
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
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 useAccountBalanceData from 'components/Account/AccountBalancesTable/useAccountBalanceData'
|
||||||
import AccountFundFullPage from 'components/Account/AccountFund/AccountFundFullPage'
|
import AccountFundFullPage from 'components/Account/AccountFund/AccountFundFullPage'
|
||||||
import AssetRate from 'components/Asset/AssetRate'
|
|
||||||
import ActionButton from 'components/Button/ActionButton'
|
import ActionButton from 'components/Button/ActionButton'
|
||||||
import DisplayCurrency from 'components/DisplayCurrency'
|
import Card from 'components/Card'
|
||||||
import { FormattedNumber } from 'components/FormattedNumber'
|
import Table from 'components/Table'
|
||||||
import { SortAsc, SortDesc, SortNone } from 'components/Icons'
|
import ConditionalWrapper from 'hocs/ConditionalWrapper'
|
||||||
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 useCurrentAccount from 'hooks/useCurrentAccount'
|
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||||
import useMarketAssets from 'hooks/useMarketAssets'
|
|
||||||
import useStore from 'store'
|
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'
|
import { getPage, getRoute } from 'utils/route'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
account: Account
|
account: Account
|
||||||
lendingData: LendingMarketTableData[]
|
lendingData: LendingMarketTableData[]
|
||||||
borrowingData: BorrowMarketTableData[]
|
borrowingData: BorrowMarketTableData[]
|
||||||
|
hideCard?: boolean
|
||||||
tableBodyClassName?: string
|
tableBodyClassName?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Index(props: Props) {
|
export default function AccountBalancesTable(props: Props) {
|
||||||
const { account, lendingData, borrowingData, tableBodyClassName } = props
|
const { account, lendingData, borrowingData, tableBodyClassName, hideCard } = props
|
||||||
const { data: markets } = useMarketAssets()
|
|
||||||
const currentAccount = useCurrentAccount()
|
const currentAccount = useCurrentAccount()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { pathname } = useLocation()
|
const { pathname } = useLocation()
|
||||||
const address = useStore((s) => s.address)
|
const address = useStore((s) => s.address)
|
||||||
const [sorting, setSorting] = useState<SortingState>([])
|
|
||||||
const updatedAccount = useStore((s) => s.updatedAccount)
|
const updatedAccount = useStore((s) => s.updatedAccount)
|
||||||
const accountBalanceData = useAccountBalanceData({
|
const accountBalanceData = useAccountBalanceData({
|
||||||
account,
|
account,
|
||||||
@ -54,206 +34,51 @@ export default function Index(props: Props) {
|
|||||||
borrowingData,
|
borrowingData,
|
||||||
})
|
})
|
||||||
|
|
||||||
const columns = useMemo<ColumnDef<AccountBalanceRow>[]>(
|
const columns = useAccountBalancesColumns()
|
||||||
() => [
|
|
||||||
{
|
|
||||||
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(),
|
|
||||||
})
|
|
||||||
|
|
||||||
if (accountBalanceData.length === 0)
|
if (accountBalanceData.length === 0)
|
||||||
return (
|
return (
|
||||||
<div className='w-full p-4'>
|
<ConditionalWrapper
|
||||||
<ActionButton
|
condition={!hideCard}
|
||||||
className='w-full'
|
wrapper={(children) => (
|
||||||
text='Fund this Account'
|
<Card className='w-full' title='Balances'>
|
||||||
color='tertiary'
|
{children}
|
||||||
onClick={() => {
|
</Card>
|
||||||
if (currentAccount?.id !== account.id) {
|
)}
|
||||||
navigate(getRoute(getPage(pathname), address, account.id))
|
>
|
||||||
}
|
<div className='w-full p-4'>
|
||||||
useStore.setState({
|
<ActionButton
|
||||||
focusComponent: {
|
className='w-full'
|
||||||
component: <AccountFundFullPage />,
|
text='Fund this Account'
|
||||||
onClose: () => {
|
color='tertiary'
|
||||||
useStore.setState({ getStartedModal: true })
|
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 (
|
return (
|
||||||
<table className='w-full'>
|
<Table
|
||||||
<thead className='border-b border-white/10'>
|
title='Balances'
|
||||||
{table.getHeaderGroups().map((headerGroup) => (
|
isBalancesTable={true}
|
||||||
<tr key={headerGroup.id}>
|
columns={columns}
|
||||||
{headerGroup.headers.map((header) => {
|
data={accountBalanceData}
|
||||||
return (
|
tableBodyClassName={classNames(tableBodyClassName, 'text-white/60')}
|
||||||
<th
|
initialSorting={[]}
|
||||||
key={header.id}
|
spacingClassName='p-2'
|
||||||
onClick={header.column.getToggleSortingHandler()}
|
hideCard={hideCard}
|
||||||
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>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -180,6 +180,7 @@ function AccountDetails(props: Props) {
|
|||||||
account={account}
|
account={account}
|
||||||
borrowingData={borrowAssetsData}
|
borrowingData={borrowAssetsData}
|
||||||
lendingData={lendingAssetsData}
|
lendingData={lendingAssetsData}
|
||||||
|
hideCard
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
@ -130,6 +130,7 @@ export default function AccountSummary(props: Props) {
|
|||||||
account={props.account}
|
account={props.account}
|
||||||
borrowingData={borrowAssetsData}
|
borrowingData={borrowAssetsData}
|
||||||
lendingData={lendingAssetsData}
|
lendingData={lendingAssetsData}
|
||||||
|
hideCard
|
||||||
/>
|
/>
|
||||||
) : null,
|
) : null,
|
||||||
isOpen: accountSummaryTabs[1],
|
isOpen: accountSummaryTabs[1],
|
||||||
|
@ -10,8 +10,7 @@ import DepositCap, {
|
|||||||
import MaxLTV, { LTV_MAX_META } from 'components/Earn/Farm/Table/Columns/MaxLTV'
|
import MaxLTV, { LTV_MAX_META } from 'components/Earn/Farm/Table/Columns/MaxLTV'
|
||||||
import Name, { NAME_META } from 'components/Earn/Farm/Table/Columns/Name'
|
import Name, { NAME_META } from 'components/Earn/Farm/Table/Columns/Name'
|
||||||
import TVL, { TVL_META } from 'components/Earn/Farm/Table/Columns/TVL'
|
import TVL, { TVL_META } from 'components/Earn/Farm/Table/Columns/TVL'
|
||||||
|
import { DETAILS_META } from 'components/Earn/Farm/Table/Columns/Details'
|
||||||
import { DETAILS_META } from './Details'
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isLoading: boolean
|
isLoading: boolean
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Suspense, useMemo } from 'react'
|
import { Suspense, useMemo } from 'react'
|
||||||
|
|
||||||
import { NAME_META } from 'components/Earn/Farm/Table/Columns/Name'
|
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 Table from 'components/Table'
|
||||||
import { ENV } from 'constants/env'
|
import { ENV } from 'constants/env'
|
||||||
import { BN_ZERO } from 'constants/math'
|
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 useVaults from 'hooks/useVaults'
|
||||||
import { NETWORK } from 'types/enums/network'
|
import { NETWORK } from 'types/enums/network'
|
||||||
|
|
||||||
import useAvailableColumns from './Table/Columns/useAvailableColumns'
|
|
||||||
|
|
||||||
const title = 'Available HLS Vaults'
|
const title = 'Available HLS Vaults'
|
||||||
|
|
||||||
function Content() {
|
function Content() {
|
||||||
|
@ -29,6 +29,7 @@ function Content(props: Props) {
|
|||||||
account={account}
|
account={account}
|
||||||
borrowingData={borrowAssets}
|
borrowingData={borrowAssets}
|
||||||
lendingData={lendingAssets}
|
lendingData={lendingAssets}
|
||||||
|
hideCard
|
||||||
/>
|
/>
|
||||||
</Skeleton>
|
</Skeleton>
|
||||||
)
|
)
|
||||||
|
@ -7,6 +7,12 @@ interface Props<T> {
|
|||||||
renderExpanded?: (row: TanstackRow<T>, table: TanstackTable<T>) => JSX.Element
|
renderExpanded?: (row: TanstackRow<T>, table: TanstackTable<T>) => JSX.Element
|
||||||
rowClassName?: string
|
rowClassName?: string
|
||||||
rowClickHandler?: () => void
|
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>) {
|
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) => {
|
{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 (
|
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())}
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||||
</td>
|
</td>
|
||||||
)
|
)
|
||||||
|
@ -15,6 +15,7 @@ import Card from 'components/Card'
|
|||||||
import { SortAsc, SortDesc, SortNone } from 'components/Icons'
|
import { SortAsc, SortDesc, SortNone } from 'components/Icons'
|
||||||
import Row from 'components/Table/Row'
|
import Row from 'components/Table/Row'
|
||||||
import Text from 'components/Text'
|
import Text from 'components/Text'
|
||||||
|
import ConditionalWrapper from 'hocs/ConditionalWrapper'
|
||||||
|
|
||||||
interface Props<T> {
|
interface Props<T> {
|
||||||
title: string
|
title: string
|
||||||
@ -22,6 +23,10 @@ interface Props<T> {
|
|||||||
data: T[]
|
data: T[]
|
||||||
initialSorting: SortingState
|
initialSorting: SortingState
|
||||||
renderExpanded?: (row: TanstackRow<T>, table: TanstackTable<T>) => JSX.Element
|
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>) {
|
export default function Table<T>(props: Props<T>) {
|
||||||
@ -39,9 +44,19 @@ export default function Table<T>(props: Props<T>) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className='w-full h-fit bg-white/5' title={props.title}>
|
<ConditionalWrapper
|
||||||
<table className='w-full'>
|
condition={!props.hideCard}
|
||||||
<thead className='bg-black/20'>
|
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) => (
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
<tr key={headerGroup.id}>
|
<tr key={headerGroup.id}>
|
||||||
{headerGroup.headers.map((header) => {
|
{headerGroup.headers.map((header) => {
|
||||||
@ -50,7 +65,7 @@ export default function Table<T>(props: Props<T>) {
|
|||||||
key={header.id}
|
key={header.id}
|
||||||
onClick={header.column.getToggleSortingHandler()}
|
onClick={header.column.getToggleSortingHandler()}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'px-4 py-3',
|
props.spacingClassName ?? 'px-4 py-3',
|
||||||
header.column.getCanSort() && 'hover:cursor-pointer',
|
header.column.getCanSort() && 'hover:cursor-pointer',
|
||||||
header.id === 'symbol' || header.id === 'name' ? 'text-left' : 'text-right',
|
header.id === 'symbol' || header.id === 'name' ? 'text-left' : 'text-right',
|
||||||
)}
|
)}
|
||||||
@ -75,8 +90,8 @@ export default function Table<T>(props: Props<T>) {
|
|||||||
</span>
|
</span>
|
||||||
<Text
|
<Text
|
||||||
tag='span'
|
tag='span'
|
||||||
size='xs'
|
size='sm'
|
||||||
className='flex items-center font-normal text-white/40'
|
className='flex items-center font-normal text-white/70'
|
||||||
>
|
>
|
||||||
{flexRender(header.column.columnDef.header, header.getContext())}
|
{flexRender(header.column.columnDef.header, header.getContext())}
|
||||||
</Text>
|
</Text>
|
||||||
@ -89,10 +104,17 @@ export default function Table<T>(props: Props<T>) {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{table.getRowModel().rows.map((row) => (
|
{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>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</Card>
|
</ConditionalWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
|
|
||||||
import AccountBalancesTable from 'components/Account/AccountBalancesTable'
|
import AccountBalancesTable from 'components/Account/AccountBalancesTable'
|
||||||
import Card from 'components/Card'
|
|
||||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||||
@ -19,13 +18,11 @@ export default function AccountDetailsCard() {
|
|||||||
|
|
||||||
if (account)
|
if (account)
|
||||||
return (
|
return (
|
||||||
<Card className='h-fit' title='Balances'>
|
<AccountBalancesTable
|
||||||
<AccountBalancesTable
|
account={account}
|
||||||
account={account}
|
borrowingData={borrowAssetsData}
|
||||||
borrowingData={borrowAssetsData}
|
lendingData={lendingAssetsData}
|
||||||
lendingData={lendingAssetsData}
|
tableBodyClassName='gradient-card-content'
|
||||||
tableBodyClassName='gradient-card-content'
|
/>
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,7 @@ import {
|
|||||||
import { byDenom } from 'utils/array'
|
import { byDenom } from 'utils/array'
|
||||||
import { getAssetByDenom } from 'utils/assets'
|
import { getAssetByDenom } from 'utils/assets'
|
||||||
import { BN } from 'utils/helpers'
|
import { BN } from 'utils/helpers'
|
||||||
|
import { convertApyToApr } from 'utils/parsers'
|
||||||
import { convertApyToApr } from './parsers'
|
|
||||||
|
|
||||||
export const calculateAccountBalanceValue = (
|
export const calculateAccountBalanceValue = (
|
||||||
account: Account | AccountChange,
|
account: Account | AccountChange,
|
||||||
|
Loading…
Reference in New Issue
Block a user