Merge pull request #345 from blockworks-foundation/saml33/spot-market-trade-fixes

fix spot market trade form
This commit is contained in:
saml33 2023-12-09 22:08:19 +11:00 committed by GitHub
commit ff34ee757e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 82 additions and 51 deletions

View File

@ -2,6 +2,8 @@ import useMangoAccount from 'hooks/useMangoAccount'
import LeverageSlider from '../shared/LeverageSlider'
import { TokenMaxResults } from './useTokenMax'
import mangoStore from '@store/mangoStore'
import { useMemo } from 'react'
import { floorToDecimal } from 'utils/numbers'
const SwapSlider = ({
amount,
@ -24,6 +26,13 @@ const SwapSlider = ({
const { amount: tokenMax, amountWithBorrow } = maxAmount(useMargin)
const { inputBank } = mangoStore((s) => s.swap)
const max = useMemo(() => {
if (!inputBank) return 0
return useMargin
? floorToDecimal(amountWithBorrow, inputBank.mintDecimals).toNumber()
: floorToDecimal(tokenMax, inputBank.mintDecimals).toNumber()
}, [tokenMax, amountWithBorrow, inputBank, useMargin])
return (
<>
{!mangoAccount ? (
@ -39,9 +48,7 @@ const SwapSlider = ({
<LeverageSlider
amount={amount}
decimals={inputBank?.mintDecimals}
leverageMax={
useMargin ? amountWithBorrow.toNumber() : tokenMax.toNumber()
}
leverageMax={max}
onChange={onChange}
step={step}
handleStartDrag={handleStartDrag}

View File

@ -49,6 +49,7 @@ import SheenLoader from '@components/shared/SheenLoader'
import { fetchJupiterTransaction } from '@components/swap/SwapReviewRouteInfo'
import MaxMarketTradeAmount from './MaxMarketTradeAmount'
import useMangoAccount from 'hooks/useMangoAccount'
import InlineNotification from '@components/shared/InlineNotification'
const set = mangoStore.getState().set
@ -73,31 +74,53 @@ export default function SpotMarketOrderSwapForm() {
const [savedCheckboxSettings, setSavedCheckboxSettings] =
useLocalStorageState(TRADE_CHECKBOXES_KEY, DEFAULT_CHECKBOX_SETTINGS)
const {
selectedMarket,
price: oraclePrice,
baseLogoURI,
baseSymbol,
quoteLogoURI,
quoteSymbol,
selectedMarket,
serumOrPerpMarket,
} = useSelectedMarket()
const { amount: tokenMax, amountWithBorrow } = useTokenMax(
savedCheckboxSettings.margin,
)
const [inputBank, outputBank] = useMemo(() => {
const group = mangoStore.getState().group
if (!group || !(selectedMarket instanceof Serum3Market)) return []
const quoteBank = group?.getFirstBankByTokenIndex(
selectedMarket.quoteTokenIndex,
)
const baseBank = group.getFirstBankByTokenIndex(
selectedMarket.baseTokenIndex,
)
if (side === 'buy') {
set((s) => {
s.swap.inputBank = quoteBank
s.swap.outputBank = baseBank
})
return [quoteBank, baseBank]
} else {
set((s) => {
s.swap.inputBank = baseBank
s.swap.outputBank = quoteBank
})
return [baseBank, quoteBank]
}
}, [selectedMarket, side])
const handleBaseSizeChange = useCallback(
(e: NumberFormatValues, info: SourceInfo) => {
if (info.source !== 'event') return
console.log(e.value)
set((s) => {
const price =
s.tradeForm.tradeType === 'Market'
? oraclePrice
: Number(s.tradeForm.price)
s.tradeForm.baseSize = e.value
if (price && e.value !== '' && !Number.isNaN(Number(e.value))) {
s.tradeForm.quoteSize = new Decimal(price).mul(e.value).toFixed()
if (oraclePrice && e.value !== '' && !Number.isNaN(Number(e.value))) {
s.tradeForm.quoteSize = new Decimal(oraclePrice)
.mul(e.value)
.toFixed()
} else {
s.tradeForm.quoteSize = ''
}
@ -110,14 +133,9 @@ export default function SpotMarketOrderSwapForm() {
(e: NumberFormatValues, info: SourceInfo) => {
if (info.source !== 'event') return
set((s) => {
const price =
s.tradeForm.tradeType === 'Market'
? oraclePrice
: Number(s.tradeForm.price)
s.tradeForm.quoteSize = e.value
if (price && e.value !== '' && !Number.isNaN(Number(e.value))) {
s.tradeForm.baseSize = new Decimal(e.value).div(price).toFixed()
if (oraclePrice && e.value !== '' && !Number.isNaN(Number(e.value))) {
s.tradeForm.baseSize = new Decimal(e.value).div(oraclePrice).toFixed()
} else {
s.tradeForm.baseSize = ''
}
@ -187,39 +205,20 @@ export default function SpotMarketOrderSwapForm() {
[side, handleBaseSizeChange, handleQuoteSizeChange],
)
const [inputBank, outputBank] = useMemo(() => {
const group = mangoStore.getState().group
if (!group || !(selectedMarket instanceof Serum3Market)) return []
const quoteBank = group?.getFirstBankByTokenIndex(
selectedMarket.quoteTokenIndex,
)
const baseBank = group.getFirstBankByTokenIndex(
selectedMarket.baseTokenIndex,
)
if (side === 'buy') {
set((s) => {
s.swap.inputBank = quoteBank
s.swap.outputBank = baseBank
})
return [quoteBank, baseBank]
} else {
set((s) => {
s.swap.inputBank = baseBank
s.swap.outputBank = quoteBank
})
return [baseBank, quoteBank]
}
}, [selectedMarket, side])
const slippage = mangoStore.getState().swap.slippage
const jupiterQuoteAmount = side === 'buy' ? quoteSize : baseSize
const roundedQuoteAmount = useMemo(() => {
if (!jupiterQuoteAmount) return ''
return new Decimal(jupiterQuoteAmount)
.toDecimalPlaces(inputBank?.mintDecimals || 6, Decimal.ROUND_FLOOR)
.toFixed()
}, [jupiterQuoteAmount, inputBank])
const { bestRoute: selectedRoute, isInitialLoading: loadingRoute } =
useQuoteRoutes({
inputMint: inputBank?.mint.toString() || '',
outputMint: outputBank?.mint.toString() || '',
amount: jupiterQuoteAmount,
amount: roundedQuoteAmount,
slippage,
swapMode: 'ExactIn',
wallet: publicKey?.toBase58(),
@ -403,11 +402,21 @@ export default function SpotMarketOrderSwapForm() {
savedCheckboxSettings.margin,
])
const quoteError =
!!selectedRoute?.error ||
!!(
!selectedRoute &&
!loadingRoute &&
!isDraggingSlider &&
jupiterQuoteAmount
)
const disabled =
(connected && (!baseSize || !oraclePrice)) ||
!serumOrPerpMarket ||
loadingRoute ||
tooMuchSize
tooMuchSize ||
quoteError
return (
<>
@ -589,6 +598,14 @@ export default function SpotMarketOrderSwapForm() {
</Button>
)}
</div>
{quoteError ? (
<div className="mb-4">
<InlineNotification
type="error"
desc={t('trade:error-no-route')}
/>
</div>
) : null}
<div className="space-y-2">
<div className="flex justify-between text-xs">
<p>{t('trade:order-value')}</p>
@ -625,15 +642,15 @@ export default function SpotMarketOrderSwapForm() {
</SheenLoader>
) : (
<p className="text-right font-mono text-th-fgd-2">
{selectedRoute
? selectedRoute?.priceImpactPct * 100 < 0.1
{selectedRoute?.priceImpactPct
? selectedRoute.priceImpactPct * 100 < 0.1
? '<0.1%'
: `${(selectedRoute?.priceImpactPct * 100).toFixed(2)}%`
: '-'}
: ''}
</p>
)}
</div>
{borrowAmount && inputBank ? (
{borrowAmount && inputBank && savedCheckboxSettings.margin ? (
<>
<div className="flex justify-between text-xs">
<Tooltip
@ -705,6 +722,8 @@ export default function SpotMarketOrderSwapForm() {
<SheenLoader>
<div className="h-3.5 w-20 bg-th-bkg-2" />
</SheenLoader>
) : !selectedRoute || selectedRoute?.error ? (
<span className="text-th-fgd-2"></span>
) : (
<div className="flex items-center overflow-hidden text-th-fgd-2">
<Tooltip

View File

@ -25,6 +25,7 @@
"depth": "Depth",
"edit-order": "Edit Order",
"error-no-long": "No long position to reduce",
"error-no-route": "No route found. Try adjusting your size",
"error-no-short": "No borrow position to reduce",
"error-perp-positions-full": "You've used all of your available perp market account slots. Close unused slots to trade this market or open a new account.",
"error-serum-positions-full": "You've used all of your available spot market account slots. Close unused slots to trade this market or open a new account.",

View File

@ -25,6 +25,7 @@
"depth": "Depth",
"edit-order": "Edit Order",
"error-no-long": "No long position to reduce",
"error-no-route": "No route found. Try adjusting your size",
"error-no-short": "No borrow position to reduce",
"error-perp-positions-full": "You've used all of your available perp market account slots. Close unused slots to trade this market or open a new account.",
"error-serum-positions-full": "You've used all of your available spot market account slots. Close unused slots to trade this market or open a new account.",

View File

@ -25,6 +25,7 @@
"depth": "Depth",
"edit-order": "Edit Order",
"error-no-long": "No long position to reduce",
"error-no-route": "No route found. Try adjusting your size",
"error-no-short": "No borrow position to reduce",
"error-perp-positions-full": "You've used all of your available perp market account slots. Close unused slots to trade this market or open a new account.",
"error-serum-positions-full": "You've used all of your available spot market account slots. Close unused slots to trade this market or open a new account.",

View File

@ -25,6 +25,7 @@
"depth": "深度",
"edit-order": "编辑订单",
"error-no-long": "无做多持仓可减少",
"error-no-route": "No route found. Try adjusting your size",
"error-no-short": "无做空持仓可减少",
"error-trigger-above": "触发价格必须高于预言机价格",
"error-trigger-below": "触发价格必须低于预言机价格",

View File

@ -25,6 +25,7 @@
"depth": "深度",
"edit-order": "編輯訂單",
"error-no-long": "無做多持倉可減少",
"error-no-route": "No route found. Try adjusting your size",
"error-no-short": "無做空持倉可減少",
"error-trigger-above": "觸發價格必須高於預言機價格",
"error-trigger-below": "觸發價格必須低於預言機價格",