perp positions table mobile
This commit is contained in:
parent
ebad7d753f
commit
6e4323ee6e
|
@ -1,16 +1,20 @@
|
|||
import { useCallback, useState } from 'react'
|
||||
import useMangoStore from '../stores/useMangoStore'
|
||||
import { Table, Thead, Tbody, Tr, Th, Td } from 'react-super-responsive-table'
|
||||
import {
|
||||
getMarketByPublicKey,
|
||||
PerpMarket,
|
||||
ZERO_BN,
|
||||
} from '@blockworks-foundation/mango-client'
|
||||
import SideBadge from './SideBadge'
|
||||
import { useViewport } from '../hooks/useViewport'
|
||||
import { breakpoints } from './TradePageGrid'
|
||||
import { Table, Td, Th, TrBody, TrHead } from './TableElements'
|
||||
import { formatUsdValue, usdFormatter } from '../utils'
|
||||
import useTradeHistory from '../hooks/useTradeHistory'
|
||||
import usePerpPositions from '../hooks/usePerpPositions'
|
||||
import MarketCloseModal from './MarketCloseModal'
|
||||
import { ExpandableRow } from './TableElements'
|
||||
import MobileTableHeader from './mobile/MobileTableHeader'
|
||||
|
||||
export function getAvgEntryPrice(
|
||||
mangoAccount,
|
||||
|
@ -68,6 +72,8 @@ const PositionsTable = () => {
|
|||
const tradeHistory = useTradeHistory()
|
||||
const setMangoStore = useMangoStore((s) => s.set)
|
||||
const perpPositions = usePerpPositions()
|
||||
const { width } = useViewport()
|
||||
const isMobile = width ? width < breakpoints.md : false
|
||||
|
||||
const handleCloseWarning = useCallback(() => {
|
||||
setShowMarketCloseModal(false)
|
||||
|
@ -84,34 +90,20 @@ const PositionsTable = () => {
|
|||
<div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||
<div className="align-middle inline-block min-w-full sm:px-6 lg:px-8">
|
||||
{perpPositions.length ? (
|
||||
<div className="overflow-hidden border-b border-th-bkg-2 sm:rounded-m">
|
||||
<Table className="min-w-full divide-y divide-th-bkg-2">
|
||||
<Thead>
|
||||
<Tr className="text-th-fgd-3 text-xs">
|
||||
<Th scope="col" className="px-6 py-2 text-left font-normal">
|
||||
Market
|
||||
</Th>
|
||||
<Th scope="col" className="px-2 py-2 text-left font-normal">
|
||||
Side
|
||||
</Th>
|
||||
<Th scope="col" className="px-2 py-2 text-left font-normal">
|
||||
Position size
|
||||
</Th>
|
||||
<Th scope="col" className="px-2 py-2 text-left font-normal">
|
||||
Notional size
|
||||
</Th>
|
||||
<Th scope="col" className="px-2 py-2 text-left font-normal">
|
||||
Avg entry price
|
||||
</Th>
|
||||
<Th scope="col" className="px-2 py-2 text-left font-normal">
|
||||
Break-even price
|
||||
</Th>
|
||||
<Th scope="col" className="px-2 py-2 text-left font-normal">
|
||||
PnL
|
||||
</Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
!isMobile ? (
|
||||
<Table>
|
||||
<thead>
|
||||
<TrHead>
|
||||
<Th>Market</Th>
|
||||
<Th>Side</Th>
|
||||
<Th>Position Size</Th>
|
||||
<Th>Notional Size</Th>
|
||||
<Th>Avg entry Price</Th>
|
||||
<Th>Break-even Price</Th>
|
||||
<Th>PnL</Th>
|
||||
</TrHead>
|
||||
</thead>
|
||||
<tbody>
|
||||
{perpPositions.map(({ perpAccount, marketIndex }, index) => {
|
||||
const perpMarketInfo = mangoGroup.perpMarkets[marketIndex]
|
||||
const marketConfig = getMarketByPublicKey(
|
||||
|
@ -147,13 +139,8 @@ const PositionsTable = () => {
|
|||
: null
|
||||
|
||||
return (
|
||||
<Tr
|
||||
key={`${marketIndex}`}
|
||||
className={`border-b border-th-bkg-3
|
||||
${index % 2 === 0 ? `bg-th-bkg-3` : `bg-th-bkg-2`}
|
||||
`}
|
||||
>
|
||||
<Td className="px-6 py-2 whitespace-nowrap text-sm text-th-fgd-1">
|
||||
<TrBody index={index} key={`${marketIndex}`}>
|
||||
<Td>
|
||||
<div className="flex items-center">
|
||||
<img
|
||||
alt=""
|
||||
|
@ -165,7 +152,7 @@ const PositionsTable = () => {
|
|||
<div>{marketConfig.name}</div>
|
||||
</div>
|
||||
</Td>
|
||||
<Td className="px-2 py-2 whitespace-nowrap text-sm text-th-fgd-1">
|
||||
<Td>
|
||||
{!perpAccount.basePosition.eq(ZERO_BN) ? (
|
||||
<SideBadge
|
||||
side={
|
||||
|
@ -178,7 +165,7 @@ const PositionsTable = () => {
|
|||
'-'
|
||||
)}
|
||||
</Td>
|
||||
<Td className="px-2 py-2 whitespace-nowrap text-sm text-th-fgd-1">
|
||||
<Td>
|
||||
{perpAccount &&
|
||||
Math.abs(
|
||||
perpMarket.baseLotsToNumber(
|
||||
|
@ -207,10 +194,7 @@ const PositionsTable = () => {
|
|||
`0 ${marketConfig.baseSymbol}`
|
||||
)}
|
||||
</Td>
|
||||
<Th
|
||||
scope="col"
|
||||
className="px-2 py-2 text-left font-normal"
|
||||
>
|
||||
<Td>
|
||||
{usdFormatter(
|
||||
Math.abs(
|
||||
perpMarket.baseLotsToNumber(
|
||||
|
@ -221,8 +205,8 @@ const PositionsTable = () => {
|
|||
.toNumber()
|
||||
)
|
||||
)}
|
||||
</Th>
|
||||
<Td className="px-2 py-2 whitespace-nowrap text-sm text-th-fgd-1">
|
||||
</Td>
|
||||
<Td>
|
||||
{getAvgEntryPrice(
|
||||
mangoAccount,
|
||||
perpAccount,
|
||||
|
@ -230,7 +214,7 @@ const PositionsTable = () => {
|
|||
perpTradeHistory
|
||||
)}
|
||||
</Td>
|
||||
<Td className="px-2 py-2 whitespace-nowrap text-sm text-th-fgd-1">
|
||||
<Td>
|
||||
{getBreakEvenPrice(
|
||||
mangoAccount,
|
||||
perpAccount,
|
||||
|
@ -238,12 +222,20 @@ const PositionsTable = () => {
|
|||
perpTradeHistory
|
||||
)}
|
||||
</Td>
|
||||
<Td
|
||||
className={`px-2 py-2 whitespace-nowrap text-sm text-th-fgd-1 ${
|
||||
pnl >= 0 ? 'text-th-green' : 'text-th-red'
|
||||
}`}
|
||||
>
|
||||
{pnl !== null ? usdFormatter(pnl) : '--'}
|
||||
<Td>
|
||||
{pnl !== null ? (
|
||||
pnl > 0 ? (
|
||||
<span className="text-th-green">
|
||||
{usdFormatter(pnl)}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-th-red">
|
||||
{usdFormatter(pnl)}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
'--'
|
||||
)}
|
||||
</Td>
|
||||
{showMarketCloseModal ? (
|
||||
<MarketCloseModal
|
||||
|
@ -253,12 +245,157 @@ const PositionsTable = () => {
|
|||
marketIndex={marketIndex}
|
||||
/>
|
||||
) : null}
|
||||
</Tr>
|
||||
</TrBody>
|
||||
)
|
||||
})}
|
||||
</Tbody>
|
||||
</tbody>
|
||||
</Table>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<MobileTableHeader
|
||||
headerTemplate={<div className="col-span-11">Position</div>}
|
||||
/>
|
||||
{perpPositions.map(({ perpAccount, marketIndex }, index) => {
|
||||
const perpMarketInfo = mangoGroup.perpMarkets[marketIndex]
|
||||
const marketConfig = getMarketByPublicKey(
|
||||
groupConfig,
|
||||
perpMarketInfo.perpMarket
|
||||
)
|
||||
const perpMarket = allMarkets[
|
||||
perpMarketInfo.perpMarket.toString()
|
||||
] as PerpMarket
|
||||
const perpTradeHistory = tradeHistory.filter(
|
||||
(t) => t.marketName === marketConfig.name
|
||||
)
|
||||
let breakEvenPrice
|
||||
try {
|
||||
breakEvenPrice = perpAccount.getBreakEvenPrice(
|
||||
mangoAccount,
|
||||
perpMarket,
|
||||
perpTradeHistory
|
||||
)
|
||||
} catch (e) {
|
||||
breakEvenPrice = null
|
||||
}
|
||||
|
||||
const pnl =
|
||||
breakEvenPrice !== null
|
||||
? perpMarket.baseLotsToNumber(perpAccount.basePosition) *
|
||||
(mangoGroup
|
||||
.getPrice(marketIndex, mangoCache)
|
||||
.toNumber() -
|
||||
parseFloat(breakEvenPrice))
|
||||
: null
|
||||
return (
|
||||
<ExpandableRow
|
||||
buttonTemplate={
|
||||
<>
|
||||
<div className="col-span-11 flex items-center text-fgd-1">
|
||||
<div className="flex items-center">
|
||||
<img
|
||||
alt=""
|
||||
width="20"
|
||||
height="20"
|
||||
src={`/assets/icons/${marketConfig.baseSymbol.toLowerCase()}.svg`}
|
||||
className={`mr-2.5`}
|
||||
/>
|
||||
<div>
|
||||
<div className="mb-0.5 text-left">
|
||||
{marketConfig.name}
|
||||
</div>
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
<span
|
||||
className={`mr-1
|
||||
${
|
||||
perpAccount.basePosition.gt(ZERO_BN)
|
||||
? 'text-th-green'
|
||||
: 'text-th-red'
|
||||
}
|
||||
`}
|
||||
>
|
||||
{perpAccount.basePosition.gt(ZERO_BN)
|
||||
? 'LONG'
|
||||
: 'SHORT'}
|
||||
</span>
|
||||
{`${
|
||||
Math.abs(
|
||||
perpMarket.baseLotsToNumber(
|
||||
perpAccount.basePosition
|
||||
)
|
||||
) > 0
|
||||
? Math.abs(
|
||||
perpMarket.baseLotsToNumber(
|
||||
perpAccount.basePosition
|
||||
)
|
||||
)
|
||||
: 0
|
||||
} at ${getAvgEntryPrice(
|
||||
mangoAccount,
|
||||
perpAccount,
|
||||
perpMarket,
|
||||
perpTradeHistory
|
||||
)}`}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
key={`${index}`}
|
||||
index={index}
|
||||
panelTemplate={
|
||||
<>
|
||||
<div className="col-span-1 text-left">
|
||||
<div className="pb-0.5 text-th-fgd-3 text-xs">
|
||||
Notional Size
|
||||
</div>
|
||||
{usdFormatter(
|
||||
Math.abs(
|
||||
perpMarket.baseLotsToNumber(
|
||||
perpAccount.basePosition
|
||||
) *
|
||||
mangoGroup
|
||||
.getPrice(marketIndex, mangoCache)
|
||||
.toNumber()
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
<div className="col-span-1 text-left">
|
||||
<div className="pb-0.5 text-th-fgd-3 text-xs">
|
||||
Break-even Price
|
||||
</div>
|
||||
{getBreakEvenPrice(
|
||||
mangoAccount,
|
||||
perpAccount,
|
||||
perpMarket,
|
||||
perpTradeHistory
|
||||
)}
|
||||
</div>
|
||||
<div className="col-span-1 text-left">
|
||||
<div className="pb-0.5 text-th-fgd-3 text-xs">
|
||||
PnL
|
||||
</div>
|
||||
{pnl !== null ? (
|
||||
pnl > 0 ? (
|
||||
<span className="text-th-green">
|
||||
{usdFormatter(pnl)}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-th-red">
|
||||
{usdFormatter(pnl)}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
'--'
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
) : (
|
||||
<div
|
||||
className={`w-full text-center py-6 bg-th-bkg-1 text-th-fgd-3 rounded-md`}
|
||||
|
|
Loading…
Reference in New Issue