pre-fill spot balance (#41)
* pre-fill spot balance * fix undefined basePosition
This commit is contained in:
parent
6925a46df8
commit
f5f243a9a8
|
@ -5,7 +5,10 @@ import Button, { LinkButton } from '../components/Button'
|
|||
import { notify } from '../utils/notifications'
|
||||
import { ArrowSmDownIcon, ExclamationIcon } from '@heroicons/react/outline'
|
||||
import { Market } from '@project-serum/serum'
|
||||
import { getTokenBySymbol } from '@blockworks-foundation/mango-client'
|
||||
import {
|
||||
getMarketIndexBySymbol,
|
||||
getTokenBySymbol,
|
||||
} from '@blockworks-foundation/mango-client'
|
||||
import { useState } from 'react'
|
||||
import Loading from './Loading'
|
||||
import { useViewport } from '../hooks/useViewport'
|
||||
|
@ -39,10 +42,42 @@ const BalancesTable = ({ showZeroBalances = false }) => {
|
|||
const mangoGroup = useMangoStore((s) => s.selectedMangoGroup.current)
|
||||
const mangoGroupConfig = useMangoStore((s) => s.selectedMangoGroup.config)
|
||||
const mangoClient = useMangoStore((s) => s.connection.client)
|
||||
const selectedMarket = useMangoStore((s) => s.selectedMarket.current)
|
||||
const marketConfig = useMangoStore((s) => s.selectedMarket.config)
|
||||
const setMangoStore = useMangoStore((s) => s.set)
|
||||
const price = useMangoStore((s) => s.tradeForm.price)
|
||||
const mangoGroupCache = useMangoStore((s) => s.selectedMangoGroup.cache)
|
||||
const { width } = useViewport()
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const isMobile = width ? width < breakpoints.md : false
|
||||
|
||||
const handleSizeClick = (size, symbol) => {
|
||||
const step = selectedMarket.minOrderSize
|
||||
const marketIndex = getMarketIndexBySymbol(
|
||||
mangoGroupConfig,
|
||||
marketConfig.baseSymbol
|
||||
)
|
||||
const priceOrDefault = price
|
||||
? price
|
||||
: mangoGroup.getPrice(marketIndex, mangoGroupCache).toNumber()
|
||||
if (symbol === 'USDC') {
|
||||
const baseSize = Math.floor(size / priceOrDefault / step) * step
|
||||
setMangoStore((state) => {
|
||||
state.tradeForm.baseSize = baseSize
|
||||
state.tradeForm.quoteSize = (baseSize * priceOrDefault).toFixed(2)
|
||||
state.tradeForm.side = 'buy'
|
||||
})
|
||||
} else {
|
||||
const roundedSize = Math.round(size / step) * step
|
||||
const quoteSize = roundedSize * priceOrDefault
|
||||
setMangoStore((state) => {
|
||||
state.tradeForm.baseSize = roundedSize
|
||||
state.tradeForm.quoteSize = quoteSize.toFixed(2)
|
||||
state.tradeForm.side = 'sell'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleOpenDepositModal = useCallback((symbol) => {
|
||||
setActionSymbol(symbol)
|
||||
setShowDepositModal(true)
|
||||
|
@ -312,7 +347,26 @@ const BalancesTable = ({ showZeroBalances = false }) => {
|
|||
<Td>{balance.borrows.toFixed()}</Td>
|
||||
<Td>{balance.orders}</Td>
|
||||
<Td>{balance.unsettled}</Td>
|
||||
<Td>{balance.net.toFixed()}</Td>
|
||||
<Td>
|
||||
{marketConfig.kind === 'spot' &&
|
||||
marketConfig.name.includes(balance.symbol) &&
|
||||
selectedMarket ? (
|
||||
<span
|
||||
className={
|
||||
balance.net.toNumber() > 0
|
||||
? 'cursor-pointer underline hover:no-underline'
|
||||
: ''
|
||||
}
|
||||
onClick={() =>
|
||||
handleSizeClick(balance.net, balance.symbol)
|
||||
}
|
||||
>
|
||||
{balance.net.toFixed()}
|
||||
</span>
|
||||
) : (
|
||||
balance.net.toFixed()
|
||||
)}
|
||||
</Td>
|
||||
<Td>{formatUsdValue(balance.value)}</Td>
|
||||
<Td>
|
||||
<span className="text-th-green">
|
||||
|
|
|
@ -3,7 +3,7 @@ import useMangoStore from '../stores/useMangoStore'
|
|||
import { i80f48ToPercent, floorToDecimal } from '../utils/index'
|
||||
import Tooltip from './Tooltip'
|
||||
import {
|
||||
getTokenBySymbol,
|
||||
getMarketIndexBySymbol,
|
||||
nativeI80F48ToUi,
|
||||
} from '@blockworks-foundation/mango-client'
|
||||
import { useViewport } from '../hooks/useViewport'
|
||||
|
@ -16,12 +16,41 @@ export default function MarketBalances() {
|
|||
const mangoAccount = useMangoStore((s) => s.selectedMangoAccount.current)
|
||||
const selectedMarket = useMangoStore((s) => s.selectedMarket.current)
|
||||
const marketConfig = useMangoStore((s) => s.selectedMarket.config)
|
||||
const setMangoStore = useMangoStore((s) => s.set)
|
||||
const price = useMangoStore((s) => s.tradeForm.price)
|
||||
const connected = useMangoStore((s) => s.wallet.connected)
|
||||
const isLoading = useMangoStore((s) => s.selectedMangoAccount.initialLoad)
|
||||
const baseSymbol = marketConfig.baseSymbol
|
||||
const { width } = useViewport()
|
||||
const isMobile = width ? width < breakpoints.sm : false
|
||||
|
||||
const handleSizeClick = (size, symbol) => {
|
||||
const step = selectedMarket.minOrderSize
|
||||
const marketIndex = getMarketIndexBySymbol(
|
||||
mangoGroupConfig,
|
||||
marketConfig.baseSymbol
|
||||
)
|
||||
const priceOrDefault = price
|
||||
? price
|
||||
: mangoGroup.getPrice(marketIndex, mangoGroupCache).toNumber()
|
||||
if (symbol === 'USDC') {
|
||||
const baseSize = Math.floor(size / priceOrDefault / step) * step
|
||||
setMangoStore((state) => {
|
||||
state.tradeForm.baseSize = baseSize
|
||||
state.tradeForm.quoteSize = (baseSize * priceOrDefault).toFixed(2)
|
||||
state.tradeForm.side = 'buy'
|
||||
})
|
||||
} else {
|
||||
const roundedSize = Math.round(size / step) * step
|
||||
const quoteSize = roundedSize * priceOrDefault
|
||||
setMangoStore((state) => {
|
||||
state.tradeForm.baseSize = roundedSize
|
||||
state.tradeForm.quoteSize = quoteSize.toFixed(2)
|
||||
state.tradeForm.side = 'sell'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (!mangoGroup || !selectedMarket) return null
|
||||
|
||||
return (
|
||||
|
@ -32,7 +61,7 @@ export default function MarketBalances() {
|
|||
{mangoGroupConfig.tokens
|
||||
.filter((t) => t.symbol === baseSymbol || t.symbol === 'USDC')
|
||||
.reverse()
|
||||
.map(({ symbol, mintKey }) => {
|
||||
.map(({ decimals, symbol, mintKey }) => {
|
||||
const tokenIndex = mangoGroup.getTokenIndex(mintKey)
|
||||
const deposit = mangoAccount
|
||||
? mangoAccount.getUiDeposit(
|
||||
|
@ -48,6 +77,21 @@ export default function MarketBalances() {
|
|||
tokenIndex
|
||||
)
|
||||
: null
|
||||
|
||||
const availableBalance = mangoAccount
|
||||
? floorToDecimal(
|
||||
nativeI80F48ToUi(
|
||||
mangoAccount.getAvailableBalance(
|
||||
mangoGroup,
|
||||
mangoGroupCache,
|
||||
tokenIndex
|
||||
),
|
||||
decimals
|
||||
).toNumber(),
|
||||
decimals
|
||||
)
|
||||
: 0
|
||||
|
||||
return (
|
||||
<div
|
||||
className="border border-th-bkg-4 p-4 rounded-md"
|
||||
|
@ -87,21 +131,18 @@ export default function MarketBalances() {
|
|||
Available Balance
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div className={`text-th-fgd-1`}>
|
||||
<div
|
||||
className={`text-th-fgd-1 ${
|
||||
availableBalance > selectedMarket.minOrderSize
|
||||
? 'cursor-pointer underline hover:no-underline'
|
||||
: ''
|
||||
}`}
|
||||
onClick={() => handleSizeClick(availableBalance, symbol)}
|
||||
>
|
||||
{isLoading ? (
|
||||
<DataLoader />
|
||||
) : mangoAccount ? (
|
||||
floorToDecimal(
|
||||
nativeI80F48ToUi(
|
||||
mangoAccount.getAvailableBalance(
|
||||
mangoGroup,
|
||||
mangoGroupCache,
|
||||
tokenIndex
|
||||
),
|
||||
mangoGroup.tokens[tokenIndex].decimals
|
||||
).toNumber(),
|
||||
getTokenBySymbol(mangoGroupConfig, symbol).decimals
|
||||
)
|
||||
availableBalance
|
||||
) : (
|
||||
0
|
||||
)}
|
||||
|
|
|
@ -84,6 +84,7 @@ export default function MarketPosition() {
|
|||
const connected = useMangoStore((s) => s.wallet.connected)
|
||||
const isLoading = useMangoStore((s) => s.selectedMangoAccount.initialLoad)
|
||||
const setMangoStore = useMangoStore((s) => s.set)
|
||||
const price = useMangoStore((s) => s.tradeForm.price)
|
||||
const baseSymbol = marketConfig.baseSymbol
|
||||
const marketName = marketConfig.name
|
||||
const tradeHistory = useTradeHistory()
|
||||
|
@ -109,9 +110,18 @@ export default function MarketPosition() {
|
|||
)
|
||||
}
|
||||
|
||||
const handleSizeClick = (size) => {
|
||||
const handleSizeClick = (size, side) => {
|
||||
const step = selectedMarket.minOrderSize
|
||||
|
||||
const priceOrDefault = price
|
||||
? price
|
||||
: mangoGroup.getPrice(marketIndex, mangoGroupCache).toNumber()
|
||||
const roundedSize = Math.round(size / step) * step
|
||||
const quoteSize = roundedSize * priceOrDefault
|
||||
setMangoStore((state) => {
|
||||
state.tradeForm.baseSize = size
|
||||
state.tradeForm.baseSize = roundedSize
|
||||
state.tradeForm.quoteSize = quoteSize.toFixed(2)
|
||||
state.tradeForm.side = side === 'buy' ? 'sell' : 'buy'
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -126,6 +136,12 @@ export default function MarketPosition() {
|
|||
})
|
||||
}
|
||||
|
||||
const side = perpAccount
|
||||
? perpAccount.basePosition.gt(ZERO_BN)
|
||||
? 'long'
|
||||
: 'short'
|
||||
: null
|
||||
|
||||
if (!mangoGroup || !selectedMarket) return null
|
||||
|
||||
return selectedMarket instanceof PerpMarket ? (
|
||||
|
@ -139,9 +155,7 @@ export default function MarketPosition() {
|
|||
{isLoading ? (
|
||||
<DataLoader />
|
||||
) : perpAccount && !perpAccount.basePosition.eq(ZERO_BN) ? (
|
||||
<SideBadge
|
||||
side={perpAccount.basePosition.gt(ZERO_BN) ? 'long' : 'short'}
|
||||
/>
|
||||
<SideBadge side={side} />
|
||||
) : (
|
||||
'--'
|
||||
)}
|
||||
|
@ -163,7 +177,8 @@ export default function MarketPosition() {
|
|||
handleSizeClick(
|
||||
Math.abs(
|
||||
selectedMarket.baseLotsToNumber(perpAccount.basePosition)
|
||||
)
|
||||
),
|
||||
side === 'long' ? 'buy' : 'sell'
|
||||
)
|
||||
}
|
||||
>
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { useCallback, useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import useMangoStore from '../stores/useMangoStore'
|
||||
import {
|
||||
getMarketByPublicKey,
|
||||
getMarketIndexBySymbol,
|
||||
PerpMarket,
|
||||
ZERO_BN,
|
||||
} from '@blockworks-foundation/mango-client'
|
||||
|
@ -67,20 +69,36 @@ const PositionsTable = () => {
|
|||
const mangoAccount = useMangoStore((s) => s.selectedMangoAccount.current)
|
||||
const mangoCache = useMangoStore((s) => s.selectedMangoGroup.cache)
|
||||
const allMarkets = useMangoStore((s) => s.selectedMangoGroup.markets)
|
||||
const selectedMarket = useMangoStore((s) => s.selectedMarket.current)
|
||||
const marketConfig = useMangoStore((s) => s.selectedMarket.config)
|
||||
const price = useMangoStore((s) => s.tradeForm.price)
|
||||
const [showMarketCloseModal, setShowMarketCloseModal] = useState(false)
|
||||
const tradeHistory = useTradeHistory()
|
||||
const setMangoStore = useMangoStore((s) => s.set)
|
||||
const perpPositions = usePerpPositions()
|
||||
const { width } = useViewport()
|
||||
const isMobile = width ? width < breakpoints.md : false
|
||||
const { asPath } = useRouter()
|
||||
|
||||
const handleCloseWarning = useCallback(() => {
|
||||
setShowMarketCloseModal(false)
|
||||
}, [])
|
||||
|
||||
const handleSizeClick = (size) => {
|
||||
const handleSizeClick = (size, side) => {
|
||||
const step = selectedMarket.minOrderSize
|
||||
const marketIndex = getMarketIndexBySymbol(
|
||||
groupConfig,
|
||||
marketConfig.baseSymbol
|
||||
)
|
||||
const priceOrDefault = price
|
||||
? price
|
||||
: mangoGroup.getPrice(marketIndex, mangoCache).toNumber()
|
||||
const roundedSize = Math.round(size / step) * step
|
||||
const quoteSize = roundedSize * priceOrDefault
|
||||
setMangoStore((state) => {
|
||||
state.tradeForm.baseSize = size
|
||||
state.tradeForm.baseSize = roundedSize
|
||||
state.tradeForm.quoteSize = quoteSize.toFixed(2)
|
||||
state.tradeForm.side = side === 'buy' ? 'sell' : 'buy'
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -137,6 +155,10 @@ const PositionsTable = () => {
|
|||
parseFloat(breakEvenPrice))
|
||||
: null
|
||||
|
||||
const basePosition = Math.abs(
|
||||
perpMarket.baseLotsToNumber(perpAccount.basePosition)
|
||||
)
|
||||
|
||||
return (
|
||||
<TrBody index={index} key={`${marketIndex}`}>
|
||||
<Td>
|
||||
|
@ -165,30 +187,25 @@ const PositionsTable = () => {
|
|||
)}
|
||||
</Td>
|
||||
<Td>
|
||||
{perpAccount &&
|
||||
Math.abs(
|
||||
perpMarket.baseLotsToNumber(
|
||||
perpAccount.basePosition
|
||||
)
|
||||
) > 0 ? (
|
||||
<span
|
||||
className="cursor-pointer underline hover:no-underline"
|
||||
onClick={() =>
|
||||
handleSizeClick(
|
||||
Math.abs(
|
||||
perpMarket.baseLotsToNumber(
|
||||
perpAccount.basePosition
|
||||
)
|
||||
{perpAccount && basePosition > 0 ? (
|
||||
marketConfig.kind === 'perp' &&
|
||||
asPath.includes(marketConfig.baseSymbol) ? (
|
||||
<span
|
||||
className="cursor-pointer underline hover:no-underline"
|
||||
onClick={() =>
|
||||
handleSizeClick(
|
||||
basePosition,
|
||||
perpAccount.basePosition.gt(ZERO_BN)
|
||||
? 'buy'
|
||||
: 'sell'
|
||||
)
|
||||
)
|
||||
}
|
||||
>
|
||||
{`${Math.abs(
|
||||
perpMarket.baseLotsToNumber(
|
||||
perpAccount.basePosition
|
||||
)
|
||||
)} ${marketConfig.baseSymbol}`}
|
||||
</span>
|
||||
}
|
||||
>
|
||||
{`${basePosition} ${marketConfig.baseSymbol}`}
|
||||
</span>
|
||||
) : (
|
||||
`${basePosition} ${marketConfig.baseSymbol}`
|
||||
)
|
||||
) : (
|
||||
`0 ${marketConfig.baseSymbol}`
|
||||
)}
|
||||
|
|
Loading…
Reference in New Issue