Skip to content

Commit

Permalink
cherry-pick vulcan change (#1236)
Browse files Browse the repository at this point in the history
  • Loading branch information
dydxwill authored Mar 25, 2024
1 parent 5b5e26f commit 1033ffd
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 4 deletions.
22 changes: 21 additions & 1 deletion indexer/packages/v4-proto-parser/__tests__/order-helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IndexerOrderId } from '@dydxprotocol-indexer/v4-protos';
import { getOrderIdHash, isStatefulOrder } from '../src/order-helpers';
import { getOrderIdHash, isLongTermOrder, isStatefulOrder } from '../src/order-helpers';
import { ORDER_FLAG_CONDITIONAL, ORDER_FLAG_LONG_TERM, ORDER_FLAG_SHORT_TERM } from '../src';

describe('getOrderIdHash', () => {
Expand Down Expand Up @@ -65,3 +65,23 @@ describe('isStatefulOrder', () => {
expect(isStatefulOrder(flag)).toEqual(isStateful);
});
});

describe('isLongTermOrder', () => {
it.each([
[ORDER_FLAG_SHORT_TERM.toString(), 'string', false],
['4', 'string', false],
[ORDER_FLAG_CONDITIONAL.toString(), 'string', false],
[ORDER_FLAG_LONG_TERM.toString(), 'string', true],
[ORDER_FLAG_SHORT_TERM, 'number', false],
[3, 'number', false],
[ORDER_FLAG_CONDITIONAL, 'number', false],
[ORDER_FLAG_LONG_TERM, 'number', true],
['abc', 'string', false],
])('Checks if flag %s with type %s is a long term order', (
flag: number | string,
_type: string,
isLongTerm: boolean,
) => {
expect(isLongTermOrder(flag)).toEqual(isLongTerm);
});
});
9 changes: 9 additions & 0 deletions indexer/packages/v4-proto-parser/src/order-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ export function isStatefulOrder(orderFlag: number | String): boolean {
return numberOrderFlag === ORDER_FLAG_CONDITIONAL || numberOrderFlag === ORDER_FLAG_LONG_TERM;
}

export function isLongTermOrder(orderFlag: number | String): boolean {
const numberOrderFlag: number = Number(orderFlag);
// A string that is not a number will be converted to NaN, and should return false.
if (Number.isNaN(numberOrderFlag)) {
return false;
}
return numberOrderFlag === ORDER_FLAG_LONG_TERM;
}

