From c9596de9c3b190fa325e1e8b0bafe896b29eee56 Mon Sep 17 00:00:00 2001 From: moo-onthelawn <70078372+moo-onthelawn@users.noreply.github.com> Date: Fri, 26 Jan 2024 17:03:32 -0500 Subject: [PATCH] TRCL-3322 Implement reduce-only checkbox on frontend (#246) * implemented * eol lint again * update with correct abacus version * update localization to latest * fix localization v --- package.json | 4 +- pnpm-lock.yaml | 16 +++--- src/components/Checkbox.stories.tsx | 12 ++++- src/components/Checkbox.tsx | 24 +++++++-- src/constants/tooltips/trade.ts | 12 +++++ src/state/inputsSelectors.ts | 4 ++ src/views/forms/TradeForm.tsx | 5 +- .../forms/TradeForm/AdvancedTradeOptions.tsx | 50 ++++++++++--------- 8 files changed, 86 insertions(+), 41 deletions(-) diff --git a/package.json b/package.json index ac200a9..e861653 100644 --- a/package.json +++ b/package.json @@ -39,9 +39,9 @@ "@cosmjs/proto-signing": "^0.32.1", "@cosmjs/stargate": "^0.32.1", "@cosmjs/tendermint-rpc": "^0.32.1", - "@dydxprotocol/v4-abacus": "^1.2.5", + "@dydxprotocol/v4-abacus": "^1.3.2", "@dydxprotocol/v4-client-js": "^1.0.17", - "@dydxprotocol/v4-localization": "^1.1.11", + "@dydxprotocol/v4-localization": "^1.1.17", "@ethersproject/providers": "^5.7.2", "@js-joda/core": "^5.5.3", "@radix-ui/react-accordion": "^1.1.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 70eb80a..c1dec29 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,14 +27,14 @@ dependencies: specifier: ^0.32.1 version: 0.32.2 '@dydxprotocol/v4-abacus': - specifier: ^1.2.5 - version: 1.2.5 + specifier: ^1.3.2 + version: 1.3.2 '@dydxprotocol/v4-client-js': specifier: ^1.0.17 version: 1.0.17 '@dydxprotocol/v4-localization': - specifier: ^1.1.11 - version: 1.1.11 + specifier: ^1.1.17 + version: 1.1.17 '@ethersproject/providers': specifier: ^5.7.2 version: 5.7.2 @@ -1086,8 +1086,8 @@ packages: resolution: {integrity: sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==} dev: true - /@dydxprotocol/v4-abacus@1.2.5: - resolution: {integrity: sha512-pB3Fv1bzJRUDp29kAN61daZ34gTSGrSTNh+/AP3TUB63/Q/gaXQVBf91xVcso4Hw23xM3FwIcrRK0cvOSWgXKg==} + /@dydxprotocol/v4-abacus@1.3.2: + resolution: {integrity: sha512-zo0IHjGMlJRKOYDgNqNFQ9GtBJKJP4+Y9YY7V0X3Wt61ppKAYzodaYQhc9V/RYchcZTtS/xkicLug444YrvehQ==} dev: false /@dydxprotocol/v4-client-js@1.0.17: @@ -1119,8 +1119,8 @@ packages: - utf-8-validate dev: false - /@dydxprotocol/v4-localization@1.1.11: - resolution: {integrity: sha512-ZHnyrWD1bEpvY1tctkcmSV6A5+hQSYBFwyjbiyOqepqDqrv24J5a3hlZU94lDyYf+7Sdk3alOvy9Z7Lpk59nvw==} + /@dydxprotocol/v4-localization@1.1.17: + resolution: {integrity: sha512-kal1LrcihLMEv5YxaA/hd6Zl10Mp3x6jicoXDcXvtyNdrczAl3YapyI2nmeifRAPvfueOaY3W/sKkm2BiSKSsA==} dev: false /@dydxprotocol/v4-proto@3.0.0-dev.0: diff --git a/src/components/Checkbox.stories.tsx b/src/components/Checkbox.stories.tsx index 248519c..3a4f24a 100644 --- a/src/components/Checkbox.stories.tsx +++ b/src/components/Checkbox.stories.tsx @@ -5,7 +5,7 @@ import { Checkbox, CheckboxProps } from '@/components/Checkbox'; import { StoryWrapper } from '.ladle/components'; -export const Checkboxes: Story = (args) => { +export const CheckboxStory: Story = (args) => { const [isChecked, setIsChecked] = useState(false); return ( @@ -21,4 +21,12 @@ export const Checkboxes: Story = (args) => { ); }; -Checkboxes.args = {}; +CheckboxStory.args = {}; + +CheckboxStory.argTypes = { + disabled: { + options: [true, false], + control: { type: 'select' }, + defaultValue: false, + } +} diff --git a/src/components/Checkbox.tsx b/src/components/Checkbox.tsx index 037f881..f916091 100644 --- a/src/components/Checkbox.tsx +++ b/src/components/Checkbox.tsx @@ -1,4 +1,4 @@ -import styled, { type AnyStyledComponent } from 'styled-components'; +import styled, { css, type AnyStyledComponent } from 'styled-components'; import { Root, Indicator } from '@radix-ui/react-checkbox'; import { CheckIcon } from '@radix-ui/react-icons'; @@ -9,6 +9,7 @@ type ElementProps = { onCheckedChange: (checked: boolean) => void; id?: string; label?: React.ReactNode; + disabled?: boolean; }; type StyleProps = { @@ -23,14 +24,15 @@ export const Checkbox: React.FC = ({ onCheckedChange, id, label, + disabled }) => ( - + - {label && } + {label && {label}} ); @@ -48,17 +50,23 @@ Styled.Container = styled.div` Styled.Root = styled(Root)` --checkbox-backgroundColor: var(--color-layer-0); + --checkbox-borderColor: var(--color-border); min-width: 1.25rem; height: 1.25rem; border-radius: 0.375rem; - border: var(--border-width) solid var(--color-border); + border: var(--border-width) solid var(--checkbox-borderColor); background-color: var(--checkbox-backgroundColor); &[data-state='checked'] { --checkbox-backgroundColor: var(--color-accent); } + + &[data-disabled] { + cursor: not-allowed; + --checkbox-backgroundColor: var(--color-layer-1); + } `; Styled.Indicator = styled(Indicator)` @@ -68,3 +76,11 @@ Styled.Indicator = styled(Indicator)` color: var(--color-text-2); `; + +Styled.label = styled.div<{ disabled: boolean; }>` + color: var(--color-text-2); + + ${({disabled}) => disabled && css` + color: var(--color-text-0); + `} +`; diff --git a/src/constants/tooltips/trade.ts b/src/constants/tooltips/trade.ts index d4b1695..84724b9 100644 --- a/src/constants/tooltips/trade.ts +++ b/src/constants/tooltips/trade.ts @@ -138,6 +138,10 @@ export const tradeTooltips: TooltipStrings = { title: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_TITLE }), body: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_BODY }), }), + 'post-only-timeinforce-gtt': ({ stringGetter }) => ({ + title: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_TIMEINFORCE_GTT_TITLE }), + body: stringGetter({ key: TOOLTIP_STRING_KEYS.POST_ONLY_TIMEINFORCE_GTT_BODY }), + }), 'price-impact': ({ stringGetter }) => ({ title: stringGetter({ key: TOOLTIP_STRING_KEYS.PRICE_IMPACT_TITLE }), body: stringGetter({ key: TOOLTIP_STRING_KEYS.PRICE_IMPACT_BODY }), @@ -151,6 +155,14 @@ export const tradeTooltips: TooltipStrings = { body: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_BODY }), learnMoreLink: urlConfigs?.reduceOnlyLearnMore, }), + 'reduce-only-execution-ioc-fok': ({ stringGetter }) => ({ + title: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_EXECUTION_IOC_FOK_TITLE }), + body: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_EXECUTION_IOC_FOK_BODY }), + }), + 'reduce-only-timeinforce-ioc-fok': ({ stringGetter }) => ({ + title: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_TIMEINFORCE_IOC_FOK_TITLE }), + body: stringGetter({ key: TOOLTIP_STRING_KEYS.REDUCE_ONLY_TIMEINFORCE_IOC_FOK_BODY }), + }), spread: () => ({ title: 'Spread', body: 'The difference in price between the highest bid (the price a buyer is willing to buy for) and lowest ask (the price a seller is willing to sell for) an asset.', diff --git a/src/state/inputsSelectors.ts b/src/state/inputsSelectors.ts index e9d5e3c..5b88f64 100644 --- a/src/state/inputsSelectors.ts +++ b/src/state/inputsSelectors.ts @@ -96,6 +96,8 @@ export const useTradeFormData = () => { needsGoodUntil, needsPostOnly, needsReduceOnly, + postOnlyTooltip, + reduceOnlyTooltip, timeInForceOptions, } = tradeOptions || {}; @@ -111,6 +113,8 @@ export const useTradeFormData = () => { needsGoodUntil, needsPostOnly, needsReduceOnly, + postOnlyTooltip, + reduceOnlyTooltip, timeInForceOptions, tradeErrors, diff --git a/src/views/forms/TradeForm.tsx b/src/views/forms/TradeForm.tsx index 78f5759..921c356 100644 --- a/src/views/forms/TradeForm.tsx +++ b/src/views/forms/TradeForm.tsx @@ -10,7 +10,6 @@ import { type HumanReadablePlaceOrderPayload, type Nullable, TradeInputErrorAction, - TradeInputField, ValidationError, } from '@/constants/abacus'; @@ -96,6 +95,8 @@ export const TradeForm = ({ needsGoodUntil, needsPostOnly, needsReduceOnly, + postOnlyTooltip, + reduceOnlyTooltip, timeInForceOptions, tradeErrors, } = useTradeFormData(); @@ -108,7 +109,7 @@ export const TradeForm = ({ const { limitPriceInput, triggerPriceInput, trailingPercentInput } = tradeFormInputValues; const needsAdvancedOptions = - needsGoodUntil || timeInForceOptions || executionOptions || needsPostOnly || needsReduceOnly; + needsGoodUntil || timeInForceOptions || executionOptions || (needsPostOnly || postOnlyTooltip) || (needsReduceOnly || reduceOnlyTooltip); const tradeFormInputs: TradeBoxInputConfig[] = []; diff --git a/src/views/forms/TradeForm/AdvancedTradeOptions.tsx b/src/views/forms/TradeForm/AdvancedTradeOptions.tsx index cc3300b..507f204 100644 --- a/src/views/forms/TradeForm/AdvancedTradeOptions.tsx +++ b/src/views/forms/TradeForm/AdvancedTradeOptions.tsx @@ -31,12 +31,15 @@ export const AdvancedTradeOptions = () => { const { execution, goodTil, postOnly, reduceOnly, timeInForce, type } = inputTradeData || {}; - const { executionOptions, needsGoodUntil, needsPostOnly, needsReduceOnly, timeInForceOptions } = + const { executionOptions, needsGoodUntil, needsPostOnly, needsReduceOnly, postOnlyTooltip, reduceOnlyTooltip, timeInForceOptions } = currentTradeFormConfig || {}; const { duration, unit } = goodTil || {}; - const needsExecution = executionOptions || needsPostOnly || needsReduceOnly; + const showPostOnly = (needsPostOnly || postOnlyTooltip); + const showReduceOnly = (needsReduceOnly || reduceOnlyTooltip); + + const needsExecution = executionOptions || showPostOnly || showReduceOnly; const hasTimeInForce = timeInForceOptions?.toArray()?.length; return ( @@ -129,26 +132,9 @@ export const AdvancedTradeOptions = () => { ))} )} - {needsPostOnly && ( - - abacusStateManager.setTradeValue({ - value: checked, - field: TradeInputField.postOnly, - }) - } - id="post-only" - label={ - - {stringGetter({ key: STRING_KEYS.POST_ONLY })} - - } - /> - )} - {needsReduceOnly && ( - abacusStateManager.setTradeValue({ value: checked, @@ -157,11 +143,29 @@ export const AdvancedTradeOptions = () => { } id="reduce-only" label={ - + {stringGetter({ key: STRING_KEYS.REDUCE_ONLY })} } /> + } + {showPostOnly && ( + + abacusStateManager.setTradeValue({ + value: checked, + field: TradeInputField.postOnly, + }) + } + id="post-only" + label={ + + {stringGetter({ key: STRING_KEYS.POST_ONLY })} + + } + /> )} )}