From c1dcca43c8bc3f48869c226fb1f7edbdd2089aa4 Mon Sep 17 00:00:00 2001 From: jaredvu Date: Wed, 23 Aug 2023 23:32:02 -0700 Subject: [PATCH] Render TradeBoxOrderView from Abacus typeOptions --- src/constants/abacus.ts | 19 ++++- src/constants/trade.ts | 10 +-- src/views/TradeBoxOrderView.tsx | 78 +++++++++++-------- .../DetailsDialog/OrderDetailsDialog.tsx | 2 +- 4 files changed, 69 insertions(+), 40 deletions(-) diff --git a/src/constants/abacus.ts b/src/constants/abacus.ts index 55c0ad7..80d9747 100644 --- a/src/constants/abacus.ts +++ b/src/constants/abacus.ts @@ -1,6 +1,6 @@ import Abacus, { kollections } from '@dydxprotocol/abacus'; import { OrderSide } from '@dydxprotocol/v4-client'; -import { PositionSide } from './trade'; +import { PositionSide, TradeTypes } from './trade'; import { STRING_KEYS } from './localization'; export type Nullable = T | null | undefined; @@ -99,6 +99,7 @@ export type TradeInputSummary = Abacus.exchange.dydx.abacus.output.input.TradeIn export type TransferInputs = Abacus.exchange.dydx.abacus.output.input.TransferInput; export type InputError = Abacus.exchange.dydx.abacus.output.input.ValidationError; export const ErrorType = Abacus.exchange.dydx.abacus.output.input.ErrorType; +export const InputSelectionOption = Abacus.exchange.dydx.abacus.output.input.SelectionOption; // ------ Wallet ------ // export type Wallet = Abacus.exchange.dydx.abacus.output.Wallet; @@ -215,3 +216,19 @@ export const ORDER_STATUS_STRINGS: Record, + Nullable +> = { + [AbacusOrderType.limit.name]: TradeTypes.LIMIT, + [AbacusOrderType.market.name]: TradeTypes.MARKET, + [AbacusOrderType.stopLimit.name]: TradeTypes.STOP_LIMIT, + [AbacusOrderType.stopMarket.name]: TradeTypes.STOP_MARKET, + [AbacusOrderType.takeProfitLimit.name]: TradeTypes.TAKE_PROFIT, + [AbacusOrderType.takeProfitMarket.name]: TradeTypes.TAKE_PROFIT_MARKET, + + [AbacusOrderType.liquidated.name]: null, + [AbacusOrderType.liquidation.name]: null, + [AbacusOrderType.trailingStop.name]: null, +}; diff --git a/src/constants/trade.ts b/src/constants/trade.ts index bff4237..7444c49 100644 --- a/src/constants/trade.ts +++ b/src/constants/trade.ts @@ -10,7 +10,7 @@ export enum TradeTypes { LIMIT = 'LIMIT', STOP_LIMIT = 'STOP_LIMIT', STOP_MARKET = 'STOP_MARKET', - TAKE_PROFIT_LIMIT = 'TAKE_PROFIT_LIMIT', + TAKE_PROFIT = 'TAKE_PROFIT', TAKE_PROFIT_MARKET = 'TAKE_PROFIT_MARKET', TRAILING_STOP = 'TRAILING_STOP', } @@ -30,9 +30,9 @@ export enum PositionSide { export const UNCOMMITTED_ORDER_TIMEOUT = 10_000; export const ORDER_SIDE_STRINGS = { - [OrderSide.SIDE_BUY]: STRING_KEYS.BUY, - [OrderSide.SIDE_SELL]: STRING_KEYS.SELL, -} + [OrderSide.BUY]: STRING_KEYS.BUY, + [OrderSide.SELL]: STRING_KEYS.SELL, +}; export const POSITION_SIDE_STRINGS: Record = { [PositionSide.None]: STRING_KEYS.NONE, @@ -68,7 +68,7 @@ export const TRADE_TYPE_STRINGS: Record< tradeTypeKey: STRING_KEYS.STOP_MARKET, descriptionKey: STRING_KEYS.STOP_MARKET_DESCRIPTION, }, - [TradeTypes.TAKE_PROFIT_LIMIT]: { + [TradeTypes.TAKE_PROFIT]: { tradeTypeKeyShort: STRING_KEYS.TAKE_PROFIT_LIMIT, tradeTypeKey: STRING_KEYS.TAKE_PROFIT_LIMIT, descriptionKey: STRING_KEYS.TAKE_PROFIT_LIMIT_DESCRIPTION, diff --git a/src/views/TradeBoxOrderView.tsx b/src/views/TradeBoxOrderView.tsx index 948f8d1..52696d0 100644 --- a/src/views/TradeBoxOrderView.tsx +++ b/src/views/TradeBoxOrderView.tsx @@ -1,58 +1,70 @@ +import { useCallback } from 'react'; import styled, { AnyStyledComponent } from 'styled-components'; import { shallowEqual, useSelector } from 'react-redux'; +import { createSelector } from 'reselect'; import { TradeInputField } from '@/constants/abacus'; -import { TradeTypes, TRADE_TYPE_STRINGS } from '@/constants/trade'; +import { TradeTypes } from '@/constants/trade'; import { STRING_KEYS } from '@/constants/localization'; import { useStringGetter } from '@/hooks'; import { layoutMixins } from '@/styles/layoutMixins'; import { Tabs } from '@/components/Tabs'; -import { getInputTradeData } from '@/state/inputsSelectors'; +import { getInputTradeData, getInputTradeOptions } from '@/state/inputsSelectors'; import abacusStateManager from '@/lib/abacus'; -import { getSelectedTradeType } from '@/lib/tradeData'; +import { isTruthy } from '@/lib/isTruthy'; import { TradeForm } from './forms/TradeForm'; -export const TradeBoxOrderView = () => { +const useTradeTypeOptions = () => { const stringGetter = useStringGetter(); - const currentTradeData = useSelector(getInputTradeData, shallowEqual); - const { type } = currentTradeData || {}; - const selectedTradeType = getSelectedTradeType(type); + const selectedTradeType = useSelector( + createSelector( + [getInputTradeData], + (currentTradeData) => (currentTradeData?.type?.rawValue as TradeTypes) ?? TradeTypes.LIMIT + ) + ); + const { typeOptions } = useSelector(getInputTradeOptions, shallowEqual) ?? {}; + const allTradeTypeItems = typeOptions?.toArray()?.map(({ type, stringKey }) => ({ + value: type, + label: stringGetter({ key: stringKey }), + })); - const onTradeTypeChange = (tradeType?: TradeTypes) => { + return { + selectedTradeType, + tradeTypeItems: allTradeTypeItems + ? [ + allTradeTypeItems?.shift(), // Limit order is always first + allTradeTypeItems?.shift(), // Market order is always second + // All conditional orders labeled under "Stop Order" + allTradeTypeItems?.length && { + label: stringGetter({ key: STRING_KEYS.STOP_ORDER_SHORT }), + subitems: allTradeTypeItems + ?.map( + ({ value, label }) => + value && { + value: value as TradeTypes, + label, + } + ) + .filter(isTruthy), + }, + ].filter(isTruthy) + : [], + }; +}; + +export const TradeBoxOrderView = () => { + const onTradeTypeChange = useCallback((tradeType?: TradeTypes) => { if (tradeType) { abacusStateManager.clearTradeInputValues(); abacusStateManager.setTradeValue({ value: tradeType, field: TradeInputField.type }); } - }; + }, []); - const tradeTypeItems = [ - { - value: TradeTypes.LIMIT, - label: stringGetter({ key: TRADE_TYPE_STRINGS[TradeTypes.LIMIT].tradeTypeKeyShort }), - }, - { - value: TradeTypes.MARKET, - label: stringGetter({ key: TRADE_TYPE_STRINGS[TradeTypes.MARKET].tradeTypeKeyShort }), - }, - { - label: stringGetter({ key: STRING_KEYS.STOP_ORDER_SHORT }), - subitems: [ - TradeTypes.STOP_LIMIT, - TradeTypes.STOP_MARKET, - TradeTypes.TRAILING_STOP, - TradeTypes.TAKE_PROFIT_LIMIT, - TradeTypes.TAKE_PROFIT_MARKET, - ].map((tradeType) => ({ - value: tradeType, - label: stringGetter({ key: TRADE_TYPE_STRINGS[tradeType].tradeTypeKeyShort }), - disabled: tradeType === TradeTypes.TRAILING_STOP, - })), - }, - ]; + const { selectedTradeType, tradeTypeItems } = useTradeTypeOptions(); return ( void; + setIsOpen: (open: boolean) => void; }; export const OrderDetailsDialog = ({ orderId, setIsOpen }: ElementProps) => {