mango-v4-ui/components/trade/AdvancedTradeForm.tsx

657 lines
22 KiB
TypeScript
Raw Normal View History

2022-09-13 23:24:26 -07:00
import {
2022-10-29 18:17:11 -07:00
PerpMarket,
PerpOrderSide,
PerpOrderType,
2022-10-10 19:16:13 -07:00
Serum3Market,
2022-09-13 23:24:26 -07:00
Serum3OrderType,
Serum3SelfTradeBehavior,
Serum3Side,
} from '@blockworks-foundation/mango-v4'
import Checkbox from '@components/forms/Checkbox'
import Button from '@components/shared/Button'
import Tooltip from '@components/shared/Tooltip'
import mangoStore from '@store/mangoStore'
import Decimal from 'decimal.js'
import { useTranslation } from 'next-i18next'
import {
ChangeEvent,
FormEvent,
useCallback,
useEffect,
useMemo,
useState,
} from 'react'
2022-09-26 12:56:06 -07:00
import NumberFormat, {
NumberFormatValues,
SourceInfo,
} from 'react-number-format'
2022-09-13 23:24:26 -07:00
import { notify } from 'utils/notifications'
2022-09-21 18:52:25 -07:00
import SpotSlider from './SpotSlider'
import { calculateLimitPriceForMarketOrder } from 'utils/tradeForm'
2022-10-28 14:46:38 -07:00
import Image from 'next/legacy/image'
2023-01-03 03:06:37 -08:00
import { LinkIcon, QuestionMarkCircleIcon } from '@heroicons/react/20/solid'
2022-10-03 16:26:12 -07:00
import Loading from '@components/shared/Loading'
2022-10-25 21:44:09 -07:00
import TabUnderline from '@components/shared/TabUnderline'
2022-10-29 18:17:11 -07:00
import PerpSlider from './PerpSlider'
2022-11-15 17:32:55 -08:00
import useLocalStorageState from 'hooks/useLocalStorageState'
2023-01-02 04:19:30 -08:00
import { SIZE_INPUT_UI_KEY, SOUND_SETTINGS_KEY } from 'utils/constants'
2022-11-15 17:32:55 -08:00
import SpotButtonGroup from './SpotButtonGroup'
import PerpButtonGroup from './PerpButtonGroup'
2022-11-17 20:43:23 -08:00
import SolBalanceWarnings from '@components/shared/SolBalanceWarnings'
2022-11-19 17:40:06 -08:00
import useSelectedMarket from 'hooks/useSelectedMarket'
import { getDecimalCount } from 'utils/numbers'
2022-12-09 16:33:27 -08:00
import LogoWithFallback from '@components/shared/LogoWithFallback'
2022-12-19 13:58:22 -08:00
import useIpAddress from 'hooks/useIpAddress'
2022-12-21 20:19:00 -08:00
import ButtonGroup from '@components/forms/ButtonGroup'
import TradeSummary from './TradeSummary'
import useMangoAccount from 'hooks/useMangoAccount'
import MaxSizeButton from './MaxSizeButton'
2023-01-02 04:19:30 -08:00
import { INITIAL_SOUND_SETTINGS } from '@components/settings/SoundSettings'
import { Howl } from 'howler'
2023-01-03 03:06:37 -08:00
import { useWallet } from '@solana/wallet-adapter-react'
import { useEnhancedWallet } from '@components/wallet/EnhancedWalletProvider'
2023-02-27 23:20:11 -08:00
import { isMangoError } from 'types'
import InlineNotification from '@components/shared/InlineNotification'
2022-09-13 23:24:26 -07:00
const set = mangoStore.getState().set
2023-01-02 04:19:30 -08:00
const successSound = new Howl({
src: ['/sounds/swap-success.mp3'],
volume: 0.5,
})
2022-09-13 23:24:26 -07:00
const AdvancedTradeForm = () => {
2022-10-03 03:38:05 -07:00
const { t } = useTranslation(['common', 'trade'])
2022-12-21 20:19:00 -08:00
const { mangoAccount } = useMangoAccount()
2022-09-13 23:24:26 -07:00
const tradeForm = mangoStore((s) => s.tradeForm)
const [useMargin, setUseMargin] = useState(true)
2022-10-03 16:26:12 -07:00
const [placingOrder, setPlacingOrder] = useState(false)
2023-01-19 12:41:11 -08:00
const [tradeFormSizeUi] = useLocalStorageState(SIZE_INPUT_UI_KEY, 'slider')
2022-12-19 13:58:22 -08:00
const { ipAllowed, ipCountry } = useIpAddress()
2023-01-02 04:19:30 -08:00
const [soundSettings] = useLocalStorageState(
SOUND_SETTINGS_KEY,
INITIAL_SOUND_SETTINGS
)
2023-01-03 03:06:37 -08:00
const { connected } = useWallet()
const { handleConnect } = useEnhancedWallet()
2023-01-14 21:01:30 -08:00
const {
selectedMarket,
price: oraclePrice,
baseLogoURI,
baseSymbol,
quoteLogoURI,
quoteSymbol,
} = useSelectedMarket()
2022-10-02 20:42:45 -07:00
const setTradeType = useCallback((tradeType: 'Limit' | 'Market') => {
set((s) => {
s.tradeForm.tradeType = tradeType
})
}, [])
2022-09-13 23:24:26 -07:00
const handlePriceChange = useCallback(
2022-09-26 12:56:06 -07:00
(e: NumberFormatValues, info: SourceInfo) => {
if (info.source !== 'event') return
2022-09-13 23:24:26 -07:00
set((s) => {
s.tradeForm.price = e.value
2022-10-31 09:39:43 -07:00
if (s.tradeForm.baseSize && !Number.isNaN(Number(e.value))) {
2022-09-26 12:56:06 -07:00
s.tradeForm.quoteSize = (
2022-11-19 17:40:06 -08:00
(parseFloat(e.value) || 0) * parseFloat(s.tradeForm.baseSize)
2022-09-26 12:56:06 -07:00
).toString()
}
2022-09-13 23:24:26 -07:00
})
},
[]
2022-09-13 23:24:26 -07:00
)
const handleBaseSizeChange = useCallback(
2022-09-26 12:56:06 -07:00
(e: NumberFormatValues, info: SourceInfo) => {
if (info.source !== 'event') return
2022-09-13 23:24:26 -07:00
set((s) => {
2022-11-20 15:35:59 -08:00
const price =
s.tradeForm.tradeType === 'Market'
? oraclePrice
: Number(s.tradeForm.price)
2022-11-19 17:40:06 -08:00
2022-09-13 23:24:26 -07:00
s.tradeForm.baseSize = e.value
2022-11-19 17:40:06 -08:00
if (price && e.value !== '' && !Number.isNaN(Number(e.value))) {
s.tradeForm.quoteSize = (price * parseFloat(e.value)).toString()
} else {
s.tradeForm.quoteSize = ''
2022-09-26 12:56:06 -07:00
}
})
},
[oraclePrice]
2022-09-26 12:56:06 -07:00
)
const handleQuoteSizeChange = useCallback(
(e: NumberFormatValues, info: SourceInfo) => {
if (info.source !== 'event') return
set((s) => {
2022-11-20 15:35:59 -08:00
const price =
s.tradeForm.tradeType === 'Market'
? oraclePrice
: Number(s.tradeForm.price)
2022-09-26 12:56:06 -07:00
2022-11-19 17:40:06 -08:00
s.tradeForm.quoteSize = e.value
if (price && e.value !== '' && !Number.isNaN(Number(e.value))) {
s.tradeForm.baseSize = (parseFloat(e.value) / price).toString()
} else {
s.tradeForm.baseSize = ''
2022-09-26 12:56:06 -07:00
}
2022-09-13 23:24:26 -07:00
})
},
[oraclePrice]
2022-09-13 23:24:26 -07:00
)
const handlePostOnlyChange = useCallback((postOnly: boolean) => {
set((s) => {
s.tradeForm.postOnly = postOnly
if (s.tradeForm.ioc === true) {
s.tradeForm.ioc = !postOnly
}
})
}, [])
2022-09-13 23:24:26 -07:00
const handleIocChange = useCallback((ioc: boolean) => {
set((s) => {
s.tradeForm.ioc = ioc
if (s.tradeForm.postOnly === true) {
s.tradeForm.postOnly = !ioc
}
})
}, [])
2023-01-16 20:00:42 -08:00
const handleReduceOnlyChange = useCallback((reduceOnly: boolean) => {
set((s) => {
s.tradeForm.reduceOnly = reduceOnly
})
}, [])
const handleSetSide = useCallback((side: 'buy' | 'sell') => {
set((s) => {
s.tradeForm.side = side
})
}, [])
2023-01-14 21:01:30 -08:00
const handleSetMargin = useCallback((e: ChangeEvent<HTMLInputElement>) => {
if (!e.target.checked) {
set((s) => {
s.tradeForm.quoteSize = ''
s.tradeForm.baseSize = ''
})
}
2023-01-14 21:01:30 -08:00
setUseMargin(e.target.checked)
}, [])
2023-01-04 17:09:43 -08:00
const [tickDecimals, tickSize] = useMemo(() => {
2022-12-15 21:12:10 -08:00
const group = mangoStore.getState().group
2023-01-04 17:09:43 -08:00
if (!group || !selectedMarket) return [1, 0.1]
2022-12-15 21:12:10 -08:00
let tickSize: number
if (selectedMarket instanceof Serum3Market) {
const market = group.getSerum3ExternalMarket(
selectedMarket.serumMarketExternal
)
tickSize = market.tickSize
} else {
tickSize = selectedMarket.tickSize
}
2023-01-04 17:09:43 -08:00
const tickDecimals = getDecimalCount(tickSize)
return [tickDecimals, tickSize]
2022-12-15 21:12:10 -08:00
}, [selectedMarket])
2023-01-19 13:01:46 -08:00
const [minOrderDecimals, minOrderSize] = useMemo(() => {
const group = mangoStore.getState().group
if (!group || !selectedMarket) return [1, 0.1]
let minOrderSize: number
if (selectedMarket instanceof Serum3Market) {
const market = group.getSerum3ExternalMarket(
selectedMarket.serumMarketExternal
)
minOrderSize = market.minOrderSize
} else {
minOrderSize = selectedMarket.minOrderSize
}
const minOrderDecimals = getDecimalCount(minOrderSize)
return [minOrderDecimals, minOrderSize]
}, [selectedMarket])
/*
* Updates the limit price on page load
*/
useEffect(() => {
if (tradeForm.price === undefined) {
const group = mangoStore.getState().group
if (!group || !oraclePrice) return
2022-09-13 23:24:26 -07:00
set((s) => {
2022-12-15 21:12:10 -08:00
s.tradeForm.price = oraclePrice.toFixed(tickDecimals)
2022-09-13 23:24:26 -07:00
})
}
2022-12-15 21:12:10 -08:00
}, [oraclePrice, tickDecimals, tradeForm.price])
2022-09-13 23:24:26 -07:00
/*
* Updates the price and the quote size when a Market order is selected
*/
2022-09-26 12:56:06 -07:00
useEffect(() => {
const group = mangoStore.getState().group
if (
tradeForm.tradeType === 'Market' &&
oraclePrice &&
selectedMarket &&
group
) {
2022-12-14 10:48:13 -08:00
if (!isNaN(parseFloat(tradeForm.baseSize))) {
const baseSize = new Decimal(tradeForm.baseSize)?.toNumber()
const quoteSize = baseSize * oraclePrice
set((s) => {
2022-12-15 21:12:10 -08:00
s.tradeForm.price = oraclePrice.toFixed(tickDecimals)
s.tradeForm.quoteSize = quoteSize.toFixed(tickDecimals)
})
} else {
set((s) => {
2022-12-15 21:12:10 -08:00
s.tradeForm.price = oraclePrice.toFixed(tickDecimals)
})
}
}
2022-12-15 21:12:10 -08:00
}, [oraclePrice, selectedMarket, tickDecimals, tradeForm])
2022-09-26 12:56:06 -07:00
2022-09-13 23:24:26 -07:00
const handlePlaceOrder = useCallback(async () => {
const client = mangoStore.getState().client
const group = mangoStore.getState().group
const mangoAccount = mangoStore.getState().mangoAccount.current
const tradeForm = mangoStore.getState().tradeForm
const actions = mangoStore.getState().actions
2022-09-25 19:02:58 -07:00
const selectedMarket = mangoStore.getState().selectedMarket.current
2022-09-13 23:24:26 -07:00
if (!group || !mangoAccount) return
2022-10-03 16:26:12 -07:00
setPlacingOrder(true)
2022-09-13 23:24:26 -07:00
try {
const baseSize = Number(tradeForm.baseSize)
let price = Number(tradeForm.price)
2022-09-25 19:02:58 -07:00
if (tradeForm.tradeType === 'Market') {
const orderbook = mangoStore.getState().selectedMarket.orderbook
price = calculateLimitPriceForMarketOrder(
orderbook,
baseSize,
tradeForm.side
)
2022-09-25 19:02:58 -07:00
}
2022-10-10 19:16:13 -07:00
if (selectedMarket instanceof Serum3Market) {
2022-10-29 18:17:11 -07:00
const spotOrderType = tradeForm.ioc
? Serum3OrderType.immediateOrCancel
2023-03-04 20:06:45 -08:00
: tradeForm.postOnly && tradeForm.tradeType !== 'Market'
2022-10-29 18:17:11 -07:00
? Serum3OrderType.postOnly
: Serum3OrderType.limit
2022-10-10 19:16:13 -07:00
const tx = await client.serum3PlaceOrder(
group,
mangoAccount,
2022-11-19 17:40:06 -08:00
selectedMarket.serumMarketExternal,
2022-10-10 19:16:13 -07:00
tradeForm.side === 'buy' ? Serum3Side.bid : Serum3Side.ask,
price,
baseSize,
Serum3SelfTradeBehavior.decrementTake,
2022-10-29 18:17:11 -07:00
spotOrderType,
2022-10-10 19:16:13 -07:00
Date.now(),
10
)
actions.fetchOpenOrders(true)
2023-01-02 04:19:30 -08:00
set((s) => {
s.successAnimation.trade = true
})
if (soundSettings['swap-success']) {
successSound.play()
}
2022-10-10 19:16:13 -07:00
notify({
type: 'success',
title: 'Transaction successful',
txid: tx,
})
2022-10-29 18:17:11 -07:00
} else if (selectedMarket instanceof PerpMarket) {
const perpOrderType =
tradeForm.tradeType === 'Market'
? PerpOrderType.market
: tradeForm.ioc
? PerpOrderType.immediateOrCancel
: tradeForm.postOnly
? PerpOrderType.postOnly
: PerpOrderType.limit
const tx = await client.perpPlaceOrder(
group,
mangoAccount,
selectedMarket.perpMarketIndex,
tradeForm.side === 'buy' ? PerpOrderSide.bid : PerpOrderSide.ask,
price,
2022-11-20 18:29:51 -08:00
Math.abs(baseSize),
2022-10-29 18:17:11 -07:00
undefined, // maxQuoteQuantity
Date.now(),
perpOrderType,
2023-01-16 20:00:42 -08:00
selectedMarket.reduceOnly || tradeForm.reduceOnly,
2022-10-29 18:17:11 -07:00
undefined,
undefined
)
actions.fetchOpenOrders(true)
2023-01-20 03:03:31 -08:00
set((s) => {
s.successAnimation.trade = true
})
if (soundSettings['swap-success']) {
successSound.play()
}
2022-10-29 18:17:11 -07:00
notify({
type: 'success',
title: 'Transaction successful',
txid: tx,
})
2022-10-10 19:16:13 -07:00
}
2023-02-27 23:20:11 -08:00
} catch (e) {
console.error('Place trade error:', e)
if (!isMangoError(e)) return
2022-09-13 23:24:26 -07:00
notify({
2022-09-25 19:02:58 -07:00
title: 'There was an issue.',
2022-09-13 23:24:26 -07:00
description: e.message,
2022-09-25 19:02:58 -07:00
txid: e?.txid,
2022-09-13 23:24:26 -07:00
type: 'error',
})
2022-10-03 16:26:12 -07:00
} finally {
setPlacingOrder(false)
2022-09-13 23:24:26 -07:00
}
}, [])
2022-09-13 23:24:26 -07:00
2023-03-11 01:35:13 -08:00
const sideNames = useMemo(() => {
return selectedMarket instanceof PerpMarket
? [t('trade:long'), t('trade:short')]
: [t('buy'), t('sell')]
2023-03-25 11:47:37 -07:00
}, [selectedMarket, t])
2023-03-11 01:35:13 -08:00
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()
connected ? handlePlaceOrder() : handleConnect()
}
2022-09-13 23:24:26 -07:00
return (
<div>
2023-01-19 13:25:19 -08:00
<div className="mt-1.5 px-2 md:mt-0 md:px-4 md:pt-5 lg:mt-5 lg:pt-0">
2022-12-21 20:19:00 -08:00
<TabUnderline
activeValue={tradeForm.side}
values={['buy', 'sell']}
2023-03-11 01:35:13 -08:00
names={sideNames}
2023-02-27 23:20:11 -08:00
onChange={(v) => handleSetSide(v as 'buy' | 'sell')}
2022-12-21 20:19:00 -08:00
small
2022-09-21 22:32:48 -07:00
/>
2022-09-13 23:24:26 -07:00
</div>
2022-12-08 03:55:31 -08:00
<div className="px-3 md:px-4">
<SolBalanceWarnings className="mt-4" />
2022-11-17 20:43:23 -08:00
</div>
2022-12-21 20:19:00 -08:00
<div className="mt-1 px-2 md:mt-3 md:px-4">
<p className="mb-2 text-xs">{t('trade:order-type')}</p>
<ButtonGroup
activeValue={tradeForm.tradeType}
onChange={(tab: 'Limit' | 'Market') => setTradeType(tab)}
values={['Limit', 'Market']}
2022-10-25 21:44:09 -07:00
/>
2022-09-13 23:24:26 -07:00
</div>
<form onSubmit={(e) => handleSubmit(e)}>
<div className="mt-3 px-3 md:px-4">
{tradeForm.tradeType === 'Limit' ? (
<>
<div className="mb-2 mt-3 flex items-center justify-between">
<p className="text-xs text-th-fgd-3">
{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">
{quoteLogoURI ? (
<div className="h-5 w-5 flex-shrink-0">
<Image alt="" width="20" height="20" src={quoteLogoURI} />
</div>
) : (
<div className="h-5 w-5 flex-shrink-0">
<QuestionMarkCircleIcon className="h-5 w-5 text-th-fgd-3" />
</div>
)}
<NumberFormat
inputMode="decimal"
thousandSeparator=","
allowNegative={false}
isNumericString={true}
decimalScale={6}
name="price"
id="price"
className="ml-2 w-full bg-transparent font-mono focus:outline-none"
placeholder="0.00"
value={tradeForm.price}
onValueChange={handlePriceChange}
/>
<div className="text-xs font-normal text-th-fgd-4">
{quoteSymbol}
</div>
</div>
</>
) : null}
<MaxSizeButton
minOrderDecimals={minOrderDecimals}
tickDecimals={tickDecimals}
useMargin={useMargin}
/>
<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">
<LogoWithFallback
alt=""
className="z-10 drop-shadow-md"
width={'24'}
height={'24'}
src={baseLogoURI || `/icons/${baseSymbol?.toLowerCase()}.svg`}
fallback={
<QuestionMarkCircleIcon
className={`h-5 w-5 text-th-fgd-3`}
/>
}
/>
</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">
{baseSymbol}
</div>
2022-09-19 17:30:29 -07:00
</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">
2022-11-22 15:49:42 -08:00
{quoteLogoURI ? (
2022-12-15 20:45:01 -08:00
<div className="h-5 w-5 flex-shrink-0">
<Image alt="" width="20" height="20" src={quoteLogoURI} />
</div>
2022-11-22 15:49:42 -08:00
) : (
2022-12-15 20:45:01 -08:00
<div className="h-5 w-5 flex-shrink-0">
<QuestionMarkCircleIcon className="h-5 w-5 text-th-fgd-3" />
</div>
2022-11-22 15:49:42 -08:00
)}
2022-09-19 17:30:29 -07:00
<NumberFormat
inputMode="decimal"
thousandSeparator=","
allowNegative={false}
isNumericString={true}
decimalScale={tickDecimals}
name="quote"
id="quote"
2022-11-22 15:49:42 -08:00
className="ml-2 w-full bg-transparent font-mono focus:outline-none"
2022-09-19 17:30:29 -07:00
placeholder="0.00"
value={tradeForm.quoteSize}
onValueChange={handleQuoteSizeChange}
2022-09-19 17:30:29 -07:00
/>
2022-09-26 12:56:06 -07:00
<div className="text-xs font-normal text-th-fgd-4">
2022-09-19 17:30:29 -07:00
{quoteSymbol}
</div>
</div>
2022-09-21 18:52:25 -07:00
</div>
</div>
<div className="mt-2 flex">
{selectedMarket instanceof Serum3Market ? (
tradeFormSizeUi === 'slider' ? (
<SpotSlider
minOrderDecimals={minOrderDecimals}
tickDecimals={tickDecimals}
step={tradeForm.side === 'buy' ? tickSize : minOrderSize}
useMargin={useMargin}
/>
) : (
<SpotButtonGroup
minOrderDecimals={minOrderDecimals}
tickDecimals={tickDecimals}
useMargin={useMargin}
/>
)
) : tradeFormSizeUi === 'slider' ? (
<PerpSlider
2022-12-21 20:19:00 -08:00
minOrderDecimals={minOrderDecimals}
tickDecimals={tickDecimals}
/>
2022-11-15 17:32:55 -08:00
) : (
<PerpButtonGroup
2022-12-21 20:19:00 -08:00
minOrderDecimals={minOrderDecimals}
tickDecimals={tickDecimals}
/>
)}
</div>
<div className="flex flex-wrap px-5 md:flex-nowrap">
{tradeForm.tradeType === 'Limit' ? (
<div className="flex">
<div className="mr-3 mt-4" id="trade-step-six">
<Tooltip
className="hidden md:block"
delay={100}
placement="left"
content={t('trade:tooltip-post')}
>
<Checkbox
checked={tradeForm.postOnly}
onChange={(e) => handlePostOnlyChange(e.target.checked)}
>
{t('trade:post')}
</Checkbox>
</Tooltip>
</div>
<div className="mr-3 mt-4" id="trade-step-seven">
<Tooltip
className="hidden md:block"
delay={100}
placement="left"
content={t('trade:tooltip-ioc')}
>
<div className="flex items-center text-xs text-th-fgd-3">
<Checkbox
checked={tradeForm.ioc}
onChange={(e) => handleIocChange(e.target.checked)}
>
IOC
</Checkbox>
</div>
</Tooltip>
</div>
</div>
) : null}
{selectedMarket instanceof Serum3Market ? (
<div className="mt-4" id="trade-step-eight">
2022-09-13 23:24:26 -07:00
<Tooltip
className="hidden md:block"
2023-03-10 10:01:47 -08:00
delay={100}
2022-09-13 23:24:26 -07:00
placement="left"
content={t('trade:tooltip-enable-margin')}
2022-09-13 23:24:26 -07:00
>
<Checkbox checked={useMargin} onChange={handleSetMargin}>
{t('trade:margin')}
2022-09-13 23:24:26 -07:00
</Checkbox>
</Tooltip>
</div>
) : (
<div className="mr-3 mt-4">
2022-09-13 23:24:26 -07:00
<Tooltip
className="hidden md:block"
2023-03-10 10:01:47 -08:00
delay={100}
2022-10-03 03:38:05 -07:00
placement="left"
content={
'Reduce will only decrease the size of an open position. This is often used for closing a position.'
}
2022-09-13 23:24:26 -07:00
>
<div className="flex items-center text-xs text-th-fgd-3">
<Checkbox
checked={tradeForm.reduceOnly}
onChange={(e) => handleReduceOnlyChange(e.target.checked)}
2022-09-13 23:24:26 -07:00
>
{t('trade:reduce-only')}
2022-09-13 23:24:26 -07:00
</Checkbox>
2023-01-16 20:00:42 -08:00
</div>
</Tooltip>
</div>
)}
</div>
<div className="mt-6 mb-4 flex px-3 md:px-4">
{ipAllowed ? (
<Button
className={`flex w-full items-center justify-center ${
!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'
}`}
disabled={connected && !tradeForm.baseSize}
size="large"
type="submit"
2023-01-16 20:16:25 -08:00
>
{!connected ? (
<div className="flex items-center">
<LinkIcon className="mr-2 h-5 w-5" />
{t('connect')}
</div>
) : !placingOrder ? (
<span>
{t('trade:place-order', {
side:
tradeForm.side === 'buy' ? sideNames[0] : sideNames[1],
})}
</span>
) : (
<div className="flex items-center space-x-2">
<Loading />
<span className="hidden sm:block">
{t('trade:placing-order')}
</span>
</div>
)}
</Button>
) : (
<Button disabled className="w-full leading-tight" size="large">
{t('country-not-allowed', {
country: ipCountry ? `(${ipCountry})` : '',
})}
</Button>
)}
</div>
</form>
{tradeForm.tradeType === 'Market' ? (
<div className="m-4">
<InlineNotification
type="warning"
desc="Use caution with market orders. Liquidity may be low."
/>
</div>
) : null}
2023-03-17 05:48:38 -07:00
<TradeSummary mangoAccount={mangoAccount} useMargin={useMargin} />
2022-09-13 23:24:26 -07:00
</div>
)
}
export default AdvancedTradeForm