UNPKG

@drift-labs/sdk

Version:
79 lines (78 loc) 4.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.simulateOrderFill = exports.calculateWeightedTokenValue = exports.getWorstCaseTokenAmounts = exports.isSpotPositionAvailable = void 0; const numericConstants_1 = require("../constants/numericConstants"); const anchor_1 = require("@coral-xyz/anchor"); const spotBalance_1 = require("./spotBalance"); function isSpotPositionAvailable(position) { return position.scaledBalance.eq(numericConstants_1.ZERO) && position.openOrders === 0; } exports.isSpotPositionAvailable = isSpotPositionAvailable; function getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory, customMarginRatio) { const tokenAmount = (0, spotBalance_1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType); const tokenValue = (0, spotBalance_1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice); if (spotPosition.openBids.eq(numericConstants_1.ZERO) && spotPosition.openAsks.eq(numericConstants_1.ZERO)) { const { weight, weightedTokenValue } = calculateWeightedTokenValue(tokenAmount, tokenValue, strictOraclePrice.current, spotMarketAccount, marginCategory, customMarginRatio); return { tokenAmount, ordersValue: numericConstants_1.ZERO, tokenValue, weight, weightedTokenValue, freeCollateralContribution: weightedTokenValue, }; } const bidsSimulation = simulateOrderFill(tokenAmount, tokenValue, spotPosition.openBids, strictOraclePrice, spotMarketAccount, marginCategory, customMarginRatio); const asksSimulation = simulateOrderFill(tokenAmount, tokenValue, spotPosition.openAsks, strictOraclePrice, spotMarketAccount, marginCategory, customMarginRatio); if (asksSimulation.freeCollateralContribution.lt(bidsSimulation.freeCollateralContribution)) { return asksSimulation; } else { return bidsSimulation; } } exports.getWorstCaseTokenAmounts = getWorstCaseTokenAmounts; function calculateWeightedTokenValue(tokenAmount, tokenValue, oraclePrice, spotMarket, marginCategory, customMarginRatio) { let weight; if (tokenValue.gte(numericConstants_1.ZERO)) { weight = (0, spotBalance_1.calculateAssetWeight)(tokenAmount, oraclePrice, spotMarket, marginCategory); } else { weight = (0, spotBalance_1.calculateLiabilityWeight)(tokenAmount.abs(), spotMarket, marginCategory); } if (marginCategory === 'Initial' && customMarginRatio && spotMarket.marketIndex !== numericConstants_1.QUOTE_SPOT_MARKET_INDEX) { const userCustomAssetWeight = tokenValue.gte(numericConstants_1.ZERO) ? anchor_1.BN.max(numericConstants_1.ZERO, numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION.subn(customMarginRatio)) : numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION.addn(customMarginRatio); weight = tokenValue.gte(numericConstants_1.ZERO) ? anchor_1.BN.min(weight, userCustomAssetWeight) : anchor_1.BN.max(weight, userCustomAssetWeight); } return { weight: weight, weightedTokenValue: tokenValue .mul(weight) .div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION), }; } exports.calculateWeightedTokenValue = calculateWeightedTokenValue; function simulateOrderFill(tokenAmount, tokenValue, openOrders, strictOraclePrice, spotMarket, marginCategory, customMarginRatio) { const ordersValue = (0, spotBalance_1.getTokenValue)(openOrders.neg(), spotMarket.decimals, { price: strictOraclePrice.max(), }); const tokenAmountAfterFill = tokenAmount.add(openOrders); const tokenValueAfterFill = tokenValue.add(ordersValue.neg()); const { weight, weightedTokenValue: weightedTokenValueAfterFill } = calculateWeightedTokenValue(tokenAmountAfterFill, tokenValueAfterFill, strictOraclePrice.current, spotMarket, marginCategory, customMarginRatio); const freeCollateralContribution = weightedTokenValueAfterFill.add(ordersValue); return { tokenAmount: tokenAmountAfterFill, ordersValue: ordersValue, tokenValue: tokenValueAfterFill, weight, weightedTokenValue: weightedTokenValueAfterFill, freeCollateralContribution, }; } exports.simulateOrderFill = simulateOrderFill;