UNPKG

@drift-labs/common

Version:

Common functions for Drift

125 lines 7.13 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.USER_UTILS = void 0; const sdk_1 = require("@drift-labs/sdk"); const types_1 = require("../types"); const trading_1 = require("./trading"); const utils_1 = require("../utils"); const getOpenPositionData = (driftClient, userPositions, user, perpMarketLookup, markPriceCallback) => { const oracleGuardRails = driftClient.getStateAccount().oracleGuardRails; const newResult = userPositions .filter((position) => !position.baseAssetAmount.eq(sdk_1.ZERO) || !position.quoteAssetAmount.eq(sdk_1.ZERO) || !position.lpShares.eq(sdk_1.ZERO)) .map((position) => { var _a, _b, _c; const perpMarketConfig = perpMarketLookup[position.marketIndex]; const perpMarket = driftClient.getPerpMarketAccount(position.marketIndex); const usdcSpotMarket = driftClient.getSpotMarketAccount(sdk_1.QUOTE_SPOT_MARKET_INDEX); const oraclePriceData = driftClient.getOracleDataForPerpMarket(position.marketIndex); let oraclePrice = oraclePriceData.price; // mark price fetched with a callback so we don't need extra dlob server calls. fallback to oracle let markPrice = markPriceCallback ? (_a = markPriceCallback(position.marketIndex)) !== null && _a !== void 0 ? _a : oraclePriceData.price : oraclePriceData.price; let estExitPrice = user.getPositionEstimatedExitPriceAndPnl(position, position.baseAssetAmount)[0]; const entryPrice = (0, sdk_1.calculateEntryPrice)(position); const isShort = position.baseAssetAmount.isNeg(); if (types_1.UIMarket.checkIsPredictionMarket(perpMarketConfig)) { const isResolved = utils_1.ENUM_UTILS.match(perpMarket === null || perpMarket === void 0 ? void 0 : perpMarket.status, sdk_1.MarketStatus.SETTLEMENT) || utils_1.ENUM_UTILS.match(perpMarket === null || perpMarket === void 0 ? void 0 : perpMarket.status, sdk_1.MarketStatus.DELISTED); if (isResolved) { const resolvedToNo = perpMarket.expiryPrice.lte(sdk_1.ZERO.add(perpMarket.amm.orderTickSize)); const price = resolvedToNo ? sdk_1.ZERO.mul(sdk_1.PRICE_PRECISION) : sdk_1.ONE.mul(sdk_1.PRICE_PRECISION); estExitPrice = price; markPrice = price; oraclePrice = price; } } // if for any reason oracle or mark price blips to 0, fallback to the other one so we don't show a crazy pnl if (markPrice.lte(sdk_1.ZERO) && oraclePrice.gt(sdk_1.ZERO)) { markPrice = oraclePrice; } if (oraclePrice.lte(sdk_1.ZERO) && markPrice.gt(sdk_1.ZERO)) { oraclePrice = markPrice; } const pnlVsMark = trading_1.TRADING_UTILS.calculatePotentialProfit({ currentPositionSize: sdk_1.BigNum.from(position.baseAssetAmount.abs(), sdk_1.BASE_PRECISION_EXP), currentPositionDirection: isShort ? sdk_1.PositionDirection.SHORT : sdk_1.PositionDirection.LONG, currentPositionEntryPrice: sdk_1.BigNum.from(entryPrice, sdk_1.PRICE_PRECISION_EXP), tradeDirection: isShort ? sdk_1.PositionDirection.LONG : sdk_1.PositionDirection.SHORT, exitBaseSize: sdk_1.BigNum.from(position.baseAssetAmount.abs(), sdk_1.BASE_PRECISION_EXP), exitPrice: sdk_1.BigNum.from(markPrice, sdk_1.PRICE_PRECISION_EXP), takerFeeBps: 0, }).estimatedProfit.shiftTo(sdk_1.QUOTE_PRECISION_EXP).val; const pnlVsOracle = trading_1.TRADING_UTILS.calculatePotentialProfit({ currentPositionSize: sdk_1.BigNum.from(position.baseAssetAmount.abs(), sdk_1.BASE_PRECISION_EXP), currentPositionDirection: isShort ? sdk_1.PositionDirection.SHORT : sdk_1.PositionDirection.LONG, currentPositionEntryPrice: sdk_1.BigNum.from(entryPrice, sdk_1.PRICE_PRECISION_EXP), tradeDirection: isShort ? sdk_1.PositionDirection.LONG : sdk_1.PositionDirection.SHORT, exitBaseSize: sdk_1.BigNum.from(position.baseAssetAmount.abs(), sdk_1.BASE_PRECISION_EXP), exitPrice: sdk_1.BigNum.from(oraclePrice, sdk_1.PRICE_PRECISION_EXP), takerFeeBps: 0, }).estimatedProfit.shiftTo(sdk_1.QUOTE_PRECISION_EXP).val; return { marketIndex: position.marketIndex, marketSymbol: perpMarketConfig.symbol, direction: isShort ? 'short' : 'long', notional: user .getPerpPositionValue(position.marketIndex, oraclePriceData) .abs(), baseSize: position.baseAssetAmount, markPrice, entryPrice, exitPrice: estExitPrice, liqPrice: user.liquidationPrice(position.marketIndex, sdk_1.ZERO), quoteAssetNotionalAmount: position.quoteAssetAmount, quoteEntryAmount: position.quoteEntryAmount, quoteBreakEvenAmount: position.quoteBreakEvenAmount, pnlVsMark, pnlVsOracle, unsettledPnl: (0, sdk_1.calculateClaimablePnl)(perpMarket, usdcSpotMarket, position, oraclePriceData), unsettledFundingPnl: (0, sdk_1.calculateUnsettledFundingPnl)(perpMarket, position), // Includes both settled and unsettled funding as well as fees feesAndFundingPnl: (0, sdk_1.calculateFeesAndFundingPnl)(perpMarket, position), totalUnrealizedPnl: (0, sdk_1.calculatePositionPNL)(perpMarket, position, true, oraclePriceData), unrealizedFundingPnl: user.getUnrealizedFundingPNL(position.marketIndex), lastCumulativeFundingRate: position.lastCumulativeFundingRate, openOrders: position.openOrders, costBasis: (0, sdk_1.calculateCostBasis)(position), realizedPnl: position.settledPnl, pnlIsClaimable: (0, sdk_1.isOracleValid)(perpMarket, oraclePriceData, oracleGuardRails, (_b = perpMarket.amm.lastUpdateSlot) === null || _b === void 0 ? void 0 : _b.toNumber()), lpShares: position.lpShares, remainderBaseAmount: (_c = position.remainderBaseAssetAmount) !== null && _c !== void 0 ? _c : 0, lpDeriskPrice: user.liquidationPrice(position.marketIndex, undefined, undefined, 'Initial', true), maxMarginRatio: position.maxMarginRatio, }; }); return newResult; }; const checkIfUserAccountExists = async (driftClient, config) => { let userPubKey; if (config.type === 'userPubKey') { userPubKey = config.userPubKey; } else { userPubKey = (0, sdk_1.getUserAccountPublicKeySync)(driftClient.program.programId, config.authority, config.subAccountId); } const accountInfo = await driftClient.connection.getAccountInfo(userPubKey); return accountInfo !== null; }; exports.USER_UTILS = { getOpenPositionData, checkIfUserAccountExists, }; //# sourceMappingURL=user.js.map