From b89523efb2101b783072a1dc61d71b5f996baadc Mon Sep 17 00:00:00 2001 From: "m.ray" <16125548+MadalinaRaicu@users.noreply.github.com> Date: Wed, 13 Mar 2024 19:43:18 +0200 Subject: [PATCH] feat(trading): update validation and rules on take profit and stop loss (#5987) --- .../txs/details/shared/tx-details-shared.tsx | 2 +- .../app/components/txs/tx-transfer.spec.tsx | 4 +- apps/trading/.env | 1 + apps/trading/.env.capsule | 2 + apps/trading/.env.mainnet | 1 + apps/trading/.env.stagnet1 | 1 + apps/trading/.env.testnet | 1 + apps/trading/.env.validators-testnet | 1 + .../deal-ticket/deal-ticket-price-tp-sl.tsx | 17 +----- .../components/deal-ticket/deal-ticket.tsx | 57 +++++++++++-------- libs/environment/src/hooks/use-environment.ts | 6 ++ libs/environment/src/types.ts | 1 + .../src/utils/validate-environment.ts | 1 + .../market-info/market-info-panels.tsx | 3 +- .../utils/src/lib/validate/validate-amount.ts | 6 +- 15 files changed, 56 insertions(+), 48 deletions(-) diff --git a/apps/explorer/src/app/components/txs/details/shared/tx-details-shared.tsx b/apps/explorer/src/app/components/txs/details/shared/tx-details-shared.tsx index 17c9aeef1..384decc0c 100644 --- a/apps/explorer/src/app/components/txs/details/shared/tx-details-shared.tsx +++ b/apps/explorer/src/app/components/txs/details/shared/tx-details-shared.tsx @@ -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) { diff --git a/apps/explorer/src/app/components/txs/tx-transfer.spec.tsx b/apps/explorer/src/app/components/txs/tx-transfer.spec.tsx index f9c67e18d..4f5e5f29e 100644 --- a/apps/explorer/src/app/components/txs/tx-transfer.spec.tsx +++ b/apps/explorer/src/app/components/txs/tx-transfer.spec.tsx @@ -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', () => { diff --git a/apps/trading/.env b/apps/trading/.env index 2c6c06afa..8b4f4d571 100644 --- a/apps/trading/.env +++ b/apps/trading/.env @@ -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 diff --git a/apps/trading/.env.capsule b/apps/trading/.env.capsule index f49446f32..121d0789f 100644 --- a/apps/trading/.env.capsule +++ b/apps/trading/.env.capsule @@ -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 diff --git a/apps/trading/.env.mainnet b/apps/trading/.env.mainnet index a37ccdf44..38919a016 100644 --- a/apps/trading/.env.mainnet +++ b/apps/trading/.env.mainnet @@ -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 diff --git a/apps/trading/.env.stagnet1 b/apps/trading/.env.stagnet1 index 6cb9bf821..775602eb5 100644 --- a/apps/trading/.env.stagnet1 +++ b/apps/trading/.env.stagnet1 @@ -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 diff --git a/apps/trading/.env.testnet b/apps/trading/.env.testnet index 39e3202db..0201f07a2 100644 --- a/apps/trading/.env.testnet +++ b/apps/trading/.env.testnet @@ -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 diff --git a/apps/trading/.env.validators-testnet b/apps/trading/.env.validators-testnet index b5ef5a6e7..caf021109 100644 --- a/apps/trading/.env.validators-testnet +++ b/apps/trading/.env.validators-testnet @@ -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 diff --git a/libs/deal-ticket/src/components/deal-ticket/deal-ticket-price-tp-sl.tsx b/libs/deal-ticket/src/components/deal-ticket/deal-ticket-price-tp-sl.tsx index c638438bd..79dadc021 100644 --- a/libs/deal-ticket/src/components/deal-ticket/deal-ticket-price-tp-sl.tsx +++ b/libs/deal-ticket/src/components/deal-ticket/deal-ticket-price-tp-sl.tsx @@ -28,8 +28,8 @@ export const DealTicketPriceTakeProfitStopLoss = ({ quoteName, }: DealTicketPriceTakeProfitStopLossProps) => { const t = useT(); - const validateAmount = useValidateAmount(); const priceStep = determinePriceStep(market); + const validateAmount = useValidateAmount(); return (
@@ -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 }) => ( diff --git a/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx b/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx index 64cae4e08..a86d49c84 100644 --- a/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx +++ b/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx @@ -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 = ({ )} /> )} - ( - {t('TP_SL_TOOLTIP', 'Take profit / Stop loss')}

- } - > -
- -
-
- )} - /> + {featureFlags.TAKE_PROFIT_STOP_LOSS && ( + ( + {t('TP_SL_TOOLTIP', 'Take profit / Stop loss')}

+ } + > +
+ +
+
+ )} + /> + )}
{isLimitType && iceberg && ( )} - {tpSl && ( + {featureFlags.TAKE_PROFIT_STOP_LOSS && tpSl && ( { 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', diff --git a/libs/environment/src/types.ts b/libs/environment/src/types.ts index b68a89119..3c5b2e82c 100644 --- a/libs/environment/src/types.ts +++ b/libs/environment/src/types.ts @@ -21,6 +21,7 @@ export type CosmicElevatorFlags = Pick< FeatureFlags, | 'ICEBERG_ORDERS' | 'ISOLATED_MARGIN' + | 'TAKE_PROFIT_STOP_LOSS' | 'STOP_ORDERS' | 'SUCCESSOR_MARKETS' | 'PRODUCT_PERPETUALS' diff --git a/libs/environment/src/utils/validate-environment.ts b/libs/environment/src/utils/validate-environment.ts index 07c9710e2..24f339e5f 100644 --- a/libs/environment/src/utils/validate-environment.ts +++ b/libs/environment/src/utils/validate-environment.ts @@ -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()), diff --git a/libs/markets/src/lib/components/market-info/market-info-panels.tsx b/libs/markets/src/lib/components/market-info/market-info-panels.tsx index 336f62fc2..b7f45f324 100644 --- a/libs/markets/src/lib/components/market-info/market-info-panels.tsx +++ b/libs/markets/src/lib/components/market-info/market-info-panels.tsx @@ -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 ( <> -
+

{t('{{probability}} probability price bounds', { probability: formatNumberPercentage( diff --git a/libs/utils/src/lib/validate/validate-amount.ts b/libs/utils/src/lib/validate/validate-amount.ts index e5ddde5a9..89062740e 100644 --- a/libs/utils/src/lib/validate/validate-amount.ts +++ b/libs/utils/src/lib/validate/validate-amount.ts @@ -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); };