@drift-labs/sdk 0.2.0-master.0 → 0.2.0-master.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/lib/admin.d.ts +8 -5
  2. package/lib/admin.js +43 -11
  3. package/lib/clearingHouse.d.ts +28 -18
  4. package/lib/clearingHouse.js +366 -143
  5. package/lib/clearingHouseUser.d.ts +2 -2
  6. package/lib/clearingHouseUser.js +8 -17
  7. package/lib/config.js +1 -1
  8. package/lib/constants/banks.js +9 -2
  9. package/lib/constants/numericConstants.d.ts +2 -0
  10. package/lib/constants/numericConstants.js +3 -1
  11. package/lib/factory/bigNum.d.ts +8 -2
  12. package/lib/factory/bigNum.js +14 -6
  13. package/lib/idl/clearing_house.json +805 -202
  14. package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  15. package/lib/index.d.ts +3 -2
  16. package/lib/index.js +7 -2
  17. package/lib/math/amm.d.ts +6 -1
  18. package/lib/math/amm.js +124 -41
  19. package/lib/math/auction.js +4 -1
  20. package/lib/math/orders.d.ts +2 -2
  21. package/lib/math/orders.js +18 -11
  22. package/lib/math/position.js +3 -1
  23. package/lib/math/repeg.js +1 -1
  24. package/lib/math/trade.d.ts +1 -1
  25. package/lib/math/trade.js +7 -10
  26. package/lib/orderParams.d.ts +14 -5
  27. package/lib/orderParams.js +8 -96
  28. package/lib/orders.d.ts +1 -2
  29. package/lib/orders.js +6 -85
  30. package/lib/slot/SlotSubscriber.d.ts +7 -0
  31. package/lib/slot/SlotSubscriber.js +3 -0
  32. package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +7 -5
  33. package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +41 -40
  34. package/lib/tx/utils.js +1 -1
  35. package/lib/types.d.ts +137 -14
  36. package/lib/types.js +53 -1
  37. package/lib/util/computeUnits.js +1 -1
  38. package/package.json +3 -3
  39. package/src/accounts/bulkAccountLoader.js +197 -0
  40. package/src/accounts/bulkUserSubscription.js +33 -0
  41. package/src/accounts/fetch.js +29 -0
  42. package/src/accounts/pollingClearingHouseAccountSubscriber.js +311 -0
  43. package/src/accounts/pollingOracleSubscriber.js +93 -0
  44. package/src/accounts/pollingTokenAccountSubscriber.js +90 -0
  45. package/src/accounts/pollingUserAccountSubscriber.js +132 -0
  46. package/src/accounts/types.js +10 -0
  47. package/src/accounts/utils.js +7 -0
  48. package/src/accounts/webSocketAccountSubscriber.js +93 -0
  49. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +233 -0
  50. package/src/accounts/webSocketUserAccountSubscriber.js +62 -0
  51. package/src/addresses/marketAddresses.js +26 -0
  52. package/src/addresses/pda.js +104 -0
  53. package/src/admin.ts +66 -14
  54. package/src/assert/assert.js +9 -0
  55. package/src/clearingHouse.ts +558 -230
  56. package/src/clearingHouseUser.ts +12 -23
  57. package/src/config.ts +1 -1
  58. package/src/constants/banks.ts +9 -2
  59. package/src/constants/numericConstants.ts +2 -0
  60. package/src/events/eventList.js +77 -0
  61. package/src/events/eventSubscriber.js +139 -0
  62. package/src/events/fetchLogs.js +50 -0
  63. package/src/events/pollingLogProvider.js +64 -0
  64. package/src/events/sort.js +44 -0
  65. package/src/events/txEventCache.js +71 -0
  66. package/src/events/types.js +20 -0
  67. package/src/events/webSocketLogProvider.js +41 -0
  68. package/src/examples/makeTradeExample.js +80 -0
  69. package/src/factory/bigNum.js +364 -0
  70. package/src/factory/bigNum.ts +26 -9
  71. package/src/factory/oracleClient.js +20 -0
  72. package/src/idl/clearing_house.json +805 -202
  73. package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  74. package/src/index.js +100 -0
  75. package/src/index.ts +3 -2
  76. package/src/math/amm.js +369 -0
  77. package/src/math/amm.ts +207 -52
  78. package/src/math/auction.js +42 -0
  79. package/src/math/auction.ts +5 -1
  80. package/src/math/bankBalance.js +75 -0
  81. package/src/math/conversion.js +11 -0
  82. package/src/math/funding.js +248 -0
  83. package/src/math/market.js +57 -0
  84. package/src/math/oracles.js +26 -0
  85. package/src/math/orders.js +110 -0
  86. package/src/math/orders.ts +17 -13
  87. package/src/math/position.js +140 -0
  88. package/src/math/position.ts +5 -1
  89. package/src/math/repeg.js +128 -0
  90. package/src/math/repeg.ts +2 -1
  91. package/src/math/state.js +15 -0
  92. package/src/math/trade.js +253 -0
  93. package/src/math/trade.ts +23 -25
  94. package/src/math/utils.js +0 -1
  95. package/src/mockUSDCFaucet.js +280 -0
  96. package/src/oracles/oracleClientCache.js +19 -0
  97. package/src/oracles/pythClient.js +46 -0
  98. package/src/oracles/quoteAssetOracleClient.js +32 -0
  99. package/src/oracles/switchboardClient.js +69 -0
  100. package/src/oracles/types.js +2 -0
  101. package/src/orderParams.js +20 -0
  102. package/src/orderParams.ts +20 -141
  103. package/src/orders.js +134 -0
  104. package/src/orders.ts +7 -131
  105. package/src/slot/SlotSubscriber.js +39 -0
  106. package/src/slot/SlotSubscriber.ts +11 -1
  107. package/src/token/index.js +38 -0
  108. package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +48 -59
  109. package/src/tx/retryTxSender.js +188 -0
  110. package/src/tx/types.js +2 -0
  111. package/src/tx/utils.js +17 -0
  112. package/src/tx/utils.ts +1 -1
  113. package/src/types.js +114 -0
  114. package/src/types.ts +132 -16
  115. package/src/userName.js +20 -0
  116. package/src/util/computeUnits.ts +1 -1
  117. package/src/util/promiseTimeout.js +14 -0
  118. package/src/util/tps.js +27 -0
  119. package/src/wallet.js +35 -0
  120. package/src/util/computeUnits.js +0 -17
  121. package/src/util/computeUnits.js.map +0 -1
