@drift-labs/sdk 2.31.1-beta.14 → 2.31.1-beta.15

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.
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.31.1-beta.14
1
+ 2.31.1-beta.15
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.31.1-beta.13",
2
+ "version": "2.31.1-beta.14",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
@@ -50,6 +50,13 @@ export declare function getTokenValue(tokenAmount: BN, spotDecimals: number, ora
50
50
  export declare function calculateAssetWeight(balanceAmount: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
51
51
  export declare function calculateLiabilityWeight(size: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
52
52
  export declare function calculateUtilization(bank: SpotMarketAccount): BN;
53
+ /**
54
+ * calculates max borrow amount where rate would stay below targetBorrowRate
55
+ * @param spotMarketAccount
56
+ * @param targetBorrowRate
57
+ * @returns : Precision: TOKEN DECIMALS
58
+ */
59
+ export declare function calculateSpotMarketBorrowCapacity(spotMarketAccount: SpotMarketAccount, targetBorrowRate: BN): BN;
53
60
  export declare function calculateInterestRate(bank: SpotMarketAccount): BN;
54
61
  export declare function calculateDepositRate(bank: SpotMarketAccount): BN;
55
62
  export declare function calculateBorrowRate(bank: SpotMarketAccount): BN;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateWithdrawLimit = exports.calculateInterestAccumulated = exports.calculateBorrowRate = exports.calculateDepositRate = exports.calculateInterestRate = exports.calculateUtilization = exports.calculateLiabilityWeight = exports.calculateAssetWeight = exports.getTokenValue = exports.getStrictTokenValue = exports.getSignedTokenAmount = exports.getTokenAmount = exports.getBalance = void 0;
3
+ exports.calculateWithdrawLimit = exports.calculateInterestAccumulated = exports.calculateBorrowRate = exports.calculateDepositRate = exports.calculateInterestRate = exports.calculateSpotMarketBorrowCapacity = exports.calculateUtilization = exports.calculateLiabilityWeight = exports.calculateAssetWeight = exports.getTokenValue = exports.getStrictTokenValue = exports.getSignedTokenAmount = exports.getTokenAmount = exports.getBalance = void 0;
4
4
  const types_1 = require("../types");
5
5
  const anchor_1 = require("@coral-xyz/anchor");
6
6
  const numericConstants_1 = require("../constants/numericConstants");
@@ -174,6 +174,48 @@ function calculateUtilization(bank) {
174
174
  return utilization;
175
175
  }
176
176
  exports.calculateUtilization = calculateUtilization;
177
+ /**
178
+ * calculates max borrow amount where rate would stay below targetBorrowRate
179
+ * @param spotMarketAccount
180
+ * @param targetBorrowRate
181
+ * @returns : Precision: TOKEN DECIMALS
182
+ */
183
+ function calculateSpotMarketBorrowCapacity(spotMarketAccount, targetBorrowRate) {
184
+ const currentBorrowRate = calculateBorrowRate(spotMarketAccount);
185
+ if (currentBorrowRate.gte(targetBorrowRate)) {
186
+ return numericConstants_1.ZERO;
187
+ }
188
+ else {
189
+ const tokenDepositAmount = getTokenAmount(spotMarketAccount.depositBalance, spotMarketAccount, types_1.SpotBalanceType.DEPOSIT);
190
+ const tokenBorrowAmount = getTokenAmount(spotMarketAccount.borrowBalance, spotMarketAccount, types_1.SpotBalanceType.BORROW);
191
+ let targetUtilization;
192
+ // target utilization past mid point
193
+ if (targetBorrowRate.gte(new anchor_1.BN(spotMarketAccount.optimalBorrowRate))) {
194
+ const borrowRateSlope = new anchor_1.BN(spotMarketAccount.maxBorrowRate - spotMarketAccount.optimalBorrowRate)
195
+ .mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
196
+ .div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION.sub(new anchor_1.BN(spotMarketAccount.optimalUtilization)));
197
+ const surplusTargetUtilization = targetBorrowRate
198
+ .sub(new anchor_1.BN(spotMarketAccount.optimalBorrowRate))
199
+ .mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
200
+ .div(borrowRateSlope);
201
+ targetUtilization = surplusTargetUtilization.add(new anchor_1.BN(spotMarketAccount.optimalUtilization));
202
+ }
203
+ else {
204
+ const borrowRateSlope = new anchor_1.BN(spotMarketAccount.optimalBorrowRate)
205
+ .mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
206
+ .div(new anchor_1.BN(spotMarketAccount.optimalUtilization));
207
+ targetUtilization = targetBorrowRate
208
+ .mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
209
+ .div(borrowRateSlope);
210
+ }
211
+ const targetBorrowAmount = tokenDepositAmount
212
+ .mul(targetUtilization)
213
+ .div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION);
214
+ const capacity = anchor_1.BN.max(numericConstants_1.ZERO, targetBorrowAmount.sub(tokenBorrowAmount));
215
+ return capacity;
216
+ }
217
+ }
218
+ exports.calculateSpotMarketBorrowCapacity = calculateSpotMarketBorrowCapacity;
177
219
  function calculateInterestRate(bank) {
178
220
  const utilization = calculateUtilization(bank);
179
221
  let interestRate;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.31.1-beta.14",
3
+ "version": "2.31.1-beta.15",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.31.1-beta.14",
2
+ "version": "2.31.1-beta.15",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
@@ -262,6 +262,73 @@ export function calculateUtilization(bank: SpotMarketAccount): BN {
262
262
  return utilization;
263
263
  }
264
264
 
265
+ /**
266
+ * calculates max borrow amount where rate would stay below targetBorrowRate
267
+ * @param spotMarketAccount
268
+ * @param targetBorrowRate
269
+ * @returns : Precision: TOKEN DECIMALS
270
+ */
271
+ export function calculateSpotMarketBorrowCapacity(
272
+ spotMarketAccount: SpotMarketAccount,
273
+ targetBorrowRate: BN
274
+ ): BN {
275
+ const currentBorrowRate = calculateBorrowRate(spotMarketAccount);
276
+
277
+ if (currentBorrowRate.gte(targetBorrowRate)) {
278
+ return ZERO;
279
+ } else {
280
+ const tokenDepositAmount = getTokenAmount(
281
+ spotMarketAccount.depositBalance,
282
+ spotMarketAccount,
283
+ SpotBalanceType.DEPOSIT
284
+ );
285
+ const tokenBorrowAmount = getTokenAmount(
286
+ spotMarketAccount.borrowBalance,
287
+ spotMarketAccount,
288
+ SpotBalanceType.BORROW
289
+ );
290
+
291
+ let targetUtilization;
292
+
293
+ // target utilization past mid point
294
+ if (targetBorrowRate.gte(new BN(spotMarketAccount.optimalBorrowRate))) {
295
+ const borrowRateSlope = new BN(
296
+ spotMarketAccount.maxBorrowRate - spotMarketAccount.optimalBorrowRate
297
+ )
298
+ .mul(SPOT_MARKET_UTILIZATION_PRECISION)
299
+ .div(
300
+ SPOT_MARKET_UTILIZATION_PRECISION.sub(
301
+ new BN(spotMarketAccount.optimalUtilization)
302
+ )
303
+ );
304
+
305
+ const surplusTargetUtilization = targetBorrowRate
306
+ .sub(new BN(spotMarketAccount.optimalBorrowRate))
307
+ .mul(SPOT_MARKET_UTILIZATION_PRECISION)
308
+ .div(borrowRateSlope);
309
+
310
+ targetUtilization = surplusTargetUtilization.add(
311
+ new BN(spotMarketAccount.optimalUtilization)
312
+ );
313
+ } else {
314
+ const borrowRateSlope = new BN(spotMarketAccount.optimalBorrowRate)
315
+ .mul(SPOT_MARKET_UTILIZATION_PRECISION)
316
+ .div(new BN(spotMarketAccount.optimalUtilization));
317
+
318
+ targetUtilization = targetBorrowRate
319
+ .mul(SPOT_MARKET_UTILIZATION_PRECISION)
320
+ .div(borrowRateSlope);
321
+ }
322
+
323
+ const targetBorrowAmount = tokenDepositAmount
324
+ .mul(targetUtilization)
325
+ .div(SPOT_MARKET_UTILIZATION_PRECISION);
326
+ const capacity = BN.max(ZERO, targetBorrowAmount.sub(tokenBorrowAmount));
327
+
328
+ return capacity;
329
+ }
330
+ }
331
+
265
332
  export function calculateInterestRate(bank: SpotMarketAccount): BN {
266
333
  const utilization = calculateUtilization(bank);
267
334
 
@@ -0,0 +1,102 @@
1
+ import { BN, ZERO, calculateSpotMarketBorrowCapacity } from '../../src';
2
+ import { mockSpotMarkets } from '../dlob/helpers';
3
+
4
+ import { assert } from '../../src/assert/assert';
5
+ import { SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION } from '@drift-labs/sdk';
6
+
7
+ describe('Spot Tests', () => {
8
+ it('base borrow capacity', () => {
9
+ const mockSpot = mockSpotMarkets[0];
10
+ mockSpot.maxBorrowRate = 1000000;
11
+ mockSpot.optimalBorrowRate = 100000;
12
+ mockSpot.optimalUtilization = 700000;
13
+
14
+ mockSpot.decimals = 9;
15
+ mockSpot.cumulativeDepositInterest = SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION;
16
+ mockSpot.cumulativeBorrowInterest = SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION;
17
+
18
+ const tokenAmount = 100000;
19
+ // no borrows
20
+ mockSpot.depositBalance = new BN(tokenAmount * 1e9);
21
+ mockSpot.borrowBalance = ZERO;
22
+
23
+ // todo, should incorp all other spot market constraints?
24
+ const aboveMaxAmount = calculateSpotMarketBorrowCapacity(mockSpot, new BN(2000000));
25
+ assert(aboveMaxAmount.gt(mockSpot.depositBalance));
26
+
27
+ const maxAmount = calculateSpotMarketBorrowCapacity(mockSpot, new BN(1000000));
28
+ assert(maxAmount.eq(mockSpot.depositBalance));
29
+
30
+ const optAmount = calculateSpotMarketBorrowCapacity(mockSpot, new BN(100000));
31
+ const ans = new BN(mockSpot.depositBalance.toNumber() * 7 / 10);
32
+ // console.log('optAmount:', optAmount.toNumber(), ans.toNumber());
33
+ assert(optAmount.eq(ans));
34
+
35
+ const betweenOptMaxAmount = calculateSpotMarketBorrowCapacity(mockSpot, new BN(810000));
36
+ // console.log('betweenOptMaxAmount:', betweenOptMaxAmount.toNumber());
37
+ assert(betweenOptMaxAmount.lt(mockSpot.depositBalance));
38
+ assert(betweenOptMaxAmount.gt(ans));
39
+ assert(betweenOptMaxAmount.eq(new BN(93666600000000)));
40
+
41
+ const belowOptAmount = calculateSpotMarketBorrowCapacity(mockSpot, new BN(50000));
42
+ // console.log('belowOptAmount:', belowOptAmount.toNumber());
43
+ assert(belowOptAmount.eq(ans.div(new BN(2))));
44
+
45
+ const belowOptAmount2 = calculateSpotMarketBorrowCapacity(mockSpot, new BN(24900));
46
+ // console.log('belowOptAmount2:', belowOptAmount2.toNumber());
47
+ assert(belowOptAmount2.lt(ans.div(new BN(4))));
48
+ assert(belowOptAmount2.eq(new BN('17430000000000')));
49
+
50
+ const belowOptAmount3 = calculateSpotMarketBorrowCapacity(mockSpot, new BN(1));
51
+ // console.log('belowOptAmount3:', belowOptAmount3.toNumber());
52
+ assert(belowOptAmount3.eq(new BN('700000000'))); //0.7
53
+ });
54
+
55
+
56
+ it('complex borrow capacity', () => {
57
+ const mockSpot = mockSpotMarkets[0];
58
+ mockSpot.maxBorrowRate = 1000000;
59
+ mockSpot.optimalBorrowRate = 70000;
60
+ mockSpot.optimalUtilization = 700000;
61
+
62
+ mockSpot.decimals = 9;
63
+ mockSpot.cumulativeDepositInterest = new BN(1.0154217042 * SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION.toNumber());
64
+ mockSpot.cumulativeBorrowInterest = new BN(1.0417153549 * SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION.toNumber());
65
+
66
+ mockSpot.depositBalance = new BN(88522.734106451 * 1e9);
67
+ mockSpot.borrowBalance = new BN(7089.91675884 * 1e9);
68
+
69
+ // todo, should incorp all other spot market constraints?
70
+ const aboveMaxAmount = calculateSpotMarketBorrowCapacity(mockSpot, new BN(2000000));
71
+ assert(aboveMaxAmount.eq(new BN('111498270939007')));
72
+
73
+ const maxAmount = calculateSpotMarketBorrowCapacity(mockSpot, new BN(1000000));
74
+ assert(maxAmount.eq(new BN('82502230374168')));
75
+ // console.log('aboveMaxAmount:', aboveMaxAmount.toNumber(), 'maxAmount:', maxAmount.toNumber());
76
+ const optAmount = calculateSpotMarketBorrowCapacity(mockSpot, new BN(70000));
77
+ // console.log('optAmount:', optAmount.toNumber());
78
+ assert(optAmount.eq(new BN('55535858716123'))); // ~ 55535
79
+
80
+ const betweenOptMaxAmount = calculateSpotMarketBorrowCapacity(mockSpot, new BN(810000));
81
+ // console.log('betweenOptMaxAmount:', betweenOptMaxAmount.toNumber());
82
+ assert(betweenOptMaxAmount.lt(maxAmount));
83
+ assert(betweenOptMaxAmount.eq(new BN(76992910756523)));
84
+ assert(betweenOptMaxAmount.gt(optAmount));
85
+
86
+ const belowOptAmount = calculateSpotMarketBorrowCapacity(mockSpot, new BN(50000));
87
+ // console.log('belowOptAmount:', belowOptAmount.toNumber());
88
+ assert(belowOptAmount.eq(new BN('37558277610760')));
89
+
90
+ const belowOptAmount2 = calculateSpotMarketBorrowCapacity(mockSpot, new BN(24900));
91
+ // console.log('belowOptAmount2:', belowOptAmount2.toNumber());
92
+ assert(belowOptAmount2.eq(new BN('14996413323529')));
93
+
94
+ const belowOptAmount3 = calculateSpotMarketBorrowCapacity(mockSpot, new BN(4900));
95
+ // console.log('belowOptAmount2:', belowOptAmount3.toNumber());
96
+ assert(belowOptAmount3.eq(new BN('0')));
97
+
98
+ const belowOptAmount4 = calculateSpotMarketBorrowCapacity(mockSpot, new BN(1));
99
+ // console.log('belowOptAmount3:', belowOptAmount4.toNumber());
100
+ assert(belowOptAmount4.eq(new BN('0')));
101
+ });
102
+ });