@drift-labs/sdk
Version:
SDK for Drift Protocol
79 lines (78 loc) • 4.46 kB
JavaScript
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;
;