@drift-labs/sdk-browser
Version:
SDK for Drift Protocol
197 lines (196 loc) • 8.48 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MarginCalculation = exports.IsolatedMarginCalculation = exports.MarginContext = exports.MarketIdentifier = void 0;
const numericConstants_1 = require("./constants/numericConstants");
const types_1 = require("./types");
class MarketIdentifier {
constructor(marketType, marketIndex) {
this.marketType = marketType;
this.marketIndex = marketIndex;
}
static spot(marketIndex) {
return new MarketIdentifier(types_1.MarketType.SPOT, marketIndex);
}
static perp(marketIndex) {
return new MarketIdentifier(types_1.MarketType.PERP, marketIndex);
}
equals(other) {
return (!!other &&
(0, types_1.isVariant)(this.marketType, (0, types_1.getVariant)(other.marketType)) &&
this.marketIndex === other.marketIndex);
}
}
exports.MarketIdentifier = MarketIdentifier;
class MarginContext {
constructor(marginType) {
this.marginType = marginType;
this.mode = { type: 'Standard' };
this.strict = false;
this.ignoreInvalidDepositOracles = false;
this.isolatedMarginBuffers = new Map();
}
static standard(marginType) {
return new MarginContext(marginType);
}
static liquidation(crossMarginBuffer, isolatedMarginBuffers) {
const ctx = new MarginContext('Maintenance');
ctx.mode = { type: 'Liquidation' };
ctx.crossMarginBuffer = crossMarginBuffer;
ctx.isolatedMarginBuffers = isolatedMarginBuffers;
return ctx;
}
strictMode(strict) {
this.strict = strict;
return this;
}
ignoreInvalidDeposits(ignore) {
this.ignoreInvalidDepositOracles = ignore;
return this;
}
setCrossMarginBuffer(crossMarginBuffer) {
this.crossMarginBuffer = crossMarginBuffer;
return this;
}
setIsolatedMarginBuffers(isolatedMarginBuffers) {
this.isolatedMarginBuffers = isolatedMarginBuffers;
return this;
}
setIsolatedMarginBuffer(marketIndex, isolatedMarginBuffer) {
this.isolatedMarginBuffers.set(marketIndex, isolatedMarginBuffer);
return this;
}
}
exports.MarginContext = MarginContext;
class IsolatedMarginCalculation {
constructor() {
this.marginRequirement = numericConstants_1.ZERO;
this.totalCollateral = numericConstants_1.ZERO;
this.totalCollateralBuffer = numericConstants_1.ZERO;
this.marginRequirementPlusBuffer = numericConstants_1.ZERO;
}
getTotalCollateralPlusBuffer() {
return this.totalCollateral.add(this.totalCollateralBuffer);
}
meetsMarginRequirement() {
return this.totalCollateral.gte(this.marginRequirement);
}
meetsMarginRequirementWithBuffer() {
return this.getTotalCollateralPlusBuffer().gte(this.marginRequirementPlusBuffer);
}
marginShortage() {
const shortage = this.marginRequirementPlusBuffer.sub(this.getTotalCollateralPlusBuffer());
return shortage.isNeg() ? numericConstants_1.ZERO : shortage;
}
}
exports.IsolatedMarginCalculation = IsolatedMarginCalculation;
class MarginCalculation {
constructor(context) {
this.context = context;
this.totalCollateral = numericConstants_1.ZERO;
this.totalCollateralBuffer = numericConstants_1.ZERO;
this.marginRequirement = numericConstants_1.ZERO;
this.marginRequirementPlusBuffer = numericConstants_1.ZERO;
this.isolatedMarginCalculations = new Map();
this.allDepositOraclesValid = true;
this.allLiabilityOraclesValid = true;
this.withPerpIsolatedLiability = false;
this.withSpotIsolatedLiability = false;
this.totalPerpLiabilityValue = numericConstants_1.ZERO;
this.trackedMarketMarginRequirement = numericConstants_1.ZERO;
this.fuelDeposits = 0;
this.fuelBorrows = 0;
this.fuelPositions = 0;
}
addCrossMarginTotalCollateral(delta) {
const crossMarginBuffer = this.context.crossMarginBuffer;
this.totalCollateral = this.totalCollateral.add(delta);
if (crossMarginBuffer.gt(numericConstants_1.ZERO) && delta.isNeg()) {
this.totalCollateralBuffer = this.totalCollateralBuffer.add(delta.mul(crossMarginBuffer).div(numericConstants_1.MARGIN_PRECISION));
}
}
addCrossMarginRequirement(marginRequirement, liabilityValue) {
const crossMarginBuffer = this.context.crossMarginBuffer;
this.marginRequirement = this.marginRequirement.add(marginRequirement);
if (crossMarginBuffer.gt(numericConstants_1.ZERO)) {
this.marginRequirementPlusBuffer = this.marginRequirementPlusBuffer.add(marginRequirement.add(liabilityValue.mul(crossMarginBuffer).div(numericConstants_1.MARGIN_PRECISION)));
}
}
addIsolatedMarginCalculation(marketIndex, depositValue, pnl, liabilityValue, marginRequirement) {
var _a;
const totalCollateral = depositValue.add(pnl);
const isolatedMarginBuffer = (_a = this.context.isolatedMarginBuffers.get(marketIndex)) !== null && _a !== void 0 ? _a : numericConstants_1.ZERO;
const totalCollateralBuffer = isolatedMarginBuffer.gt(numericConstants_1.ZERO) && pnl.isNeg()
? pnl.mul(isolatedMarginBuffer).div(numericConstants_1.MARGIN_PRECISION)
: numericConstants_1.ZERO;
const marginRequirementPlusBuffer = isolatedMarginBuffer.gt(numericConstants_1.ZERO)
? marginRequirement.add(liabilityValue.mul(isolatedMarginBuffer).div(numericConstants_1.MARGIN_PRECISION))
: marginRequirement;
const iso = new IsolatedMarginCalculation();
iso.marginRequirement = marginRequirement;
iso.totalCollateral = totalCollateral;
iso.totalCollateralBuffer = totalCollateralBuffer;
iso.marginRequirementPlusBuffer = marginRequirementPlusBuffer;
this.isolatedMarginCalculations.set(marketIndex, iso);
}
addPerpLiabilityValue(perpLiabilityValue) {
this.totalPerpLiabilityValue =
this.totalPerpLiabilityValue.add(perpLiabilityValue);
}
updateAllDepositOraclesValid(valid) {
this.allDepositOraclesValid = this.allDepositOraclesValid && valid;
}
updateAllLiabilityOraclesValid(valid) {
this.allLiabilityOraclesValid = this.allLiabilityOraclesValid && valid;
}
updateWithSpotIsolatedLiability(isolated) {
this.withSpotIsolatedLiability = this.withSpotIsolatedLiability || isolated;
}
updateWithPerpIsolatedLiability(isolated) {
this.withPerpIsolatedLiability = this.withPerpIsolatedLiability || isolated;
}
getCrossTotalCollateralPlusBuffer() {
return this.totalCollateral.add(this.totalCollateralBuffer);
}
meetsCrossMarginRequirement() {
return this.totalCollateral.gte(this.marginRequirement);
}
meetsCrossMarginRequirementWithBuffer() {
return this.getCrossTotalCollateralPlusBuffer().gte(this.marginRequirementPlusBuffer);
}
meetsMarginRequirement() {
if (!this.meetsCrossMarginRequirement())
return false;
for (const [, iso] of this.isolatedMarginCalculations) {
if (!iso.meetsMarginRequirement())
return false;
}
return true;
}
meetsMarginRequirementWithBuffer() {
if (!this.meetsCrossMarginRequirementWithBuffer())
return false;
for (const [, iso] of this.isolatedMarginCalculations) {
if (!iso.meetsMarginRequirementWithBuffer())
return false;
}
return true;
}
getCrossFreeCollateral() {
const free = this.totalCollateral.sub(this.marginRequirement);
return free.isNeg() ? numericConstants_1.ZERO : free;
}
getIsolatedFreeCollateral(marketIndex) {
const iso = this.isolatedMarginCalculations.get(marketIndex);
if (!iso)
throw new Error('InvalidMarginCalculation: missing isolated calc');
const free = iso.totalCollateral.sub(iso.marginRequirement);
return free.isNeg() ? numericConstants_1.ZERO : free;
}
getIsolatedMarginCalculation(marketIndex) {
return this.isolatedMarginCalculations.get(marketIndex);
}
hasIsolatedMarginCalculation(marketIndex) {
return this.isolatedMarginCalculations.has(marketIndex);
}
}
exports.MarginCalculation = MarginCalculation;