UNPKG

@drift-labs/sdk

Version:
114 lines (113 loc) 4.37 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.numberToSafeBN = exports.isBNSafe = exports.checkSameDate = exports.timeRemainingUntilUpdate = exports.sigNum = exports.divCeil = exports.squareRootBN = exports.clampBN = void 0; const anchor_1 = require("@coral-xyz/anchor"); const numericConstants_1 = require("../constants/numericConstants"); function clampBN(x, min, max) { return anchor_1.BN.max(min, anchor_1.BN.min(x, max)); } exports.clampBN = clampBN; const squareRootBN = (n) => { if (n.lt(new anchor_1.BN(0))) { throw new Error('Sqrt only works on non-negtiave inputs'); } if (n.lt(new anchor_1.BN(2))) { return n; } const smallCand = (0, exports.squareRootBN)(n.shrn(2)).shln(1); const largeCand = smallCand.add(new anchor_1.BN(1)); if (largeCand.mul(largeCand).gt(n)) { return smallCand; } else { return largeCand; } }; exports.squareRootBN = squareRootBN; const divCeil = (a, b) => { const quotient = a.div(b); const remainder = a.mod(b); if (remainder.gt(numericConstants_1.ZERO)) { return quotient.add(numericConstants_1.ONE); } else { return quotient; } }; exports.divCeil = divCeil; const sigNum = (x) => { return x.isNeg() ? new anchor_1.BN(-1) : new anchor_1.BN(1); }; exports.sigNum = sigNum; /** * calculates the time remaining until the next update based on a rounded, "on-the-hour" update schedule * this schedule is used for Perpetual Funding Rate and Revenue -> Insurance Updates * @param now: current blockchain unix timestamp * @param lastUpdateTs: the unix timestamp of the last update * @param updatePeriod: desired interval between updates (in seconds) * @returns: timeRemainingUntilUpdate (in seconds) */ function timeRemainingUntilUpdate(now, lastUpdateTs, updatePeriod) { const timeSinceLastUpdate = now.sub(lastUpdateTs); // round next update time to be available on the hour let nextUpdateWait = updatePeriod; if (updatePeriod.gt(new anchor_1.BN(1))) { const lastUpdateDelay = lastUpdateTs.umod(updatePeriod); if (!lastUpdateDelay.isZero()) { const maxDelayForNextPeriod = updatePeriod.div(new anchor_1.BN(3)); const twoFundingPeriods = updatePeriod.mul(new anchor_1.BN(2)); if (lastUpdateDelay.gt(maxDelayForNextPeriod)) { // too late for on the hour next period, delay to following period nextUpdateWait = twoFundingPeriods.sub(lastUpdateDelay); } else { // allow update on the hour nextUpdateWait = updatePeriod.sub(lastUpdateDelay); } if (nextUpdateWait.gt(twoFundingPeriods)) { nextUpdateWait = nextUpdateWait.sub(updatePeriod); } } } const timeRemainingUntilUpdate = nextUpdateWait .sub(timeSinceLastUpdate) .isNeg() ? numericConstants_1.ZERO : nextUpdateWait.sub(timeSinceLastUpdate); return timeRemainingUntilUpdate; } exports.timeRemainingUntilUpdate = timeRemainingUntilUpdate; const checkSameDate = (dateString1, dateString2) => { const date1 = new Date(dateString1); const date2 = new Date(dateString2); const isSameDate = date1.getDate() === date2.getDate() && date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear(); return isSameDate; }; exports.checkSameDate = checkSameDate; function isBNSafe(number) { return number <= 0x1fffffffffffff; } exports.isBNSafe = isBNSafe; /** * Converts a number to BN makes sure the number is safe to convert to BN (that it does not overflow number after multiplying by precision) * @param number the number to convert to BN * @param precision the BN precision to use (i.e. QUOTE_PRECISION and BASE_PRECISION from drift sdk) */ function numberToSafeBN(number, precision) { // check if number has decimals const candidate = number * precision.toNumber(); if (isBNSafe(candidate)) { return new anchor_1.BN(candidate); } else { if (number % 1 === 0) { return new anchor_1.BN(number.toString()).mul(precision); } else { return new anchor_1.BN(number).mul(precision); } } } exports.numberToSafeBN = numberToSafeBN;