UNPKG

@drift-labs/sdk-browser

Version:
197 lines (196 loc) 8.48 kB
"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;