perp positions table mobile

This commit is contained in:
saml33 2021-09-08 11:52:45 +10:00
parent ebad7d753f
commit 6e4323ee6e
1 changed files with 191 additions and 54 deletions

View File

@ -1,16 +1,20 @@
import { useCallback, useState } from 'react' import { useCallback, useState } from 'react'
import useMangoStore from '../stores/useMangoStore' import useMangoStore from '../stores/useMangoStore'
import { Table, Thead, Tbody, Tr, Th, Td } from 'react-super-responsive-table'
import { import {
getMarketByPublicKey, getMarketByPublicKey,
PerpMarket, PerpMarket,
ZERO_BN, ZERO_BN,
} from '@blockworks-foundation/mango-client' } from '@blockworks-foundation/mango-client'
import SideBadge from './SideBadge' 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 { formatUsdValue, usdFormatter } from '../utils'
import useTradeHistory from '../hooks/useTradeHistory' import useTradeHistory from '../hooks/useTradeHistory'
import usePerpPositions from '../hooks/usePerpPositions' import usePerpPositions from '../hooks/usePerpPositions'
import MarketCloseModal from './MarketCloseModal' import MarketCloseModal from './MarketCloseModal'
import { ExpandableRow } from './TableElements'
import MobileTableHeader from './mobile/MobileTableHeader'
export function getAvgEntryPrice( export function getAvgEntryPrice(
mangoAccount, mangoAccount,
@ -68,6 +72,8 @@ const PositionsTable = () => {
const tradeHistory = useTradeHistory() const tradeHistory = useTradeHistory()
const setMangoStore = useMangoStore((s) => s.set) const setMangoStore = useMangoStore((s) => s.set)
const perpPositions = usePerpPositions() const perpPositions = usePerpPositions()
const { width } = useViewport()
const isMobile = width ? width < breakpoints.md : false
const handleCloseWarning = useCallback(() => { const handleCloseWarning = useCallback(() => {
setShowMarketCloseModal(false) setShowMarketCloseModal(false)
@ -84,34 +90,20 @@ const PositionsTable = () => {
<div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8"> <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"> <div className="align-middle inline-block min-w-full sm:px-6 lg:px-8">
{perpPositions.length ? ( {perpPositions.length ? (
<div className="overflow-hidden border-b border-th-bkg-2 sm:rounded-m"> !isMobile ? (
<Table className="min-w-full divide-y divide-th-bkg-2"> <Table>
<Thead> <thead>
<Tr className="text-th-fgd-3 text-xs"> <TrHead>
<Th scope="col" className="px-6 py-2 text-left font-normal"> <Th>Market</Th>
Market <Th>Side</Th>
</Th> <Th>Position Size</Th>
<Th scope="col" className="px-2 py-2 text-left font-normal"> <Th>Notional Size</Th>
Side <Th>Avg entry Price</Th>
</Th> <Th>Break-even Price</Th>
<Th scope="col" className="px-2 py-2 text-left font-normal"> <Th>PnL</Th>
Position size </TrHead>
</Th> </thead>
<Th scope="col" className="px-2 py-2 text-left font-normal"> <tbody>
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>
{perpPositions.map(({ perpAccount, marketIndex }, index) => { {perpPositions.map(({ perpAccount, marketIndex }, index) => {
const perpMarketInfo = mangoGroup.perpMarkets[marketIndex] const perpMarketInfo = mangoGroup.perpMarkets[marketIndex]
const marketConfig = getMarketByPublicKey( const marketConfig = getMarketByPublicKey(
@ -147,13 +139,8 @@ const PositionsTable = () => {
: null : null
return ( return (
<Tr <TrBody index={index} key={`${marketIndex}`}>
key={`${marketIndex}`} <Td>
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">
<div className="flex items-center"> <div className="flex items-center">
<img <img
alt="" alt=""
@ -165,7 +152,7 @@ const PositionsTable = () => {
<div>{marketConfig.name}</div> <div>{marketConfig.name}</div>
</div> </div>
</Td> </Td>
<Td className="px-2 py-2 whitespace-nowrap text-sm text-th-fgd-1"> <Td>
{!perpAccount.basePosition.eq(ZERO_BN) ? ( {!perpAccount.basePosition.eq(ZERO_BN) ? (
<SideBadge <SideBadge
side={ side={
@ -178,7 +165,7 @@ const PositionsTable = () => {
'-' '-'
)} )}
</Td> </Td>
<Td className="px-2 py-2 whitespace-nowrap text-sm text-th-fgd-1"> <Td>
{perpAccount && {perpAccount &&
Math.abs( Math.abs(
perpMarket.baseLotsToNumber( perpMarket.baseLotsToNumber(
@ -207,10 +194,7 @@ const PositionsTable = () => {
`0 ${marketConfig.baseSymbol}` `0 ${marketConfig.baseSymbol}`
)} )}
</Td> </Td>
<Th <Td>
scope="col"
className="px-2 py-2 text-left font-normal"
>
{usdFormatter( {usdFormatter(
Math.abs( Math.abs(
perpMarket.baseLotsToNumber( perpMarket.baseLotsToNumber(
@ -221,8 +205,8 @@ const PositionsTable = () => {
.toNumber() .toNumber()
) )
)} )}
</Th> </Td>
<Td className="px-2 py-2 whitespace-nowrap text-sm text-th-fgd-1"> <Td>
{getAvgEntryPrice( {getAvgEntryPrice(
mangoAccount, mangoAccount,
perpAccount, perpAccount,
@ -230,7 +214,7 @@ const PositionsTable = () => {
perpTradeHistory perpTradeHistory
)} )}
</Td> </Td>
<Td className="px-2 py-2 whitespace-nowrap text-sm text-th-fgd-1"> <Td>
{getBreakEvenPrice( {getBreakEvenPrice(
mangoAccount, mangoAccount,
perpAccount, perpAccount,
@ -238,12 +222,20 @@ const PositionsTable = () => {
perpTradeHistory perpTradeHistory
)} )}
</Td> </Td>
<Td <Td>
className={`px-2 py-2 whitespace-nowrap text-sm text-th-fgd-1 ${ {pnl !== null ? (
pnl >= 0 ? 'text-th-green' : 'text-th-red' pnl > 0 ? (
}`} <span className="text-th-green">
> {usdFormatter(pnl)}
{pnl !== null ? usdFormatter(pnl) : '--'} </span>
) : (
<span className="text-th-red">
{usdFormatter(pnl)}
</span>
)
) : (
'--'
)}
</Td> </Td>
{showMarketCloseModal ? ( {showMarketCloseModal ? (
<MarketCloseModal <MarketCloseModal
@ -253,12 +245,157 @@ const PositionsTable = () => {
marketIndex={marketIndex} marketIndex={marketIndex}
/> />
) : null} ) : null}
</Tr> </TrBody>
) )
})} })}
</Tbody> </tbody>
</Table> </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 <div
className={`w-full text-center py-6 bg-th-bkg-1 text-th-fgd-3 rounded-md`} className={`w-full text-center py-6 bg-th-bkg-1 text-th-fgd-3 rounded-md`}