package/src/math/amm.ts CHANGED
@@ -6,8 +6,10 @@ import {
6
6
  ZERO,
7
7
  BID_ASK_SPREAD_PRECISION,
8
8
  ONE,
9
- // QUOTE_PRECISION,
10
9
  AMM_TO_QUOTE_PRECISION_RATIO,
10
+ QUOTE_PRECISION,
11
+ MARGIN_PRECISION,
12
+ PRICE_DIV_PEG,
11
13
  } from '../constants/numericConstants';
12
14
  import {
13
15
  AMM,
@@ -25,6 +27,71 @@ import {
25
27
  calculateAdjustKCost,
26
28
  calculateBudgetedPeg,
27
29
  } from './repeg';
30
+
31
+ export function calculatePegFromTargetPrice(
32
+ targetPrice: BN,
33
+ baseAssetReserve: BN,
34
+ quoteAssetReserve: BN
35
+ ): BN {
36
+ return targetPrice
37
+ .mul(baseAssetReserve)
38
+ .div(quoteAssetReserve)
39
+ .add(PRICE_DIV_PEG.div(new BN(2)))
40
+ .div(PRICE_DIV_PEG);
41
+ }
42
+
43
+ export function calculateOptimalPegAndBudget(
44
+ amm: AMM,
45
+ oraclePriceData: OraclePriceData
46
+ ): [BN, BN, BN, boolean] {
47
+ const markPriceBefore = calculatePrice(
48
+ amm.baseAssetReserve,
49
+ amm.quoteAssetReserve,
50
+ amm.pegMultiplier
51
+ );
52
+ const targetPrice = oraclePriceData.price;
53
+ const newPeg = calculatePegFromTargetPrice(
54
+ targetPrice,
55
+ amm.baseAssetReserve,
56
+ amm.quoteAssetReserve
57
+ );
58
+ const prePegCost = calculateRepegCost(amm, newPeg);
59
+
60
+ const totalFeeLB = amm.totalExchangeFee.div(new BN(2));
61
+ const budget = BN.max(ZERO, amm.totalFeeMinusDistributions.sub(totalFeeLB));
62
+ if (budget.lt(prePegCost)) {
63
+ const maxPriceSpread = new BN(amm.maxSpread)
64
+ .mul(targetPrice)
65
+ .div(BID_ASK_SPREAD_PRECISION);
66
+
67
+ let newTargetPrice: BN;
68
+ let newOptimalPeg: BN;
69
+ let newBudget: BN;
70
+ const targetPriceGap = markPriceBefore.sub(targetPrice);
71
+
72
+ if (targetPriceGap.abs().gt(maxPriceSpread)) {
73
+ const markAdj = targetPriceGap.abs().sub(maxPriceSpread);
74
+
75
+ if (targetPriceGap.lt(new BN(0))) {
76
+ newTargetPrice = markPriceBefore.add(markAdj);
77
+ } else {
78
+ newTargetPrice = markPriceBefore.sub(markAdj);
79
+ }
80
+
81
+ newOptimalPeg = calculatePegFromTargetPrice(
82
+ newTargetPrice,
83
+ amm.baseAssetReserve,
84
+ amm.quoteAssetReserve
85
+ );
86
+
87
+ newBudget = calculateRepegCost(amm, newOptimalPeg);
88
+ return [newTargetPrice, newOptimalPeg, newBudget, false];
89
+ }
90
+ }
91
+
92
+ return [targetPrice, newPeg, budget, true];
93
+ }
94
+
28
95
  export function calculateNewAmm(
29
96
  amm: AMM,
30
97
  oraclePriceData: OraclePriceData
@@ -32,18 +99,12 @@ export function calculateNewAmm(
32
99
  let pKNumer = new BN(1);
33
100
  let pKDenom = new BN(1);
34
101
 
35
- const targetPrice = oraclePriceData.price;
36
- let newPeg = targetPrice
37
- .mul(amm.baseAssetReserve)
38
- .div(amm.quoteAssetReserve)
39
- .add(MARK_PRICE_PRECISION.div(PEG_PRECISION).div(new BN(2)))
40
- .div(MARK_PRICE_PRECISION.div(PEG_PRECISION));
41
- let prePegCost = calculateRepegCost(amm, newPeg);
42
-
43
- const totalFeeLB = amm.totalExchangeFee.div(new BN(2));
44
- const budget = BN.max(ZERO, amm.totalFeeMinusDistributions.sub(totalFeeLB));
102
+ const [targetPrice, _newPeg, budget, checkLowerBound] =
103
+ calculateOptimalPegAndBudget(amm, oraclePriceData);
104
+ let prePegCost = calculateRepegCost(amm, _newPeg);
105
+ let newPeg = _newPeg;
45
106
 
46
- if (prePegCost.gt(budget)) {
107
+ if (prePegCost.gt(budget) && checkLowerBound) {
47
108
  [pKNumer, pKDenom] = [new BN(999), new BN(1000)];
48
109
  const deficitMadeup = calculateAdjustKCost(amm, pKNumer, pKDenom);
49
110
  assert(deficitMadeup.lte(new BN(0)));
@@ -136,9 +197,16 @@ export function calculateUpdatedAMMSpreadReserves(
136
197
 
137
198
  export function calculateBidAskPrice(
138
199
  amm: AMM,
139
- oraclePriceData: OraclePriceData
200
+ oraclePriceData: OraclePriceData,
201
+ withUpdate = true
140
202
  ): [BN, BN] {
141
- const newAmm = calculateUpdatedAMM(amm, oraclePriceData);
203
+ let newAmm: AMM;
204
+ if (withUpdate) {
205
+ newAmm = calculateUpdatedAMM(amm, oraclePriceData);
206
+ } else {
207
+ newAmm = amm;
208
+ }
209
+
142
210
  const askReserves = calculateSpreadReserves(
143
211
  newAmm,
144
212
  PositionDirection.LONG,
@@ -237,15 +305,115 @@ export function calculateAmmReservesAfterSwap(
237
305
  return [newQuoteAssetReserve, newBaseAssetReserve];
238
306
  }
239
307
 
308
+ export function calculateEffectiveLeverage(
309
+ baseSpread: number,
310
+ quoteAssetReserve: BN,
311
+ terminalQuoteAssetReserve: BN,
312
+ pegMultiplier: BN,
313
+ netBaseAssetAmount: BN,
314
+ markPrice: BN,
315
+ totalFeeMinusDistributions: BN
316
+ ): number {
317
+ // inventory skew
318
+ const netBaseAssetValue = quoteAssetReserve
319
+ .sub(terminalQuoteAssetReserve)
320
+ .mul(pegMultiplier)
321
+ .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
322
+
323
+ const localBaseAssetValue = netBaseAssetAmount
324
+ .mul(markPrice)
325
+ .div(AMM_TO_QUOTE_PRECISION_RATIO.mul(MARK_PRICE_PRECISION));
326
+
327
+ const effectiveLeverage =
328
+ localBaseAssetValue.sub(netBaseAssetValue).toNumber() /
329
+ (Math.max(0, totalFeeMinusDistributions.toNumber()) + 1) +
330
+ 1 / QUOTE_PRECISION.toNumber();
331
+
332
+ return effectiveLeverage;
333
+ }
334
+
335
+ export function calculateMaxSpread(marginRatioInitial: number): number {
336
+ const maxTargetSpread: number = new BN(marginRatioInitial)
337
+ .mul(BID_ASK_SPREAD_PRECISION.div(MARGIN_PRECISION))
338
+ .toNumber();
339
+
340
+ return maxTargetSpread;
341
+ }
342
+
343
+ export function calculateSpreadBN(
344
+ baseSpread: number,
345
+ lastOracleMarkSpreadPct: BN,
346
+ lastOracleConfPct: BN,
347
+ maxSpread: number,
348
+ quoteAssetReserve: BN,
349
+ terminalQuoteAssetReserve: BN,
350
+ pegMultiplier: BN,
351
+ netBaseAssetAmount: BN,
352
+ markPrice: BN,
353
+ totalFeeMinusDistributions: BN
354
+ ): [number, number] {
355
+ let longSpread = baseSpread / 2;
356
+ let shortSpread = baseSpread / 2;
357
+
358
+ if (lastOracleMarkSpreadPct.gt(ZERO)) {
359
+ shortSpread = Math.max(
360
+ shortSpread,
361
+ lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber()
362
+ );
363
+ } else if (lastOracleMarkSpreadPct.lt(ZERO)) {
364
+ longSpread = Math.max(
365
+ longSpread,
366
+ lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber()
367
+ );
368
+ }
369
+
370
+ const maxTargetSpread: number = maxSpread;
371
+
372
+ const MAX_INVENTORY_SKEW = 5;
373
+
374
+ const effectiveLeverage = calculateEffectiveLeverage(
375
+ baseSpread,
376
+ quoteAssetReserve,
377
+ terminalQuoteAssetReserve,
378
+ pegMultiplier,
379
+ netBaseAssetAmount,
380
+ markPrice,
381
+ totalFeeMinusDistributions
382
+ );
383
+
384
+ if (totalFeeMinusDistributions.gt(ZERO)) {
385
+ const spreadScale = Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
386
+ if (netBaseAssetAmount.gt(ZERO)) {
387
+ longSpread *= spreadScale;
388
+ } else {
389
+ shortSpread *= spreadScale;
390
+ }
391
+ } else {
392
+ longSpread *= MAX_INVENTORY_SKEW;
393
+ shortSpread *= MAX_INVENTORY_SKEW;
394
+ }
395
+
396
+ const totalSpread = longSpread + shortSpread;
397
+ if (totalSpread > maxTargetSpread) {
398
+ if (longSpread > shortSpread) {
399
+ longSpread = Math.min(longSpread, maxTargetSpread);
400
+ shortSpread = maxTargetSpread - longSpread;
401
+ } else {
402
+ shortSpread = Math.min(shortSpread, maxTargetSpread);
403
+ longSpread = maxTargetSpread - shortSpread;
404
+ }
405
+ }
406
+
407
+ return [longSpread, shortSpread];
408
+ }
409
+
240
410
  export function calculateSpread(
241
411
  amm: AMM,
242
412
  direction: PositionDirection,
243
413
  oraclePriceData: OraclePriceData
244
414
  ): number {
245
- let spread = amm.baseSpread / 2;
246
-
247
415
  if (amm.baseSpread == 0 || amm.curveUpdateIntensity == 0) {
248
- return spread;
416
+ return amm.baseSpread / 2;
249
417
  }
250
418
 
251
419
  const markPrice = calculatePrice(
@@ -255,49 +423,36 @@ export function calculateSpread(
255
423
  );
256
424
 
257
425
  const targetPrice = oraclePriceData?.price || markPrice;
426
+ const confInterval = oraclePriceData.confidence || ZERO;
258
427
 
259
428
  const targetMarkSpreadPct = markPrice
260
429
  .sub(targetPrice)
261
430
  .mul(BID_ASK_SPREAD_PRECISION)
262
431
  .div(markPrice);
263
432
 
264
- // oracle retreat
265
- if (
266
- (isVariant(direction, 'long') && targetMarkSpreadPct.lt(ZERO)) ||
267
- (isVariant(direction, 'short') && targetMarkSpreadPct.gt(ZERO))
268
- ) {
269
- spread = Math.max(spread, targetMarkSpreadPct.abs().toNumber());
270
- }
433
+ const confIntervalPct = confInterval
434
+ .mul(BID_ASK_SPREAD_PRECISION)
435
+ .div(markPrice);
271
436
 
272
- // inventory skew
273
- const MAX_INVENTORY_SKEW = 5;
274
- if (
275
- (amm.netBaseAssetAmount.gt(ZERO) && isVariant(direction, 'long')) ||
276
- (amm.netBaseAssetAmount.lt(ZERO) && isVariant(direction, 'short')) ||
277
- amm.totalFeeMinusDistributions.eq(ZERO)
278
- ) {
279
- const netCostBasis = amm.quoteAssetAmountLong.sub(
280
- amm.quoteAssetAmountShort
281
- );
282
- const netBaseAssetValue = amm.quoteAssetReserve
283
- .sub(amm.terminalQuoteAssetReserve)
284
- .mul(amm.pegMultiplier)
285
- .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
286
-
287
- const localBaseAssetValue = amm.netBaseAssetAmount
288
- .mul(markPrice)
289
- .div(AMM_TO_QUOTE_PRECISION_RATIO.mul(MARK_PRICE_PRECISION));
290
- const netPnl = netBaseAssetValue.sub(netCostBasis);
291
- const localPnl = localBaseAssetValue.sub(netCostBasis);
292
-
293
- let effectiveLeverage = MAX_INVENTORY_SKEW;
294
- if (amm.totalFeeMinusDistributions.gt(ZERO)) {
295
- effectiveLeverage =
296
- localPnl.sub(netPnl).toNumber() /
297
- amm.totalFeeMinusDistributions.toNumber();
298
- }
437
+ const [longSpread, shortSpread] = calculateSpreadBN(
438
+ amm.baseSpread,
439
+ targetMarkSpreadPct,
440
+ confIntervalPct,
441
+ amm.maxSpread,
442
+ amm.quoteAssetReserve,
443
+ amm.terminalQuoteAssetReserve,
444
+ amm.pegMultiplier,
445
+ amm.netBaseAssetAmount,
446
+ markPrice,
447
+ amm.totalFeeMinusDistributions
448
+ );
449
+
450
+ let spread: number;
299
451
 
300
- spread *= Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
452
+ if (isVariant(direction, 'long')) {
453
+ spread = longSpread;
454
+ } else {
455
+ spread = shortSpread;
301
456
  }
302
457
 
303
458
  return spread;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAuctionPrice = exports.isAuctionComplete = void 0;
4
+ const types_1 = require("../types");
5
+ const _1 = require("../.");
6
+ function isAuctionComplete(order, slot) {
7
+ if (order.auctionDuration === 0) {
8
+ return true;
9
+ }
10
+ return new _1.BN(slot).sub(order.slot).gt(new _1.BN(order.auctionDuration));
11
+ }
12
+ exports.isAuctionComplete = isAuctionComplete;
13
+ function getAuctionPrice(order, slot) {
14
+ const slotsElapsed = new _1.BN(slot).sub(order.slot);
15
+ const deltaDenominator = new _1.BN(order.auctionDuration);
16
+ const deltaNumerator = _1.BN.min(slotsElapsed, deltaDenominator);
17
+ if (deltaDenominator.eq(_1.ZERO)) {
18
+ return order.auctionEndPrice;
19
+ }
20
+ let priceDelta;
21
+ if (types_1.isVariant(order.direction, 'long')) {
22
+ priceDelta = order.auctionEndPrice
23
+ .sub(order.auctionStartPrice)
24
+ .mul(deltaNumerator)
25
+ .div(deltaDenominator);
26
+ }
27
+ else {
28
+ priceDelta = order.auctionStartPrice
29
+ .sub(order.auctionEndPrice)
30
+ .mul(deltaNumerator)
31
+ .div(deltaDenominator);
32
+ }
33
+ let price;
34
+ if (types_1.isVariant(order.direction, 'long')) {
35
+ price = order.auctionStartPrice.add(priceDelta);
36
+ }
37
+ else {
38
+ price = order.auctionStartPrice.sub(priceDelta);
39
+ }
40
+ return price;
41
+ }
42
+ exports.getAuctionPrice = getAuctionPrice;
@@ -2,7 +2,11 @@ import { isVariant, Order } from '../types';
2
2
  import { BN, ZERO } from '../.';
3
3
 
4
4
  export function isAuctionComplete(order: Order, slot: number): boolean {
5
- return new BN(slot).sub(order.slot).gte(new BN(order.auctionDuration));
5
+ if (order.auctionDuration === 0) {
6
+ return true;
7
+ }
8
+
9
+ return new BN(slot).sub(order.slot).gt(new BN(order.auctionDuration));
6
10
  }
7
11
 
8
12
  export function getAuctionPrice(order: Order, slot: number): BN {
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculateInterestAccumulated = exports.getTokenAmount = exports.getBalance = void 0;
4
+ const types_1 = require("../types");
5
+ const anchor_1 = require("@project-serum/anchor");
6
+ const numericConstants_1 = require("../constants/numericConstants");
7
+ function getBalance(tokenAmount, bank, balanceType) {
8
+ const precisionIncrease = numericConstants_1.TEN.pow(new anchor_1.BN(16 - bank.decimals));
9
+ const cumulativeInterest = types_1.isVariant(balanceType, 'deposit')
10
+ ? bank.cumulativeDepositInterest
11
+ : bank.cumulativeBorrowInterest;
12
+ let balance = tokenAmount.mul(precisionIncrease).div(cumulativeInterest);
13
+ if (!balance.eq(numericConstants_1.ZERO) && types_1.isVariant(balanceType, 'borrow')) {
14
+ balance = balance.add(numericConstants_1.ONE);
15
+ }
16
+ return balance;
17
+ }
18
+ exports.getBalance = getBalance;
19
+ function getTokenAmount(balanceAmount, bank, balanceType) {
20
+ const precisionDecrease = numericConstants_1.TEN.pow(new anchor_1.BN(16 - bank.decimals));
21
+ const cumulativeInterest = types_1.isVariant(balanceType, 'deposit')
22
+ ? bank.cumulativeDepositInterest
23
+ : bank.cumulativeBorrowInterest;
24
+ return balanceAmount.mul(cumulativeInterest).div(precisionDecrease);
25
+ }
26
+ exports.getTokenAmount = getTokenAmount;
27
+ function calculateInterestAccumulated(bank, now) {
28
+ const token_deposit_amount = getTokenAmount(bank.depositBalance, bank, types_1.BankBalanceType.DEPOSIT);
29
+ const token_borrow_amount = getTokenAmount(bank.borrowBalance, bank, types_1.BankBalanceType.BORROW);
30
+ let utilization;
31
+ if (token_borrow_amount.eq(numericConstants_1.ZERO) && token_deposit_amount.eq(numericConstants_1.ZERO)) {
32
+ utilization = numericConstants_1.ZERO;
33
+ }
34
+ else if (token_deposit_amount.eq(numericConstants_1.ZERO)) {
35
+ utilization = numericConstants_1.BANK_UTILIZATION_PRECISION;
36
+ }
37
+ else {
38
+ utilization = token_borrow_amount
39
+ .mul(numericConstants_1.BANK_UTILIZATION_PRECISION)
40
+ .div(token_deposit_amount);
41
+ }
42
+ let interest_rate;
43
+ if (utilization.gt(bank.optimalUtilization)) {
44
+ const surplusUtilization = utilization.sub(bank.optimalUtilization);
45
+ const borrowRateSlope = bank.maxBorrowRate
46
+ .sub(bank.optimalBorrowRate)
47
+ .mul(numericConstants_1.BANK_UTILIZATION_PRECISION)
48
+ .div(numericConstants_1.BANK_UTILIZATION_PRECISION.sub(bank.optimalUtilization));
49
+ interest_rate = bank.optimalBorrowRate.add(surplusUtilization.mul(borrowRateSlope).div(numericConstants_1.BANK_UTILIZATION_PRECISION));
50
+ }
51
+ else {
52
+ const borrowRateSlope = bank.optimalBorrowRate
53
+ .mul(numericConstants_1.BANK_UTILIZATION_PRECISION)
54
+ .div(numericConstants_1.BANK_UTILIZATION_PRECISION.sub(bank.optimalUtilization));
55
+ interest_rate = utilization
56
+ .mul(borrowRateSlope)
57
+ .div(numericConstants_1.BANK_UTILIZATION_PRECISION);
58
+ }
59
+ const timeSinceLastUpdate = now.sub(bank.lastUpdated);
60
+ const modifiedBorrowRate = interest_rate.mul(timeSinceLastUpdate);
61
+ const modifiedDepositRate = modifiedBorrowRate
62
+ .mul(utilization)
63
+ .div(numericConstants_1.BANK_UTILIZATION_PRECISION);
64
+ const borrowInterest = bank.cumulativeBorrowInterest
65
+ .mul(modifiedBorrowRate)
66
+ .div(numericConstants_1.ONE_YEAR)
67
+ .div(numericConstants_1.BANK_INTEREST_PRECISION)
68
+ .add(numericConstants_1.ONE);
69
+ const depositInterest = bank.cumulativeDepositInterest
70
+ .mul(modifiedDepositRate)
71
+ .div(numericConstants_1.ONE_YEAR)
72
+ .div(numericConstants_1.BANK_INTEREST_PRECISION);
73
+ return { borrowInterest, depositInterest };
74
+ }
75
+ exports.calculateInterestAccumulated = calculateInterestAccumulated;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertToNumber = void 0;
4
+ const numericConstants_1 = require("../constants/numericConstants");
5
+ const convertToNumber = (bigNumber, precision = numericConstants_1.MARK_PRICE_PRECISION) => {
6
+ if (!bigNumber)
7
+ return 0;
8
+ return (bigNumber.div(precision).toNumber() +
9
+ bigNumber.mod(precision).toNumber() / precision.toNumber());
10
+ };
11
+ exports.convertToNumber = convertToNumber;