move leverage calculation to components
This commit is contained in:
parent
201a8ad62a
commit
ea2ef43b41
|
@ -33,14 +33,13 @@ import PerpButtonGroup from './PerpButtonGroup'
|
|||
import SolBalanceWarnings from '@components/shared/SolBalanceWarnings'
|
||||
import useJupiterMints from 'hooks/useJupiterMints'
|
||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import { getDecimalCount, trimDecimals } from 'utils/numbers'
|
||||
import { getDecimalCount } from 'utils/numbers'
|
||||
import LogoWithFallback from '@components/shared/LogoWithFallback'
|
||||
import useIpAddress from 'hooks/useIpAddress'
|
||||
import ButtonGroup from '@components/forms/ButtonGroup'
|
||||
import TradeSummary from './TradeSummary'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import MaxAmountButton from '@components/shared/MaxAmountButton'
|
||||
import { FadeInFadeOut } from '@components/shared/Transitions'
|
||||
import MaxSizeButton from './MaxSizeButton'
|
||||
|
||||
const set = mangoStore.getState().set
|
||||
|
||||
|
@ -233,42 +232,6 @@ const AdvancedTradeForm = () => {
|
|||
}
|
||||
}, [oraclePrice, selectedMarket, tickDecimals, tradeForm])
|
||||
|
||||
const leverageMax = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
if (!mangoAccount || !group || !selectedMarket) return 100
|
||||
|
||||
try {
|
||||
if (selectedMarket instanceof Serum3Market) {
|
||||
if (tradeForm.side === 'buy') {
|
||||
return mangoAccount.getMaxQuoteForSerum3BidUi(
|
||||
group,
|
||||
selectedMarket.serumMarketExternal
|
||||
)
|
||||
} else {
|
||||
return mangoAccount.getMaxBaseForSerum3AskUi(
|
||||
group,
|
||||
selectedMarket.serumMarketExternal
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (tradeForm.side === 'buy') {
|
||||
return mangoAccount.getMaxQuoteForPerpBidUi(
|
||||
group,
|
||||
selectedMarket.perpMarketIndex
|
||||
)
|
||||
} else {
|
||||
return mangoAccount.getMaxBaseForPerpAskUi(
|
||||
group,
|
||||
selectedMarket.perpMarketIndex
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error calculating max leverage: spot btn group: ', e)
|
||||
return 0
|
||||
}
|
||||
}, [mangoAccount, tradeForm.side, selectedMarket])
|
||||
|
||||
const handlePlaceOrder = useCallback(async () => {
|
||||
const client = mangoStore.getState().client
|
||||
const group = mangoStore.getState().group
|
||||
|
@ -372,59 +335,6 @@ const AdvancedTradeForm = () => {
|
|||
return minOrderDecimals
|
||||
}, [selectedMarket])
|
||||
|
||||
const handleMax = useCallback(() => {
|
||||
const set = mangoStore.getState().set
|
||||
set((state) => {
|
||||
if (tradeForm.side === 'buy') {
|
||||
state.tradeForm.quoteSize = trimDecimals(
|
||||
leverageMax,
|
||||
tickDecimals
|
||||
).toFixed(tickDecimals)
|
||||
if (tradeForm.tradeType === 'Market' || !tradeForm.price) {
|
||||
state.tradeForm.baseSize = trimDecimals(
|
||||
leverageMax / oraclePrice,
|
||||
minOrderDecimals
|
||||
).toFixed(minOrderDecimals)
|
||||
} else {
|
||||
state.tradeForm.baseSize = trimDecimals(
|
||||
leverageMax / parseFloat(tradeForm.price),
|
||||
minOrderDecimals
|
||||
).toFixed(minOrderDecimals)
|
||||
}
|
||||
} else {
|
||||
state.tradeForm.baseSize = trimDecimals(
|
||||
leverageMax,
|
||||
tickDecimals
|
||||
).toFixed(tickDecimals)
|
||||
if (tradeForm.tradeType === 'Market' || !tradeForm.price) {
|
||||
state.tradeForm.quoteSize = trimDecimals(
|
||||
leverageMax * oraclePrice,
|
||||
minOrderDecimals
|
||||
).toFixed(minOrderDecimals)
|
||||
} else {
|
||||
state.tradeForm.quoteSize = trimDecimals(
|
||||
leverageMax * parseFloat(tradeForm.price),
|
||||
minOrderDecimals
|
||||
).toFixed(minOrderDecimals)
|
||||
}
|
||||
}
|
||||
})
|
||||
}, [leverageMax, tradeForm])
|
||||
|
||||
const maxAmount = useMemo(() => {
|
||||
if (!tradeForm.price) return '0'
|
||||
if (tradeForm.side === 'buy') {
|
||||
return trimDecimals(
|
||||
leverageMax / parseFloat(tradeForm.price),
|
||||
tickDecimals
|
||||
).toFixed(tickDecimals)
|
||||
} else {
|
||||
return trimDecimals(leverageMax, minOrderDecimals).toFixed(
|
||||
minOrderDecimals
|
||||
)
|
||||
}
|
||||
}, [leverageMax, minOrderDecimals, tickDecimals, tradeForm])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="mt-1.5 px-2 md:mt-0 md:border-t md:border-th-bkg-3 md:px-4 md:pt-5 lg:mt-5 lg:border-t-0 lg:pt-0">
|
||||
|
@ -481,17 +391,10 @@ const AdvancedTradeForm = () => {
|
|||
</div>
|
||||
</>
|
||||
) : null}
|
||||
<div className="mb-2 mt-3 flex items-center justify-between">
|
||||
<p className="text-xs text-th-fgd-3">{t('trade:size')}</p>
|
||||
<FadeInFadeOut show={!!tradeForm.price}>
|
||||
<MaxAmountButton
|
||||
className="text-xs"
|
||||
label={t('max')}
|
||||
onClick={handleMax}
|
||||
value={maxAmount}
|
||||
/>
|
||||
</FadeInFadeOut>
|
||||
</div>
|
||||
<MaxSizeButton
|
||||
minOrderDecimals={minOrderDecimals}
|
||||
tickDecimals={tickDecimals}
|
||||
/>
|
||||
<div className="flex flex-col">
|
||||
<div className="default-transition flex items-center rounded-md rounded-b-none border border-th-input-border bg-th-input-bkg p-2 text-sm font-bold text-th-fgd-1 md:hover:z-10 md:hover:border-th-input-border-hover lg:text-base">
|
||||
<div className="h-5 w-5 flex-shrink-0">
|
||||
|
@ -556,26 +459,22 @@ const AdvancedTradeForm = () => {
|
|||
{selectedMarket instanceof Serum3Market ? (
|
||||
tradeFormSizeUi === 'slider' ? (
|
||||
<SpotSlider
|
||||
max={leverageMax}
|
||||
minOrderDecimals={minOrderDecimals}
|
||||
tickDecimals={tickDecimals}
|
||||
/>
|
||||
) : (
|
||||
<SpotButtonGroup
|
||||
max={leverageMax}
|
||||
minOrderDecimals={minOrderDecimals}
|
||||
tickDecimals={tickDecimals}
|
||||
/>
|
||||
)
|
||||
) : tradeFormSizeUi === 'slider' ? (
|
||||
<PerpSlider
|
||||
max={leverageMax}
|
||||
minOrderDecimals={minOrderDecimals}
|
||||
tickDecimals={tickDecimals}
|
||||
/>
|
||||
) : (
|
||||
<PerpButtonGroup
|
||||
max={leverageMax}
|
||||
minOrderDecimals={minOrderDecimals}
|
||||
tickDecimals={tickDecimals}
|
||||
/>
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
import { Serum3Market } from '@blockworks-foundation/mango-v4'
|
||||
import MaxAmountButton from '@components/shared/MaxAmountButton'
|
||||
import { FadeInFadeOut } from '@components/shared/Transitions'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { trimDecimals } from 'utils/numbers'
|
||||
|
||||
const MaxSizeButton = ({
|
||||
minOrderDecimals,
|
||||
tickDecimals,
|
||||
}: {
|
||||
minOrderDecimals: number
|
||||
tickDecimals: number
|
||||
}) => {
|
||||
const { t } = useTranslation(['common', 'trade'])
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const { selectedMarket, price: oraclePrice } = useSelectedMarket()
|
||||
const tradeForm = mangoStore((s) => s.tradeForm)
|
||||
|
||||
const leverageMax = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
if (!mangoAccount || !group || !selectedMarket) return 0
|
||||
|
||||
try {
|
||||
if (selectedMarket instanceof Serum3Market) {
|
||||
if (tradeForm.side === 'buy') {
|
||||
return mangoAccount.getMaxQuoteForSerum3BidUi(
|
||||
group,
|
||||
selectedMarket.serumMarketExternal
|
||||
)
|
||||
} else {
|
||||
return mangoAccount.getMaxBaseForSerum3AskUi(
|
||||
group,
|
||||
selectedMarket.serumMarketExternal
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (tradeForm.side === 'buy') {
|
||||
return mangoAccount.getMaxQuoteForPerpBidUi(
|
||||
group,
|
||||
selectedMarket.perpMarketIndex
|
||||
)
|
||||
} else {
|
||||
return mangoAccount.getMaxBaseForPerpAskUi(
|
||||
group,
|
||||
selectedMarket.perpMarketIndex
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error calculating max leverage: spot btn group: ', e)
|
||||
return 0
|
||||
}
|
||||
}, [mangoAccount, tradeForm.side, selectedMarket])
|
||||
|
||||
const handleMax = useCallback(() => {
|
||||
const set = mangoStore.getState().set
|
||||
set((state) => {
|
||||
if (tradeForm.side === 'buy') {
|
||||
state.tradeForm.quoteSize = trimDecimals(
|
||||
leverageMax,
|
||||
tickDecimals
|
||||
).toFixed(tickDecimals)
|
||||
if (tradeForm.tradeType === 'Market' || !tradeForm.price) {
|
||||
state.tradeForm.baseSize = trimDecimals(
|
||||
leverageMax / oraclePrice,
|
||||
minOrderDecimals
|
||||
).toFixed(minOrderDecimals)
|
||||
} else {
|
||||
state.tradeForm.baseSize = trimDecimals(
|
||||
leverageMax / parseFloat(tradeForm.price),
|
||||
minOrderDecimals
|
||||
).toFixed(minOrderDecimals)
|
||||
}
|
||||
} else {
|
||||
state.tradeForm.baseSize = trimDecimals(
|
||||
leverageMax,
|
||||
tickDecimals
|
||||
).toFixed(tickDecimals)
|
||||
if (tradeForm.tradeType === 'Market' || !tradeForm.price) {
|
||||
state.tradeForm.quoteSize = trimDecimals(
|
||||
leverageMax * oraclePrice,
|
||||
minOrderDecimals
|
||||
).toFixed(minOrderDecimals)
|
||||
} else {
|
||||
state.tradeForm.quoteSize = trimDecimals(
|
||||
leverageMax * parseFloat(tradeForm.price),
|
||||
minOrderDecimals
|
||||
).toFixed(minOrderDecimals)
|
||||
}
|
||||
}
|
||||
})
|
||||
}, [leverageMax, tradeForm])
|
||||
|
||||
const maxAmount = useMemo(() => {
|
||||
if (!tradeForm.price) return '0'
|
||||
if (tradeForm.side === 'buy') {
|
||||
return trimDecimals(
|
||||
leverageMax / parseFloat(tradeForm.price),
|
||||
tickDecimals
|
||||
).toFixed(tickDecimals)
|
||||
} else {
|
||||
return trimDecimals(leverageMax, minOrderDecimals).toFixed(
|
||||
minOrderDecimals
|
||||
)
|
||||
}
|
||||
}, [leverageMax, minOrderDecimals, tickDecimals, tradeForm])
|
||||
|
||||
return (
|
||||
<div className="mb-2 mt-3 flex items-center justify-between">
|
||||
<p className="text-xs text-th-fgd-3">{t('trade:size')}</p>
|
||||
<FadeInFadeOut show={!!tradeForm.price}>
|
||||
<MaxAmountButton
|
||||
className="text-xs"
|
||||
label={t('max')}
|
||||
onClick={handleMax}
|
||||
value={maxAmount}
|
||||
/>
|
||||
</FadeInFadeOut>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default MaxSizeButton
|
|
@ -1,24 +1,52 @@
|
|||
import { PerpMarket } from '@blockworks-foundation/mango-v4'
|
||||
import ButtonGroup from '@components/forms/ButtonGroup'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import { useCallback, useState } from 'react'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { trimDecimals } from 'utils/numbers'
|
||||
|
||||
const PerpButtonGroup = ({
|
||||
max,
|
||||
minOrderDecimals,
|
||||
tickDecimals,
|
||||
}: {
|
||||
max: number
|
||||
minOrderDecimals: number
|
||||
tickDecimals: number
|
||||
}) => {
|
||||
const side = mangoStore((s) => s.tradeForm.side)
|
||||
const { selectedMarket } = useSelectedMarket()
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const [sizePercentage, setSizePercentage] = useState('')
|
||||
const tradeFormPrice = mangoStore((s) => s.tradeForm.price)
|
||||
|
||||
const leverageMax = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
if (!mangoAccount || !group || !selectedMarket) return 100
|
||||
if (!(selectedMarket instanceof PerpMarket)) return 100
|
||||
|
||||
try {
|
||||
if (side === 'buy') {
|
||||
return mangoAccount.getMaxQuoteForPerpBidUi(
|
||||
group,
|
||||
selectedMarket.perpMarketIndex
|
||||
)
|
||||
} else {
|
||||
return mangoAccount.getMaxBaseForPerpAskUi(
|
||||
group,
|
||||
selectedMarket.perpMarketIndex
|
||||
)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error calculating max leverage perp btn grp: ', e)
|
||||
return 0
|
||||
}
|
||||
}, [side, selectedMarket, mangoAccount, tradeFormPrice])
|
||||
|
||||
const handleSizePercentage = useCallback(
|
||||
(percentage: string) => {
|
||||
const set = mangoStore.getState().set
|
||||
setSizePercentage(percentage)
|
||||
const size = max * (Number(percentage) / 100)
|
||||
const size = leverageMax * (Number(percentage) / 100)
|
||||
|
||||
set((s) => {
|
||||
if (s.tradeForm.side === 'buy') {
|
||||
|
@ -48,7 +76,7 @@ const PerpButtonGroup = ({
|
|||
}
|
||||
})
|
||||
},
|
||||
[max, minOrderDecimals, tickDecimals]
|
||||
[leverageMax, minOrderDecimals, tickDecimals]
|
||||
)
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
import { PerpMarket } from '@blockworks-foundation/mango-v4'
|
||||
import LeverageSlider from '@components/shared/LeverageSlider'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { trimDecimals } from 'utils/numbers'
|
||||
|
||||
const PerpSlider = ({
|
||||
max,
|
||||
minOrderDecimals,
|
||||
tickDecimals,
|
||||
}: {
|
||||
max: number
|
||||
minOrderDecimals: number
|
||||
tickDecimals: number
|
||||
}) => {
|
||||
const side = mangoStore((s) => s.tradeForm.side)
|
||||
const { selectedMarket, price: marketPrice } = useSelectedMarket()
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const tradeForm = mangoStore((s) => s.tradeForm)
|
||||
|
||||
const step = useMemo(() => {
|
||||
|
@ -24,6 +25,29 @@ const PerpSlider = ({
|
|||
return 0.01
|
||||
}, [selectedMarket])
|
||||
|
||||
const leverageMax = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
if (!mangoAccount || !group || !selectedMarket) return 100
|
||||
if (!(selectedMarket instanceof PerpMarket)) return 100
|
||||
|
||||
try {
|
||||
if (side === 'buy') {
|
||||
return mangoAccount.getMaxQuoteForPerpBidUi(
|
||||
group,
|
||||
selectedMarket.perpMarketIndex
|
||||
)
|
||||
} else {
|
||||
return mangoAccount.getMaxBaseForPerpAskUi(
|
||||
group,
|
||||
selectedMarket.perpMarketIndex
|
||||
)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error calculating max leverage for PerpSlider: ', e)
|
||||
return 0
|
||||
}
|
||||
}, [side, selectedMarket, mangoAccount])
|
||||
|
||||
const handleSlide = useCallback(
|
||||
(val: string) => {
|
||||
const set = mangoStore.getState().set
|
||||
|
@ -66,7 +90,7 @@ const PerpSlider = ({
|
|||
? parseFloat(tradeForm.quoteSize)
|
||||
: parseFloat(tradeForm.baseSize)
|
||||
}
|
||||
leverageMax={max}
|
||||
leverageMax={leverageMax}
|
||||
onChange={handleSlide}
|
||||
step={step}
|
||||
/>
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
import { Serum3Market } from '@blockworks-foundation/mango-v4'
|
||||
import ButtonGroup from '@components/forms/ButtonGroup'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { trimDecimals } from 'utils/numbers'
|
||||
|
||||
const SpotButtonGroup = ({
|
||||
max,
|
||||
minOrderDecimals,
|
||||
tickDecimals,
|
||||
}: {
|
||||
max: number
|
||||
minOrderDecimals: number
|
||||
tickDecimals: number
|
||||
}) => {
|
||||
|
@ -19,11 +18,34 @@ const SpotButtonGroup = ({
|
|||
const { mangoAccount } = useMangoAccount()
|
||||
const [sizePercentage, setSizePercentage] = useState('')
|
||||
|
||||
const leverageMax = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
if (!mangoAccount || !group || !selectedMarket) return 100
|
||||
if (!(selectedMarket instanceof Serum3Market)) return 100
|
||||
|
||||
try {
|
||||
if (side === 'buy') {
|
||||
return mangoAccount.getMaxQuoteForSerum3BidUi(
|
||||
group,
|
||||
selectedMarket.serumMarketExternal
|
||||
)
|
||||
} else {
|
||||
return mangoAccount.getMaxBaseForSerum3AskUi(
|
||||
group,
|
||||
selectedMarket.serumMarketExternal
|
||||
)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error calculating max leverage: spot btn group: ', e)
|
||||
return 0
|
||||
}
|
||||
}, [side, selectedMarket, mangoAccount])
|
||||
|
||||
const handleSizePercentage = useCallback(
|
||||
(percentage: string) => {
|
||||
const set = mangoStore.getState().set
|
||||
setSizePercentage(percentage)
|
||||
const size = max * (Number(percentage) / 100)
|
||||
const size = leverageMax * (Number(percentage) / 100)
|
||||
|
||||
set((s) => {
|
||||
if (s.tradeForm.side === 'buy') {
|
||||
|
|
|
@ -1,21 +1,46 @@
|
|||
import { Serum3Market } from '@blockworks-foundation/mango-v4'
|
||||
import LeverageSlider from '@components/shared/LeverageSlider'
|
||||
import mangoStore from '@store/mangoStore'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import { useCallback } from 'react'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { trimDecimals } from 'utils/numbers'
|
||||
|
||||
const SpotSlider = ({
|
||||
max,
|
||||
minOrderDecimals,
|
||||
tickDecimals,
|
||||
}: {
|
||||
max: number
|
||||
minOrderDecimals: number
|
||||
tickDecimals: number
|
||||
}) => {
|
||||
const { price: marketPrice } = useSelectedMarket()
|
||||
const side = mangoStore((s) => s.tradeForm.side)
|
||||
const { selectedMarket, price: marketPrice } = useSelectedMarket()
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const tradeForm = mangoStore((s) => s.tradeForm)
|
||||
|
||||
const leverageMax = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
if (!mangoAccount || !group || !selectedMarket) return 100
|
||||
if (!(selectedMarket instanceof Serum3Market)) return 100
|
||||
|
||||
try {
|
||||
if (side === 'buy') {
|
||||
return mangoAccount.getMaxQuoteForSerum3BidUi(
|
||||
group,
|
||||
selectedMarket.serumMarketExternal
|
||||
)
|
||||
} else {
|
||||
return mangoAccount.getMaxBaseForSerum3AskUi(
|
||||
group,
|
||||
selectedMarket.serumMarketExternal
|
||||
)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error calculating max leverage for spot slider: ', e)
|
||||
return 0
|
||||
}
|
||||
}, [side, selectedMarket, mangoAccount])
|
||||
|
||||
const handleSlide = useCallback(
|
||||
(val: string) => {
|
||||
const set = mangoStore.getState().set
|
||||
|
@ -58,7 +83,7 @@ const SpotSlider = ({
|
|||
? parseFloat(tradeForm.quoteSize)
|
||||
: parseFloat(tradeForm.baseSize)
|
||||
}
|
||||
leverageMax={max}
|
||||
leverageMax={leverageMax}
|
||||
onChange={handleSlide}
|
||||
step={0.01}
|
||||
/>
|
||||
|
|
Loading…
Reference in New Issue