@drift-labs/sdk
Version:
SDK for Drift Protocol
114 lines (113 loc) • 4.37 kB
JavaScript
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;
;