Merge pull request #345 from blockworks-foundation/saml33/spot-market-trade-fixes
fix spot market trade form
This commit is contained in:
commit
ff34ee757e
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.",
|
||||
|
|
|
@ -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.",
|
||||
|
|
|
@ -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.",
|
||||
|
|
|
@ -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": "触发价格必须低于预言机价格",
|
||||
|
|
|
@ -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": "觸發價格必須低於預言機價格",
|
||||
|
|
Loading…
Reference in New Issue