UNPKG

@dainprotocol/drift-sdk

Version:

SDK for Drift Protocol

180 lines (156 loc) 4.61 kB
import { isOneOfVariant, isVariant, Order, PositionDirection } from '../types'; import { BN, getVariant, ONE, OrderBitFlag, 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', 'triggerLimit']) || (isVariant(order.orderType, 'triggerMarket') && (order.bitFlags & OrderBitFlag.OracleTriggerMarket) === 0) ) { return getAuctionPriceForFixedAuction(order, slot); } else if (isVariant(order.orderType, 'limit')) { if (order.oraclePriceOffset !== 0) { return getAuctionPriceForOracleOffsetAuction(order, slot, oraclePrice); } else { return getAuctionPriceForFixedAuction(order, slot); } } else if ( isVariant(order.orderType, 'oracle') || (isVariant(order.orderType, 'triggerMarket') && (order.bitFlags & OrderBitFlag.OracleTriggerMarket) !== 0) ) { 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 BN.max(oraclePrice.add(order.auctionEndPrice), ONE); } 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 BN.max(oraclePrice.add(priceOffset), ONE); } export function deriveOracleAuctionParams({ direction, oraclePrice, auctionStartPrice, auctionEndPrice, limitPrice, auctionPriceCaps, }: { direction: PositionDirection; oraclePrice: BN; auctionStartPrice: BN; auctionEndPrice: BN; limitPrice: BN; auctionPriceCaps?: { min: BN; max: BN; }; }): { auctionStartPrice: BN; auctionEndPrice: BN; oraclePriceOffset: number } { let oraclePriceOffset; if (limitPrice.eq(ZERO) || oraclePrice.eq(ZERO)) { oraclePriceOffset = ZERO; } else { 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; } if (auctionPriceCaps) { auctionStartPrice = BN.min( BN.max(auctionStartPrice, auctionPriceCaps.min), auctionPriceCaps.max ); auctionEndPrice = BN.min( BN.max(auctionEndPrice, auctionPriceCaps.min), auctionPriceCaps.max ); } return { auctionStartPrice: auctionStartPrice.sub(oraclePrice), auctionEndPrice: auctionEndPrice.sub(oraclePrice), oraclePriceOffset: oraclePriceOffsetNum, }; }