utilize zustand for perppositions
This commit is contained in:
parent
8f27393c22
commit
a6d432f32d
|
@ -132,6 +132,7 @@ const BalancesTable = ({
|
|||
}
|
||||
} finally {
|
||||
actions.reloadOrders()
|
||||
// actions.reloadMangoAccount()
|
||||
setSubmitting(false)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import {
|
|||
ZERO_BN,
|
||||
ZERO_I80F48,
|
||||
} from '@blockworks-foundation/mango-client'
|
||||
import usePerpPositions from '../hooks/usePerpPositions'
|
||||
import { formatUsdValue } from '../utils'
|
||||
|
||||
interface CloseAccountModalProps {
|
||||
|
@ -40,7 +39,12 @@ const CloseAccountModal: FunctionComponent<CloseAccountModalProps> = ({
|
|||
const mangoGroup = useMangoStore((s) => s.selectedMangoGroup.current)
|
||||
const mangoAccount = useMangoStore((s) => s.selectedMangoAccount.current)
|
||||
const mangoCache = useMangoStore((s) => s.selectedMangoGroup.cache)
|
||||
const { openPositions, unsettledPositions } = usePerpPositions()
|
||||
const openPositions = useMangoStore(
|
||||
(s) => s.selectedMangoAccount.openPerpPositions
|
||||
)
|
||||
const unsettledPositions = useMangoStore(
|
||||
(s) => s.selectedMangoAccount.unsettledPerpPositions
|
||||
)
|
||||
const [hasBorrows, setHasBorrows] = useState(false)
|
||||
const [hasOpenPositions, setHasOpenPositions] = useState(false)
|
||||
const [totalAccountSOL, setTotalAccountSOL] = useState(0)
|
||||
|
|
|
@ -12,14 +12,12 @@ import {
|
|||
PerpMarket,
|
||||
QUOTE_INDEX,
|
||||
} from '@blockworks-foundation/mango-client'
|
||||
import useTradeHistory from '../hooks/useTradeHistory'
|
||||
import { notify } from '../utils/notifications'
|
||||
import MarketCloseModal from './MarketCloseModal'
|
||||
import PnlText from './PnlText'
|
||||
import Loading from './Loading'
|
||||
import { useViewport } from '../hooks/useViewport'
|
||||
import { breakpoints } from './TradePageGrid'
|
||||
import { collectPerpPosition } from '../hooks/usePerpPositions'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import useMangoAccount from '../hooks/useMangoAccount'
|
||||
|
||||
|
@ -76,9 +74,10 @@ export default function MarketPosition() {
|
|||
const connected = useMangoStore((s) => s.wallet.connected)
|
||||
const setMangoStore = useMangoStore((s) => s.set)
|
||||
const price = useMangoStore((s) => s.tradeForm.price)
|
||||
const perpAccounts =
|
||||
useMangoStore.getState().selectedMangoAccount.perpAccounts
|
||||
const baseSymbol = marketConfig.baseSymbol
|
||||
const marketName = marketConfig.name
|
||||
const tradeHistory = useTradeHistory()
|
||||
|
||||
const [showMarketCloseModal, setShowMarketCloseModal] = useState(false)
|
||||
const [settling, setSettling] = useState(false)
|
||||
|
@ -124,19 +123,16 @@ export default function MarketPosition() {
|
|||
return null
|
||||
|
||||
const {
|
||||
basePosition,
|
||||
avgEntryPrice,
|
||||
breakEvenPrice,
|
||||
notionalSize,
|
||||
unsettledPnl,
|
||||
} = collectPerpPosition(
|
||||
mangoAccount,
|
||||
mangoGroup,
|
||||
mangoCache,
|
||||
marketConfig,
|
||||
selectedMarket,
|
||||
tradeHistory
|
||||
)
|
||||
basePosition = 0,
|
||||
avgEntryPrice = 0,
|
||||
breakEvenPrice = 0,
|
||||
notionalSize = 0,
|
||||
unsettledPnl = 0,
|
||||
} = perpAccounts.length
|
||||
? perpAccounts.find((pa) =>
|
||||
pa.perpMarket.publicKey.equals(selectedMarket.publicKey)
|
||||
)
|
||||
: {}
|
||||
|
||||
function SettlePnlTooltip() {
|
||||
return (
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
import { useCallback, useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import Link from 'next/link'
|
||||
import useMangoStore from '../stores/useMangoStore'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { ExclamationIcon } from '@heroicons/react/outline'
|
||||
|
||||
import useMangoStore from '../stores/useMangoStore'
|
||||
import Button from '../components/Button'
|
||||
import { useViewport } from '../hooks/useViewport'
|
||||
import { breakpoints } from './TradePageGrid'
|
||||
import { ExpandableRow, Table, Td, Th, TrBody, TrHead } from './TableElements'
|
||||
import { formatUsdValue } from '../utils'
|
||||
import Loading from './Loading'
|
||||
import usePerpPositions from '../hooks/usePerpPositions'
|
||||
import MarketCloseModal from './MarketCloseModal'
|
||||
import PerpSideBadge from './PerpSideBadge'
|
||||
import PnlText from './PnlText'
|
||||
import { settlePnl } from './MarketPosition'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import MobileTableHeader from './mobile/MobileTableHeader'
|
||||
|
||||
const PositionsTable = () => {
|
||||
|
@ -30,7 +30,11 @@ const PositionsTable = () => {
|
|||
const price = useMangoStore((s) => s.tradeForm.price)
|
||||
const [showMarketCloseModal, setShowMarketCloseModal] = useState(false)
|
||||
const setMangoStore = useMangoStore((s) => s.set)
|
||||
const { openPositions, unsettledPositions } = usePerpPositions()
|
||||
const openPositions = useMangoStore(
|
||||
(s) => s.selectedMangoAccount.openPerpPositions
|
||||
)
|
||||
const unsettledPositions =
|
||||
useMangoStore.getState().selectedMangoAccount.unsettledPerpPositions
|
||||
const { width } = useViewport()
|
||||
const isMobile = width ? width < breakpoints.md : false
|
||||
const { asPath } = useRouter()
|
||||
|
@ -120,7 +124,6 @@ const PositionsTable = () => {
|
|||
{openPositions.map(
|
||||
(
|
||||
{
|
||||
marketIndex,
|
||||
marketConfig,
|
||||
perpMarket,
|
||||
perpAccount,
|
||||
|
@ -134,7 +137,10 @@ const PositionsTable = () => {
|
|||
index
|
||||
) => {
|
||||
return (
|
||||
<TrBody index={index} key={`${marketIndex}`}>
|
||||
<TrBody
|
||||
index={index}
|
||||
key={`${marketConfig.marketIndex}`}
|
||||
>
|
||||
<Td>
|
||||
<div className="flex items-center">
|
||||
<img
|
||||
|
@ -215,7 +221,7 @@ const PositionsTable = () => {
|
|||
isOpen={showMarketCloseModal}
|
||||
onClose={handleCloseWarning}
|
||||
market={perpMarket}
|
||||
marketIndex={marketIndex}
|
||||
marketIndex={marketConfig.marketIndex}
|
||||
/>
|
||||
) : null}
|
||||
</TrBody>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import useMangoStore from '../stores/useMangoStore'
|
||||
import usePerpPositions from '../hooks/usePerpPositions'
|
||||
import OpenOrdersTable from './OpenOrdersTable'
|
||||
import BalancesTable from './BalancesTable'
|
||||
import PositionsTable from './PerpPositionsTable'
|
||||
|
@ -8,7 +7,6 @@ import TradeHistoryTable from './TradeHistoryTable'
|
|||
import ManualRefresh from './ManualRefresh'
|
||||
import Tabs from './Tabs'
|
||||
import FeeDiscountsTable from './FeeDiscountsTable'
|
||||
import useMangoAccount from '../hooks/useMangoAccount'
|
||||
import { marketConfigSelector } from '../stores/selectors'
|
||||
|
||||
const TABS = [
|
||||
|
@ -23,8 +21,10 @@ const UserInfoTabs = ({ activeTab, setActiveTab }) => {
|
|||
const totalOpenOrders = useMangoStore(
|
||||
(s) => s.selectedMangoAccount.totalOpenOrders
|
||||
)
|
||||
const { openPositions } = usePerpPositions()
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const totalOpenPerpPositions = useMangoStore(
|
||||
(s) => s.selectedMangoAccount.totalOpenPerpPositions
|
||||
)
|
||||
const mangoAccount = useMangoStore((s) => s.selectedMangoAccount.current)
|
||||
|
||||
const handleTabChange = (tabName) => {
|
||||
setActiveTab(tabName)
|
||||
|
@ -35,14 +35,10 @@ const UserInfoTabs = ({ activeTab, setActiveTab }) => {
|
|||
<Tabs
|
||||
activeTab={activeTab}
|
||||
onChange={handleTabChange}
|
||||
showCount={
|
||||
totalOpenOrders > 0 && openPositions
|
||||
? [
|
||||
{ tabName: 'Orders', count: totalOpenOrders },
|
||||
{ tabName: 'Positions', count: openPositions.length },
|
||||
]
|
||||
: null
|
||||
}
|
||||
showCount={[
|
||||
{ tabName: 'Orders', count: totalOpenOrders },
|
||||
{ tabName: 'Positions', count: totalOpenPerpPositions },
|
||||
]}
|
||||
tabs={TABS}
|
||||
/>
|
||||
{mangoAccount ? (
|
||||
|
|
|
@ -61,7 +61,7 @@ const useHydrateStore = () => {
|
|||
if (mangoAccount) {
|
||||
actions.reloadOrders()
|
||||
}
|
||||
}, 30 * SECONDS)
|
||||
}, 20 * SECONDS)
|
||||
|
||||
useInterval(() => {
|
||||
if (mangoAccount) {
|
||||
|
|
|
@ -9,13 +9,14 @@ import {
|
|||
PerpMarketConfig,
|
||||
} from '@blockworks-foundation/mango-client'
|
||||
import useTradeHistory from './useTradeHistory'
|
||||
import useMangoAccount from './useMangoAccount'
|
||||
import {
|
||||
mangoCacheSelector,
|
||||
mangoGroupConfigSelector,
|
||||
mangoGroupSelector,
|
||||
marketsSelector,
|
||||
} from '../stores/selectors'
|
||||
import { useEffect } from 'react'
|
||||
import useMangoAccount from './useMangoAccount'
|
||||
|
||||
export const collectPerpPosition = (
|
||||
mangoAccount: MangoAccount,
|
||||
|
@ -34,9 +35,8 @@ export const collectPerpPosition = (
|
|||
)
|
||||
return {}
|
||||
|
||||
const marketIndex = marketConfig.marketIndex
|
||||
const perpMarketInfo = mangoGroup.perpMarkets[marketIndex]
|
||||
const perpAccount = mangoAccount.perpAccounts[marketIndex]
|
||||
const perpMarketInfo = mangoGroup.perpMarkets[marketConfig.marketIndex]
|
||||
const perpAccount = mangoAccount.perpAccounts[marketConfig.marketIndex]
|
||||
|
||||
let avgEntryPrice = 0,
|
||||
breakEvenPrice = 0
|
||||
|
@ -52,24 +52,25 @@ export const collectPerpPosition = (
|
|||
.getBreakEvenPrice(mangoAccount, perpMarket, perpTradeHistory)
|
||||
.toNumber()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
// console.error(e)
|
||||
}
|
||||
|
||||
const basePosition = perpMarket?.baseLotsToNumber(perpAccount.basePosition)
|
||||
const indexPrice = mangoGroup.getPrice(marketIndex, mangoCache).toNumber()
|
||||
const indexPrice = mangoGroup
|
||||
.getPrice(marketConfig.marketIndex, mangoCache)
|
||||
.toNumber()
|
||||
const notionalSize = Math.abs(basePosition * indexPrice)
|
||||
const unrealizedPnl = basePosition * (indexPrice - breakEvenPrice)
|
||||
const unsettledPnl = +nativeI80F48ToUi(
|
||||
perpAccount.getPnl(
|
||||
mangoGroup.perpMarkets[marketIndex],
|
||||
mangoCache.perpMarketCache[marketIndex],
|
||||
mangoCache.priceCache[marketIndex].price
|
||||
perpMarketInfo,
|
||||
mangoCache.perpMarketCache[marketConfig.marketIndex],
|
||||
mangoCache.priceCache[marketConfig.marketIndex].price
|
||||
),
|
||||
marketConfig.quoteDecimals
|
||||
).toNumber()
|
||||
|
||||
return {
|
||||
marketIndex,
|
||||
perpMarketInfo,
|
||||
marketConfig,
|
||||
perpMarket,
|
||||
|
@ -85,6 +86,7 @@ export const collectPerpPosition = (
|
|||
}
|
||||
|
||||
const usePerpPositions = () => {
|
||||
const setMangoStore = useMangoStore((s) => s.set)
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const groupConfig = useMangoStore(mangoGroupConfigSelector)
|
||||
const mangoGroup = useMangoStore(mangoGroupSelector)
|
||||
|
@ -92,29 +94,43 @@ const usePerpPositions = () => {
|
|||
const allMarkets = useMangoStore(marketsSelector)
|
||||
const tradeHistory = useTradeHistory()
|
||||
|
||||
const perpAccounts = mangoAccount
|
||||
? groupConfig.perpMarkets.map((m) =>
|
||||
collectPerpPosition(
|
||||
mangoAccount,
|
||||
mangoGroup,
|
||||
mangoCache,
|
||||
m,
|
||||
allMarkets[m.publicKey.toBase58()] as PerpMarket,
|
||||
tradeHistory
|
||||
)
|
||||
useEffect(() => {
|
||||
if (mangoAccount) {
|
||||
const perpAccounts = mangoAccount
|
||||
? groupConfig.perpMarkets.map((m) =>
|
||||
collectPerpPosition(
|
||||
mangoAccount,
|
||||
mangoGroup,
|
||||
mangoCache,
|
||||
m,
|
||||
allMarkets[m.publicKey.toBase58()] as PerpMarket,
|
||||
tradeHistory
|
||||
)
|
||||
)
|
||||
: []
|
||||
|
||||
const openPerpPositions = perpAccounts.filter(
|
||||
({ perpAccount }) =>
|
||||
perpAccount?.basePosition && !perpAccount.basePosition.eq(new BN(0))
|
||||
)
|
||||
: []
|
||||
|
||||
const openPositions = perpAccounts.filter(
|
||||
({ perpAccount }) =>
|
||||
perpAccount?.basePosition && !perpAccount.basePosition.eq(new BN(0))
|
||||
)
|
||||
const unsettledPositions = perpAccounts.filter(
|
||||
({ perpAccount, unsettledPnl }) =>
|
||||
perpAccount?.basePosition?.eq(new BN(0)) && unsettledPnl != 0
|
||||
)
|
||||
|
||||
return { openPositions, unsettledPositions }
|
||||
setMangoStore((state) => {
|
||||
state.selectedMangoAccount.perpAccounts = perpAccounts
|
||||
state.selectedMangoAccount.openPerpPositions = openPerpPositions
|
||||
if (
|
||||
openPerpPositions.length !==
|
||||
state.selectedMangoAccount.totalOpenPerpPositions
|
||||
) {
|
||||
state.selectedMangoAccount.totalOpenPerpPositions =
|
||||
openPerpPositions.length
|
||||
}
|
||||
state.selectedMangoAccount.unsettledPerpPositions = perpAccounts.filter(
|
||||
({ perpAccount, unsettledPnl }) =>
|
||||
perpAccount?.basePosition?.eq(new BN(0)) && unsettledPnl != 0
|
||||
)
|
||||
})
|
||||
}
|
||||
}, [mangoAccount, mangoCache])
|
||||
}
|
||||
|
||||
export default usePerpPositions
|
||||
|
|
|
@ -17,12 +17,25 @@ import { appWithTranslation } from 'next-i18next'
|
|||
import ErrorBoundary from '../components/ErrorBoundary'
|
||||
import GlobalNotification from '../components/GlobalNotification'
|
||||
import { useOpenOrders } from '../hooks/useOpenOrders'
|
||||
import usePerpPositions from '../hooks/usePerpPositions'
|
||||
|
||||
const MangoStoreUpdater = () => {
|
||||
useHydrateStore()
|
||||
useWallet()
|
||||
useOpenOrders()
|
||||
return null
|
||||
}
|
||||
|
||||
const WalletStoreUpdater = () => {
|
||||
useWallet()
|
||||
return null
|
||||
}
|
||||
|
||||
const OpenOrdersStoreUpdater = () => {
|
||||
useOpenOrders()
|
||||
return null
|
||||
}
|
||||
|
||||
const PerpPositionsStoreUpdater = () => {
|
||||
usePerpPositions()
|
||||
return null
|
||||
}
|
||||
|
||||
|
@ -93,6 +106,9 @@ function App({ Component, pageProps }) {
|
|||
<ErrorBoundary>
|
||||
<PageTitle />
|
||||
<MangoStoreUpdater />
|
||||
<WalletStoreUpdater />
|
||||
<OpenOrdersStoreUpdater />
|
||||
<PerpPositionsStoreUpdater />
|
||||
</ErrorBoundary>
|
||||
|
||||
<ThemeProvider defaultTheme="Mango">
|
||||
|
|
|
@ -167,6 +167,10 @@ interface MangoStore extends State {
|
|||
lastSlot: number
|
||||
openOrders: any[]
|
||||
totalOpenOrders: number
|
||||
perpAccounts: any[]
|
||||
openPerpPositions: any[]
|
||||
totalOpenPerpPositions: number
|
||||
unsettledPerpPositions: any[]
|
||||
}
|
||||
tradeForm: {
|
||||
side: 'buy' | 'sell'
|
||||
|
@ -274,6 +278,10 @@ const useMangoStore = create<MangoStore>((set, get) => {
|
|||
lastSlot: 0,
|
||||
openOrders: [],
|
||||
totalOpenOrders: 0,
|
||||
perpAccounts: [],
|
||||
openPerpPositions: [],
|
||||
totalOpenPerpPositions: 0,
|
||||
unsettledPerpPositions: [],
|
||||
},
|
||||
tradeForm: {
|
||||
side: 'buy',
|
||||
|
|
Loading…
Reference in New Issue