@drift-labs/common
Version:
Common functions for Drift
200 lines • 10.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ORDER_COMMON_UTILS = void 0;
const sdk_1 = require("@drift-labs/sdk");
const orders_1 = require("../constants/orders");
const utils_1 = require("../utils");
const trade_1 = require("../constants/trade");
const market_1 = require("./market");
const getOrderLabelFromOrderDetails = (orderDetails) => {
var _a;
if ((0, utils_1.matchEnum)(orderDetails.orderType, sdk_1.OrderType.MARKET))
return orders_1.UI_ORDER_TYPES.market.label;
if ((0, utils_1.matchEnum)(orderDetails.orderType, sdk_1.OrderType.LIMIT))
return `${orderDetails.oraclePriceOffset &&
!((_a = orderDetails.oraclePriceOffset) === null || _a === void 0 ? void 0 : _a.eqZero())
? 'Oracle '
: ''}${orders_1.UI_ORDER_TYPES.limit.label}`;
if ((0, utils_1.matchEnum)(orderDetails.orderType, sdk_1.OrderType.ORACLE))
return orders_1.UI_ORDER_TYPES.oracle.label;
if ((0, utils_1.matchEnum)(orderDetails.orderType, sdk_1.OrderType.TRIGGER_MARKET)) {
const isTriggered = (0, utils_1.matchEnum)(orderDetails.triggerCondition, sdk_1.OrderTriggerCondition.TRIGGERED_ABOVE) ||
(0, utils_1.matchEnum)(orderDetails.triggerCondition, sdk_1.OrderTriggerCondition.TRIGGERED_BELOW);
if (isTriggered) {
return 'Market (Triggered)';
}
const isTriggerAbove = (0, utils_1.matchEnum)(orderDetails.triggerCondition, sdk_1.OrderTriggerCondition.ABOVE);
const isExistingPositionShort = (0, utils_1.matchEnum)(orderDetails.existingPositionDirection, sdk_1.PositionDirection.SHORT);
const isOrderDirectionShort = (0, utils_1.matchEnum)(orderDetails.direction, sdk_1.PositionDirection.SHORT);
if (isTriggerAbove) {
return isExistingPositionShort
? isOrderDirectionShort
? 'Trigger Market' // trigger above, existing position short, order direction short
: orders_1.UI_ORDER_TYPES.stopMarket.label // trigger above, existing position short, order direction long
: isOrderDirectionShort
? orders_1.UI_ORDER_TYPES.takeProfitMarket.label // trigger above, existing position long, order direction short
: 'Trigger Market'; // trigger above, existing position long, order direction long
}
else {
return isExistingPositionShort
? isOrderDirectionShort
? 'Trigger Market' // trigger below, existing position short, order direction short
: orders_1.UI_ORDER_TYPES.takeProfitMarket.label // trigger below, existing position short, order direction long
: isOrderDirectionShort
? orders_1.UI_ORDER_TYPES.stopMarket.label // trigger below, existing position long, order direction short
: 'Trigger Market'; // trigger below, existing position long, order direction long
}
}
if ((0, utils_1.matchEnum)(orderDetails.orderType, sdk_1.OrderType.TRIGGER_LIMIT)) {
const isTriggered = (0, utils_1.matchEnum)(orderDetails.triggerCondition, sdk_1.OrderTriggerCondition.TRIGGERED_ABOVE) ||
(0, utils_1.matchEnum)(orderDetails.triggerCondition, sdk_1.OrderTriggerCondition.TRIGGERED_BELOW);
const isTriggerAbove = (0, utils_1.matchEnum)(orderDetails.triggerCondition, sdk_1.OrderTriggerCondition.ABOVE);
const isExistingPositionLong = (0, utils_1.matchEnum)(orderDetails.existingPositionDirection, sdk_1.PositionDirection.LONG);
const isOrderDirectionLong = (0, utils_1.matchEnum)(orderDetails.direction, sdk_1.PositionDirection.LONG);
if (isTriggered) {
return 'Limit (Triggered)';
}
if (isTriggerAbove) {
return isExistingPositionLong
? isOrderDirectionLong
? 'Trigger Limit' // trigger above, existing position long, order direction long
: orders_1.UI_ORDER_TYPES.takeProfitLimit.label // trigger above, existing position long, order direction short
: isExistingPositionLong
? orders_1.UI_ORDER_TYPES.stopLimit.label // trigger above, existing position short, order direction long
: 'Trigger Limit'; // trigger above, existing position short, order direction short
}
else {
return isExistingPositionLong
? isOrderDirectionLong
? 'Trigger Limit' // trigger below, existing position long, order direction long
: orders_1.UI_ORDER_TYPES.stopLimit.label // trigger below, existing position long, order direction short
: isExistingPositionLong
? orders_1.UI_ORDER_TYPES.takeProfitLimit.label // trigger below, existing position short, order direction long
: 'Trigger Limit'; // trigger below, existing position short, order direction short
}
}
return '-';
};
const getLimitPriceFromOracleOffset = (order, oraclePrice) => {
if ((order.price && !order.price.eqZero()) ||
!order.oraclePriceOffset ||
order.oraclePriceOffset.eqZero() ||
!oraclePrice ||
(oraclePrice === null || oraclePrice === void 0 ? void 0 : oraclePrice.eqZero())) {
return order.price;
}
return oraclePrice.add(order.oraclePriceOffset);
};
function isAuctionEmpty(auctionParams) {
return (auctionParams.auctionStartPrice ===
trade_1.EMPTY_AUCTION_PARAMS.auctionStartPrice &&
auctionParams.auctionEndPrice === trade_1.EMPTY_AUCTION_PARAMS.auctionEndPrice &&
auctionParams.auctionDuration === trade_1.EMPTY_AUCTION_PARAMS.auctionDuration);
}
const getUIOrderTypeFromSdkOrderType = (orderType, triggerCondition, direction, oracleOffset) => {
const isLong = utils_1.ENUM_UTILS.match(direction, sdk_1.PositionDirection.LONG);
const triggerAbove = (0, utils_1.matchEnum)(triggerCondition, sdk_1.OrderTriggerCondition.ABOVE) ||
(0, utils_1.matchEnum)(triggerCondition, sdk_1.OrderTriggerCondition.TRIGGERED_ABOVE);
const triggerBelow = (0, utils_1.matchEnum)(triggerCondition, sdk_1.OrderTriggerCondition.BELOW) ||
(0, utils_1.matchEnum)(triggerCondition, sdk_1.OrderTriggerCondition.TRIGGERED_BELOW);
// Buy side + trigger below: take profit for a short position
// Buy side + trigger above: stop loss for a short position
// Sell side + trigger above: take profit for a long position
// Sell side + trigger below: stop loss for a long position
if ((0, utils_1.matchEnum)(orderType, sdk_1.OrderType.MARKET)) {
return orders_1.MARKET_ORDER_TYPE_CONFIG;
}
else if ((0, utils_1.matchEnum)(orderType, sdk_1.OrderType.LIMIT)) {
if (oracleOffset && !oracleOffset.eq(sdk_1.ZERO)) {
return orders_1.ORACLE_LIMIT_ORDER_TYPE_CONFIG;
}
else {
return orders_1.LIMIT_ORDER_TYPE_CONFIG;
}
}
else if ((0, utils_1.matchEnum)(orderType, sdk_1.OrderType.TRIGGER_MARKET)) {
if (isLong) {
if (triggerAbove) {
return orders_1.STOP_MARKET_ORDER_TYPE_CONFIG;
}
else if (triggerBelow) {
return orders_1.TAKE_PROFIT_MARKET_ORDER_TYPE_CONFIG;
}
}
else {
if (triggerAbove) {
return orders_1.TAKE_PROFIT_MARKET_ORDER_TYPE_CONFIG;
}
else if (triggerBelow) {
return orders_1.STOP_MARKET_ORDER_TYPE_CONFIG;
}
}
}
else if ((0, utils_1.matchEnum)(orderType, sdk_1.OrderType.TRIGGER_LIMIT)) {
if (isLong) {
if (triggerAbove) {
return orders_1.STOP_LIMIT_ORDER_TYPE_CONFIG;
}
else if (triggerBelow) {
return orders_1.TAKE_PROFIT_LIMIT_ORDER_TYPE_CONFIG;
}
}
else {
if (triggerAbove) {
return orders_1.TAKE_PROFIT_LIMIT_ORDER_TYPE_CONFIG;
}
else if (triggerBelow) {
return orders_1.STOP_LIMIT_ORDER_TYPE_CONFIG;
}
}
}
else if ((0, utils_1.matchEnum)(orderType, sdk_1.OrderType.ORACLE)) {
return orders_1.ORACLE_MARKET_ORDER_TYPE_CONFIG;
}
throw new Error('Invalid order type');
};
function getPerpAuctionDuration(priceDiff, price, contractTier) {
const percentDiff = priceDiff.mul(sdk_1.PERCENTAGE_PRECISION).div(price);
const slotsPerBp = (0, sdk_1.isOneOfVariant)(contractTier, ['a', 'b'])
? new sdk_1.BN(100)
: new sdk_1.BN(60);
const rawSlots = percentDiff
.mul(slotsPerBp)
.div(sdk_1.PERCENTAGE_PRECISION.divn(100));
const clamped = sdk_1.BN.min(sdk_1.BN.max(rawSlots, new sdk_1.BN(5)), new sdk_1.BN(180));
return clamped.toNumber();
}
/**
* Mainly checks if the user will be entering high leverage mode through this order.
*/
function getPerpOrderParamsBitFlags(marketIndex, driftClient, userAccount, quoteSize, side, enterHighLeverageModeBufferPct = 2) {
if (quoteSize.lte(sdk_1.ZERO)) {
return undefined;
}
const { hasHighLeverage: isMarketAHighLeverageMarket } = market_1.MARKET_UTILS.getMaxLeverageForMarket(sdk_1.MarketType.PERP, marketIndex, driftClient);
if (!isMarketAHighLeverageMarket) {
return undefined;
}
// Check if user is already in high leverage mode
if (userAccount.isHighLeverageMode('Initial')) {
return undefined;
}
// Get max trade size without entering high leverage mode
const maxTradeWithoutHLM = userAccount.getMaxTradeSizeUSDCForPerp(marketIndex, side, undefined, false // enterHighLeverageMode = false
);
// If order exceeds non-HLM free collateral, enable high leverage mode
// if within 2%, also enable high lev mode to avoid failures
if (quoteSize.gte(maxTradeWithoutHLM.tradeSize.muln(1 - enterHighLeverageModeBufferPct / 100))) {
return sdk_1.OrderParamsBitFlag.UpdateHighLeverageMode;
}
return undefined;
}
exports.ORDER_COMMON_UTILS = {
getOrderLabelFromOrderDetails,
getLimitPriceFromOracleOffset,
isAuctionEmpty,
getUIOrderTypeFromSdkOrderType,
getPerpAuctionDuration,
getPerpOrderParamsBitFlags,
};
//# sourceMappingURL=order.js.map