pre-fill spot balance (#41)

* pre-fill spot balance

* fix undefined basePosition
This commit is contained in:
saml33 2021-10-03 13:01:06 +11:00 committed by GitHub
parent 6925a46df8
commit f5f243a9a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 174 additions and 47 deletions

View File

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

View File

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

View File

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

View File

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