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 AvailableBorrowingsTable from 'components/borrow/Table/AvailableBorrowingsTable'
import DepositedBorrowingsTable from 'components/borrow/Table/DepositedBorrowingsTable'
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData' import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
import { BN_ZERO } from 'constants/math' import { BN_ZERO } from 'constants/math'
import useBorrowEnabledAssets from 'hooks/assets/useBorrowEnabledAssets' import useBorrowEnabledAssets from 'hooks/assets/useBorrowEnabledAssets'
@ -12,7 +12,7 @@ export default function Borrowings() {
} }
return ( return (
<> <>
<DepositedBorrowingsTable data={accountBorrowedAssets} isLoading={false} /> <ActiveBorrowingsTable data={accountBorrowedAssets} isLoading={false} />
<AvailableBorrowingsTable data={availableAssets} 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 { DEBT_VALUE_META } from 'components/borrow/Table/Columns/DebtValue'
import { NAME_META } from 'components/borrow/Table/Columns/Name' 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 MarketDetails from 'components/common/MarketDetails'
import Table from 'components/common/Table' import Table from 'components/common/Table'
@ -13,8 +13,8 @@ type Props = {
v1?: boolean v1?: boolean
} }
export default function DepositedBorrowingsTable(props: Props) { export default function ActiveBorrowingsTable(props: Props) {
const columns = useDepositedColumns() const columns = useBorrowingsColumns({ v1: props.v1 })
const renderExpanded = useCallback((row: Row<BorrowMarketTableData>) => { const renderExpanded = useCallback((row: Row<BorrowMarketTableData>) => {
return <MarketDetails row={row} type='borrow' /> return <MarketDetails row={row} type='borrow' />

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -13,9 +13,11 @@ import DepositValue, {
} from 'components/earn/lend/Table/Columns/DepositValue' } from 'components/earn/lend/Table/Columns/DepositValue'
import Manage, { MANAGE_META } from 'components/earn/lend/Table/Columns/Manage' import Manage, { MANAGE_META } from 'components/earn/lend/Table/Columns/Manage'
import Name, { NAME_META } from 'components/earn/lend/Table/Columns/Name' import Name, { NAME_META } from 'components/earn/lend/Table/Columns/Name'
import Action from 'components/v1/Table/deposits/Columns/Action'
interface Props { interface Props {
isLoading: boolean isLoading: boolean
v1?: boolean
} }
export default function useDepositedColumns(props: Props) { export default function useDepositedColumns(props: Props) {
@ -49,12 +51,13 @@ export default function useDepositedColumns(props: Props) {
}, },
{ {
...MANAGE_META, ...MANAGE_META,
cell: ({ row }) => <Manage data={row.original} />, cell: ({ row }) =>
props.v1 ? <Action data={row.original} /> : <Manage data={row.original} />,
}, },
{ {
...CHEVRON_META, ...CHEVRON_META,
cell: ({ row }) => <Chevron isExpanded={row.getIsExpanded()} />, 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) { export default function DepositedLendsTable(props: Props) {
const columns = useDepositedColumns({ isLoading: props.isLoading }) const columns = useDepositedColumns({ isLoading: props.isLoading, v1: props.v1 })
const renderExpanded = useCallback( const renderExpanded = useCallback(
(row: Row<LendingMarketTableData>) => <MarketDetails row={row} type='lend' />, (row: Row<LendingMarketTableData>) => <MarketDetails row={row} type='lend' />,

View File

@ -17,6 +17,7 @@ import { DEFAULT_PORTFOLIO_STATS } from 'utils/constants'
interface Props { interface Props {
accountId: string accountId: string
v1?: boolean
} }
function Content(props: Props) { function Content(props: Props) {
@ -78,17 +79,17 @@ function Content(props: Props) {
options={{ suffix: 'x' }} 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 ( return (
<Skeleton <Skeleton
stats={stats} stats={stats}
health={health} health={health}
healthFactor={healthFactor} healthFactor={healthFactor}
title={`Credit Account ${props.accountId}`} title={props.v1 ? 'V1 Portfolio' : `Credit Account ${props.accountId}`}
accountId={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 useV1BorrowingsTableData from 'components/v1/Table/useV1BorrowingsTableData'
import { BN_ZERO } from 'constants/math' import { BN_ZERO } from 'constants/math'
import useBorrowEnabledAssets from 'hooks/assets/useBorrowEnabledAssets' 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 { useMemo } from 'react'
import { BN_ZERO } from 'constants/math' import { BN_ZERO } from 'constants/math'
import useAccount from 'hooks/accounts/useAccount'
import useMarkets from 'hooks/markets/useMarkets' import useMarkets from 'hooks/markets/useMarkets'
import useDisplayCurrencyPrice from 'hooks/useDisplayCurrencyPrice' import useDisplayCurrencyPrice from 'hooks/useDisplayCurrencyPrice'
import useV1Positions from 'hooks/v1/useV1Positions'
import useStore from 'store' import useStore from 'store'
export default function useV1BorrowingsTableData() { export default function useV1BorrowingsTableData() {
const address = useStore((s) => s.address) const address = useStore((s) => s.address)
const markets = useMarkets() const markets = useMarkets()
const { data: v1Positions } = useV1Positions(address) const { data: v1Positions } = useAccount(address)
const userDebts = v1Positions?.debts ?? []
const { convertAmount } = useDisplayCurrencyPrice() const { convertAmount } = useDisplayCurrencyPrice()
return useMemo((): { return useMemo((): {
debtAssets: BorrowMarketTableData[] debtAssets: BorrowMarketTableData[]
} => { } => {
const userDebts = v1Positions?.debts ?? []
const debtAssets: BorrowMarketTableData[] = [] const debtAssets: BorrowMarketTableData[] = []
markets markets
@ -34,5 +34,5 @@ export default function useV1BorrowingsTableData() {
}) })
return { debtAssets } return { debtAssets }
}, [userDebts, markets, convertAmount]) }, [v1Positions, markets, convertAmount])
} }

View File

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

View File

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

View File

@ -1,14 +1,20 @@
import useSWR from 'swr' import useSWR from 'swr'
import getAccount from 'api/accounts/getAccount' import getAccount from 'api/accounts/getAccount'
import getV1Positions from 'api/v1/getV1Positions'
import useChainConfig from 'hooks/useChainConfig' import useChainConfig from 'hooks/useChainConfig'
export default function useAccount(accountId?: string, suspense?: boolean) { export default function useAccount(accountId?: string, suspense?: boolean) {
const chainConfig = useChainConfig() const chainConfig = useChainConfig()
const isV1 = isNaN(parseInt(accountId || ''))
const cacheKey = isV1
? `chains/${chainConfig.id}/v1/user/${accountId}`
: `chains/${chainConfig.id}/accounts/${accountId}`
return useSWR( return useSWR(
accountId && `chains/${chainConfig.id}/accounts/${accountId}`, accountId && cacheKey,
() => getAccount(chainConfig, accountId), () => (isV1 ? getV1Positions(chainConfig, accountId) : getAccount(chainConfig, accountId)),
{ {
suspense: suspense, suspense: suspense,
revalidateOnFocus: false, 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 MigrationBanner from 'components/common/MigrationBanner'
import Summary from 'components/portfolio/Account/Summary'
import Borrowings from 'components/v1/Borrowings' import Borrowings from 'components/v1/Borrowings'
import Deposits from 'components/v1/Deposits' import Deposits from 'components/v1/Deposits'
import V1Intro from 'components/v1/V1Intro' import V1Intro from 'components/v1/V1Intro'
import useStore from 'store'
export default function V1Page() { export default function V1Page() {
const address = useStore((s) => s.address)
return ( return (
<div className='flex flex-wrap w-full gap-6'> <div className='flex flex-wrap w-full gap-6'>
<MigrationBanner /> <MigrationBanner />
<V1Intro /> <V1Intro />
{address && <Summary accountId={address} v1 />}
<Deposits /> <Deposits />
<Borrowings /> <Borrowings />
</div> </div>