import { PerpMarket, PerpPosition } from '@blockworks-foundation/mango-v4' import Button, { LinkButton } from '@components/shared/Button' import ConnectEmptyState from '@components/shared/ConnectEmptyState' import FormatNumericValue from '@components/shared/FormatNumericValue' import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements' import { NoSymbolIcon } from '@heroicons/react/20/solid' import { useWallet } from '@solana/wallet-adapter-react' import mangoStore from '@store/mangoStore' import useMangoAccount from 'hooks/useMangoAccount' import useMangoGroup from 'hooks/useMangoGroup' import useSelectedMarket from 'hooks/useSelectedMarket' import useUnownedAccount from 'hooks/useUnownedAccount' import { useViewport } from 'hooks/useViewport' import { useTranslation } from 'next-i18next' import Link from 'next/link' import { useRouter } from 'next/router' import { useCallback, useState } from 'react' import { floorToDecimal, getDecimalCount } from 'utils/numbers' import { breakpoints } from 'utils/theme' import { calculateLimitPriceForMarketOrder } from 'utils/tradeForm' import MarketCloseModal from './MarketCloseModal' import MarketLogos from './MarketLogos' import PerpSideBadge from './PerpSideBadge' import TableMarketName from './TableMarketName' const PerpPositions = () => { const { t } = useTranslation(['common', 'trade']) const { group } = useMangoGroup() const [showMarketCloseModal, setShowMarketCloseModal] = useState(false) const [positionToClose, setPositionToClose] = useState( null ) const perpPositions = mangoStore((s) => s.mangoAccount.perpPositions) const { selectedMarket } = useSelectedMarket() const { connected } = useWallet() const { mangoAccountAddress } = useMangoAccount() const { isUnownedAccount } = useUnownedAccount() const { width } = useViewport() const showTableView = width ? width > breakpoints.md : false const { asPath } = useRouter() const handlePositionClick = (positionSize: number, market: PerpMarket) => { const tradeForm = mangoStore.getState().tradeForm const set = mangoStore.getState().set let price = Number(tradeForm.price) if (tradeForm.tradeType === 'Market') { const orderbook = mangoStore.getState().selectedMarket.orderbook price = calculateLimitPriceForMarketOrder( orderbook, positionSize, tradeForm.side ) } const newSide = positionSize > 0 ? 'sell' : 'buy' const quoteSize = floorToDecimal( positionSize * price, getDecimalCount(market.tickSize) ) set((s) => { s.tradeForm.side = newSide s.tradeForm.baseSize = positionSize.toString() s.tradeForm.quoteSize = quoteSize.toString() }) } const showClosePositionModal = useCallback((position: PerpPosition) => { setShowMarketCloseModal(true) setPositionToClose(position) }, []) const hideClosePositionModal = useCallback(() => { setShowMarketCloseModal(false) setPositionToClose(null) }, []) if (!group) return null const openPerpPositions = Object.values(perpPositions).filter((p) => p.basePositionLots.toNumber() ) return mangoAccountAddress && openPerpPositions.length ? ( showTableView ? ( <>
{!isUnownedAccount ? {openPerpPositions.map((position) => { const market = group.getPerpMarketByMarketIndex( position.marketIndex ) const basePosition = position.getBasePositionUi(market) const floorBasePosition = floorToDecimal( basePosition, getDecimalCount(market.minOrderSize) ).toNumber() const isSelectedMarket = selectedMarket instanceof PerpMarket && selectedMarket.perpMarketIndex === position.marketIndex if (!basePosition) return null const unsettledPnl = position.getUnsettledPnlUi(market) const cummulativePnl = position.cumulativePnlOverPositionLifetimeUi(market) return ( {!isUnownedAccount ? ( ) : null} ) })}
{t('market')} {t('trade:side')} {t('trade:size')} {t('trade:notional')} {t('trade:entry-price')} {t('trade:oracle-price')} {`${t('trade:unsettled')} ${t( 'pnl' )}`} {t('pnl')} : null}

{isSelectedMarket ? ( handlePositionClick(floorBasePosition, market) } > ) : ( )}

0 ? 'text-th-up' : 'text-th-down' }`} >
{showMarketCloseModal && positionToClose ? ( ) : null} ) : ( <> {openPerpPositions.map((position) => { const market = group.getPerpMarketByMarketIndex(position.marketIndex) const basePosition = position.getBasePositionUi(market) const floorBasePosition = floorToDecimal( basePosition, getDecimalCount(market.minOrderSize) ).toNumber() const isSelectedMarket = selectedMarket instanceof PerpMarket && selectedMarket.perpMarketIndex === position.marketIndex if (!basePosition) return null const cummulativePnl = position.cumulativePnlOverPositionLifetimeUi(market) return (
{selectedMarket?.name === market.name ? ( {market.name} ) : (
{market.name}
)}

{isSelectedMarket && asPath === '/trade' ? ( handlePositionClick(floorBasePosition, market) } > ) : ( )} from

0 ? 'text-th-up' : 'text-th-down' }`} >

PnL

{!isUnownedAccount ? ( ) : null}
) })} ) ) : mangoAccountAddress || connected ? (

{t('trade:no-positions')}

) : (
) } export default PerpPositions