diff --git a/apps/simple-trading-app/src/app/components/deal-ticket/deal-ticket-steps.tsx b/apps/simple-trading-app/src/app/components/deal-ticket/deal-ticket-steps.tsx index 452c83a31..d5a5691fa 100644 --- a/apps/simple-trading-app/src/app/components/deal-ticket/deal-ticket-steps.tsx +++ b/apps/simple-trading-app/src/app/components/deal-ticket/deal-ticket-steps.tsx @@ -100,7 +100,6 @@ export const DealTicketSteps = ({ }, [maxTrade, market.positionDecimalPlaces]); const { message: invalidText, isDisabled } = useOrderValidation({ - step, market, orderType, orderTimeInForce, diff --git a/libs/deal-ticket/src/components/deal-ticket-amount.tsx b/libs/deal-ticket/src/components/deal-ticket-amount.tsx index 000153aea..f16e8558f 100644 --- a/libs/deal-ticket/src/components/deal-ticket-amount.tsx +++ b/libs/deal-ticket/src/components/deal-ticket-amount.tsx @@ -3,10 +3,11 @@ import { VegaWalletOrderType } from '@vegaprotocol/wallet'; import type { Order } from '@vegaprotocol/orders'; import { DealTicketMarketAmount } from './deal-ticket-market-amount'; import { DealTicketLimitAmount } from './deal-ticket-limit-amount'; +import type { DealTicketQuery_market } from './__generated__/DealTicketQuery'; export interface DealTicketAmountProps { orderType: VegaWalletOrderType; - step: number; + market: DealTicketQuery_market; register: UseFormRegister; quoteName: string; price?: string; diff --git a/libs/deal-ticket/src/components/deal-ticket-limit-amount.tsx b/libs/deal-ticket/src/components/deal-ticket-limit-amount.tsx index b97cc589c..6831f7a2a 100644 --- a/libs/deal-ticket/src/components/deal-ticket-limit-amount.tsx +++ b/libs/deal-ticket/src/components/deal-ticket-limit-amount.tsx @@ -1,5 +1,5 @@ import { FormGroup, Input } from '@vegaprotocol/ui-toolkit'; -import { t } from '@vegaprotocol/react-helpers'; +import { t, toDecimal } from '@vegaprotocol/react-helpers'; import { validateSize } from '@vegaprotocol/orders'; import type { DealTicketAmountProps } from './deal-ticket-amount'; @@ -10,9 +10,12 @@ export type DealTicketLimitAmountProps = Omit< export const DealTicketLimitAmount = ({ register, - step, + market, quoteName, }: DealTicketLimitAmountProps) => { + const priceStep = toDecimal(market.decimalPlaces); + const sizeStep = toDecimal(market.positionDecimalPlaces); + return (
@@ -21,13 +24,13 @@ export const DealTicketLimitAmount = ({ id="input-order-size-limit" className="w-full" type="number" - step={step} - min={step} + step={sizeStep} + min={sizeStep} data-testid="order-size" {...register('size', { required: true, - min: step, - validate: validateSize(step), + min: sizeStep, + validate: validateSize(sizeStep), })} /> @@ -43,7 +46,7 @@ export const DealTicketLimitAmount = ({ id="input-price-quote" className="w-full" type="number" - step={step} + step={priceStep} defaultValue={0} data-testid="order-price" {...register('price', { required: true, min: 0 })} diff --git a/libs/deal-ticket/src/components/deal-ticket-market-amount.tsx b/libs/deal-ticket/src/components/deal-ticket-market-amount.tsx index 64e90b066..908173ce7 100644 --- a/libs/deal-ticket/src/components/deal-ticket-market-amount.tsx +++ b/libs/deal-ticket/src/components/deal-ticket-market-amount.tsx @@ -1,5 +1,5 @@ import { FormGroup, Input } from '@vegaprotocol/ui-toolkit'; -import { t } from '@vegaprotocol/react-helpers'; +import { t, toDecimal } from '@vegaprotocol/react-helpers'; import { validateSize } from '@vegaprotocol/orders'; import type { DealTicketAmountProps } from './deal-ticket-amount'; @@ -11,9 +11,10 @@ export type DealTicketMarketAmountProps = Omit< export const DealTicketMarketAmount = ({ register, price, - step, + market, quoteName, }: DealTicketMarketAmountProps) => { + const sizeStep = toDecimal(market.positionDecimalPlaces); return (
@@ -22,13 +23,13 @@ export const DealTicketMarketAmount = ({ id="input-order-size-market" className="w-full" type="number" - step={step} - min={step} + step={sizeStep} + min={sizeStep} data-testid="order-size" {...register('size', { required: true, - min: step, - validate: validateSize(step), + min: sizeStep, + validate: validateSize(sizeStep), })} /> diff --git a/libs/deal-ticket/src/components/deal-ticket.tsx b/libs/deal-ticket/src/components/deal-ticket.tsx index 98ed58ed3..fc3f58c9d 100644 --- a/libs/deal-ticket/src/components/deal-ticket.tsx +++ b/libs/deal-ticket/src/components/deal-ticket.tsx @@ -4,11 +4,7 @@ import { VegaWalletOrderType, VegaWalletOrderTimeInForce, } from '@vegaprotocol/wallet'; -import { - t, - toDecimal, - addDecimalsFormatNumber, -} from '@vegaprotocol/react-helpers'; +import { t, addDecimalsFormatNumber } from '@vegaprotocol/react-helpers'; import { Button, InputError } from '@vegaprotocol/ui-toolkit'; import { TypeSelector } from './type-selector'; import { SideSelector } from './side-selector'; @@ -45,11 +41,9 @@ export const DealTicket = ({ defaultValues: getDefaultOrder(market), }); - const step = toDecimal(market.positionDecimalPlaces); const orderType = watch('type'); const orderTimeInForce = watch('timeInForce'); const { message, isDisabled: disabled } = useOrderValidation({ - step, market, orderType, orderTimeInForce, @@ -94,7 +88,7 @@ export const DealTicket = ({ /> ({ - price: Number(addDecimal(priceLevel.price, decimalPlaces)), - volume: Number(priceLevel.volume), + price: Number(addDecimal(priceLevel.price, priceDecimalPlaces)), + volume: Number(addDecimal(priceLevel.volume, volumeDecimalPlaces)), }); const updateLevels = ( @@ -50,10 +52,15 @@ const updateLevels = ( | MarketDepthSubscription_marketDepthUpdate_sell )[], decimalPlaces: number, + positionDecimalPlaces: number, reverse = false ) => { updates.forEach((update) => { - const updateLevel = formatLevel(update, decimalPlaces); + const updateLevel = parseLevel( + update, + decimalPlaces, + positionDecimalPlaces + ); let index = levels.findIndex((level) => level.price === updateLevel.price); if (index !== -1) { if (update.volume === '0') { @@ -86,7 +93,8 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => { const theme = useContext(ThemeContext); const variables = useMemo(() => ({ marketId }), [marketId]); const [depthData, setDepthData] = useState(null); - const decimalPlacesRef = useRef(0); + const [decimalPlaces, setDecimalPlaces] = useState(0); + const [positionDecimalPlaces, setPositionDecimalPlaces] = useState(0); const dataRef = useRef(null); const setDepthDataThrottledRef = useRef(throttle(setDepthData, 1000)); @@ -99,17 +107,15 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => { dataRef.current = { ...dataRef.current, midPrice: delta.market.data?.staticMidPrice - ? formatMidPrice( - delta.market.data?.staticMidPrice, - decimalPlacesRef.current - ) + ? formatMidPrice(delta.market.data?.staticMidPrice, decimalPlaces) : undefined, data: { buy: delta.buy ? updateLevels( dataRef.current.data.buy, delta.buy, - decimalPlacesRef.current, + decimalPlaces, + positionDecimalPlaces, true ) : dataRef.current.data.buy, @@ -117,7 +123,8 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => { ? updateLevels( dataRef.current.data.sell, delta.sell, - decimalPlacesRef.current + decimalPlaces, + positionDecimalPlaces ) : dataRef.current.data.sell, }, @@ -125,7 +132,7 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => { setDepthDataThrottledRef.current(dataRef.current); return true; }, - [] + [decimalPlaces, positionDecimalPlaces] ); const { data, error, loading } = useDataProvider({ @@ -147,21 +154,41 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => { data: { buy: data.depth.buy?.map((priceLevel) => - formatLevel(priceLevel, data.decimalPlaces) + parseLevel( + priceLevel, + data.decimalPlaces, + data.positionDecimalPlaces + ) ) ?? [], sell: data.depth.sell?.map((priceLevel) => - formatLevel(priceLevel, data.decimalPlaces) + parseLevel( + priceLevel, + data.decimalPlaces, + data.positionDecimalPlaces + ) ) ?? [], }, }; setDepthData(dataRef.current); - decimalPlacesRef.current = data.decimalPlaces; + setDecimalPlaces(data.decimalPlaces); + setPositionDecimalPlaces(data.positionDecimalPlaces); }, [data]); return ( - {depthData && } + {depthData && ( + + addDecimalsFormatNumber(volume, data?.positionDecimalPlaces || 0) + } + priceFormat={(price) => + addDecimalsFormatNumber(price, data?.decimalPlaces || 0) + } + /> + )} ); }; diff --git a/libs/orders/src/lib/order-hooks/use-order-validation.tsx b/libs/orders/src/lib/order-hooks/use-order-validation.tsx index e85a006e4..0c0ee209e 100644 --- a/libs/orders/src/lib/order-hooks/use-order-validation.tsx +++ b/libs/orders/src/lib/order-hooks/use-order-validation.tsx @@ -1,6 +1,6 @@ import type { FieldErrors } from 'react-hook-form'; import { useMemo } from 'react'; -import { t } from '@vegaprotocol/react-helpers'; +import { t, toDecimal } from '@vegaprotocol/react-helpers'; import { useVegaWallet, VegaWalletOrderTimeInForce as OrderTimeInForce, @@ -11,7 +11,6 @@ import { ERROR_SIZE_DECIMAL } from '../utils/validate-size'; import type { Order } from './use-order-submit'; export type ValidationArgs = { - step: number; market: { state: MarketState; tradingMode: MarketTradingMode; @@ -32,13 +31,13 @@ export const marketTranslations = (marketState: MarketState) => { }; export const useOrderValidation = ({ - step, market, fieldErrors = {}, orderType, orderTimeInForce, }: ValidationArgs) => { const { keypair } = useVegaWallet(); + const minSize = toDecimal(market.positionDecimalPlaces); const { message, isDisabled } = useMemo(() => { if (!keypair) { @@ -182,7 +181,7 @@ export const useOrderValidation = ({ if (fieldErrors?.size?.type === 'min') { return { isDisabled: true, - message: t(`The amount cannot be lower than "${step}"`), + message: t(`The amount cannot be lower than "${minSize}"`), }; } @@ -220,8 +219,8 @@ export const useOrderValidation = ({ return { isDisabled: false, message: '' }; }, [ + minSize, keypair, - step, market, fieldErrors?.size?.type, fieldErrors?.size?.message, diff --git a/package.json b/package.json index 1fdad4289..2c56dae56 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "js-sha3": "^0.8.0", "lodash": "^4.17.21", "next": "12.0.9", - "pennant": "^0.4.12", + "pennant": "^0.4.14", "react": "18.2.0", "react-copy-to-clipboard": "^5.0.4", "react-dom": "^18.2.0", diff --git a/yarn.lock b/yarn.lock index beb70ec62..072d9bb54 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7259,19 +7259,7 @@ ajv@^8.0.0, ajv@^8.0.1, ajv@^8.8.0: require-from-string "^2.0.2" uri-js "^4.2.2" -allotment@1.14.2: - version "1.14.2" - resolved "https://registry.yarnpkg.com/allotment/-/allotment-1.14.2.tgz#b89364ede0b3fbeb2927f7c1f80bc90f13248bbf" - integrity sha512-Gqfl2DW2hQ3RT22uiJs2yK1bSwwFbDMC4drTe3uWEjKMmwlAZmS7/vqLD1v25kqbAqdjWSzr+aqgHsRXT51BPQ== - dependencies: - classnames "^2.3.0" - eventemitter3 "^4.0.0" - lodash.clamp "^4.0.0" - lodash.debounce "^4.0.0" - lodash.isequal "^4.5.0" - use-resize-observer "^9.0.0" - -allotment@^1.14.5: +allotment@1.15.0, allotment@^1.14.5: version "1.15.0" resolved "https://registry.yarnpkg.com/allotment/-/allotment-1.15.0.tgz#3e27eb0d048b8da3d1acb8bc53610b63f84d5c5a" integrity sha512-9JXAm59/XD5Djfpso0rgGZdA23n3v5XeicwjNoInp2qlBa/HFZtnMDujm6NHOSjOCQPWhkOt4ybYgz8H3ed+8A== @@ -17186,10 +17174,10 @@ pend@~1.2.0: resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== -pennant@^0.4.12: - version "0.4.12" - resolved "https://registry.yarnpkg.com/pennant/-/pennant-0.4.12.tgz#c37860fcea96b79114c2ee4f22c5c18bd8e9d5a2" - integrity sha512-3j7YIsEcIceWIDT5A8WdkBdTPK0rzqcUzFKK3UfFYAv0xGPI7aJyyX2Gu5QfEML01A0oGtgLsjbWoxHdiSp7Hw== +pennant@^0.4.14: + version "0.4.14" + resolved "https://registry.yarnpkg.com/pennant/-/pennant-0.4.14.tgz#9d51fc47faf9b51efee965c6df8a0746c70bdce6" + integrity sha512-O0a5uPGrQfX8eDULVJVuSsYloLjPl/91kdmbaZbc3bq+N9nYIRNu5uRdxAm0LPaqVhNU+Tp1dwNPeL6JFF73xw== dependencies: "@babel/runtime" "^7.13.10" "@d3fc/d3fc-technical-indicator" "^8.0.1" @@ -17209,7 +17197,7 @@ pennant@^0.4.12: "@types/react" "^18.0.14" "@types/react-dom" "^18.0.5" "@types/react-virtualized-auto-sizer" "^1.0.0" - allotment "1.14.2" + allotment "1.15.0" classnames "^2.2.6" d3-array "2.3.3" d3-delaunay "^6.0.2"