@ox-fun/drift-sdk
Version:
SDK for Drift Protocol
150 lines (129 loc) • 3.72 kB
text/typescript
import { isOneOfVariant, isVariant, Order, PositionDirection } from '../types';
import { BN, getVariant, ONE, ZERO } from '../.';
export function isAuctionComplete(order: Order, slot: number): boolean {
if (order.auctionDuration === 0) {
return true;
}
return new BN(slot).sub(order.slot).gt(new BN(order.auctionDuration));
}
export function isFallbackAvailableLiquiditySource(
order: Order,
minAuctionDuration: number,
slot: number
): boolean {
if (minAuctionDuration === 0) {
return true;
}
return new BN(slot).sub(order.slot).gt(new BN(minAuctionDuration));
}
export function getAuctionPrice(
order: Order,
slot: number,
oraclePrice: BN
): BN {
if (
isOneOfVariant(order.orderType, [
'market',
'triggerMarket',
'limit',
'triggerLimit',
])
) {
return getAuctionPriceForFixedAuction(order, slot);
} else if (isVariant(order.orderType, 'oracle')) {
return getAuctionPriceForOracleOffsetAuction(order, slot, oraclePrice);
} else {
throw Error(
`Cant get auction price for order type ${getVariant(order.orderType)}`
);
}
}
export function getAuctionPriceForFixedAuction(order: Order, slot: number): BN {
const slotsElapsed = new BN(slot).sub(order.slot);
const deltaDenominator = new BN(order.auctionDuration);
const deltaNumerator = BN.min(slotsElapsed, deltaDenominator);
if (deltaDenominator.eq(ZERO)) {
return order.auctionEndPrice;
}
let priceDelta;
if (isVariant(order.direction, 'long')) {
priceDelta = order.auctionEndPrice
.sub(order.auctionStartPrice)
.mul(deltaNumerator)
.div(deltaDenominator);
} else {
priceDelta = order.auctionStartPrice
.sub(order.auctionEndPrice)
.mul(deltaNumerator)
.div(deltaDenominator);
}
let price;
if (isVariant(order.direction, 'long')) {
price = order.auctionStartPrice.add(priceDelta);
} else {
price = order.auctionStartPrice.sub(priceDelta);
}
return price;
}
export function getAuctionPriceForOracleOffsetAuction(
order: Order,
slot: number,
oraclePrice: BN
): BN {
const slotsElapsed = new BN(slot).sub(order.slot);
const deltaDenominator = new BN(order.auctionDuration);
const deltaNumerator = BN.min(slotsElapsed, deltaDenominator);
if (deltaDenominator.eq(ZERO)) {
return oraclePrice.add(order.auctionEndPrice);
}
let priceOffsetDelta;
if (isVariant(order.direction, 'long')) {
priceOffsetDelta = order.auctionEndPrice
.sub(order.auctionStartPrice)
.mul(deltaNumerator)
.div(deltaDenominator);
} else {
priceOffsetDelta = order.auctionStartPrice
.sub(order.auctionEndPrice)
.mul(deltaNumerator)
.div(deltaDenominator);
}
let priceOffset;
if (isVariant(order.direction, 'long')) {
priceOffset = order.auctionStartPrice.add(priceOffsetDelta);
} else {
priceOffset = order.auctionStartPrice.sub(priceOffsetDelta);
}
return oraclePrice.add(priceOffset);
}
export function deriveOracleAuctionParams({
direction,
oraclePrice,
auctionStartPrice,
auctionEndPrice,
limitPrice,
}: {
direction: PositionDirection;
oraclePrice: BN;
auctionStartPrice: BN;
auctionEndPrice: BN;
limitPrice: BN;
}): { auctionStartPrice: BN; auctionEndPrice: BN; oraclePriceOffset: number } {
let oraclePriceOffset = limitPrice.sub(oraclePrice);
if (oraclePriceOffset.eq(ZERO)) {
oraclePriceOffset = isVariant(direction, 'long')
? auctionEndPrice.sub(oraclePrice).add(ONE)
: auctionEndPrice.sub(oraclePrice).sub(ONE);
}
let oraclePriceOffsetNum;
try {
oraclePriceOffsetNum = oraclePriceOffset.toNumber();
} catch (e) {
oraclePriceOffsetNum = 0;
}
return {
auctionStartPrice: auctionStartPrice.sub(oraclePrice),
auctionEndPrice: auctionEndPrice.sub(oraclePrice),
oraclePriceOffset: oraclePriceOffsetNum,
};
}