feat: added v1 based buttons and a portfolio summary

This commit is contained in:
Linkie Link 2024-02-15 16:08:04 +01:00
parent 40593ae987
commit 106de661a8
No known key found for this signature in database
GPG Key ID: 5318B0F2564D38EA
21 changed files with 184 additions and 48 deletions

View File

@ -1,5 +1,5 @@
import ActiveBorrowingsTable from 'components/borrow/Table/ActiveBorrowingsTable'
import AvailableBorrowingsTable from 'components/borrow/Table/AvailableBorrowingsTable'
import DepositedBorrowingsTable from 'components/borrow/Table/DepositedBorrowingsTable'
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
import { BN_ZERO } from 'constants/math'
import useBorrowEnabledAssets from 'hooks/assets/useBorrowEnabledAssets'
@ -12,7 +12,7 @@ export default function Borrowings() {
}
return (
<>
<DepositedBorrowingsTable data={accountBorrowedAssets} isLoading={false} />
<ActiveBorrowingsTable data={accountBorrowedAssets} isLoading={false} />
<AvailableBorrowingsTable data={availableAssets} isLoading={false} />
</>
)

View File

@ -3,7 +3,7 @@ import { useCallback } from 'react'
import { DEBT_VALUE_META } from 'components/borrow/Table/Columns/DebtValue'
import { NAME_META } from 'components/borrow/Table/Columns/Name'
import useDepositedColumns from 'components/borrow/Table/Columns/useDepositedColumns'
import useBorrowingsColumns from 'components/borrow/Table/Columns/useActiveColumns'
import MarketDetails from 'components/common/MarketDetails'
import Table from 'components/common/Table'
@ -13,8 +13,8 @@ type Props = {
v1?: boolean
}
export default function DepositedBorrowingsTable(props: Props) {
const columns = useDepositedColumns()
export default function ActiveBorrowingsTable(props: Props) {
const columns = useBorrowingsColumns({ v1: props.v1 })
const renderExpanded = useCallback((row: Row<BorrowMarketTableData>) => {
return <MarketDetails row={row} type='borrow' />

View File

@ -16,6 +16,7 @@ export const BORROW_BUTTON_META = {
interface Props {
data: LendingMarketTableData
v1?: boolean
}
export default function BorrowButton(props: Props) {
const account = useCurrentAccount()

View File

@ -12,6 +12,7 @@ export const MANAGE_META = {
interface Props {
data: BorrowMarketTableData
v1?: boolean
}
export default function Manage(props: Props) {
@ -48,7 +49,7 @@ export default function Manage(props: Props) {
if (!address) return null
return (
<div className='flex justify-end z-10'>
<div className='z-10 flex justify-end'>
<DropDownButton items={ITEMS} text='Manage' color='tertiary' />
</div>
)

View File

@ -13,8 +13,13 @@ import Liquidity, {
} from 'components/borrow/Table/Columns/Liquidity'
import Manage, { MANAGE_META } from 'components/borrow/Table/Columns/Manage'
import Name, { NAME_META } from 'components/borrow/Table/Columns/Name'
import Action from 'components/v1/Table/borrowings/Columns/Action'
export default function useDepositedColumns() {
interface Props {
v1?: boolean
}
export default function useActiveColumns(props: Props) {
return useMemo<ColumnDef<BorrowMarketTableData>[]>(() => {
return [
{
@ -39,12 +44,13 @@ export default function useDepositedColumns() {
},
{
...MANAGE_META,
cell: ({ row }) => <Manage data={row.original} />,
cell: ({ row }) =>
props.v1 ? <Action data={row.original} /> : <Manage data={row.original} />,
},
{
...CHEVRON_META,
cell: ({ row }) => <Chevron isExpanded={row.getIsExpanded()} />,
},
]
}, [])
}, [props.v1])
}

View File

@ -23,7 +23,7 @@ export default function MarketDetails({ row, type }: Props) {
symbol: displayCurrencySymbol,
} = useDisplayCurrencyPrice()
const { asset, ltv, cap, liquidity, deposits, debt } = row.original
const { asset, ltv, deposits, debt } = row.original
const details: Detail[] = useMemo(() => {
const isDollar = displayCurrencySymbol === '$'

View File

@ -2,6 +2,7 @@ import { ColumnDef } from '@tanstack/react-table'
import { useMemo } from 'react'
import Apy, { APY_META } from 'components/earn/farm/Table/Columns/Apy'
import { Deposit, DEPOSIT_META } from 'components/earn/farm/Table/Columns/Deposit'
import DepositCap, {
DEPOSIT_CAP_META,
depositCapSortingFn,
@ -10,8 +11,6 @@ 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 { Deposit, DEPOSIT_META } from './Deposit'
interface Props {
isLoading: boolean
}

View File

@ -13,9 +13,11 @@ import DepositValue, {
} from 'components/earn/lend/Table/Columns/DepositValue'
import Manage, { MANAGE_META } from 'components/earn/lend/Table/Columns/Manage'
import Name, { NAME_META } from 'components/earn/lend/Table/Columns/Name'
import Action from 'components/v1/Table/deposits/Columns/Action'
interface Props {
isLoading: boolean
v1?: boolean
}
export default function useDepositedColumns(props: Props) {
@ -49,12 +51,13 @@ export default function useDepositedColumns(props: Props) {
},
{
...MANAGE_META,
cell: ({ row }) => <Manage data={row.original} />,
cell: ({ row }) =>
props.v1 ? <Action data={row.original} /> : <Manage data={row.original} />,
},
{
...CHEVRON_META,
cell: ({ row }) => <Chevron isExpanded={row.getIsExpanded()} />,
},
]
}, [props.isLoading])
}, [props.isLoading, props.v1])
}

View File

@ -14,7 +14,7 @@ type Props = {
}
export default function DepositedLendsTable(props: Props) {
const columns = useDepositedColumns({ isLoading: props.isLoading })
const columns = useDepositedColumns({ isLoading: props.isLoading, v1: props.v1 })
const renderExpanded = useCallback(
(row: Row<LendingMarketTableData>) => <MarketDetails row={row} type='lend' />,

View File

@ -17,6 +17,7 @@ import { DEFAULT_PORTFOLIO_STATS } from 'utils/constants'
interface Props {
accountId: string
v1?: boolean
}
function Content(props: Props) {
@ -78,17 +79,17 @@ function Content(props: Props) {
options={{ suffix: 'x' }}
/>
),
sub: DEFAULT_PORTFOLIO_STATS[4].sub,
sub: props.v1 ? 'Total Leverage' : DEFAULT_PORTFOLIO_STATS[4].sub,
},
]
}, [account, assets, borrowAssets, hlsStrategies, lendingAssets, prices, vaultAprs])
}, [account, assets, borrowAssets, hlsStrategies, lendingAssets, prices, vaultAprs, props.v1])
return (
<Skeleton
stats={stats}
health={health}
healthFactor={healthFactor}
title={`Credit Account ${props.accountId}`}
title={props.v1 ? 'V1 Portfolio' : `Credit Account ${props.accountId}`}
accountId={props.accountId}
/>
)

View File

@ -1,4 +1,4 @@
import BorrowingsTable from 'components/borrow/Table/DepositedBorrowingsTable'
import BorrowingsTable from 'components/borrow/Table/ActiveBorrowingsTable'
import useV1BorrowingsTableData from 'components/v1/Table/useV1BorrowingsTableData'
import { BN_ZERO } from 'constants/math'
import useBorrowEnabledAssets from 'hooks/assets/useBorrowEnabledAssets'

View File

@ -0,0 +1,20 @@
import BorrowButton from 'components/borrow/Table/Columns/BorrowButton'
import Manage from 'components/borrow/Table/Columns/Manage'
export const MANAGE_META = {
accessorKey: 'manage',
enableSorting: false,
header: '',
}
interface Props {
data: BorrowMarketTableData
}
export default function Action(props: Props) {
const hasDebt = !props.data.accountDebtAmount?.isZero() ?? false
if (hasDebt) return <Manage data={props.data} v1 />
return <BorrowButton data={props.data} v1 />
}

View File

@ -0,0 +1,19 @@
import DepositButton from 'components/v1/Table/deposits/Columns/DepositButton'
import Manage from 'components/v1/Table/deposits/Columns/Manage'
export const MANAGE_META = {
accessorKey: 'manage',
enableSorting: false,
header: '',
}
interface Props {
data: LendingMarketTableData
}
export default function Action(props: Props) {
const hasDeposits = !props.data.accountLentAmount?.isZero() ?? false
if (hasDeposits) return <Manage data={props.data} />
return <DepositButton data={props.data} />
}

View File

@ -0,0 +1,48 @@
import ActionButton from 'components/common/Button/ActionButton'
import { ArrowUpLine } from 'components/common/Icons'
import Text from 'components/common/Text'
import { Tooltip } from 'components/common/Tooltip'
import ConditionalWrapper from 'hocs/ConditionalWrapper'
import useWalletBalances from 'hooks/useWalletBalances'
import useStore from 'store'
import { byDenom } from 'utils/array'
interface Props {
data: LendingMarketTableData
}
export default function DepositButton(props: Props) {
const address = useStore((s) => s.address)
const { data: balances } = useWalletBalances(address)
const hasBalance = !!balances.find(byDenom(props.data.asset.denom))
return (
<div className='flex justify-end'>
<ConditionalWrapper
condition={!hasBalance}
wrapper={(children) => (
<Tooltip
type='warning'
content={
<Text size='sm'>{`You dont have any ${props.data.asset.symbol} in your Wallet.`}</Text>
}
contentClassName='max-w-[200px]'
className='ml-auto'
>
{children}
</Tooltip>
)}
>
<ActionButton
leftIcon={<ArrowUpLine />}
disabled={!hasBalance}
color='tertiary'
onClick={(e) => {
useStore.setState({ fundAndWithdrawModal: 'fund' })
e.stopPropagation()
}}
text='Deposit'
/>
</ConditionalWrapper>
</div>
)
}

View File

@ -0,0 +1,45 @@
import { useMemo } from 'react'
import DropDownButton from 'components/common/Button/DropDownButton'
import { ArrowDownLine, ArrowUpLine } from 'components/common/Icons'
import useLendAndReclaimModal from 'hooks/useLendAndReclaimModal'
import useWalletBalances from 'hooks/useWalletBalances'
import useStore from 'store'
import { byDenom } from 'utils/array'
interface Props {
data: LendingMarketTableData
}
export default function Manage(props: Props) {
const { openLend, openReclaim } = useLendAndReclaimModal()
const address = useStore((s) => s.address)
const { data: balances } = useWalletBalances(address)
const hasBalance = !!balances.find(byDenom(props.data.asset.denom))
console.log(balances)
const ITEMS: DropDownItem[] = useMemo(
() => [
{
icon: <ArrowUpLine />,
text: 'Deposit more',
onClick: () => openLend(props.data),
disabled: !hasBalance,
disabledTooltip: `You dont have any ${props.data.asset.symbol} in your Wallet.`,
},
{
icon: <ArrowDownLine />,
text: 'Withdraw',
onClick: () => openReclaim(props.data),
},
],
[hasBalance, openLend, openReclaim, props.data],
)
return (
<div className='z-10 flex justify-end'>
<DropDownButton items={ITEMS} text='Manage' color='tertiary' />
</div>
)
}

View File

@ -1,21 +1,21 @@
import { useMemo } from 'react'
import { BN_ZERO } from 'constants/math'
import useAccount from 'hooks/accounts/useAccount'
import useMarkets from 'hooks/markets/useMarkets'
import useDisplayCurrencyPrice from 'hooks/useDisplayCurrencyPrice'
import useV1Positions from 'hooks/v1/useV1Positions'
import useStore from 'store'
export default function useV1BorrowingsTableData() {
const address = useStore((s) => s.address)
const markets = useMarkets()
const { data: v1Positions } = useV1Positions(address)
const userDebts = v1Positions?.debts ?? []
const { data: v1Positions } = useAccount(address)
const { convertAmount } = useDisplayCurrencyPrice()
return useMemo((): {
debtAssets: BorrowMarketTableData[]
} => {
const userDebts = v1Positions?.debts ?? []
const debtAssets: BorrowMarketTableData[] = []
markets
@ -34,5 +34,5 @@ export default function useV1BorrowingsTableData() {
})
return { debtAssets }
}, [userDebts, markets, convertAmount])
}, [v1Positions, markets, convertAmount])
}

View File

@ -1,9 +1,9 @@
import { useMemo } from 'react'
import { BN_ZERO } from 'constants/math'
import useAccount from 'hooks/accounts/useAccount'
import useMarkets from 'hooks/markets/useMarkets'
import useDisplayCurrencyPrice from 'hooks/useDisplayCurrencyPrice'
import useV1Positions from 'hooks/v1/useV1Positions'
import useStore from 'store'
import { byDenom } from 'utils/array'
@ -12,12 +12,12 @@ export default function useV1DepositsTableData(): {
} {
const address = useStore((s) => s.address)
const markets = useMarkets()
const { data: v1Positions } = useV1Positions(address)
const userCollateral = v1Positions?.lends ?? []
const { data: v1Positions } = useAccount(address)
const { convertAmount } = useDisplayCurrencyPrice()
return useMemo(() => {
const depositAssets: LendingMarketTableData[] = []
const userCollateral = v1Positions?.lends ?? []
markets.forEach((market) => {
const amount = userCollateral.find(byDenom(market.asset.denom))?.amount ?? BN_ZERO
@ -35,5 +35,5 @@ export default function useV1DepositsTableData(): {
return {
depositAssets,
}
}, [markets, userCollateral, convertAmount])
}, [markets, v1Positions, convertAmount])
}

View File

@ -12,8 +12,8 @@ export default function V1Intro() {
<br />
This is the first version (v1) of the Red Bank. It provides simple lending and borrowing,
without the use of Credit Accounts. Funds are{' '}
<span className='text-white'>not cross-collateralized</span> and can't be used on v2 as
collateral.
<span className='text-white'>not cross-collateralized</span> and can&lsquo;t be used on v2
as collateral.
</>
}
bg='v1'

View File

@ -1,14 +1,20 @@
import useSWR from 'swr'
import getAccount from 'api/accounts/getAccount'
import getV1Positions from 'api/v1/getV1Positions'
import useChainConfig from 'hooks/useChainConfig'
export default function useAccount(accountId?: string, suspense?: boolean) {
const chainConfig = useChainConfig()
const isV1 = isNaN(parseInt(accountId || ''))
const cacheKey = isV1
? `chains/${chainConfig.id}/v1/user/${accountId}`
: `chains/${chainConfig.id}/accounts/${accountId}`
return useSWR(
accountId && `chains/${chainConfig.id}/accounts/${accountId}`,
() => getAccount(chainConfig, accountId),
accountId && cacheKey,
() => (isV1 ? getV1Positions(chainConfig, accountId) : getAccount(chainConfig, accountId)),
{
suspense: suspense,
revalidateOnFocus: false,

View File

@ -1,17 +0,0 @@
import useSWR from 'swr'
import getV1Positions from 'api/v1/getV1Positions'
import useChainConfig from 'hooks/useChainConfig'
export default function useV1Positions(user?: string, suspense?: boolean) {
const chainConfig = useChainConfig()
return useSWR(
user && `chains/${chainConfig.id}/v1/${user}`,
() => getV1Positions(chainConfig, user),
{
suspense: suspense,
revalidateOnFocus: false,
},
)
}

View File

@ -1,13 +1,17 @@
import MigrationBanner from 'components/common/MigrationBanner'
import Summary from 'components/portfolio/Account/Summary'
import Borrowings from 'components/v1/Borrowings'
import Deposits from 'components/v1/Deposits'
import V1Intro from 'components/v1/V1Intro'
import useStore from 'store'
export default function V1Page() {
const address = useStore((s) => s.address)
return (
<div className='flex flex-wrap w-full gap-6'>
<MigrationBanner />
<V1Intro />
{address && <Summary accountId={address} v1 />}
<Deposits />
<Borrowings />
</div>