use latest client
This commit is contained in:
parent
352eb42d16
commit
3faaaf1088
|
@ -32,12 +32,12 @@ import { LinkIcon, QuestionMarkCircleIcon } from '@heroicons/react/20/solid'
|
|||
import Loading from '@components/shared/Loading'
|
||||
import TabUnderline from '@components/shared/TabUnderline'
|
||||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
import { SOUND_SETTINGS_KEY } from 'utils/constants'
|
||||
import { SOUND_SETTINGS_KEY, TRADE_CHECKBOXES_KEY } from 'utils/constants'
|
||||
import SpotButtonGroup from './SpotButtonGroup'
|
||||
import PerpButtonGroup from './PerpButtonGroup'
|
||||
import SolBalanceWarnings from '@components/shared/SolBalanceWarnings'
|
||||
import useSelectedMarket from 'hooks/useSelectedMarket'
|
||||
import { getDecimalCount } from 'utils/numbers'
|
||||
import { floorToDecimal, getDecimalCount } from 'utils/numbers'
|
||||
import LogoWithFallback from '@components/shared/LogoWithFallback'
|
||||
import useIpAddress from 'hooks/useIpAddress'
|
||||
import ButtonGroup from '@components/forms/ButtonGroup'
|
||||
|
@ -58,12 +58,25 @@ const successSound = new Howl({
|
|||
volume: 0.5,
|
||||
})
|
||||
|
||||
const INPUT_SUFFIX_CLASSNAMES =
|
||||
'absolute right-[1px] top-1/2 flex h-[calc(100%-2px)] -translate-y-1/2 items-center rounded-r-md bg-th-input-bkg px-2 text-xs font-normal text-th-fgd-4'
|
||||
|
||||
const INPUT_PREFIX_CLASSNAMES =
|
||||
'absolute left-2 top-1/2 h-5 w-5 flex-shrink-0 -translate-y-1/2'
|
||||
|
||||
const DEFAULT_CHECKBOX_SETTINGS = {
|
||||
ioc: false,
|
||||
post: false,
|
||||
margin: true,
|
||||
}
|
||||
|
||||
const AdvancedTradeForm = () => {
|
||||
const { t } = useTranslation(['common', 'trade'])
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const tradeForm = mangoStore((s) => s.tradeForm)
|
||||
const [useMargin, setUseMargin] = useState(true)
|
||||
const [placingOrder, setPlacingOrder] = useState(false)
|
||||
const [savedCheckboxSettings, setSavedCheckboxSettings] =
|
||||
useLocalStorageState(TRADE_CHECKBOXES_KEY, DEFAULT_CHECKBOX_SETTINGS)
|
||||
const { ipAllowed, ipCountry } = useIpAddress()
|
||||
const [soundSettings] = useLocalStorageState(
|
||||
SOUND_SETTINGS_KEY,
|
||||
|
@ -78,6 +91,7 @@ const AdvancedTradeForm = () => {
|
|||
baseSymbol,
|
||||
quoteLogoURI,
|
||||
quoteSymbol,
|
||||
serumOrPerpMarket,
|
||||
} = useSelectedMarket()
|
||||
|
||||
const setTradeType = useCallback((tradeType: 'Limit' | 'Market') => {
|
||||
|
@ -141,21 +155,49 @@ const AdvancedTradeForm = () => {
|
|||
[oraclePrice]
|
||||
)
|
||||
|
||||
const handlePostOnlyChange = useCallback((postOnly: boolean) => {
|
||||
set((s) => {
|
||||
s.tradeForm.postOnly = postOnly
|
||||
if (s.tradeForm.ioc === true) {
|
||||
s.tradeForm.ioc = !postOnly
|
||||
const handlePostOnlyChange = useCallback(
|
||||
(postOnly: boolean) => {
|
||||
let ioc = tradeForm.ioc
|
||||
if (postOnly) {
|
||||
ioc = !postOnly
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
set((s) => {
|
||||
s.tradeForm.postOnly = postOnly
|
||||
s.tradeForm.ioc = ioc
|
||||
})
|
||||
setSavedCheckboxSettings({
|
||||
...savedCheckboxSettings,
|
||||
ioc: ioc,
|
||||
post: postOnly,
|
||||
})
|
||||
},
|
||||
[savedCheckboxSettings]
|
||||
)
|
||||
|
||||
const handleIocChange = useCallback((ioc: boolean) => {
|
||||
const handleIocChange = useCallback(
|
||||
(ioc: boolean) => {
|
||||
let postOnly = tradeForm.postOnly
|
||||
if (ioc) {
|
||||
postOnly = !ioc
|
||||
}
|
||||
set((s) => {
|
||||
s.tradeForm.ioc = ioc
|
||||
s.tradeForm.postOnly = postOnly
|
||||
})
|
||||
setSavedCheckboxSettings({
|
||||
...savedCheckboxSettings,
|
||||
ioc: ioc,
|
||||
post: postOnly,
|
||||
})
|
||||
},
|
||||
[savedCheckboxSettings]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
const { ioc, post } = savedCheckboxSettings
|
||||
set((s) => {
|
||||
s.tradeForm.ioc = ioc
|
||||
if (s.tradeForm.postOnly === true) {
|
||||
s.tradeForm.postOnly = !ioc
|
||||
}
|
||||
s.tradeForm.postOnly = post
|
||||
})
|
||||
}, [])
|
||||
|
||||
|
@ -171,15 +213,72 @@ const AdvancedTradeForm = () => {
|
|||
})
|
||||
}, [])
|
||||
|
||||
const handleSetMargin = useCallback((e: ChangeEvent<HTMLInputElement>) => {
|
||||
if (!e.target.checked) {
|
||||
set((s) => {
|
||||
s.tradeForm.quoteSize = ''
|
||||
s.tradeForm.baseSize = ''
|
||||
const handleSetMargin = useCallback(
|
||||
(e: ChangeEvent<HTMLInputElement>) => {
|
||||
setSavedCheckboxSettings({
|
||||
...savedCheckboxSettings,
|
||||
margin: e.target.checked,
|
||||
})
|
||||
}
|
||||
setUseMargin(e.target.checked)
|
||||
}, [])
|
||||
|
||||
const { group } = mangoStore.getState()
|
||||
const { tradeType, side, price, baseSize, quoteSize } = tradeForm
|
||||
const tradePrice = tradeType === 'Market' ? oraclePrice : price
|
||||
|
||||
if (
|
||||
!group ||
|
||||
!mangoAccount ||
|
||||
!tradePrice ||
|
||||
!(selectedMarket instanceof Serum3Market)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const isBuySide = side === 'buy'
|
||||
const tokenIndex =
|
||||
selectedMarket[isBuySide ? 'quoteTokenIndex' : 'baseTokenIndex']
|
||||
const balance = mangoAccount.getTokenBalanceUi(
|
||||
group.getFirstBankByTokenIndex(tokenIndex)
|
||||
)
|
||||
const max = Math.max(balance, 0)
|
||||
|
||||
const sizeToCompare = isBuySide ? quoteSize : baseSize
|
||||
const isSizeTooLarge = parseFloat(sizeToCompare) > max
|
||||
|
||||
set((s) => {
|
||||
if (max <= 0) {
|
||||
s.tradeForm.baseSize = ''
|
||||
s.tradeForm.quoteSize = ''
|
||||
return
|
||||
}
|
||||
if (isSizeTooLarge) {
|
||||
if (isBuySide) {
|
||||
s.tradeForm.quoteSize = floorToDecimal(max, tickDecimals).toFixed()
|
||||
s.tradeForm.baseSize = floorToDecimal(
|
||||
max / Number(tradePrice),
|
||||
minOrderDecimals
|
||||
).toFixed()
|
||||
} else {
|
||||
s.tradeForm.baseSize = floorToDecimal(
|
||||
max,
|
||||
minOrderDecimals
|
||||
).toFixed()
|
||||
s.tradeForm.quoteSize = floorToDecimal(
|
||||
max * Number(tradePrice),
|
||||
tickDecimals
|
||||
).toFixed()
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
[
|
||||
mangoAccount,
|
||||
oraclePrice,
|
||||
savedCheckboxSettings,
|
||||
selectedMarket,
|
||||
set,
|
||||
tradeForm,
|
||||
]
|
||||
)
|
||||
|
||||
const [tickDecimals] = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
|
@ -197,7 +296,7 @@ const AdvancedTradeForm = () => {
|
|||
return [tickDecimals, tickSize]
|
||||
}, [selectedMarket])
|
||||
|
||||
const [minOrderDecimals] = useMemo(() => {
|
||||
const [minOrderDecimals, minOrderSize] = useMemo(() => {
|
||||
const group = mangoStore.getState().group
|
||||
if (!group || !selectedMarket) return [1, 0.1]
|
||||
let minOrderSize: number
|
||||
|
@ -314,6 +413,8 @@ const AdvancedTradeForm = () => {
|
|||
: tradeForm.postOnly
|
||||
? PerpOrderType.postOnly
|
||||
: PerpOrderType.limit
|
||||
console.log('perpOrderType', perpOrderType)
|
||||
|
||||
const tx = await client.perpPlaceOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
|
@ -366,6 +467,11 @@ const AdvancedTradeForm = () => {
|
|||
connected ? handlePlaceOrder() : handleConnect()
|
||||
}
|
||||
|
||||
const disabled =
|
||||
(connected && (!tradeForm.baseSize || !tradeForm.price)) ||
|
||||
!serumOrPerpMarket ||
|
||||
parseFloat(tradeForm.baseSize) < serumOrPerpMarket.minOrderSize
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="mt-1.5 px-2 md:mt-0 md:px-4 md:pt-5 lg:mt-5 lg:pt-0">
|
||||
|
@ -397,13 +503,13 @@ const AdvancedTradeForm = () => {
|
|||
{t('trade:limit-price')}
|
||||
</p>
|
||||
</div>
|
||||
<div className="default-transition flex items-center rounded-md border border-th-input-border bg-th-input-bkg p-2 text-sm font-bold text-th-fgd-1 md:hover:border-th-input-border-hover lg:text-base">
|
||||
<div className="relative">
|
||||
{quoteLogoURI ? (
|
||||
<div className="h-5 w-5 flex-shrink-0">
|
||||
<div className={INPUT_PREFIX_CLASSNAMES}>
|
||||
<Image alt="" width="20" height="20" src={quoteLogoURI} />
|
||||
</div>
|
||||
) : (
|
||||
<div className="h-5 w-5 flex-shrink-0">
|
||||
<div className={INPUT_PREFIX_CLASSNAMES}>
|
||||
<QuestionMarkCircleIcon className="h-5 w-5 text-th-fgd-3" />
|
||||
</div>
|
||||
)}
|
||||
|
@ -415,28 +521,39 @@ const AdvancedTradeForm = () => {
|
|||
decimalScale={tickDecimals}
|
||||
name="price"
|
||||
id="price"
|
||||
className="ml-2 w-full bg-transparent font-mono focus:outline-none"
|
||||
className="flex w-full items-center rounded-md border border-th-input-border bg-th-input-bkg p-2 pl-9 font-mono text-sm font-bold text-th-fgd-1 focus:border-th-fgd-4 focus:outline-none md:hover:border-th-input-border-hover md:hover:focus-visible:border-th-fgd-4 lg:text-base"
|
||||
placeholder="0.00"
|
||||
value={tradeForm.price}
|
||||
onValueChange={handlePriceChange}
|
||||
/>
|
||||
<div className="text-xs font-normal text-th-fgd-4">
|
||||
{quoteSymbol}
|
||||
</div>
|
||||
<div className={INPUT_SUFFIX_CLASSNAMES}>{quoteSymbol}</div>
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
<MaxSizeButton
|
||||
minOrderDecimals={minOrderDecimals}
|
||||
tickDecimals={tickDecimals}
|
||||
useMargin={useMargin}
|
||||
useMargin={savedCheckboxSettings.margin}
|
||||
/>
|
||||
<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">
|
||||
<div className="relative">
|
||||
<NumberFormat
|
||||
inputMode="decimal"
|
||||
thousandSeparator=","
|
||||
allowNegative={false}
|
||||
isNumericString={true}
|
||||
decimalScale={minOrderDecimals}
|
||||
name="base"
|
||||
id="base"
|
||||
className="relative flex w-full items-center rounded-md rounded-b-none border border-th-input-border bg-th-input-bkg p-2 pl-9 font-mono text-sm font-bold text-th-fgd-1 focus:z-10 focus:border-th-fgd-4 focus:outline-none md:hover:z-10 md:hover:border-th-input-border-hover md:hover:focus:border-th-fgd-4 lg:text-base"
|
||||
placeholder="0.00"
|
||||
value={tradeForm.baseSize}
|
||||
onValueChange={handleBaseSizeChange}
|
||||
/>
|
||||
<div className={`z-10 ${INPUT_PREFIX_CLASSNAMES}`}>
|
||||
<LogoWithFallback
|
||||
alt=""
|
||||
className="z-10 drop-shadow-md"
|
||||
className="drop-shadow-md"
|
||||
width={'24'}
|
||||
height={'24'}
|
||||
src={baseLogoURI || `/icons/${baseSymbol?.toLowerCase()}.svg`}
|
||||
|
@ -447,30 +564,17 @@ const AdvancedTradeForm = () => {
|
|||
}
|
||||
/>
|
||||
</div>
|
||||
<NumberFormat
|
||||
inputMode="decimal"
|
||||
thousandSeparator=","
|
||||
allowNegative={false}
|
||||
isNumericString={true}
|
||||
decimalScale={minOrderDecimals}
|
||||
name="base"
|
||||
id="base"
|
||||
className="ml-2 w-full bg-transparent font-mono focus:outline-none"
|
||||
placeholder="0.00"
|
||||
value={tradeForm.baseSize}
|
||||
onValueChange={handleBaseSizeChange}
|
||||
/>
|
||||
<div className="text-xs font-normal text-th-fgd-4">
|
||||
<div className={`z-10 ${INPUT_SUFFIX_CLASSNAMES}`}>
|
||||
{baseSymbol}
|
||||
</div>
|
||||
</div>
|
||||
<div className="default-transition -mt-[1px] flex items-center rounded-md rounded-t-none border border-th-input-border bg-th-input-bkg p-2 text-sm font-bold text-th-fgd-1 md:hover:border-th-input-border-hover lg:text-base">
|
||||
<div className="relative">
|
||||
{quoteLogoURI ? (
|
||||
<div className="h-5 w-5 flex-shrink-0">
|
||||
<div className={INPUT_PREFIX_CLASSNAMES}>
|
||||
<Image alt="" width="20" height="20" src={quoteLogoURI} />
|
||||
</div>
|
||||
) : (
|
||||
<div className="h-5 w-5 flex-shrink-0">
|
||||
<div className={INPUT_PREFIX_CLASSNAMES}>
|
||||
<QuestionMarkCircleIcon className="h-5 w-5 text-th-fgd-3" />
|
||||
</div>
|
||||
)}
|
||||
|
@ -482,15 +586,25 @@ const AdvancedTradeForm = () => {
|
|||
decimalScale={tickDecimals}
|
||||
name="quote"
|
||||
id="quote"
|
||||
className="ml-2 w-full bg-transparent font-mono focus:outline-none"
|
||||
className="-mt-[1px] flex w-full items-center rounded-md rounded-t-none border border-th-input-border bg-th-input-bkg p-2 pl-9 font-mono text-sm font-bold text-th-fgd-1 focus:border-th-fgd-4 focus:outline-none md:hover:border-th-input-border-hover md:hover:focus:border-th-fgd-4 lg:text-base"
|
||||
placeholder="0.00"
|
||||
value={tradeForm.quoteSize}
|
||||
onValueChange={handleQuoteSizeChange}
|
||||
/>
|
||||
<div className="text-xs font-normal text-th-fgd-4">
|
||||
{quoteSymbol}
|
||||
</div>
|
||||
<div className={INPUT_SUFFIX_CLASSNAMES}>{quoteSymbol}</div>
|
||||
</div>
|
||||
{serumOrPerpMarket &&
|
||||
tradeForm.baseSize &&
|
||||
parseFloat(tradeForm.baseSize) < serumOrPerpMarket.minOrderSize ? (
|
||||
<div className="mt-1">
|
||||
<InlineNotification
|
||||
type="error"
|
||||
desc={`Min order size is ${minOrderSize} ${baseSymbol}`}
|
||||
hideBorder
|
||||
hidePadding
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-2 flex">
|
||||
|
@ -498,7 +612,7 @@ const AdvancedTradeForm = () => {
|
|||
<SpotButtonGroup
|
||||
minOrderDecimals={minOrderDecimals}
|
||||
tickDecimals={tickDecimals}
|
||||
useMargin={useMargin}
|
||||
useMargin={savedCheckboxSettings.margin}
|
||||
/>
|
||||
) : (
|
||||
<PerpButtonGroup
|
||||
|
@ -552,7 +666,10 @@ const AdvancedTradeForm = () => {
|
|||
placement="left"
|
||||
content={t('trade:tooltip-enable-margin')}
|
||||
>
|
||||
<Checkbox checked={useMargin} onChange={handleSetMargin}>
|
||||
<Checkbox
|
||||
checked={savedCheckboxSettings.margin}
|
||||
onChange={handleSetMargin}
|
||||
>
|
||||
{t('trade:margin')}
|
||||
</Checkbox>
|
||||
</Tooltip>
|
||||
|
@ -586,10 +703,10 @@ const AdvancedTradeForm = () => {
|
|||
!connected
|
||||
? ''
|
||||
: tradeForm.side === 'buy'
|
||||
? 'bg-th-up-dark text-white md:hover:bg-th-up'
|
||||
: 'bg-th-down-dark text-white md:hover:bg-th-down'
|
||||
? 'bg-th-up-dark text-white md:hover:bg-th-up-dark md:hover:brightness-90'
|
||||
: 'bg-th-down text-white md:hover:bg-th-down md:hover:brightness-90'
|
||||
}`}
|
||||
disabled={connected && !tradeForm.baseSize}
|
||||
disabled={disabled}
|
||||
size="large"
|
||||
type="submit"
|
||||
>
|
||||
|
@ -631,7 +748,10 @@ const AdvancedTradeForm = () => {
|
|||
/>
|
||||
</div>
|
||||
) : null}
|
||||
<TradeSummary mangoAccount={mangoAccount} useMargin={useMargin} />
|
||||
<TradeSummary
|
||||
mangoAccount={mangoAccount}
|
||||
useMargin={savedCheckboxSettings.margin}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -30,6 +30,13 @@ import { INITIAL_ANIMATION_SETTINGS } from '@components/settings/AnimationSettin
|
|||
import { ArrowPathIcon } from '@heroicons/react/20/solid'
|
||||
import { sleep } from 'utils'
|
||||
|
||||
const sizeCompacter = Intl.NumberFormat('en', {
|
||||
maximumFractionDigits: 6,
|
||||
notation: 'compact',
|
||||
})
|
||||
|
||||
const SHOW_EXPONENTIAL_THRESHOLD = 0.00001
|
||||
|
||||
const getMarket = () => {
|
||||
const group = mangoStore.getState().group
|
||||
const selectedMarket = mangoStore.getState().selectedMarket.current
|
||||
|
@ -189,7 +196,6 @@ const updatePerpMarketOnGroup = (book: BookSide, side: 'bids' | 'asks') => {
|
|||
}
|
||||
}
|
||||
|
||||
const depth = 40
|
||||
type OrderbookData = {
|
||||
bids: cumOrderbookSide[]
|
||||
asks: cumOrderbookSide[]
|
||||
|
@ -218,11 +224,14 @@ const Orderbook = () => {
|
|||
const { width } = useViewport()
|
||||
const isMobile = width ? width < breakpoints.md : false
|
||||
|
||||
const depthArray: number[] = useMemo(() => {
|
||||
const bookDepth = !isMobile ? depth : 9
|
||||
return Array(bookDepth).fill(0)
|
||||
const depth = useMemo(() => {
|
||||
return isMobile ? 9 : 40
|
||||
}, [isMobile])
|
||||
|
||||
const depthArray: number[] = useMemo(() => {
|
||||
return Array(depth).fill(0)
|
||||
}, [depth])
|
||||
|
||||
useEffect(() => {
|
||||
if (market && market.tickSize !== tickSize) {
|
||||
setTickSize(market.tickSize)
|
||||
|
@ -488,42 +497,41 @@ const Orderbook = () => {
|
|||
return (
|
||||
<div className="flex h-full flex-col">
|
||||
<div className="flex items-center justify-between border-b border-th-bkg-3 px-4 py-2">
|
||||
<div id="trade-step-three" className="flex items-center space-x-1.5">
|
||||
<div
|
||||
id="trade-step-three"
|
||||
className="hidden items-center space-x-1.5 md:flex"
|
||||
>
|
||||
<Tooltip
|
||||
className={`hidden md:block ${!showAsks ? 'md:hidden' : ''}`}
|
||||
className={`${!showAsks ? 'hidden' : ''}`}
|
||||
content={t('trade:show-bids')}
|
||||
placement="bottom"
|
||||
>
|
||||
<button
|
||||
className={`rounded ${
|
||||
showAsks ? 'bg-th-bkg-3' : 'bg-th-bkg-2'
|
||||
} default-transition flex h-6 w-6 items-center justify-center hover:border-th-fgd-4 focus:outline-none disabled:cursor-not-allowed`}
|
||||
} flex h-6 w-6 items-center justify-center hover:border-th-fgd-4 focus:outline-none focus-visible:bg-th-bkg-4 disabled:cursor-not-allowed`}
|
||||
onClick={() => toggleSides('bids')}
|
||||
>
|
||||
<OrderbookIcon className="h-4 w-4" side="buy" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
className={`hidden md:block ${!showBids ? 'md:hidden' : ''}`}
|
||||
className={`${!showBids ? 'hidden' : ''}`}
|
||||
content={t('trade:show-asks')}
|
||||
placement="bottom"
|
||||
>
|
||||
<button
|
||||
className={`rounded ${
|
||||
showBids ? 'bg-th-bkg-3' : 'bg-th-bkg-2'
|
||||
} default-transition flex h-6 w-6 items-center justify-center hover:border-th-fgd-4 focus:outline-none disabled:cursor-not-allowed`}
|
||||
} flex h-6 w-6 items-center justify-center hover:border-th-fgd-4 focus:outline-none focus-visible:bg-th-bkg-4 disabled:cursor-not-allowed`}
|
||||
onClick={() => toggleSides('asks')}
|
||||
>
|
||||
<OrderbookIcon className="h-4 w-4" side="sell" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
content={'Reset and center orderbook'}
|
||||
placement="bottom"
|
||||
>
|
||||
<Tooltip content={'Reset and center orderbook'} placement="bottom">
|
||||
<button
|
||||
className="default-transition flex h-6 w-6 items-center justify-center rounded bg-th-bkg-3 hover:border-th-fgd-4 focus:outline-none disabled:cursor-not-allowed"
|
||||
className="flex h-6 w-6 items-center justify-center rounded bg-th-bkg-3 hover:border-th-fgd-4 focus:outline-none focus-visible:bg-th-bkg-4 disabled:cursor-not-allowed"
|
||||
onClick={resetOrderbook}
|
||||
>
|
||||
<ArrowPathIcon className="h-4 w-4" />
|
||||
|
@ -531,20 +539,23 @@ const Orderbook = () => {
|
|||
</Tooltip>
|
||||
</div>
|
||||
{market ? (
|
||||
<div id="trade-step-four">
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
content={t('trade:grouping')}
|
||||
placement="left"
|
||||
delay={100}
|
||||
>
|
||||
<GroupSize
|
||||
tickSize={market.tickSize}
|
||||
onChange={onGroupSizeChange}
|
||||
value={grouping}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<>
|
||||
<p className="text-xs md:hidden">{t('trade:grouping')}:</p>
|
||||
<div id="trade-step-four">
|
||||
<Tooltip
|
||||
className="hidden md:block"
|
||||
content={t('trade:grouping')}
|
||||
placement="left"
|
||||
delay={100}
|
||||
>
|
||||
<GroupSize
|
||||
tickSize={market.tickSize}
|
||||
onChange={onGroupSizeChange}
|
||||
value={grouping}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="grid grid-cols-2 px-4 pt-2 pb-1 text-xxs text-th-fgd-4">
|
||||
|
@ -605,10 +616,12 @@ const Orderbook = () => {
|
|||
</div>
|
||||
<div className="col-span-1 text-right font-mono">
|
||||
{orderbookData?.spread
|
||||
? formatNumericValue(
|
||||
orderbookData.spread,
|
||||
market ? getDecimalCount(market.tickSize) : undefined
|
||||
)
|
||||
? orderbookData.spread < SHOW_EXPONENTIAL_THRESHOLD
|
||||
? orderbookData.spread.toExponential()
|
||||
: formatNumericValue(
|
||||
orderbookData.spread,
|
||||
market ? getDecimalCount(market.tickSize) : undefined
|
||||
)
|
||||
: null}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -685,7 +698,7 @@ const OrderbookRow = ({
|
|||
const formattedSize = useMemo(() => {
|
||||
return minOrderSize && !isNaN(size)
|
||||
? floorToDecimal(size, getDecimalCount(minOrderSize))
|
||||
: new Decimal(size)
|
||||
: new Decimal(size ?? -1)
|
||||
}, [size, minOrderSize])
|
||||
|
||||
const formattedPrice = useMemo(() => {
|
||||
|
@ -749,9 +762,10 @@ const OrderbookRow = ({
|
|||
className={`z-10 w-full text-right font-mono text-xs ${
|
||||
hasOpenOrder ? 'text-th-active' : ''
|
||||
}`}
|
||||
// onClick={handleSizeClick}
|
||||
>
|
||||
{formattedSize.toFixed(minOrderSizeDecimals)}
|
||||
{size >= 1000000
|
||||
? sizeCompacter.format(size)
|
||||
: formattedSize.toFixed(minOrderSizeDecimals)}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
@ -759,7 +773,9 @@ const OrderbookRow = ({
|
|||
onClick={handlePriceClick}
|
||||
>
|
||||
<div className="w-full text-right font-mono text-xs">
|
||||
{formattedPrice.toFixed(groupingDecimalCount)}
|
||||
{price < SHOW_EXPONENTIAL_THRESHOLD
|
||||
? formattedPrice.toExponential()
|
||||
: formattedPrice.toFixed(groupingDecimalCount)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,7 +5,7 @@ const webpack = require('webpack')
|
|||
const nextConfig = {
|
||||
i18n,
|
||||
images: {
|
||||
domains: ['raw.githubusercontent.com', 'arweave.net'],
|
||||
domains: ['raw.githubusercontent.com', 'arweave.net', 'www.dual.finance'],
|
||||
},
|
||||
reactStrictMode: true,
|
||||
async redirects() {
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
"entrypoints": []
|
||||
},
|
||||
"dependencies": {
|
||||
"@blockworks-foundation/mango-v4": "^0.9.16",
|
||||
"@blockworks-foundation/mango-v4": "^0.14.1",
|
||||
"@headlessui/react": "1.6.6",
|
||||
"@heroicons/react": "2.0.10",
|
||||
"@project-serum/anchor": "0.25.0",
|
||||
|
|
|
@ -76,6 +76,8 @@ export const MIN_SOL_BALANCE = 0.001
|
|||
|
||||
export const ACCOUNT_ACTION_MODAL_HEIGHT = '462px'
|
||||
|
||||
export const TRADE_CHECKBOXES_KEY = 'tradeCheckboxes-0.1'
|
||||
|
||||
export const ACCOUNT_ACTION_MODAL_INNER_HEIGHT = '400px'
|
||||
|
||||
export const TRADE_VOLUME_ALERT_KEY = 'tradeVolumeAlert-0.1'
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
dependencies:
|
||||
regenerator-runtime "^0.13.11"
|
||||
|
||||
"@blockworks-foundation/mango-v4@^0.9.16":
|
||||
version "0.9.16"
|
||||
resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4/-/mango-v4-0.9.16.tgz#9a3e70c95e46f112e7a204cd80d42a1c26e7d484"
|
||||
integrity sha512-tyGtLiVQeWwxggSnkv1tqT3akeIpsiFtAcNuXPiJKfm/zwgPhLLOAsFbl0cr9IGqtV7uY/+CmKSqL2dHJD2czg==
|
||||
"@blockworks-foundation/mango-v4@^0.14.1":
|
||||
version "0.14.1"
|
||||
resolved "https://registry.yarnpkg.com/@blockworks-foundation/mango-v4/-/mango-v4-0.14.1.tgz#fc5cd558e518207804acfbb80b80d6d21933d8de"
|
||||
integrity sha512-P1cjN+96lyf45rELDLUTQaC6PpAuAAXPqjynFSBV6CswW87r8sdHLPgnYaUnfJMBAqHGwd0rVuT/YMJpoHfejA==
|
||||
dependencies:
|
||||
"@coral-xyz/anchor" "^0.26.0"
|
||||
"@project-serum/serum" "0.13.65"
|
||||
|
|
Loading…
Reference in New Issue