feat(trading): update validation and rules on take profit and stop loss (#5987)
This commit is contained in:
parent
be9a5a3437
commit
b89523efb2
@ -48,7 +48,7 @@ export const TxDetailsShared = ({
|
||||
}: TxDetailsSharedProps) => {
|
||||
const { data } = useExplorerEpochForBlockQuery({
|
||||
errorPolicy: 'ignore',
|
||||
variables: { block: txData?.block.toString() || '' },
|
||||
variables: { block: txData?.block?.toString() || '' },
|
||||
});
|
||||
|
||||
if (!txData) {
|
||||
|
@ -21,7 +21,7 @@ describe('TX: Transfer: getLabelForTransfer', () => {
|
||||
},
|
||||
};
|
||||
|
||||
expect(getTypeLabelForTransfer(mock)).toEqual('Reward top up transfer');
|
||||
expect(getTypeLabelForTransfer(mock)).toEqual('Reward transfer');
|
||||
});
|
||||
|
||||
it('renders reward top up label if the TO party is network', () => {
|
||||
@ -32,7 +32,7 @@ describe('TX: Transfer: getLabelForTransfer', () => {
|
||||
},
|
||||
};
|
||||
|
||||
expect(getTypeLabelForTransfer(mock)).toEqual('Reward top up transfer');
|
||||
expect(getTypeLabelForTransfer(mock)).toEqual('Reward transfer');
|
||||
});
|
||||
|
||||
it('renders recurring label if the tx has a recurring property', () => {
|
||||
|
@ -21,6 +21,7 @@ NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_STOP_ORDERS=true
|
||||
NX_TAKE_PROFIT_STOP_LOSS=true
|
||||
NX_ISOLATED_MARGIN=true
|
||||
NX_ICEBERG_ORDERS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
|
@ -21,6 +21,8 @@ NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supp
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=false
|
||||
NX_STOP_ORDERS=false
|
||||
NX_TAKE_PROFIT_STOP_LOSS=false
|
||||
NX_TAKE_PROFIT_STOP_LOSS=true
|
||||
NX_ISOLATED_MARGIN=true
|
||||
# NX_ICEBERG_ORDERS
|
||||
# NX_PRODUCT_PERPETUALS
|
||||
|
@ -21,6 +21,7 @@ NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_STOP_ORDERS=true
|
||||
NX_TAKE_PROFIT_STOP_LOSS=false
|
||||
NX_ISOLATED_MARGIN=false
|
||||
NX_ICEBERG_ORDERS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
|
@ -21,6 +21,7 @@ NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_STOP_ORDERS=true
|
||||
NX_TAKE_PROFIT_STOP_LOSS=true
|
||||
NX_ISOLATED_MARGIN=true
|
||||
NX_ICEBERG_ORDERS=true
|
||||
# NX_PRODUCT_PERPETUALS
|
||||
|
@ -22,6 +22,7 @@ NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_STOP_ORDERS=true
|
||||
NX_TAKE_PROFIT_STOP_LOSS=true
|
||||
NX_ISOLATED_MARGIN=true
|
||||
NX_ICEBERG_ORDERS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
|
@ -22,6 +22,7 @@ NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/m
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_STOP_ORDERS=true
|
||||
NX_TAKE_PROFIT_STOP_LOSS=true
|
||||
NX_ISOLATED_MARGIN=true
|
||||
NX_ICEBERG_ORDERS=true
|
||||
# NX_PRODUCT_PERPETUALS
|
||||
|
@ -28,8 +28,8 @@ export const DealTicketPriceTakeProfitStopLoss = ({
|
||||
quoteName,
|
||||
}: DealTicketPriceTakeProfitStopLossProps) => {
|
||||
const t = useT();
|
||||
const validateAmount = useValidateAmount();
|
||||
const priceStep = determinePriceStep(market);
|
||||
const validateAmount = useValidateAmount();
|
||||
|
||||
return (
|
||||
<div className="mb-2">
|
||||
@ -50,15 +50,6 @@ export const DealTicketPriceTakeProfitStopLoss = ({
|
||||
name="takeProfit"
|
||||
control={control}
|
||||
rules={{
|
||||
min: {
|
||||
value: priceStep,
|
||||
message: t(
|
||||
'Take profit price cannot be lower than {{priceStep}}',
|
||||
{
|
||||
priceStep,
|
||||
}
|
||||
),
|
||||
},
|
||||
validate: validateAmount(priceStep, 'takeProfit'),
|
||||
}}
|
||||
render={({ field, fieldState }) => (
|
||||
@ -103,12 +94,6 @@ export const DealTicketPriceTakeProfitStopLoss = ({
|
||||
name="stopLoss"
|
||||
control={control}
|
||||
rules={{
|
||||
min: {
|
||||
value: priceStep,
|
||||
message: t('Price cannot be lower than {{priceStep}}', {
|
||||
priceStep,
|
||||
}),
|
||||
},
|
||||
validate: validateAmount(priceStep, 'stopLoss'),
|
||||
}}
|
||||
render={({ field, fieldState }) => (
|
||||
|
@ -77,7 +77,7 @@ import { DealTicketSizeIceberg } from './deal-ticket-size-iceberg';
|
||||
import noop from 'lodash/noop';
|
||||
import { isNonPersistentOrder } from '../../utils/time-in-force-persistence';
|
||||
import { KeyValue } from './key-value';
|
||||
import { DocsLinks } from '@vegaprotocol/environment';
|
||||
import { DocsLinks, useFeatureFlags } from '@vegaprotocol/environment';
|
||||
import { useT } from '../../use-t';
|
||||
import { DealTicketPriceTakeProfitStopLoss } from './deal-ticket-price-tp-sl';
|
||||
import uniqueId from 'lodash/uniqueId';
|
||||
@ -381,6 +381,7 @@ export const DealTicket = ({
|
||||
const disablePostOnlyCheckbox = nonPersistentOrder;
|
||||
const disableReduceOnlyCheckbox = !nonPersistentOrder;
|
||||
const disableIcebergCheckbox = nonPersistentOrder;
|
||||
const featureFlags = useFeatureFlags((state) => state.flags);
|
||||
|
||||
const onSubmit = useCallback(
|
||||
(formValues: OrderFormValues) => {
|
||||
@ -388,7 +389,11 @@ export const DealTicket = ({
|
||||
if (lastSubmitTime.current && now - lastSubmitTime.current < 1000) {
|
||||
return;
|
||||
}
|
||||
if (formValues.tpSl) {
|
||||
if (
|
||||
featureFlags.TAKE_PROFIT_STOP_LOSS &&
|
||||
formValues.tpSl &&
|
||||
(formValues.takeProfit || formValues.stopLoss)
|
||||
) {
|
||||
const reference = `${pubKey}-${now}-${uniqueId()}`;
|
||||
const batchMarketInstructions = mapFormValuesToTakeProfitAndStopLoss(
|
||||
formValues,
|
||||
@ -409,7 +414,7 @@ export const DealTicket = ({
|
||||
}
|
||||
lastSubmitTime.current = now;
|
||||
},
|
||||
[market, pubKey, submit]
|
||||
[featureFlags.TAKE_PROFIT_STOP_LOSS, market, pubKey, submit]
|
||||
);
|
||||
useController({
|
||||
name: 'type',
|
||||
@ -726,27 +731,29 @@ export const DealTicket = ({
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
<Controller
|
||||
name="tpSl"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<Tooltip
|
||||
description={
|
||||
<p>{t('TP_SL_TOOLTIP', 'Take profit / Stop loss')}</p>
|
||||
}
|
||||
>
|
||||
<div>
|
||||
<Checkbox
|
||||
name="tpSl"
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
disabled={false}
|
||||
label={t('TP / SL')}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
/>
|
||||
{featureFlags.TAKE_PROFIT_STOP_LOSS && (
|
||||
<Controller
|
||||
name="tpSl"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<Tooltip
|
||||
description={
|
||||
<p>{t('TP_SL_TOOLTIP', 'Take profit / Stop loss')}</p>
|
||||
}
|
||||
>
|
||||
<div>
|
||||
<Checkbox
|
||||
name="tpSl"
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
disabled={false}
|
||||
label={t('TP / SL')}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{isLimitType && iceberg && (
|
||||
<DealTicketSizeIceberg
|
||||
@ -758,7 +765,7 @@ export const DealTicket = ({
|
||||
peakSize={peakSize}
|
||||
/>
|
||||
)}
|
||||
{tpSl && (
|
||||
{featureFlags.TAKE_PROFIT_STOP_LOSS && tpSl && (
|
||||
<DealTicketPriceTakeProfitStopLoss
|
||||
market={market}
|
||||
takeProfitError={errors.takeProfit?.message}
|
||||
|
@ -390,6 +390,12 @@ export const compileFeatureFlags = (refresh = false): FeatureFlags => {
|
||||
STOP_ORDERS: TRUTHY.includes(
|
||||
windowOrDefault('NX_STOP_ORDERS', process.env['NX_STOP_ORDERS']) as string
|
||||
),
|
||||
TAKE_PROFIT_STOP_LOSS: TRUTHY.includes(
|
||||
windowOrDefault(
|
||||
'NX_TAKE_PROFIT_STOP_LOSS',
|
||||
process.env['NX_TAKE_PROFIT_STOP_LOSS']
|
||||
) as string
|
||||
),
|
||||
ISOLATED_MARGIN: TRUTHY.includes(
|
||||
windowOrDefault(
|
||||
'NX_ISOLATED_MARGIN',
|
||||
|
@ -21,6 +21,7 @@ export type CosmicElevatorFlags = Pick<
|
||||
FeatureFlags,
|
||||
| 'ICEBERG_ORDERS'
|
||||
| 'ISOLATED_MARGIN'
|
||||
| 'TAKE_PROFIT_STOP_LOSS'
|
||||
| 'STOP_ORDERS'
|
||||
| 'SUCCESSOR_MARKETS'
|
||||
| 'PRODUCT_PERPETUALS'
|
||||
|
@ -67,6 +67,7 @@ export const envSchema = z
|
||||
const COSMIC_ELEVATOR_FLAGS = {
|
||||
SUCCESSOR_MARKETS: z.optional(z.boolean()),
|
||||
STOP_ORDERS: z.optional(z.boolean()),
|
||||
TAKE_PROFIT_STOP_LOSS: z.optional(z.boolean()),
|
||||
ISOLATED_MARGIN: z.optional(z.boolean()),
|
||||
ICEBERG_ORDERS: z.optional(z.boolean()),
|
||||
PRODUCT_PERPETUALS: z.optional(z.boolean()),
|
||||
|
@ -197,6 +197,7 @@ export const MarketVolumeInfoPanel = ({ market }: MarketInfoProps) => {
|
||||
marketId={market.id}
|
||||
positionDecimalPlaces={market.positionDecimalPlaces}
|
||||
marketDecimals={market.decimalPlaces}
|
||||
quoteUnit={getQuoteName(market)}
|
||||
/>
|
||||
),
|
||||
openInterest: dash(data?.openInterest),
|
||||
@ -788,7 +789,7 @@ export const PriceMonitoringBoundsInfoPanel = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-2 grid grid-cols-2 text-sm">
|
||||
<div className="mb-2 grid grid-cols-2 text-xs">
|
||||
<p className="col-span-1">
|
||||
{t('{{probability}} probability price bounds', {
|
||||
probability: formatNumberPercentage(
|
||||
|
@ -7,7 +7,7 @@ export const useValidateAmount = () => {
|
||||
return useCallback(
|
||||
(step: number | string, field: string) => {
|
||||
return (value?: string) => {
|
||||
const isValid = validateAgainstStep(step, value);
|
||||
const isValid = value ? validateAgainstStep(step, value) : true;
|
||||
if (!isValid) {
|
||||
if (new BigNumber(step).isEqualTo(1)) {
|
||||
return t('{{field}} must be whole numbers for this market', {
|
||||
@ -33,7 +33,7 @@ const isMultipleOf = (value: BigNumber, multipleOf: BigNumber) =>
|
||||
|
||||
export const validateAgainstStep = (
|
||||
step: string | number,
|
||||
input?: string | number
|
||||
input: string | number
|
||||
) => {
|
||||
const stepValue = new BigNumber(step);
|
||||
if (stepValue.isNaN()) {
|
||||
@ -45,6 +45,6 @@ export const validateAgainstStep = (
|
||||
return true;
|
||||
}
|
||||
|
||||
const value = new BigNumber(input || '');
|
||||
const value = new BigNumber(input);
|
||||
return isMultipleOf(value, stepValue);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user