export function requiresImmediateExecution(tif: IndexerOrder_TimeInForce): boolean {
return (
tif === IndexerOrder_TimeInForce.TIME_IN_FORCE_FILL_OR_KILL ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ import { onMessage } from '../../src/lib/on-message';
import { expectCanceledOrderStatus, expectOpenOrderIds, handleInitialOrderPlace } from '../helpers/helpers';
import { expectOffchainUpdateMessage, expectWebsocketOrderbookMessage, expectWebsocketSubaccountMessage } from '../helpers/websocket-helpers';
import { OrderbookSide } from '../../src/lib/types';
import { getOrderIdHash, isStatefulOrder } from '@dydxprotocol-indexer/v4-proto-parser';
import { getOrderIdHash, isLongTermOrder, isStatefulOrder } from '@dydxprotocol-indexer/v4-proto-parser';
import config from '../../src/config';

jest.mock('@dydxprotocol-indexer/base', () => ({
...jest.requireActual('@dydxprotocol-indexer/base'),
Expand All @@ -82,6 +83,10 @@ describe('order-place-handler', () => {
jest.useRealTimers();
});

afterEach(() => {
config.SEND_SUBACCOUNT_WEBSOCKET_MESSAGE_FOR_STATEFUL_ORDERS = true;
});

describe('handle', () => {
const replacementOrder: IndexerOrder = {
...redisTestConstants.defaultOrder,
Expand Down Expand Up @@ -830,19 +835,38 @@ describe('order-place-handler', () => {
redisTestConstants.defaultOrderGoodTilBlockTime,
redisTestConstants.defaultRedisOrderGoodTilBlockTime,
dbOrderGoodTilBlockTime,
false,
],
[
'conditional',
redisTestConstants.defaultConditionalOrder,
redisTestConstants.defaultRedisOrderConditional,
dbConditionalOrder,
false,
],
[
'good-til-block-time',
redisTestConstants.defaultOrderGoodTilBlockTime,
redisTestConstants.defaultRedisOrderGoodTilBlockTime,
dbOrderGoodTilBlockTime,
true,
],
[
'conditional',
redisTestConstants.defaultConditionalOrder,
redisTestConstants.defaultRedisOrderConditional,
dbConditionalOrder,
true,
],
])('handles order place with OPEN placement status, exists initially (with %s)', async (
_name: string,
orderToPlace: IndexerOrder,
expectedRedisOrder: RedisOrder,
placedOrder: OrderFromDatabase,
sendSubaccountWebsocketMessage: boolean,
) => {
// eslint-disable-next-line max-len
config.SEND_SUBACCOUNT_WEBSOCKET_MESSAGE_FOR_STATEFUL_ORDERS = sendSubaccountWebsocketMessage;
synchronizeWrapBackgroundTask(wrapBackgroundTask);
const producerSendSpy: jest.SpyInstance = jest.spyOn(producer, 'send').mockReturnThis();
// Handle the order place event for the initial order with BEST_EFFORT_OPENED
Expand Down Expand Up @@ -883,7 +907,9 @@ describe('order-place-handler', () => {
testConstants.defaultPerpetualMarket,
APIOrderStatusEnum.OPEN,
// Subaccount messages should be sent for stateful order with OPEN status
true,
!(
isLongTermOrder(expectedRedisOrder.order!.orderId!.orderFlags) &&
!sendSubaccountWebsocketMessage),
);

expect(logger.error).not.toHaveBeenCalled();
Expand Down
3 changes: 3 additions & 0 deletions indexer/services/vulcan/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ export const configSchema = {
SEND_WEBSOCKET_MESSAGES: parseBoolean({
default: true,
}),
SEND_SUBACCOUNT_WEBSOCKET_MESSAGE_FOR_STATEFUL_ORDERS: parseBoolean({
default: true,
}),
};

export default parseSchema(configSchema);
16 changes: 15 additions & 1 deletion indexer/services/vulcan/src/handlers/order-place-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import {
getOrderIdHash,
isStatefulOrder,
isLongTermOrder,
ORDER_FLAG_SHORT_TERM,
requiresImmediateExecution,
} from '@dydxprotocol-indexer/v4-proto-parser';
Expand Down Expand Up @@ -120,7 +121,12 @@ export class OrderPlaceHandler extends Handler {

// TODO(CLOB-597): Remove this logic and log erorrs once best-effort-open is not sent for
// stateful orders in the protocol
if (this.shouldSendSubaccountMessage(orderPlace, placeOrderResult, placementStatus)) {
if (this.shouldSendSubaccountMessage(
orderPlace,
placeOrderResult,
placementStatus,
redisOrder,
)) {
// TODO(IND-171): Determine whether we should always be sending a message, even when the cache
// isn't updated.
// For stateful and conditional orders, look the order up in the db for the createdAtHeight
Expand Down Expand Up @@ -273,7 +279,15 @@ export class OrderPlaceHandler extends Handler {
orderPlace: OrderPlaceV1,
placeOrderResult: PlaceOrderResult,
placementStatus: OrderPlaceV1_OrderPlacementStatus,
redisOrder: RedisOrder,
): boolean {
if (
isLongTermOrder(redisOrder.order!.orderId!.orderFlags) &&
!config.SEND_SUBACCOUNT_WEBSOCKET_MESSAGE_FOR_STATEFUL_ORDERS
) {
return false;
}

const orderFlags: number = orderPlace.order!.orderId!.orderFlags;
const status: OrderPlaceV1_OrderPlacementStatus = orderPlace.placementStatus;
// Best-effort-opened status should only be sent for short-term orders
Expand Down

0 comments on commit 1033ffd

Please sign in to comment.