utilize zustand for perppositions

This commit is contained in:
Tyler Shipe 2022-01-27 22:57:18 -05:00
parent 8f27393c22
commit a6d432f32d
9 changed files with 114 additions and 71 deletions

View File

@ -132,6 +132,7 @@ const BalancesTable = ({
}
} finally {
actions.reloadOrders()
// actions.reloadMangoAccount()
setSubmitting(false)
}
}

View File

@ -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)

View File

@ -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 (

View File

@ -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>

View File

@ -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 ? (

View File

@ -61,7 +61,7 @@ const useHydrateStore = () => {
if (mangoAccount) {
actions.reloadOrders()
}
}, 30 * SECONDS)
}, 20 * SECONDS)
useInterval(() => {
if (mangoAccount) {

View File

@ -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

View File

@ -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">

View File

@ -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',