useStore.setState({ accountDetailsExpanded: !accountDetailsExpanded })}
+ onClick={() => {
+ if (accountDetailsExpanded) return
+ useStore.setState({ accountDetailsExpanded: true })
+ }}
>
-
-
-
- Health
-
+
+
+
+
+ Health
+
+
+
+
+ Net worth
+
+
+
+
+
+
+ APR
+
+
+
-
-
- Net worth
-
-
-
-
-
-
- APR
-
-
+
-
-
}>
-
-
Balances
-
- {account.perps.length > 0 && (
- <>
-
Perp Positions
-
- >
- )}
-
-
>
)
diff --git a/src/components/account/AccountList/Skeleton.tsx b/src/components/account/AccountList/Skeleton.tsx
index 9cdae6e6..da9fe086 100644
--- a/src/components/account/AccountList/Skeleton.tsx
+++ b/src/components/account/AccountList/Skeleton.tsx
@@ -46,12 +46,7 @@ export default function Skeleton(props: Props) {
Health
-
+
diff --git a/src/components/account/AccountMenuContent.tsx b/src/components/account/AccountMenuContent.tsx
index 3bf03670..8de2acdc 100644
--- a/src/components/account/AccountMenuContent.tsx
+++ b/src/components/account/AccountMenuContent.tsx
@@ -103,7 +103,7 @@ export default function AccountMenuContent() {
id={ACCOUNT_MENU_BUTTON_ID}
onClick={handleCreateAccountClick}
leftIcon={hasCreditAccounts ?
:
}
- color={hasCreditAccounts ? 'tertiary' : 'primary'}
+ color={hasCreditAccounts ? 'secondary' : 'primary'}
hasFocus={showMenu}
hasSubmenu={hasCreditAccounts}
>
diff --git a/src/components/account/AccountPerpPositionTable/Columns/Asset.tsx b/src/components/account/AccountPerpPositionTable/Columns/Asset.tsx
index 39092c82..ac3fb504 100644
--- a/src/components/account/AccountPerpPositionTable/Columns/Asset.tsx
+++ b/src/components/account/AccountPerpPositionTable/Columns/Asset.tsx
@@ -4,17 +4,28 @@ import DisplayCurrency from 'components/common/DisplayCurrency'
import { FormattedNumber } from 'components/common/FormattedNumber'
import Text from 'components/common/Text'
import { Tooltip } from 'components/common/Tooltip'
+import AssetImage from 'components/common/assets/AssetImage'
import TradeDirection from 'components/perps/BalancesTable/Columns/TradeDirection'
import { BN_ZERO } from 'constants/math'
import usePerpsEnabledAssets from 'hooks/assets/usePerpsEnabledAssets'
import { BNCoin } from 'types/classes/BNCoin'
import { demagnify } from 'utils/formatters'
-export const ASSET_META = { accessorKey: 'symbol', header: 'Asset', id: 'symbol' }
+export const ASSET_META = {
+ accessorKey: 'symbol',
+ header: 'Asset',
+ id: 'symbol',
+ meta: { className: 'w-40' },
+}
interface Props {
row: AccountPerpRow
}
+interface TooltipProps {
+ row: AccountPerpRow
+ asset: Asset
+}
+
function LabelAndValue(props: { label: string; children: ReactNode; className?: string }) {
const { label, children } = props
@@ -28,11 +39,8 @@ function LabelAndValue(props: { label: string; children: ReactNode; className?:
)
}
-function TooltipContent(props: Props) {
- const { row } = props
- const assets = usePerpsEnabledAssets()
- const asset = assets.find((asset) => asset.symbol === row.symbol)
- if (!asset) return null
+function TooltipContent(props: TooltipProps) {
+ const { row, asset } = props
return (
@@ -58,10 +66,14 @@ function TooltipContent(props: Props) {
export default function Asset(props: Props) {
const { row } = props
+ const assets = usePerpsEnabledAssets()
+ const asset = assets.find((asset) => asset.symbol === row.symbol)
+ if (!asset) return null
return (
-
} type='info'>
-
+ } type='info'>
+
+
{row.symbol}
diff --git a/src/components/account/AccountStrategiesTable/Columns/LiqPrice.tsx b/src/components/account/AccountStrategiesTable/Columns/LiqPrice.tsx
new file mode 100644
index 00000000..5ab28ef2
--- /dev/null
+++ b/src/components/account/AccountStrategiesTable/Columns/LiqPrice.tsx
@@ -0,0 +1,67 @@
+import { useEffect, useMemo, useState } from 'react'
+
+import DisplayCurrency from 'components/common/DisplayCurrency'
+import { InfoCircle } from 'components/common/Icons'
+import Text from 'components/common/Text'
+import { Tooltip } from 'components/common/Tooltip'
+import useLiquidationPrice from 'hooks/useLiquidationPrice'
+import { BNCoin } from 'types/classes/BNCoin'
+import { LiquidationPriceKind } from 'utils/health_computer'
+import { BN } from 'utils/helpers'
+
+export const LIQ_META = {
+ accessorKey: 'symbol',
+ header: 'Liquidation Price',
+ id: 'liqPrice',
+ meta: { className: 'w-40' },
+}
+
+interface Props {
+ amount: number
+ computeLiquidationPrice: (denom: string, kind: LiquidationPriceKind) => number | null
+ denom: string
+ type: PositionType
+ account: Account
+}
+
+export default function LiqPrice(props: Props) {
+ const { denom, type, amount, account, computeLiquidationPrice } = props
+ const [lastLiquidationPrice, setLastLiquidationPrice] = useState(null)
+ const hasDebt = account.debts.length > 0
+
+ const liqPrice = useMemo(() => {
+ if (type === 'vault' || amount === 0) return 0
+ return computeLiquidationPrice(denom, type === 'borrow' ? 'debt' : 'asset')
+ }, [amount, computeLiquidationPrice, denom, type])
+
+ const { liquidationPrice } = useLiquidationPrice(liqPrice)
+
+ useEffect(() => {
+ if (lastLiquidationPrice !== liqPrice && liqPrice !== null) setLastLiquidationPrice(liqPrice)
+ }, [liqPrice, lastLiquidationPrice])
+
+ const tooltipText = useMemo(() => {
+ if (type === 'vault')
+ return 'Liquidation prices cannot be calculated for farm positions. But it a drop in price of the underlying assets can still cause a liquidation.'
+ if (!hasDebt) return 'Your position cannot be liquidated as you currently have no debt.'
+ return 'The position size is too small to liquidate the account, even if the price goes to $0.00.'
+ }, [type, hasDebt])
+
+ if (!lastLiquidationPrice || (liquidationPrice === 0 && lastLiquidationPrice === 0))
+ return (
+
+ N/A
+
+
+
+
+ )
+
+ return (
+
+ )
+}
diff --git a/src/components/account/AccountStrategiesTable/Columns/Size.tsx b/src/components/account/AccountStrategiesTable/Columns/Size.tsx
new file mode 100644
index 00000000..a83eaa86
--- /dev/null
+++ b/src/components/account/AccountStrategiesTable/Columns/Size.tsx
@@ -0,0 +1,64 @@
+import classNames from 'classnames'
+import { useMemo } from 'react'
+
+import { getSizeChangeColor } from 'components/account/AccountStrategiesTable/functions'
+import { FormattedNumber } from 'components/common/FormattedNumber'
+import { MAX_AMOUNT_DECIMALS, MIN_AMOUNT } from 'constants/math'
+import useAllAssets from 'hooks/assets/useAllAssets'
+import { BNCoin } from 'types/classes/BNCoin'
+import { byDenom } from 'utils/array'
+import { formatAmountToPrecision } from 'utils/formatters'
+
+export const SIZE_META = { header: 'Size', meta: { className: 'w-40' } }
+
+interface Props {
+ amount: BNCoin[]
+ amountChange: BNCoin[]
+}
+
+export default function Size(props: Props) {
+ const { amount, amountChange } = props
+ const color = useMemo(() => getSizeChangeColor(amountChange), [amountChange])
+ const assets = useAllAssets()
+ const className = classNames('text-xs text-right w-full', color)
+ const minimumAmount = 0.0001
+
+ const primarySymbol = assets.find(byDenom(amount[0].denom))?.symbol
+ const primarySize = amount[0].amount.toString()
+ const primaryFormattedAmount = formatAmountToPrecision(primarySize, MAX_AMOUNT_DECIMALS)
+ const primaryLowAmount =
+ primaryFormattedAmount === 0 ? minimumAmount : Math.max(primaryFormattedAmount, MIN_AMOUNT)
+
+ const secondarySymbol = assets.find(byDenom(amount[1].denom))?.symbol
+ const secondarySize = amount[1].amount.toString()
+ const secondaryFormattedAmount = formatAmountToPrecision(secondarySize, MAX_AMOUNT_DECIMALS)
+ const secondaryLowAmount =
+ secondaryFormattedAmount === 0 ? minimumAmount : Math.max(secondaryFormattedAmount, MIN_AMOUNT)
+
+ return (
+
+
+
+
+ )
+}
diff --git a/src/components/account/AccountStrategiesTable/Columns/StrategyAndValue.tsx b/src/components/account/AccountStrategiesTable/Columns/StrategyAndValue.tsx
new file mode 100644
index 00000000..7f0a159e
--- /dev/null
+++ b/src/components/account/AccountStrategiesTable/Columns/StrategyAndValue.tsx
@@ -0,0 +1,39 @@
+import classNames from 'classnames'
+
+import { getSizeChangeColor } from 'components/account/AccountStrategiesTable/functions'
+import DisplayCurrency from 'components/common/DisplayCurrency'
+import Text from 'components/common/Text'
+import { ORACLE_DENOM } from 'constants/oracle'
+import { BNCoin } from 'types/classes/BNCoin'
+import { BN } from 'utils/helpers'
+export const STRATEGY_AND_VALUE_META = {
+ header: 'Strategy & Value',
+ id: 'name',
+ meta: { className: 'w-40' },
+}
+
+interface Props {
+ name: string
+ value: string
+ amountChange: BNCoin[]
+}
+
+export default function StrategyAndValue(props: Props) {
+ const { name, value, amountChange } = props
+ const color = getSizeChangeColor(amountChange)
+ const coin = BNCoin.fromDenomAndBigNumber(ORACLE_DENOM, BN(value))
+
+ return (
+
+
+ {`${name} LP`}
+
+
+
+ )
+}
diff --git a/src/components/account/AccountStrategiesTable/Columns/Value.tsx b/src/components/account/AccountStrategiesTable/Columns/Value.tsx
new file mode 100644
index 00000000..b1f36d03
--- /dev/null
+++ b/src/components/account/AccountStrategiesTable/Columns/Value.tsx
@@ -0,0 +1,44 @@
+import { Row } from '@tanstack/react-table'
+import classNames from 'classnames'
+
+import { getAmountChangeColor } from 'components/account/AccountBalancesTable/functions'
+import DisplayCurrency from 'components/common/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: PositionType
+}
+
+export const valueBalancesSortingFn = (
+ a: Row,
+ b: Row,
+): number => {
+ const valueA = BN(a.original.value)
+ const valueB = BN(b.original.value)
+ return valueA.minus(valueB).toNumber()
+}
+
+export const valuePerpSortingFn = (a: Row, b: Row): 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 (
+
+ )
+}
diff --git a/src/components/account/AccountStrategiesTable/Columns/useAccountStrategiesColumns.tsx b/src/components/account/AccountStrategiesTable/Columns/useAccountStrategiesColumns.tsx
new file mode 100644
index 00000000..8087e541
--- /dev/null
+++ b/src/components/account/AccountStrategiesTable/Columns/useAccountStrategiesColumns.tsx
@@ -0,0 +1,40 @@
+import { ColumnDef } from '@tanstack/react-table'
+import { useMemo } from 'react'
+
+import Apy, { APY_META } from 'components/account/AccountBalancesTable/Columns/Apy'
+import Size, { SIZE_META } from 'components/account/AccountStrategiesTable/Columns/Size'
+import StrategyAndValue, {
+ STRATEGY_AND_VALUE_META,
+} from 'components/account/AccountStrategiesTable/Columns/StrategyAndValue'
+import useMarkets from 'hooks/markets/useMarkets'
+
+export default function useAccountStrategiesColumns(account: Account) {
+ const markets = useMarkets()
+
+ return useMemo[]>(() => {
+ return [
+ {
+ ...STRATEGY_AND_VALUE_META,
+ cell: ({ row }) => (
+
+ ),
+ },
+ {
+ ...SIZE_META,
+ cell: ({ row }) => (
+
+ ),
+ },
+ {
+ ...APY_META,
+ cell: ({ row }) => (
+
+ ),
+ },
+ ]
+ }, [markets])
+}
diff --git a/src/components/account/AccountStrategiesTable/functions.ts b/src/components/account/AccountStrategiesTable/functions.ts
new file mode 100644
index 00000000..3ff1fc83
--- /dev/null
+++ b/src/components/account/AccountStrategiesTable/functions.ts
@@ -0,0 +1,70 @@
+import { BN_ONE, BN_ZERO } from 'constants/math'
+import { BNCoin } from 'types/classes/BNCoin'
+import { byDenom } from 'utils/array'
+
+export function getVaultAccountStrategiesRow(
+ vault: DepositedVault,
+ apy: number,
+ prices: BNCoin[],
+ prev?: DepositedVault,
+): AccountStrategyRow {
+ const { name } = vault
+ const previous = prev || vault
+ const totalLockedValue = vault.values.primary.plus(vault.values.secondary)
+ const totalValue = totalLockedValue.plus(vault.values.unlocked).plus(vault.values.unlocking)
+ const prevTotalValue = previous.values.primary
+ .plus(previous.values.secondary)
+ .plus(previous.values.unlocked)
+ .plus(previous.values.unlocking)
+
+ if (totalLockedValue.isLessThan(totalValue)) {
+ apy = totalLockedValue.dividedBy(totalValue).times(apy).toNumber()
+ }
+
+ const halfValue = totalValue.dividedBy(2)
+ const halfValuePrev = prevTotalValue.dividedBy(2)
+ const primaryPrice =
+ prices.find(byDenom(vault.denoms.primary)) ??
+ BNCoin.fromDenomAndBigNumber(vault.denoms.primary, BN_ONE)
+ const primaryAmount = halfValue.dividedBy(primaryPrice.amount)
+ const primaryAmountPrev = halfValuePrev.dividedBy(primaryPrice.amount)
+
+ const secondaryPrice =
+ prices.find(byDenom(vault.denoms.secondary)) ??
+ BNCoin.fromDenomAndBigNumber(vault.denoms.secondary, BN_ONE)
+ const secondaryAmount = halfValue.dividedBy(secondaryPrice.amount)
+ const secondaryAmountPrev = halfValuePrev.dividedBy(secondaryPrice.amount)
+
+ const amountChange = [
+ BNCoin.fromDenomAndBigNumber(
+ vault.denoms.primary,
+ !prev ? BN_ZERO : primaryAmount.minus(primaryAmountPrev),
+ ),
+ BNCoin.fromDenomAndBigNumber(
+ vault.denoms.secondary,
+ !prev ? BN_ZERO : secondaryAmount.minus(secondaryAmountPrev),
+ ),
+ ]
+
+ return {
+ name: name,
+ denom: vault.denoms.lp,
+ amount: [
+ BNCoin.fromDenomAndBigNumber(vault.denoms.primary, primaryAmount),
+ BNCoin.fromDenomAndBigNumber(vault.denoms.secondary, secondaryAmount),
+ ],
+ value: totalValue.toString(),
+ apy,
+ amountChange: amountChange,
+ }
+}
+
+export function getSizeChangeColor(amountChange: BNCoin[]) {
+ const primaryChange = amountChange[0].amount
+ const secondaryChange = amountChange[1].amount
+
+ if (primaryChange.isGreaterThan(0) || secondaryChange.isGreaterThan(0)) return 'text-profit'
+ if (primaryChange.isLessThan(0) || secondaryChange.isLessThan(0)) return 'text-loss'
+
+ return ''
+}
diff --git a/src/components/account/AccountStrategiesTable/index.tsx b/src/components/account/AccountStrategiesTable/index.tsx
new file mode 100644
index 00000000..be162675
--- /dev/null
+++ b/src/components/account/AccountStrategiesTable/index.tsx
@@ -0,0 +1,38 @@
+import classNames from 'classnames'
+
+import useAccountStrategiesColumns from 'components/account/AccountStrategiesTable/Columns/useAccountStrategiesColumns'
+import useAccountStrategiesData from 'components/account/AccountStrategiesTable/useAccountStrategiesData'
+import Table from 'components/common/Table'
+import useStore from 'store'
+
+interface Props {
+ account: Account
+ hideCard?: boolean
+ tableBodyClassName?: string
+}
+
+export default function AccountStrategiesTable(props: Props) {
+ const { account, tableBodyClassName, hideCard } = props
+ const updatedAccount = useStore((s) => s.updatedAccount)
+ const accountStrategiesData = useAccountStrategiesData({
+ account,
+ updatedAccount,
+ })
+
+ const columns = useAccountStrategiesColumns(account)
+
+ if (accountStrategiesData.length === 0) return null
+
+ return (
+
+ )
+}
diff --git a/src/components/account/AccountStrategiesTable/useAccountStrategiesData.tsx b/src/components/account/AccountStrategiesTable/useAccountStrategiesData.tsx
new file mode 100644
index 00000000..7900d66e
--- /dev/null
+++ b/src/components/account/AccountStrategiesTable/useAccountStrategiesData.tsx
@@ -0,0 +1,27 @@
+import { useMemo } from 'react'
+
+import { getVaultAccountStrategiesRow } from 'components/account/AccountStrategiesTable/functions'
+import usePrices from 'hooks/usePrices'
+
+interface Props {
+ account: Account
+ updatedAccount?: Account
+}
+
+export default function useAccountStategiesData(props: Props) {
+ const { account, updatedAccount } = props
+ const { data: prices } = usePrices()
+ return useMemo(() => {
+ const usedAccount = updatedAccount ?? account
+ const accountVaults = usedAccount?.vaults ?? []
+
+ return accountVaults.map((vault) => {
+ const apy = vault.apy ?? 0
+ const prevVault = updatedAccount
+ ? account?.vaults.find((position) => position.name === vault.name)
+ : vault
+
+ return getVaultAccountStrategiesRow(vault, apy, prices, prevVault)
+ })
+ }, [account, updatedAccount, prices])
+}
diff --git a/src/components/account/AccountSummary/AccountSummaryHeader.tsx b/src/components/account/AccountSummary/AccountSummaryHeader.tsx
new file mode 100644
index 00000000..54282e3b
--- /dev/null
+++ b/src/components/account/AccountSummary/AccountSummaryHeader.tsx
@@ -0,0 +1,135 @@
+import classNames from 'classnames'
+import { useCallback, useMemo } from 'react'
+
+import AccountSummaryLeverage from 'components/account/AccountSummary/AccountSummaryLeverage'
+import HealthBar from 'components/account/Health/HealthBar'
+import Button from 'components/common/Button'
+import DisplayCurrency from 'components/common/DisplayCurrency'
+import { ArrowRight, ArrowRightLine } from 'components/common/Icons'
+import Text from 'components/common/Text'
+import { BN_ZERO } from 'constants/math'
+import { ORACLE_DENOM } from 'constants/oracle'
+import useStore from 'store'
+import { BNCoin } from 'types/classes/BNCoin'
+import { calculateAccountBalanceValue } from 'utils/accounts'
+
+interface Props {
+ account: Account
+ updatedAccount?: Account
+ prices: BNCoin[]
+ assets: Asset[]
+ leverage: number
+ updatedLeverage: number | null
+ apr: number
+ health: number
+ updatedHealth: number
+ healthFactor: number
+ updatedHealthFactor: number
+ isAccountDetails?: boolean
+}
+
+export default function AccountSummaryHeader(props: Props) {
+ const {
+ account,
+ updatedAccount,
+ prices,
+ assets,
+ leverage,
+ updatedLeverage,
+ health,
+ healthFactor,
+ updatedHealth,
+ updatedHealthFactor,
+ isAccountDetails,
+ } = props
+ const onClose = useCallback(() => useStore.setState({ accountDetailsExpanded: false }), [])
+ const accountBalance = useMemo(
+ () => (account ? calculateAccountBalanceValue(account, prices, assets) : BN_ZERO),
+ [account, prices, assets],
+ )
+ const updatedAccountBalance = useMemo(
+ () =>
+ updatedAccount ? calculateAccountBalanceValue(updatedAccount, prices, assets) : undefined,
+ [updatedAccount, prices, assets],
+ )
+ const hasChanged = !updatedAccountBalance?.isEqualTo(accountBalance)
+ const increase = updatedAccountBalance?.isGreaterThan(accountBalance)
+
+ return (
+
+ {isAccountDetails && (
+
}
+ iconClassName='w-full'
+ className='!absolute top-4 right-4 w-8 h-6 px-2 z-4'
+ size='xs'
+ color='secondary'
+ />
+ )}
+ {isAccountDetails && (
+
{`Credit Account ${account.id}`}
+ )}
+
+
+ {hasChanged && updatedAccountBalance && (
+ <>
+
+
+
+
+ >
+ )}
+
+
+ Networth
+
+
+
+
+ )
+}
diff --git a/src/components/account/AccountSummary/AccountSummaryInModal.tsx b/src/components/account/AccountSummary/AccountSummaryInModal.tsx
new file mode 100644
index 00000000..be6470f9
--- /dev/null
+++ b/src/components/account/AccountSummary/AccountSummaryInModal.tsx
@@ -0,0 +1,19 @@
+import AccountSummary from 'components/account/AccountSummary'
+import Card from 'components/common/Card'
+
+interface Props {
+ account: Account
+ isHls?: boolean
+}
+
+export default function AccountSummaryInModal(props: Props) {
+ const { account, isHls } = props
+
+ return (
+
+ )
+}
diff --git a/src/components/account/AccountSummary/AccountSummaryLeverage.tsx b/src/components/account/AccountSummary/AccountSummaryLeverage.tsx
new file mode 100644
index 00000000..31da4892
--- /dev/null
+++ b/src/components/account/AccountSummary/AccountSummaryLeverage.tsx
@@ -0,0 +1,77 @@
+import classNames from 'classnames'
+
+import { FormattedNumber } from 'components/common/FormattedNumber'
+import { ArrowRight } from 'components/common/Icons'
+
+interface Props {
+ leverage: number
+ updatedLeverage: number | null
+ className?: string
+ containerClassName?: string
+ enforceSuffix?: boolean
+}
+
+export default function AccountSummaryLeverage(props: Props) {
+ const { leverage, updatedLeverage } = props
+
+ if (!updatedLeverage) {
+ return (
+
+ )
+ }
+
+ return (
+
+
+
leverage && 'text-loss',
+ updatedLeverage < leverage && 'text-profit',
+ )}
+ >
+
+
+
leverage && 'text-loss',
+ updatedLeverage < leverage && 'text-profit',
+ )}
+ amount={isNaN(updatedLeverage) ? 0 : updatedLeverage}
+ options={{
+ maxDecimals: props.enforceSuffix ? 2 : 1,
+ minDecimals: props.enforceSuffix ? 2 : 1,
+ rounded: true,
+ suffix: props.enforceSuffix ? 'x' : '',
+ }}
+ animate
+ />
+
+ )
+}
diff --git a/src/components/account/AccountSummary.tsx b/src/components/account/AccountSummary/index.tsx
similarity index 53%
rename from src/components/account/AccountSummary.tsx
rename to src/components/account/AccountSummary/index.tsx
index 0f7fc463..e77c3454 100644
--- a/src/components/account/AccountSummary.tsx
+++ b/src/components/account/AccountSummary/index.tsx
@@ -1,55 +1,49 @@
-import classNames from 'classnames'
-import { HTMLAttributes, useCallback, useMemo } from 'react'
+import { useCallback, useMemo } from 'react'
import AccountBalancesTable from 'components/account/AccountBalancesTable'
import AccountComposition from 'components/account/AccountComposition'
import AccountPerpPositionTable from 'components/account/AccountPerpPositionTable'
-import HealthBar from 'components/account/Health/HealthBar'
+import AccountStrategiesTable from 'components/account/AccountStrategiesTable'
+import AccountSummaryHeader from 'components/account/AccountSummary/AccountSummaryHeader'
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
import Accordion from 'components/common/Accordion'
-import Card from 'components/common/Card'
-import DisplayCurrency from 'components/common/DisplayCurrency'
-import { FormattedNumber } from 'components/common/FormattedNumber'
-import { ArrowRight } from 'components/common/Icons'
-import Text from 'components/common/Text'
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
import { LocalStorageKeys } from 'constants/localStorageKeys'
import { BN_ZERO } from 'constants/math'
-import { ORACLE_DENOM } from 'constants/oracle'
import useAllAssets from 'hooks/assets/useAllAssets'
import useLocalStorage from 'hooks/localStorage/useLocalStorage'
+import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
import useHealthComputer from 'hooks/useHealthComputer'
import usePrices from 'hooks/usePrices'
import useStore from 'store'
-import { BNCoin } from 'types/classes/BNCoin'
-import { calculateAccountBalanceValue, calculateAccountLeverage } from 'utils/accounts'
+import { calculateAccountApr, calculateAccountLeverage } from 'utils/accounts'
interface Props {
account: Account
+ isAccountDetails?: boolean
isHls?: boolean
}
export default function AccountSummary(props: Props) {
+ const storageKey = props.isAccountDetails
+ ? LocalStorageKeys.ACCOUNT_DETAILS_TABS
+ : LocalStorageKeys.ACCOUNT_SUMMARY_TABS
+ const defaultSetting = props.isAccountDetails
+ ? DEFAULT_SETTINGS.accountDetailsTabs
+ : DEFAULT_SETTINGS.accountSummaryTabs
const [accountSummaryTabs, setAccountSummaryTabs] = useLocalStorage(
- LocalStorageKeys.ACCOUNT_SUMMARY_TABS,
- DEFAULT_SETTINGS.accountSummaryTabs,
+ storageKey,
+ defaultSetting,
)
const { data: prices } = usePrices()
const assets = useAllAssets()
const updatedAccount = useStore((s) => s.updatedAccount)
- const accountBalance = useMemo(
- () =>
- props.account
- ? calculateAccountBalanceValue(updatedAccount ?? props.account, prices, assets)
- : BN_ZERO,
- [props.account, updatedAccount, prices, assets],
- )
const data = useBorrowMarketAssetsTableData()
const borrowAssetsData = useMemo(() => data?.allAssets || [], [data])
const { availableAssets: lendingAvailableAssets, accountLentAssets } =
useLendingMarketAssetsTableData()
-
+ const { data: hlsStrategies } = useHLSStakingAssets()
const lendingAssetsData = useMemo(
() => [...lendingAvailableAssets, ...accountLentAssets],
[lendingAvailableAssets, accountLentAssets],
@@ -76,10 +70,32 @@ export default function AccountSummary(props: Props) {
[accountSummaryTabs, setAccountSummaryTabs],
)
+ const apr = useMemo(
+ () =>
+ calculateAccountApr(
+ updatedAccount ?? props.account,
+ borrowAssetsData,
+ lendingAssetsData,
+ prices,
+ hlsStrategies,
+ assets,
+ props.account.kind === 'high_levered_strategy',
+ ),
+ [
+ props.account,
+ assets,
+ borrowAssetsData,
+ hlsStrategies,
+ lendingAssetsData,
+ prices,
+ updatedAccount,
+ ],
+ )
+
const items = useMemo(() => {
const itemsArray = [
{
- title: `Credit Account ${props.account.id} Composition`,
+ title: `Composition`,
renderContent: () =>
props.account ? : null,
isOpen: accountSummaryTabs[0],
@@ -103,14 +119,23 @@ export default function AccountSummary(props: Props) {
renderSubTitle: () => <>>,
},
]
+
+ if (props.account.vaults.length > 0)
+ itemsArray.push({
+ title: 'Strategies',
+ renderContent: () =>
+ props.account ? : null,
+ isOpen: accountSummaryTabs[2] ?? false,
+ toggleOpen: (index: number) => handleToggle(index),
+ renderSubTitle: () => <>>,
+ })
+
if (props.account.perps.length > 0)
itemsArray.push({
title: 'Perp Positions',
renderContent: () =>
- props.account && props.account.perps.length > 0 ? (
-
- ) : null,
- isOpen: accountSummaryTabs[2] ?? false,
+ props.account ? : null,
+ isOpen: accountSummaryTabs[props.account.vaults.length > 0 ? 3 : 2] ?? false,
toggleOpen: (index: number) => handleToggle(index),
renderSubTitle: () => <>>,
})
@@ -127,74 +152,22 @@ export default function AccountSummary(props: Props) {
if (!props.account) return null
return (
-
-
- -
-
-
- -
-
- {updatedLeverage && (
- <>
-
-
- >
- )}
-
- -
-
-
-
+ <>
+
-
- )
-}
-
-interface ItemProps extends HTMLAttributes {
- label: string
- classes?: string
-}
-
-function Item(props: ItemProps) {
- return (
-
-
- {props.label}
-
-
{props.children}
-
+ >
)
}
diff --git a/src/components/account/CurrentAccountSummary.tsx b/src/components/account/CurrentAccountSummary.tsx
deleted file mode 100644
index 0601eaa3..00000000
--- a/src/components/account/CurrentAccountSummary.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import AccountSummary from 'components/account/AccountSummary'
-import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
-
-function CurrentAccountSummary() {
- const account = useCurrentAccount()
- if (!account) return
- return
-}
-
-export default CurrentAccountSummary
diff --git a/src/components/account/Health/HealthBar.tsx b/src/components/account/Health/HealthBar.tsx
index d0a186d3..60baafba 100644
--- a/src/components/account/Health/HealthBar.tsx
+++ b/src/components/account/Health/HealthBar.tsx
@@ -11,13 +11,12 @@ import { getHealthIndicatorColors } from 'utils/healthIndicator'
interface Props {
className?: string
- hasLabel?: boolean
health: number
healthFactor: number
height?: string
iconClassName?: string
- updatedHealth?: number
updatedHealthFactor?: number
+ updatedHealth?: number
showIcon?: boolean
}
@@ -87,44 +86,44 @@ export default function HealthBar({
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <>
{props.items.map((item, index) => (
))}
-
+ >
)
}
diff --git a/src/components/common/AccordionContent.tsx b/src/components/common/AccordionContent.tsx
index 42bf067a..64024a5b 100644
--- a/src/components/common/AccordionContent.tsx
+++ b/src/components/common/AccordionContent.tsx
@@ -27,20 +27,29 @@ export default function AccordionContent(props: Props) {
toggleOpen(props.index)}
className={classNames(
- 'mb-0 flex hover:cursor-pointer items-center justify-between bg-white/10 p-4 text-white border-b border-transparent',
+ 'mb-0 flex hover:cursor-pointer items-center justify-between bg-white/10 py-2 px-4 text-white border-b border-transparent',
'[&::marker]:hidden [&::marker]:content-[""]',
- isOpen && 'border-white/20',
+ isOpen && 'border-white/10',
)}
>
- {title}
+
+ {title}
+
{renderSubTitle()}
{isOpen ? : }
- {isOpen && {renderContent()}
}
+
)
}
diff --git a/src/components/common/Button/EscButton.tsx b/src/components/common/Button/EscButton.tsx
index 737576fb..e9a1edfa 100644
--- a/src/components/common/Button/EscButton.tsx
+++ b/src/components/common/Button/EscButton.tsx
@@ -32,10 +32,10 @@ export default function EscButton(props: Props) {
return (
}
+ leftIcon={
}
iconClassName='w-3'
color='tertiary'
- className={props.className ? props.className : 'h-8 w-8'}
+ className='w-8 h-8'
size='xs'
/>
)
diff --git a/src/components/common/Icons/ArrowRight.svg b/src/components/common/Icons/ArrowRight.svg
index 08f15f60..6676dc57 100644
--- a/src/components/common/Icons/ArrowRight.svg
+++ b/src/components/common/Icons/ArrowRight.svg
@@ -1,3 +1,15 @@
-
)
diff --git a/src/components/earn/farm/Table/Columns/Apy.tsx b/src/components/earn/farm/Table/Columns/Apy.tsx
index c27d0e7e..21d60f5c 100644
--- a/src/components/earn/farm/Table/Columns/Apy.tsx
+++ b/src/components/earn/farm/Table/Columns/Apy.tsx
@@ -1,5 +1,3 @@
-import React from 'react'
-
import { FormattedNumber } from 'components/common/FormattedNumber'
import Loading from 'components/common/Loading'
@@ -13,7 +11,6 @@ export default function Apy(props: Props) {
const { vault } = props
if (vault.apy === null) return
}
onClick={() => {
setShowRewardsCenter(!showRewardsCenter)
diff --git a/src/components/portfolio/Account/Strategies.tsx b/src/components/portfolio/Account/Strategies.tsx
new file mode 100644
index 00000000..1df5fd9f
--- /dev/null
+++ b/src/components/portfolio/Account/Strategies.tsx
@@ -0,0 +1,52 @@
+import React, { Suspense } from 'react'
+
+import AccountStrategiesTable from 'components/account/AccountStrategiesTable'
+import Card from 'components/common/Card'
+import TableSkeleton from 'components/common/Table/TableSkeleton'
+import Text from 'components/common/Text'
+import useAccount from 'hooks/accounts/useAccount'
+
+interface Props {
+ accountId: string
+}
+
+function Content(props: Props) {
+ const { data: account } = useAccount(props.accountId, true)
+
+ if (!account || account?.vaults.length === 0) {
+ return null
+ }
+
+ return (
+
+
+
+ )
+}
+
+export default function Strategies(props: Props) {
+ return (
+
}>
+
+
+ )
+}
+
+interface SkeletonProps {
+ children?: React.ReactNode
+}
+
+function Skeleton(props: SkeletonProps) {
+ return (
+
+
Strategies
+
+ {props.children ? (
+ props.children
+ ) : (
+
+ )}
+
+
+ )
+}
diff --git a/src/components/trade/TradeChart/PoweredByPyth.tsx b/src/components/trade/TradeChart/PoweredByPyth.tsx
index 31897bd0..386ab644 100644
--- a/src/components/trade/TradeChart/PoweredByPyth.tsx
+++ b/src/components/trade/TradeChart/PoweredByPyth.tsx
@@ -5,7 +5,9 @@ export default function PoweredByPyth() {
return (
)
}
diff --git a/src/components/trade/TradeModule/AssetSelector/AssetSelectorPair.tsx b/src/components/trade/TradeModule/AssetSelector/AssetSelectorPair.tsx
index d6176157..ad274208 100644
--- a/src/components/trade/TradeModule/AssetSelector/AssetSelectorPair.tsx
+++ b/src/components/trade/TradeModule/AssetSelector/AssetSelectorPair.tsx
@@ -41,7 +41,7 @@ export default function AssetSelectorPair(props: Props) {
color='quaternary'
variant='transparent'
onClick={() => useStore.setState({ assetOverlayState: 'pair' })}
- className='flex items-center justify-between w-full py-5 bg-white/5'
+ className='flex items-center justify-between w-full py-5 bg-white/10'
>
{buyAsset.symbol}/{sellAsset.symbol}
diff --git a/src/components/trade/TradeModule/AssetSelector/AssetSelectorSingle.tsx b/src/components/trade/TradeModule/AssetSelector/AssetSelectorSingle.tsx
index 7cf7edfa..ac0a6e74 100644
--- a/src/components/trade/TradeModule/AssetSelector/AssetSelectorSingle.tsx
+++ b/src/components/trade/TradeModule/AssetSelector/AssetSelectorSingle.tsx
@@ -51,7 +51,7 @@ export default function AssetSelectorSingle(props: Props) {
}, [])
return (
-
+
Buy
Sell
diff --git a/src/components/trade/TradeModule/index.tsx b/src/components/trade/TradeModule/index.tsx
index db6d1257..e67d1438 100644
--- a/src/components/trade/TradeModule/index.tsx
+++ b/src/components/trade/TradeModule/index.tsx
@@ -14,7 +14,7 @@ export default function TradeModule(props: Props) {
asset.isEnabled && asset.isMarket)
export const DEFAULT_SETTINGS: Settings = {
- accountSummaryTabs: [true, true, false],
+ accountSummaryTabs: [true, true, true, false],
+ accountDetailsTabs: [true, true, true, true],
reduceMotion: false,
enableAutoLendGlobal: true,
tradingPairSimple: {
diff --git a/src/constants/localStorageKeys.ts b/src/constants/localStorageKeys.ts
index bde106c7..88aef68c 100644
--- a/src/constants/localStorageKeys.ts
+++ b/src/constants/localStorageKeys.ts
@@ -2,6 +2,7 @@ export enum LocalStorageKeys {
TRADING_PAIR_SIMPLE = 'tradingPairSimple',
TRADING_PAIR_ADVANCED = 'tradingPairAdvanced',
ACCOUNT_SUMMARY_TABS = 'accountSummaryTabs',
+ ACCOUNT_DETAILS_TABS = 'accountDetailsTabs',
DISPLAY_CURRENCY = 'displayCurrency',
REDUCE_MOTION = 'reduceMotion',
FAVORITE_ASSETS = 'favoriteAssets',
diff --git a/src/pages/PortfolioAccountPage.tsx b/src/pages/PortfolioAccountPage.tsx
index 371d5ba8..b0308320 100644
--- a/src/pages/PortfolioAccountPage.tsx
+++ b/src/pages/PortfolioAccountPage.tsx
@@ -5,6 +5,7 @@ import ShareBar from 'components/common/ShareBar'
import Balances from 'components/portfolio/Account/Balances'
import BreadCrumbs from 'components/portfolio/Account/BreadCrumbs'
import PerpPositions from 'components/portfolio/Account/PerpPositions'
+import Strategies from 'components/portfolio/Account/Strategies'
import Summary from 'components/portfolio/Account/Summary'
import useAccountId from 'hooks/useAccountId'
import useChainConfig from 'hooks/useChainConfig'
@@ -28,6 +29,7 @@ export default function PortfolioAccountPage() {
+ {chainConfig.farm &&
}
{chainConfig.perps &&
}
diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx
index 3bd31cf6..4fb45333 100644
--- a/src/pages/_document.tsx
+++ b/src/pages/_document.tsx
@@ -2,13 +2,13 @@ import { Head, Html, Main, NextScript } from 'next/document'
export default function Document() {
return (
-
+
-
+
diff --git a/src/pages/_layout.tsx b/src/pages/_layout.tsx
index f4490983..dba5d0a4 100644
--- a/src/pages/_layout.tsx
+++ b/src/pages/_layout.tsx
@@ -70,7 +70,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {