136 lines
3.6 KiB
TypeScript
136 lines
3.6 KiB
TypeScript
import { type Location, matchPath } from 'react-router-dom';
|
|
import { OrderSide } from '@dydxprotocol/v4-client-js';
|
|
|
|
import { StringGetterFunction } from '@/constants/localization';
|
|
|
|
import {
|
|
type Nullable,
|
|
AbacusOrderSide,
|
|
type AbacusOrderSides,
|
|
AbacusOrderTypes,
|
|
ValidationError,
|
|
ErrorType,
|
|
} from '@/constants/abacus';
|
|
|
|
import { AlertType } from '@/constants/alerts';
|
|
import { PERCENT_DECIMALS, USD_DECIMALS } from '@/constants/numbers';
|
|
import { TRADE_ROUTE } from '@/constants/routes';
|
|
import { PositionSide, TradeTypes } from '@/constants/trade';
|
|
|
|
import { MustBigNumber } from '@/lib/numbers';
|
|
|
|
export const getMarketIdFromLocation = (location: Location) => {
|
|
const { pathname } = location;
|
|
const tradeMatch = matchPath(TRADE_ROUTE, pathname);
|
|
return tradeMatch?.params.market;
|
|
};
|
|
|
|
export const getSelectedTradeType = (type: Nullable<AbacusOrderTypes>) => {
|
|
return type ? (type.rawValue as TradeTypes) : TradeTypes.LIMIT;
|
|
};
|
|
|
|
export const getSelectedOrderSide = (side: Nullable<AbacusOrderSides>) => {
|
|
return side === AbacusOrderSide.sell ? OrderSide.SELL : OrderSide.BUY;
|
|
};
|
|
|
|
export const hasPositionSideChanged = ({
|
|
currentSize,
|
|
postOrderSize,
|
|
}: {
|
|
currentSize?: Nullable<number>;
|
|
postOrderSize?: Nullable<number>;
|
|
}) => {
|
|
const currentSizeBN = MustBigNumber(currentSize);
|
|
const postOrderSizeBN = MustBigNumber(postOrderSize);
|
|
|
|
const currentPositionSide = currentSizeBN.gt(0)
|
|
? PositionSide.Long
|
|
: currentSizeBN.lt(0)
|
|
? PositionSide.Short
|
|
: PositionSide.None;
|
|
|
|
const newPositionSide = postOrderSizeBN.gt(0)
|
|
? PositionSide.Long
|
|
: postOrderSizeBN.lt(0)
|
|
? PositionSide.Short
|
|
: PositionSide.None;
|
|
|
|
return {
|
|
currentPositionSide,
|
|
newPositionSide,
|
|
positionSideHasChanged: postOrderSize !== undefined && currentPositionSide !== newPositionSide,
|
|
};
|
|
};
|
|
|
|
const formatErrorParam = ({
|
|
value,
|
|
format,
|
|
stepSizeDecimals,
|
|
tickSizeDecimals,
|
|
}: {
|
|
value: Nullable<string>;
|
|
format?: Nullable<string>;
|
|
stepSizeDecimals: Nullable<number>;
|
|
tickSizeDecimals: Nullable<number>;
|
|
}) => {
|
|
switch (format) {
|
|
case 'percent': {
|
|
const percentBN = MustBigNumber(value);
|
|
return `${percentBN.times(100).toFixed(PERCENT_DECIMALS)}%`;
|
|
}
|
|
case 'size': {
|
|
const sizeBN = MustBigNumber(value);
|
|
return sizeBN.toFixed(stepSizeDecimals ?? 0);
|
|
}
|
|
case 'price': {
|
|
const dollarBN = MustBigNumber(value);
|
|
return `$${dollarBN.toFixed(tickSizeDecimals ?? USD_DECIMALS)}`;
|
|
}
|
|
default: {
|
|
return value || '';
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @description Returns the formatted input errors.
|
|
*/
|
|
export const getTradeInputAlert = ({
|
|
abacusInputErrors,
|
|
stringGetter,
|
|
stepSizeDecimals,
|
|
tickSizeDecimals,
|
|
}: {
|
|
abacusInputErrors: ValidationError[];
|
|
stringGetter: StringGetterFunction;
|
|
stepSizeDecimals: Nullable<number>;
|
|
tickSizeDecimals: Nullable<number>;
|
|
}) => {
|
|
const inputAlerts = abacusInputErrors.map(({ action: errorAction, resources, type }) => {
|
|
const { action, text } = resources || {};
|
|
const { stringKey: actionStringKey } = action || {};
|
|
const { stringKey: alertStringKey, params: stringParams } = text || {};
|
|
|
|
const params =
|
|
stringParams?.toArray() &&
|
|
Object.fromEntries(
|
|
stringParams
|
|
.toArray()
|
|
.map(({ key, value, format }) => [
|
|
key,
|
|
formatErrorParam({ value, format, stepSizeDecimals, tickSizeDecimals }),
|
|
])
|
|
);
|
|
|
|
return {
|
|
errorAction,
|
|
actionStringKey,
|
|
alertStringKey,
|
|
alertString: alertStringKey && stringGetter({ key: alertStringKey, params }),
|
|
type: type === ErrorType.warning ? AlertType.Warning : AlertType.Error,
|
|
};
|
|
});
|
|
|
|
return inputAlerts?.[0];
|
|
};
|