fix: orderbook decimal formats (#996)

* fix: orderbook decimal formats

* fix: format position pnl by market asset decimal

* fix: update depth chart with new volume format prop

* fix: format

* fix: update orderbook row with new criteria

* fix: revert positions table change

* fix: revert price decimal

* fix: revert other price thing

* fix: add price formatting to depth chart

* fix: rename format to parse

* fix: format volume numbers with the correct decimals to have the right ratios on the depth chart

* fix: format

* fix: deal ticket price decimals

* fix: lint
This commit is contained in:
botond 2022-08-17 11:37:43 +01:00 committed by GitHub
parent dac9b8b015
commit c31841f56e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 76 additions and 64 deletions

View File

@ -100,7 +100,6 @@ export const DealTicketSteps = ({
}, [maxTrade, market.positionDecimalPlaces]);
const { message: invalidText, isDisabled } = useOrderValidation({
step,
market,
orderType,
orderTimeInForce,

View File

@ -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<Order>;
quoteName: string;
price?: string;

View File

@ -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 (
<div className="flex items-center gap-8">
<div className="flex-1">
@ -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),
})}
/>
</FormGroup>
@ -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 })}

View File

@ -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 (
<div className="flex items-center gap-8">
<div className="flex-1">
@ -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),
})}
/>
</FormGroup>

View File

@ -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 = ({
/>
<DealTicketAmount
orderType={orderType}
step={step}
market={market}
register={register}
price={
market.depth.lastTrade

View File

@ -4,6 +4,7 @@ import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import {
useDataProvider,
addDecimal,
addDecimalsFormatNumber,
ThemeContext,
} from '@vegaprotocol/react-helpers';
import dataProvider from './market-depth-data-provider';
@ -35,12 +36,13 @@ interface PriceLevel {
volume: number;
}
const formatLevel = (
const parseLevel = (
priceLevel: MarketDepth_market_depth_buy | MarketDepth_market_depth_sell,
decimalPlaces: number
priceDecimalPlaces = 0,
volumeDecimalPlaces = 0
): PriceLevel => ({
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<DepthData | null>(null);
const decimalPlacesRef = useRef<number>(0);
const [decimalPlaces, setDecimalPlaces] = useState<number>(0);
const [positionDecimalPlaces, setPositionDecimalPlaces] = useState<number>(0);
const dataRef = useRef<DepthData | null>(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 (
<AsyncRenderer loading={loading} error={error} data={data}>
{depthData && <DepthChart {...depthData} theme={theme} />}
{depthData && (
<DepthChart
{...depthData}
theme={theme}
volumeFormat={(volume) =>
addDecimalsFormatNumber(volume, data?.positionDecimalPlaces || 0)
}
priceFormat={(price) =>
addDecimalsFormatNumber(price, data?.decimalPlaces || 0)
}
/>
)}
</AsyncRenderer>
);
};

View File

@ -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,

View File

@ -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",

View File

@ -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"