-
Notifications
You must be signed in to change notification settings - Fork 79
/
utils.ts
85 lines (71 loc) · 2.24 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import { BN, ONE, ZERO } from '../';
export function clampBN(x: BN, min: BN, max: BN): BN {
return BN.max(min, BN.min(x, max));
}
export const squareRootBN = (n: BN): BN => {
if (n.lt(new BN(0))) {
throw new Error('Sqrt only works on non-negtiave inputs');
}
if (n.lt(new BN(2))) {
return n;
}
const smallCand = squareRootBN(n.shrn(2)).shln(1);
const largeCand = smallCand.add(new BN(1));
if (largeCand.mul(largeCand).gt(n)) {
return smallCand;
} else {
return largeCand;
}
};
export const divCeil = (a: BN, b: BN): BN => {
const quotient = a.div(b);
const remainder = a.mod(b);
if (remainder.gt(ZERO)) {
return quotient.add(ONE);
} else {
return quotient;
}
};
export const sigNum = (x: BN): BN => {
return x.isNeg() ? new BN(-1) : new BN(1);
};
/**
* 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)
*/
export function timeRemainingUntilUpdate(
now: BN,
lastUpdateTs: BN,
updatePeriod: BN
): BN {
const timeSinceLastUpdate = now.sub(lastUpdateTs);
// round next update time to be available on the hour
let nextUpdateWait = updatePeriod;
if (updatePeriod.gt(new BN(1))) {
const lastUpdateDelay = lastUpdateTs.umod(updatePeriod);
if (!lastUpdateDelay.isZero()) {
const maxDelayForNextPeriod = updatePeriod.div(new BN(3));
const twoFundingPeriods = updatePeriod.mul(new 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()
? ZERO
: nextUpdateWait.sub(timeSinceLastUpdate);
return timeRemainingUntilUpdate;
}