import useMangoGroup from 'hooks/useMangoGroup' import { useMemo, useState } from 'react' import { SHOW_INACTIVE_POSITIONS_KEY } from 'utils/constants' import TokenLogo from './shared/TokenLogo' import Button from './shared/Button' import { formatTokenSymbol } from 'utils/tokens' import mangoStore, { ActiveTab } from '@store/mangoStore' import Switch from './forms/Switch' import useLocalStorageState from 'hooks/useLocalStorageState' import FormatNumericValue from './shared/FormatNumericValue' import { Bank, MangoAccount, toUiDecimalsForQuote, } from '@blockworks-foundation/mango-v4' import useBankRates from 'hooks/useBankRates' import usePositions from 'hooks/usePositions' import { AdjustmentsHorizontalIcon } from '@heroicons/react/20/solid' import EditLeverageModal from './modals/EditLeverageModal' import Tooltip from './shared/Tooltip' import { useWallet } from '@solana/wallet-adapter-react' const set = mangoStore.getState().set export type Position = { borrowBalance: number stakeBalance: number pnl: number bank: Bank acct: MangoAccount | undefined } const Positions = ({ setActiveTab, }: { setActiveTab: (tab: ActiveTab) => void }) => { const [showInactivePositions, setShowInactivePositions] = useLocalStorageState(SHOW_INACTIVE_POSITIONS_KEY, true) const { positions, jlpBorrowBank, lstBorrowBank } = usePositions( showInactivePositions, ) const numberOfPositions = useMemo(() => { if (!positions.length) return 0 return positions.filter((pos) => pos.stakeBalance > 0).length }, [positions]) return ( <>

{`You have ${numberOfPositions} active position${ numberOfPositions !== 1 ? 's' : '' }`}

setShowInactivePositions(checked)} > Show Inactive
{positions.length ? ( positions.map((position) => { const { bank } = position const isUsdcBorrow = bank.name === 'JLP' || bank.name === 'USDC' return position.bank ? ( ) : null }) ) : (
Nothing to see here...
)}
) } const PositionItem = ({ position, setActiveTab, borrowBank, }: { position: Position setActiveTab: (v: ActiveTab) => void borrowBank: Bank | undefined }) => { const { connected } = useWallet() const { jlpGroup, lstGroup } = useMangoGroup() const { stakeBalance, bank, pnl, acct } = position const handleAddOrManagePosition = (token: string) => { setActiveTab('Boost!') set((state) => { state.selectedToken = token }) } const [showEditLeverageModal, setShowEditLeverageModal] = useState(false) const leverage = useMemo(() => { if (!acct || !bank) return 1 const isJlpGroup = bank.name === 'JLP' || bank.name === 'USDC' const group = isJlpGroup ? jlpGroup : lstGroup if (!group) return 1 const accountValue = toUiDecimalsForQuote(acct.getEquity(group).toNumber()) const assetsValue = toUiDecimalsForQuote( acct.getAssetsValue(group).toNumber(), ) if (isNaN(assetsValue / accountValue)) { return 0 } else { return Math.abs(1 - assetsValue / accountValue) + 1 } }, [acct, bank, jlpGroup, lstGroup]) const liquidationPrice = useMemo(() => { let price if (borrowBank?.name == 'SOL') { price = Number(bank?.uiPrice) / Number(borrowBank?.uiPrice) } else { price = Number(bank?.uiPrice) } const borrowMaintLiabWeight = Number(borrowBank?.maintLiabWeight) const stakeMaintAssetWeight = Number(bank?.maintAssetWeight) const loanOriginationFee = Number(borrowBank?.loanOriginationFeeRate) const liqPrice = price * ((borrowMaintLiabWeight * (1 + loanOriginationFee)) / stakeMaintAssetWeight) * (1 - 1 / leverage) return liqPrice.toFixed(2) }, [bank, borrowBank, leverage]) const { financialMetrics, stakeBankDepositRate, borrowBankBorrowRate } = useBankRates(bank.name, leverage) const APY_Daily_Compound = Math.pow(1 + Number(stakeBankDepositRate) / 365, 365) - 1 const uiRate = bank.name == 'USDC' ? APY_Daily_Compound * 100 : financialMetrics.APY return (

{formatTokenSymbol(bank.name)}

${bank.uiPrice.toFixed(2)}

Position Size

{' '} {'USDC'} {bank.name !== 'USDC' ? (

{' '} {formatTokenSymbol(bank.name)}

) : null}

Est. APY

{bank.name !== 'USDC' ? (

{formatTokenSymbol(bank.name)} Yield APY

{financialMetrics.collectedReturnsAPY > 0.01 ? '+' : ''} %

{formatTokenSymbol(bank.name)} Collateral Fee APY

0.01 ? 'text-th-error' : 'text-th-bkg-4' }`} > {financialMetrics?.collateralFeeAPY > 0.01 ? '-' : ''} %
{borrowBank ? ( <>

{`${borrowBank?.name} Borrow APY`}

0.01 ? 'text-th-error' : 'text-th-bkg-4' }`} > - %
) : null}
} > %
) : ( <> % )}

Total Earned

= 0 ? 'text-th-success' : 'text-th-error' }`} > {stakeBalance || pnl ? ( ) : ( '–' )}
{position.bank.name == 'USDC' ? null : ( <>

Leverage

{connected && stakeBalance && leverage ? `${leverage.toFixed(2)}x` : '–'} {connected && stakeBalance ? ( ) : null}

Est. Liquidation Price

{liquidationPrice} {borrowBank?.name == ' USDC' ? ' USDC' : ` ${bank?.name}/${borrowBank?.name}`}
{/* {liqPriceChangePercentage ? (

{liqPriceChangePercentage}%

) : null} */}
)}
{showEditLeverageModal ? ( { setShowEditLeverageModal(false) }} /> ) : null}
) } export default Positions