@drift-labs/sdk 2.31.1-beta.14 → 2.31.1-beta.16
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 +1 -1
- package/lib/driftClient.d.ts +5 -1
- package/lib/idl/drift.json +1 -1
- package/lib/math/spotBalance.d.ts +7 -0
- package/lib/math/spotBalance.js +43 -1
- package/package.json +1 -1
- package/src/driftClient.ts +1 -1
- package/src/idl/drift.json +1 -1
- package/src/math/spotBalance.ts +67 -0
- package/tests/spot/test.ts +102 -0
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.31.1-beta.
|
|
1
|
+
2.31.1-beta.16
|
package/lib/driftClient.d.ts
CHANGED
|
@@ -205,7 +205,11 @@ export declare class DriftClient {
|
|
|
205
205
|
deposit(amount: BN, marketIndex: number, associatedTokenAccount: PublicKey, subAccountId?: number, reduceOnly?: boolean): Promise<TransactionSignature>;
|
|
206
206
|
getDepositInstruction(amount: BN, marketIndex: number, userTokenAccount: PublicKey, subAccountId?: number, reduceOnly?: boolean, userInitialized?: boolean): Promise<TransactionInstruction>;
|
|
207
207
|
private checkIfAccountExists;
|
|
208
|
-
|
|
208
|
+
getWrappedSolAccountCreationIxs(amount: BN, includeRent?: boolean): Promise<{
|
|
209
|
+
ixs: anchor.web3.TransactionInstruction[];
|
|
210
|
+
signers: Signer[];
|
|
211
|
+
pubkey: PublicKey;
|
|
212
|
+
}>;
|
|
209
213
|
getAssociatedTokenAccountCreationIx(tokenMintAddress: PublicKey, associatedTokenAddress: PublicKey): anchor.web3.TransactionInstruction;
|
|
210
214
|
/**
|
|
211
215
|
* Creates the User account for a user, and deposits some initial collateral
|
package/lib/idl/drift.json
CHANGED
|
@@ -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;
|
package/lib/math/spotBalance.js
CHANGED
|
@@ -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
package/src/driftClient.ts
CHANGED
package/src/idl/drift.json
CHANGED
package/src/math/spotBalance.ts
CHANGED
|
@@ -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
|
+
});
|