Skip to content

Commit

Permalink
Merge pull request #320 from idexio/feat/ws-order-type-refactor
Browse files Browse the repository at this point in the history
feat: implement ws order type refactoring
  • Loading branch information
bradennapier committed May 23, 2024
2 parents 5ed9e35 + c3cee5e commit a94c017
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 130 deletions.
22 changes: 10 additions & 12 deletions src/client/webSocket/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,8 @@ const transformL2orderbookMessage = (
indexPrice: short.ip,
});

const transformOrderFill = (
short: idex.WebSocketResponseOrderFillShort,
): idex.IDEXOrderFillEventData =>
removeUndefinedFromObj({
function transformOrderFill(short: idex.WebSocketResponseOrderFillShort) {
return removeUndefinedFromObj({
type: short.y,
fillId: short.i,
price: short.p,
Expand All @@ -142,20 +140,20 @@ const transformOrderFill = (
txId: short.T,
txStatus: short.S,
});
}

const transformOrdersMessage = (
function transformOrdersMessage(
short: idex.WebSocketResponseOrderShort,
): idex.IDEXOrderEventData => {
if (!('o' in short)) {
): idex.IDEXOrderEventData {
if (!short.o) {
return removeUndefinedFromObj({
market: short.m,
wallet: short.w,
executionTime: short.t,
side: short.s,
...(short.F && { fills: short.F.map(transformOrderFill) }),
} satisfies
| idex.IDEXOrderEventDataLiquidation
| idex.IDEXOrderEventDataDeleverage);
// should only include a single fill but we map for future compat
fills: short.F.map(transformOrderFill),
} satisfies idex.IDEXOrderEventDataSystemFill);
}

return removeUndefinedFromObj({
Expand Down Expand Up @@ -188,7 +186,7 @@ const transformOrdersMessage = (
isLiquidationAcquisitionOnly: short.la,
...(short.F && { fills: short.F.map(transformOrderFill) }),
} satisfies idex.IDEXOrderEventDataGeneral);
};
}

const transformDepositsMessage = (
short: idex.WebSocketResponseDepositsShort,
Expand Down
67 changes: 36 additions & 31 deletions src/types/enums/response.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
OrderType,
SubscriptionNameAuthenticated,
SubscriptionNamePublic,
} from '#types/enums/request';
Expand Down Expand Up @@ -28,21 +27,10 @@ export const PositionSide = Object.freeze({
export type PositionSide = (typeof PositionSide)[keyof typeof PositionSide];

/**
* Whether the fill increases or decreases the notional value of the position
*
*
* @category Enums - Response Properties
* @enum
* Specialized fill types which do not include orders and may produce different
* messaging / types in various places within the code.
*/
export const FillType = Object.freeze({
/**
* Fills resulting from any type of market order.
*/
market: 'market',
/**
* Fills resulting from any type of limit order.
*/
limit: 'limit',
export const FillTypeSystem = Object.freeze({
/**
* Position closures resulting from forced liquidation or ADL.
*/
Expand All @@ -57,6 +45,39 @@ export const FillType = Object.freeze({
closure: 'closure',
} as const);

export type FillTypeSystem =
(typeof FillTypeSystem)[keyof typeof FillTypeSystem];

/**
* Fill types associated with an order.
*/
export const FillTypeOrder = Object.freeze({
/**
* Fills resulting from any type of market order.
*/
market: 'market',
/**
* Fills resulting from any type of limit order.
*/
limit: 'limit',
} as const);

export type FillTypeOrder = (typeof FillTypeOrder)[keyof typeof FillTypeOrder];

/**
* Whether the fill increases or decreases the notional value of the position.
*
* - Includes {@link FillTypeSysem} properties which may produce different
* message types in places like the WebSocket API.
*
* @category Enums - Response Properties
* @enum
*/
export const FillType = Object.freeze({
...FillTypeOrder,
...FillTypeSystem,
});

export type FillType = (typeof FillType)[keyof typeof FillType];

/**
Expand Down Expand Up @@ -244,22 +265,6 @@ export const OrderBookLevelType = Object.freeze({
export type OrderBookLevelType =
(typeof OrderBookLevelType)[keyof typeof OrderBookLevelType];

/**
* Can be used as a convenience when specifying your orders for WebSocket
* to benefit from inline documentation and auto-complete.
*
* @category Enums - Response Properties
* @enum
*
* @see docs [API Documentation: Order Types](https://api-docs-v4.idex.io/#order-types)
*/
export const OrderEventType = Object.freeze({
...OrderType,
} as const);

export type OrderEventType =
(typeof OrderEventType)[keyof typeof OrderEventType];

/**
* Can be used as a convenience when specifying your orders for WebSocket
* to benefit from inline documentation and auto-complete.
Expand Down
101 changes: 52 additions & 49 deletions src/types/webSocket/response/orders.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type * as idex from '#index';
import type { MessageEventType } from '#types/enums/index';
import type { OrderEventType, OrderStateChange } from '#types/enums/response';
import type { MessageEventType, OrderType } from '#types/enums/index';
import type { OrderStateChange } from '#types/enums/response';
import type { IDEXOrder } from '#types/rest/endpoints/GetOrders';
import type { IDEXSubscriptionEventBase } from '#types/webSocket/base';
import type { IDEXOrderFillEventData } from './ordersFill.js';

/**
* - `orders` updates provided to the message handler when subscribed.
*
Expand Down Expand Up @@ -59,10 +60,9 @@ export interface IDEXOrderEventDataBase
/**
* - When `undefined`, indicates the message is a `liquidation` or `deleverage`
* where `fills` will include a single {@link IDEXOrderFillEventData.type} of
* {@link idex.FillType.liquidation liquidation} or
* {@link idex.FillType.deleverage deleverage}.
* {@link idex.FillTypeSystem FillTypeSystem}.
*/
type?: OrderEventType;
readonly type?: OrderType;
/**
* Timestamp of the most recent update
*/
Expand All @@ -72,29 +72,25 @@ export interface IDEXOrderEventDataBase
*
* @see type {@link IDEXOrderFillEventData}
*/
fills?: IDEXOrderFillEventData[];
readonly fills?: IDEXOrderFillEventData[];
}

/**
* {@link OrderEventType.deleverage} and {@link OrderEventType.liquidation} updates do not
* {@link idex.IDEXOrderFillEventDataSystem IDEXOrderFillEventDataSystem} updates do not
* include many of the standard order update properties
*
* @category IDEX - Get Orders
*/
export interface IDEXOrderEventDataDeleverage extends IDEXOrderEventDataBase {}

/**
* {@link OrderEventType.deleverage} and {@link OrderEventType.liquidation} updates do not
* include many of the standard order update properties
* - Note that these types include a single {@link IDEXOrderFillEventDataSystem}.
*
* @category IDEX - Get Orders
*/
export interface IDEXOrderEventDataLiquidation extends IDEXOrderEventDataBase {}
export interface IDEXOrderEventDataSystemFill extends IDEXOrderEventDataBase {
readonly type?: undefined;
readonly fills: IDEXOrderFillEventData[];
}

/**
* All types other than {@link OrderEventType.deleverage deleverage}
* and {@link OrderEventType.liquidation liquidation} include extra
* properties representing the order update.
* All types other than {@link IDEXOrderEventDataSystemFill} include
* most properties from {@link IDEXOrder}
*
* @category IDEX - Get Orders
*/
Expand All @@ -104,7 +100,7 @@ export interface IDEXOrderEventDataGeneral
/**
* @inheritDoc
*/
readonly type: OrderEventType;
readonly type: OrderType;
/**
* Type of order update
*
Expand All @@ -117,31 +113,34 @@ export interface IDEXOrderEventDataGeneral
* @see related {@link idex.IDEXOrderBook.sequence}
*/
sequence?: idex.IDEXOrderBook['sequence'];
readonly fills?: IDEXOrderFillEventData[];
}

/**
* Order updates received from the WebSocket differ from orders retreived from the
* REST API in several ways.
*
* - In addition to the order types received when getting orders from the REST API, WebSocket update events
* may also provide the following types:
* - {@link OrderEventType.deleverage OrderEventType.deleverage}
* - {@link OrderEventType.liquidation OrderEventType.liquidation}
* may also provide the following `undefined` type indicating a {@link IDEXOrderEventDataSystemFill}
* where the `fills` property will include a {@link idex.FillTypeSystem FillTypeSystem} fill matching
* {@link idex.IDEXOrderFillEventDataSystem IDEXOrderFillEventDataSystem}
* - It is best to narrow on the `type` property between these types and all the
* others as shown in the example below.
* - This is made easiest by using the {@link OrderEventType} enum as shown.
* - This is made easiest by using the {@link OrderType} enum as shown.
*
* @example
* ```typescript
* import { OrderEventType } from '@idexio/idex-sdk';
* import { OrderType } from '@idexio/idex-sdk';
*
* if (
* orderEventData.type === OrderEventType.liquidation ||
* orderEventData.type === OrderEventType.deleverage
* ) {
* // orderLong is of type IDEXOrderEventDataLiquidation | IDEXOrderEventDataDeleverage
* if (!orderEventData.type) {
* // orderLong is of type IIDEXOrderEventDataSystemFill
* } else {
* // orderLong is of type IDEXOrderEventDataGeneral
* switch(orderEventData.type) {
* case OrderType.fill:
* break;
* // ...etc
* }
* }
* ```
*
Expand All @@ -153,14 +152,12 @@ export interface IDEXOrderEventDataGeneral
* @category WebSocket - Message Types
*
* @see union {@link IDEXOrderEventDataGeneral}
* @see union {@link IDEXOrderEventDataLiquidation}
* @see union {@link IDEXOrderEventDataDeleverage}
* @see union {@link IDEXOrderEventDataSystemFill}
* @see parent {@link IDEXOrderEvent}
*/
export type IDEXOrderEventData =
| IDEXOrderEventDataGeneral
| IDEXOrderEventDataLiquidation
| IDEXOrderEventDataDeleverage;
| IDEXOrderEventDataSystemFill
| IDEXOrderEventDataGeneral;

export interface WebSocketResponseSubscriptionMessageShortOrders
extends IDEXSubscriptionEventBase {
Expand All @@ -169,6 +166,11 @@ export interface WebSocketResponseSubscriptionMessageShortOrders
}

export interface WebSocketResponseOrderShortBase {
/**
* @see related {@link IDEXOrder.type}
* @see inflated {@link IDEXOrderEventDataGeneral.type}
*/
o?: IDEXOrderEventDataGeneral['type'];
/**
* @see related {@link IDEXOrder.market}
* @see inflated {@link IDEXOrderEventDataGeneral.market}
Expand Down Expand Up @@ -204,18 +206,17 @@ export interface WebSocketResponseOrderShortBase {
/**
* @internal
*
* `liquidation` types do not include many of the properties of other order types
*/
export interface WebSocketResponseOrderShortDeleverage
extends WebSocketResponseOrderShortBase {}

/**
* @internal
*
* `liquidation` types do not include many of the properties of other order types
* `liquidation`, `deleverage`, and `closure` types do not include many of the
* properties of other order types
*/
export interface WebSocketResponseOrderShortLiquidation
extends WebSocketResponseOrderShortBase {}
export interface WebSocketResponseOrderShortSystem
extends WebSocketResponseOrderShortBase {
/**
* @inheritDoc
*/
readonly o?: undefined;
readonly F: idex.WebSocketResponseOrderFillShort[];
}

/**
* @internal
Expand All @@ -224,6 +225,9 @@ export interface WebSocketResponseOrderShortLiquidation
*/
export interface WebSocketResponseOrderShortGeneral
extends WebSocketResponseOrderShortBase {
/**
* @inheritDoc
*/
o: IDEXOrderEventDataGeneral['type'];
/**
* @see related {@link IDEXOrder.orderId}
Expand Down Expand Up @@ -345,9 +349,9 @@ export interface WebSocketResponseOrderShortGeneral
*
* This type is a discriminated union by property `o` of two types:
* - {@link WebSocketResponseOrderShortGeneral}
* - {@link WebSocketResponseOrderShortLiquidation}
* - {@link WebSocketResponseOrderShortSystem}
*
* When `o` is `liquidation`, the type is {@link WebSocketResponseOrderShortLiquidation} and
* When `o` is `liquidation`, the type is {@link WebSocketResponseOrderShortSystem} and
* will not include many of the properties that are included when `o` is not `liquidation`.
*
* @example
Expand All @@ -361,5 +365,4 @@ export interface WebSocketResponseOrderShortGeneral
*/
export type WebSocketResponseOrderShort =
| WebSocketResponseOrderShortGeneral
| WebSocketResponseOrderShortDeleverage
| WebSocketResponseOrderShortLiquidation;
| WebSocketResponseOrderShortSystem;
Loading

0 comments on commit a94c017

Please sign in to comment.