@drift-labs/sdk 2.32.1-beta.1 → 2.32.1-beta.10
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.js +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/math/spotBalance.d.ts +4 -1
- package/lib/math/spotBalance.js +29 -28
- package/lib/math/superStake.d.ts +3 -1
- package/lib/math/superStake.js +20 -11
- package/lib/memcmp.d.ts +1 -0
- package/lib/memcmp.js +11 -1
- package/lib/user.js +3 -2
- package/package.json +1 -1
- package/src/driftClient.ts +1 -1
- package/src/index.ts +2 -0
- package/src/math/spotBalance.ts +52 -50
- package/src/math/superStake.ts +23 -10
- package/src/memcmp.ts +10 -0
- package/src/user.ts +3 -2
- package/tests/spot/test.ts +26 -48
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.32.1-beta.
|
|
1
|
+
2.32.1-beta.10
|
package/lib/driftClient.js
CHANGED
|
@@ -2039,7 +2039,7 @@ class DriftClient {
|
|
|
2039
2039
|
async getSwapIx({ outMarketIndex, inMarketIndex, amountIn, inTokenAccount, outTokenAccount, limitPrice, reduceOnly, userAccountPublicKey, }) {
|
|
2040
2040
|
const userAccountPublicKeyToUse = userAccountPublicKey || (await this.getUserAccountPublicKey());
|
|
2041
2041
|
const userAccounts = [];
|
|
2042
|
-
if (this.getUser().getUserAccountAndSlot()) {
|
|
2042
|
+
if (this.hasUser() && this.getUser().getUserAccountAndSlot()) {
|
|
2043
2043
|
userAccounts.push(this.getUser().getUserAccountAndSlot().data);
|
|
2044
2044
|
}
|
|
2045
2045
|
const remainingAccounts = this.getRemainingAccounts({
|
package/lib/index.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export * from './testClient';
|
|
|
24
24
|
export * from './user';
|
|
25
25
|
export * from './userConfig';
|
|
26
26
|
export * from './userStats';
|
|
27
|
+
export * from './userName';
|
|
27
28
|
export * from './userStatsConfig';
|
|
28
29
|
export * from './driftClient';
|
|
29
30
|
export * from './factory/oracleClient';
|
|
@@ -82,4 +83,5 @@ export * from './orderSubscriber';
|
|
|
82
83
|
export * from './orderSubscriber/types';
|
|
83
84
|
export * from './auctionSubscriber';
|
|
84
85
|
export * from './auctionSubscriber/types';
|
|
86
|
+
export * from './memcmp';
|
|
85
87
|
export { BN, PublicKey, pyth };
|
package/lib/index.js
CHANGED
|
@@ -47,6 +47,7 @@ __exportStar(require("./testClient"), exports);
|
|
|
47
47
|
__exportStar(require("./user"), exports);
|
|
48
48
|
__exportStar(require("./userConfig"), exports);
|
|
49
49
|
__exportStar(require("./userStats"), exports);
|
|
50
|
+
__exportStar(require("./userName"), exports);
|
|
50
51
|
__exportStar(require("./userStatsConfig"), exports);
|
|
51
52
|
__exportStar(require("./driftClient"), exports);
|
|
52
53
|
__exportStar(require("./factory/oracleClient"), exports);
|
|
@@ -105,3 +106,4 @@ __exportStar(require("./orderSubscriber"), exports);
|
|
|
105
106
|
__exportStar(require("./orderSubscriber/types"), exports);
|
|
106
107
|
__exportStar(require("./auctionSubscriber"), exports);
|
|
107
108
|
__exportStar(require("./auctionSubscriber/types"), exports);
|
|
109
|
+
__exportStar(require("./memcmp"), exports);
|
|
@@ -56,7 +56,10 @@ export declare function calculateUtilization(bank: SpotMarketAccount, delta?: an
|
|
|
56
56
|
* @param targetBorrowRate
|
|
57
57
|
* @returns : Precision: TOKEN DECIMALS
|
|
58
58
|
*/
|
|
59
|
-
export declare function calculateSpotMarketBorrowCapacity(spotMarketAccount: SpotMarketAccount, targetBorrowRate: BN):
|
|
59
|
+
export declare function calculateSpotMarketBorrowCapacity(spotMarketAccount: SpotMarketAccount, targetBorrowRate: BN): {
|
|
60
|
+
totalCapacity: BN;
|
|
61
|
+
remainingCapacity: BN;
|
|
62
|
+
};
|
|
60
63
|
export declare function calculateInterestRate(bank: SpotMarketAccount, delta?: any): BN;
|
|
61
64
|
export declare function calculateDepositRate(bank: SpotMarketAccount): BN;
|
|
62
65
|
export declare function calculateBorrowRate(bank: SpotMarketAccount): BN;
|
package/lib/math/spotBalance.js
CHANGED
|
@@ -188,38 +188,39 @@ exports.calculateUtilization = calculateUtilization;
|
|
|
188
188
|
*/
|
|
189
189
|
function calculateSpotMarketBorrowCapacity(spotMarketAccount, targetBorrowRate) {
|
|
190
190
|
const currentBorrowRate = calculateBorrowRate(spotMarketAccount);
|
|
191
|
+
const tokenDepositAmount = getTokenAmount(spotMarketAccount.depositBalance, spotMarketAccount, types_1.SpotBalanceType.DEPOSIT);
|
|
192
|
+
const tokenBorrowAmount = getTokenAmount(spotMarketAccount.borrowBalance, spotMarketAccount, types_1.SpotBalanceType.BORROW);
|
|
193
|
+
let targetUtilization;
|
|
194
|
+
// target utilization past mid point
|
|
195
|
+
if (targetBorrowRate.gte(new anchor_1.BN(spotMarketAccount.optimalBorrowRate))) {
|
|
196
|
+
const borrowRateSlope = new anchor_1.BN(spotMarketAccount.maxBorrowRate - spotMarketAccount.optimalBorrowRate)
|
|
197
|
+
.mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
|
|
198
|
+
.div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION.sub(new anchor_1.BN(spotMarketAccount.optimalUtilization)));
|
|
199
|
+
const surplusTargetUtilization = targetBorrowRate
|
|
200
|
+
.sub(new anchor_1.BN(spotMarketAccount.optimalBorrowRate))
|
|
201
|
+
.mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
|
|
202
|
+
.div(borrowRateSlope);
|
|
203
|
+
targetUtilization = surplusTargetUtilization.add(new anchor_1.BN(spotMarketAccount.optimalUtilization));
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
const borrowRateSlope = new anchor_1.BN(spotMarketAccount.optimalBorrowRate)
|
|
207
|
+
.mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
|
|
208
|
+
.div(new anchor_1.BN(spotMarketAccount.optimalUtilization));
|
|
209
|
+
targetUtilization = targetBorrowRate
|
|
210
|
+
.mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
|
|
211
|
+
.div(borrowRateSlope);
|
|
212
|
+
}
|
|
213
|
+
const totalCapacity = tokenDepositAmount
|
|
214
|
+
.mul(targetUtilization)
|
|
215
|
+
.div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION);
|
|
216
|
+
let remainingCapacity;
|
|
191
217
|
if (currentBorrowRate.gte(targetBorrowRate)) {
|
|
192
|
-
|
|
218
|
+
remainingCapacity = numericConstants_1.ZERO;
|
|
193
219
|
}
|
|
194
220
|
else {
|
|
195
|
-
|
|
196
|
-
const tokenBorrowAmount = getTokenAmount(spotMarketAccount.borrowBalance, spotMarketAccount, types_1.SpotBalanceType.BORROW);
|
|
197
|
-
let targetUtilization;
|
|
198
|
-
// target utilization past mid point
|
|
199
|
-
if (targetBorrowRate.gte(new anchor_1.BN(spotMarketAccount.optimalBorrowRate))) {
|
|
200
|
-
const borrowRateSlope = new anchor_1.BN(spotMarketAccount.maxBorrowRate - spotMarketAccount.optimalBorrowRate)
|
|
201
|
-
.mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
|
|
202
|
-
.div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION.sub(new anchor_1.BN(spotMarketAccount.optimalUtilization)));
|
|
203
|
-
const surplusTargetUtilization = targetBorrowRate
|
|
204
|
-
.sub(new anchor_1.BN(spotMarketAccount.optimalBorrowRate))
|
|
205
|
-
.mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
|
|
206
|
-
.div(borrowRateSlope);
|
|
207
|
-
targetUtilization = surplusTargetUtilization.add(new anchor_1.BN(spotMarketAccount.optimalUtilization));
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
const borrowRateSlope = new anchor_1.BN(spotMarketAccount.optimalBorrowRate)
|
|
211
|
-
.mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
|
|
212
|
-
.div(new anchor_1.BN(spotMarketAccount.optimalUtilization));
|
|
213
|
-
targetUtilization = targetBorrowRate
|
|
214
|
-
.mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
|
|
215
|
-
.div(borrowRateSlope);
|
|
216
|
-
}
|
|
217
|
-
const targetBorrowAmount = tokenDepositAmount
|
|
218
|
-
.mul(targetUtilization)
|
|
219
|
-
.div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION);
|
|
220
|
-
const capacity = anchor_1.BN.max(numericConstants_1.ZERO, targetBorrowAmount.sub(tokenBorrowAmount));
|
|
221
|
-
return capacity;
|
|
221
|
+
remainingCapacity = anchor_1.BN.max(numericConstants_1.ZERO, totalCapacity.sub(tokenBorrowAmount));
|
|
222
222
|
}
|
|
223
|
+
return { totalCapacity, remainingCapacity };
|
|
223
224
|
}
|
|
224
225
|
exports.calculateSpotMarketBorrowCapacity = calculateSpotMarketBorrowCapacity;
|
|
225
226
|
function calculateInterestRate(bank, delta = numericConstants_1.ZERO) {
|
package/lib/math/superStake.d.ts
CHANGED
|
@@ -4,11 +4,13 @@ import { DriftClient } from '../driftClient';
|
|
|
4
4
|
import { BN } from '@coral-xyz/anchor';
|
|
5
5
|
import { User } from '../user';
|
|
6
6
|
import { DepositRecord } from '../types';
|
|
7
|
-
export declare function findBestSuperStakeIxs({ amount, jupiterClient, driftClient, userAccountPublicKey, }: {
|
|
7
|
+
export declare function findBestSuperStakeIxs({ amount, jupiterClient, driftClient, userAccountPublicKey, marinadePrice, forceMariande, }: {
|
|
8
8
|
amount: BN;
|
|
9
9
|
jupiterClient: JupiterClient;
|
|
10
10
|
driftClient: DriftClient;
|
|
11
|
+
marinadePrice?: number;
|
|
11
12
|
userAccountPublicKey?: PublicKey;
|
|
13
|
+
forceMariande?: boolean;
|
|
12
14
|
}): Promise<{
|
|
13
15
|
ixs: TransactionInstruction[];
|
|
14
16
|
lookupTables: AddressLookupTableAccount[];
|
package/lib/math/superStake.js
CHANGED
|
@@ -10,19 +10,28 @@ const anchor_1 = require("@coral-xyz/anchor");
|
|
|
10
10
|
const types_1 = require("../types");
|
|
11
11
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
12
12
|
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
13
|
-
async function findBestSuperStakeIxs({ amount, jupiterClient, driftClient, userAccountPublicKey, }) {
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
async function findBestSuperStakeIxs({ amount, jupiterClient, driftClient, userAccountPublicKey, marinadePrice, forceMariande, }) {
|
|
14
|
+
if (!marinadePrice) {
|
|
15
|
+
const marinadeProgram = (0, marinade_1.getMarinadeFinanceProgram)(driftClient.provider);
|
|
16
|
+
marinadePrice = await (0, marinade_1.getMarinadeMSolPrice)(marinadeProgram);
|
|
17
|
+
}
|
|
16
18
|
const solMint = driftClient.getSpotMarketAccount(1).mint;
|
|
17
19
|
const mSOLMint = driftClient.getSpotMarketAccount(2).mint;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
let jupiterPrice;
|
|
21
|
+
let bestRoute;
|
|
22
|
+
try {
|
|
23
|
+
const jupiterRoutes = await jupiterClient.getRoutes({
|
|
24
|
+
inputMint: solMint,
|
|
25
|
+
outputMint: mSOLMint,
|
|
26
|
+
amount,
|
|
27
|
+
});
|
|
28
|
+
bestRoute = jupiterRoutes[0];
|
|
29
|
+
jupiterPrice = bestRoute.inAmount / bestRoute.outAmount;
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
console.error('Error getting jupiter price', e);
|
|
33
|
+
}
|
|
34
|
+
if (!jupiterPrice || marinadePrice <= jupiterPrice || forceMariande) {
|
|
26
35
|
const ixs = await driftClient.getStakeForMSOLIx({ amount });
|
|
27
36
|
return {
|
|
28
37
|
method: 'marinade',
|
package/lib/memcmp.d.ts
CHANGED
|
@@ -4,3 +4,4 @@ export declare function getNonIdleUserFilter(): MemcmpFilter;
|
|
|
4
4
|
export declare function getUserWithOrderFilter(): MemcmpFilter;
|
|
5
5
|
export declare function getUserWithAuctionFilter(): MemcmpFilter;
|
|
6
6
|
export declare function getUserThatHasBeenLP(): MemcmpFilter;
|
|
7
|
+
export declare function getUserWithName(name: string): MemcmpFilter;
|
package/lib/memcmp.js
CHANGED
|
@@ -3,9 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getUserThatHasBeenLP = exports.getUserWithAuctionFilter = exports.getUserWithOrderFilter = exports.getNonIdleUserFilter = exports.getUserFilter = void 0;
|
|
6
|
+
exports.getUserWithName = exports.getUserThatHasBeenLP = exports.getUserWithAuctionFilter = exports.getUserWithOrderFilter = exports.getNonIdleUserFilter = exports.getUserFilter = void 0;
|
|
7
7
|
const bs58_1 = __importDefault(require("bs58"));
|
|
8
8
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
9
|
+
const userName_1 = require("./userName");
|
|
9
10
|
function getUserFilter() {
|
|
10
11
|
return {
|
|
11
12
|
memcmp: {
|
|
@@ -51,3 +52,12 @@ function getUserThatHasBeenLP() {
|
|
|
51
52
|
};
|
|
52
53
|
}
|
|
53
54
|
exports.getUserThatHasBeenLP = getUserThatHasBeenLP;
|
|
55
|
+
function getUserWithName(name) {
|
|
56
|
+
return {
|
|
57
|
+
memcmp: {
|
|
58
|
+
offset: 72,
|
|
59
|
+
bytes: bs58_1.default.encode(Uint8Array.from((0, userName_1.encodeName)(name))),
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
exports.getUserWithName = getUserWithName;
|
package/lib/user.js
CHANGED
|
@@ -1151,7 +1151,7 @@ class User {
|
|
|
1151
1151
|
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION.div(new _1.BN(100)))
|
|
1152
1152
|
.div(inOraclePrice); // just assume user can go 100x
|
|
1153
1153
|
inSwap = maxSwap.div(numericConstants_1.TWO);
|
|
1154
|
-
const error =
|
|
1154
|
+
const error = freeCollateral.div(new _1.BN(10000));
|
|
1155
1155
|
let i = 0;
|
|
1156
1156
|
let freeCollateralAfter = freeCollateral;
|
|
1157
1157
|
while (freeCollateralAfter.gt(error) || freeCollateralAfter.isNeg()) {
|
|
@@ -1172,7 +1172,8 @@ class User {
|
|
|
1172
1172
|
inSwap = minSwap.add(maxSwap).div(numericConstants_1.TWO);
|
|
1173
1173
|
}
|
|
1174
1174
|
if (i++ > iterationLimit) {
|
|
1175
|
-
|
|
1175
|
+
console.log('getMaxSwapAmount iteration limit reached');
|
|
1176
|
+
break;
|
|
1176
1177
|
}
|
|
1177
1178
|
}
|
|
1178
1179
|
}
|
package/package.json
CHANGED
package/src/driftClient.ts
CHANGED
|
@@ -3574,7 +3574,7 @@ export class DriftClient {
|
|
|
3574
3574
|
userAccountPublicKey || (await this.getUserAccountPublicKey());
|
|
3575
3575
|
|
|
3576
3576
|
const userAccounts = [];
|
|
3577
|
-
if (this.getUser().getUserAccountAndSlot()) {
|
|
3577
|
+
if (this.hasUser() && this.getUser().getUserAccountAndSlot()) {
|
|
3578
3578
|
userAccounts.push(this.getUser().getUserAccountAndSlot()!.data);
|
|
3579
3579
|
}
|
|
3580
3580
|
const remainingAccounts = this.getRemainingAccounts({
|
package/src/index.ts
CHANGED
|
@@ -25,6 +25,7 @@ export * from './testClient';
|
|
|
25
25
|
export * from './user';
|
|
26
26
|
export * from './userConfig';
|
|
27
27
|
export * from './userStats';
|
|
28
|
+
export * from './userName';
|
|
28
29
|
export * from './userStatsConfig';
|
|
29
30
|
export * from './driftClient';
|
|
30
31
|
export * from './factory/oracleClient';
|
|
@@ -83,5 +84,6 @@ export * from './orderSubscriber';
|
|
|
83
84
|
export * from './orderSubscriber/types';
|
|
84
85
|
export * from './auctionSubscriber';
|
|
85
86
|
export * from './auctionSubscriber/types';
|
|
87
|
+
export * from './memcmp';
|
|
86
88
|
|
|
87
89
|
export { BN, PublicKey, pyth };
|
package/src/math/spotBalance.ts
CHANGED
|
@@ -280,62 +280,64 @@ export function calculateUtilization(
|
|
|
280
280
|
export function calculateSpotMarketBorrowCapacity(
|
|
281
281
|
spotMarketAccount: SpotMarketAccount,
|
|
282
282
|
targetBorrowRate: BN
|
|
283
|
-
): BN {
|
|
283
|
+
): { totalCapacity: BN; remainingCapacity: BN } {
|
|
284
284
|
const currentBorrowRate = calculateBorrowRate(spotMarketAccount);
|
|
285
285
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
spotMarketAccount,
|
|
292
|
-
SpotBalanceType.DEPOSIT
|
|
293
|
-
);
|
|
294
|
-
const tokenBorrowAmount = getTokenAmount(
|
|
295
|
-
spotMarketAccount.borrowBalance,
|
|
296
|
-
spotMarketAccount,
|
|
297
|
-
SpotBalanceType.BORROW
|
|
298
|
-
);
|
|
286
|
+
const tokenDepositAmount = getTokenAmount(
|
|
287
|
+
spotMarketAccount.depositBalance,
|
|
288
|
+
spotMarketAccount,
|
|
289
|
+
SpotBalanceType.DEPOSIT
|
|
290
|
+
);
|
|
299
291
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
.div(borrowRateSlope);
|
|
318
|
-
|
|
319
|
-
targetUtilization = surplusTargetUtilization.add(
|
|
320
|
-
new BN(spotMarketAccount.optimalUtilization)
|
|
292
|
+
const tokenBorrowAmount = getTokenAmount(
|
|
293
|
+
spotMarketAccount.borrowBalance,
|
|
294
|
+
spotMarketAccount,
|
|
295
|
+
SpotBalanceType.BORROW
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
let targetUtilization;
|
|
299
|
+
// target utilization past mid point
|
|
300
|
+
if (targetBorrowRate.gte(new BN(spotMarketAccount.optimalBorrowRate))) {
|
|
301
|
+
const borrowRateSlope = new BN(
|
|
302
|
+
spotMarketAccount.maxBorrowRate - spotMarketAccount.optimalBorrowRate
|
|
303
|
+
)
|
|
304
|
+
.mul(SPOT_MARKET_UTILIZATION_PRECISION)
|
|
305
|
+
.div(
|
|
306
|
+
SPOT_MARKET_UTILIZATION_PRECISION.sub(
|
|
307
|
+
new BN(spotMarketAccount.optimalUtilization)
|
|
308
|
+
)
|
|
321
309
|
);
|
|
322
|
-
} else {
|
|
323
|
-
const borrowRateSlope = new BN(spotMarketAccount.optimalBorrowRate)
|
|
324
|
-
.mul(SPOT_MARKET_UTILIZATION_PRECISION)
|
|
325
|
-
.div(new BN(spotMarketAccount.optimalUtilization));
|
|
326
|
-
|
|
327
|
-
targetUtilization = targetBorrowRate
|
|
328
|
-
.mul(SPOT_MARKET_UTILIZATION_PRECISION)
|
|
329
|
-
.div(borrowRateSlope);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
const targetBorrowAmount = tokenDepositAmount
|
|
333
|
-
.mul(targetUtilization)
|
|
334
|
-
.div(SPOT_MARKET_UTILIZATION_PRECISION);
|
|
335
|
-
const capacity = BN.max(ZERO, targetBorrowAmount.sub(tokenBorrowAmount));
|
|
336
310
|
|
|
337
|
-
|
|
311
|
+
const surplusTargetUtilization = targetBorrowRate
|
|
312
|
+
.sub(new BN(spotMarketAccount.optimalBorrowRate))
|
|
313
|
+
.mul(SPOT_MARKET_UTILIZATION_PRECISION)
|
|
314
|
+
.div(borrowRateSlope);
|
|
315
|
+
|
|
316
|
+
targetUtilization = surplusTargetUtilization.add(
|
|
317
|
+
new BN(spotMarketAccount.optimalUtilization)
|
|
318
|
+
);
|
|
319
|
+
} else {
|
|
320
|
+
const borrowRateSlope = new BN(spotMarketAccount.optimalBorrowRate)
|
|
321
|
+
.mul(SPOT_MARKET_UTILIZATION_PRECISION)
|
|
322
|
+
.div(new BN(spotMarketAccount.optimalUtilization));
|
|
323
|
+
|
|
324
|
+
targetUtilization = targetBorrowRate
|
|
325
|
+
.mul(SPOT_MARKET_UTILIZATION_PRECISION)
|
|
326
|
+
.div(borrowRateSlope);
|
|
338
327
|
}
|
|
328
|
+
|
|
329
|
+
const totalCapacity = tokenDepositAmount
|
|
330
|
+
.mul(targetUtilization)
|
|
331
|
+
.div(SPOT_MARKET_UTILIZATION_PRECISION);
|
|
332
|
+
|
|
333
|
+
let remainingCapacity;
|
|
334
|
+
if (currentBorrowRate.gte(targetBorrowRate)) {
|
|
335
|
+
remainingCapacity = ZERO;
|
|
336
|
+
} else {
|
|
337
|
+
remainingCapacity = BN.max(ZERO, totalCapacity.sub(tokenBorrowAmount));
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return { totalCapacity, remainingCapacity };
|
|
339
341
|
}
|
|
340
342
|
|
|
341
343
|
export function calculateInterestRate(
|
package/src/math/superStake.ts
CHANGED
|
@@ -18,32 +18,45 @@ export async function findBestSuperStakeIxs({
|
|
|
18
18
|
jupiterClient,
|
|
19
19
|
driftClient,
|
|
20
20
|
userAccountPublicKey,
|
|
21
|
+
marinadePrice,
|
|
22
|
+
forceMariande,
|
|
21
23
|
}: {
|
|
22
24
|
amount: BN;
|
|
23
25
|
jupiterClient: JupiterClient;
|
|
24
26
|
driftClient: DriftClient;
|
|
27
|
+
marinadePrice?: number;
|
|
25
28
|
userAccountPublicKey?: PublicKey;
|
|
29
|
+
forceMariande?: boolean;
|
|
26
30
|
}): Promise<{
|
|
27
31
|
ixs: TransactionInstruction[];
|
|
28
32
|
lookupTables: AddressLookupTableAccount[];
|
|
29
33
|
method: 'jupiter' | 'marinade';
|
|
30
34
|
price: number;
|
|
31
35
|
}> {
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
if (!marinadePrice) {
|
|
37
|
+
const marinadeProgram = getMarinadeFinanceProgram(driftClient.provider);
|
|
38
|
+
marinadePrice = await getMarinadeMSolPrice(marinadeProgram);
|
|
39
|
+
}
|
|
34
40
|
|
|
35
41
|
const solMint = driftClient.getSpotMarketAccount(1).mint;
|
|
36
42
|
const mSOLMint = driftClient.getSpotMarketAccount(2).mint;
|
|
37
|
-
const jupiterRoutes = await jupiterClient.getRoutes({
|
|
38
|
-
inputMint: solMint,
|
|
39
|
-
outputMint: mSOLMint,
|
|
40
|
-
amount,
|
|
41
|
-
});
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
let jupiterPrice;
|
|
45
|
+
let bestRoute;
|
|
46
|
+
try {
|
|
47
|
+
const jupiterRoutes = await jupiterClient.getRoutes({
|
|
48
|
+
inputMint: solMint,
|
|
49
|
+
outputMint: mSOLMint,
|
|
50
|
+
amount,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
bestRoute = jupiterRoutes[0];
|
|
54
|
+
jupiterPrice = bestRoute.inAmount / bestRoute.outAmount;
|
|
55
|
+
} catch (e) {
|
|
56
|
+
console.error('Error getting jupiter price', e);
|
|
57
|
+
}
|
|
45
58
|
|
|
46
|
-
if (marinadePrice <= jupiterPrice) {
|
|
59
|
+
if (!jupiterPrice || marinadePrice <= jupiterPrice || forceMariande) {
|
|
47
60
|
const ixs = await driftClient.getStakeForMSOLIx({ amount });
|
|
48
61
|
return {
|
|
49
62
|
method: 'marinade',
|
package/src/memcmp.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { MemcmpFilter } from '@solana/web3.js';
|
|
2
2
|
import bs58 from 'bs58';
|
|
3
3
|
import { BorshAccountsCoder } from '@coral-xyz/anchor';
|
|
4
|
+
import { encodeName } from './userName';
|
|
4
5
|
|
|
5
6
|
export function getUserFilter(): MemcmpFilter {
|
|
6
7
|
return {
|
|
@@ -46,3 +47,12 @@ export function getUserThatHasBeenLP(): MemcmpFilter {
|
|
|
46
47
|
},
|
|
47
48
|
};
|
|
48
49
|
}
|
|
50
|
+
|
|
51
|
+
export function getUserWithName(name: string): MemcmpFilter {
|
|
52
|
+
return {
|
|
53
|
+
memcmp: {
|
|
54
|
+
offset: 72,
|
|
55
|
+
bytes: bs58.encode(Uint8Array.from(encodeName(name))),
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
package/src/user.ts
CHANGED
|
@@ -2066,7 +2066,7 @@ export class User {
|
|
|
2066
2066
|
.div(SPOT_MARKET_WEIGHT_PRECISION.div(new BN(100)))
|
|
2067
2067
|
.div(inOraclePrice); // just assume user can go 100x
|
|
2068
2068
|
inSwap = maxSwap.div(TWO);
|
|
2069
|
-
const error =
|
|
2069
|
+
const error = freeCollateral.div(new BN(10000));
|
|
2070
2070
|
|
|
2071
2071
|
let i = 0;
|
|
2072
2072
|
let freeCollateralAfter = freeCollateral;
|
|
@@ -2106,7 +2106,8 @@ export class User {
|
|
|
2106
2106
|
}
|
|
2107
2107
|
|
|
2108
2108
|
if (i++ > iterationLimit) {
|
|
2109
|
-
|
|
2109
|
+
console.log('getMaxSwapAmount iteration limit reached');
|
|
2110
|
+
break;
|
|
2110
2111
|
}
|
|
2111
2112
|
}
|
|
2112
2113
|
}
|
package/tests/spot/test.ts
CHANGED
|
@@ -27,19 +27,17 @@ describe('Spot Tests', () => {
|
|
|
27
27
|
mockSpot.borrowBalance = ZERO;
|
|
28
28
|
|
|
29
29
|
// todo, should incorp all other spot market constraints?
|
|
30
|
-
const aboveMaxAmount =
|
|
31
|
-
mockSpot,
|
|
32
|
-
new BN(2000000)
|
|
33
|
-
);
|
|
30
|
+
const { remainingCapacity: aboveMaxAmount } =
|
|
31
|
+
calculateSpotMarketBorrowCapacity(mockSpot, new BN(2000000));
|
|
34
32
|
assert(aboveMaxAmount.gt(mockSpot.depositBalance));
|
|
35
33
|
|
|
36
|
-
const maxAmount = calculateSpotMarketBorrowCapacity(
|
|
34
|
+
const { remainingCapacity: maxAmount } = calculateSpotMarketBorrowCapacity(
|
|
37
35
|
mockSpot,
|
|
38
36
|
new BN(1000000)
|
|
39
37
|
);
|
|
40
38
|
assert(maxAmount.eq(mockSpot.depositBalance));
|
|
41
39
|
|
|
42
|
-
const optAmount = calculateSpotMarketBorrowCapacity(
|
|
40
|
+
const { remainingCapacity: optAmount } = calculateSpotMarketBorrowCapacity(
|
|
43
41
|
mockSpot,
|
|
44
42
|
new BN(100000)
|
|
45
43
|
);
|
|
@@ -47,34 +45,26 @@ describe('Spot Tests', () => {
|
|
|
47
45
|
// console.log('optAmount:', optAmount.toNumber(), ans.toNumber());
|
|
48
46
|
assert(optAmount.eq(ans));
|
|
49
47
|
|
|
50
|
-
const betweenOptMaxAmount =
|
|
51
|
-
mockSpot,
|
|
52
|
-
new BN(810000)
|
|
53
|
-
);
|
|
48
|
+
const { remainingCapacity: betweenOptMaxAmount } =
|
|
49
|
+
calculateSpotMarketBorrowCapacity(mockSpot, new BN(810000));
|
|
54
50
|
// console.log('betweenOptMaxAmount:', betweenOptMaxAmount.toNumber());
|
|
55
51
|
assert(betweenOptMaxAmount.lt(mockSpot.depositBalance));
|
|
56
52
|
assert(betweenOptMaxAmount.gt(ans));
|
|
57
53
|
assert(betweenOptMaxAmount.eq(new BN(93666600000000)));
|
|
58
54
|
|
|
59
|
-
const belowOptAmount =
|
|
60
|
-
mockSpot,
|
|
61
|
-
new BN(50000)
|
|
62
|
-
);
|
|
55
|
+
const { remainingCapacity: belowOptAmount } =
|
|
56
|
+
calculateSpotMarketBorrowCapacity(mockSpot, new BN(50000));
|
|
63
57
|
// console.log('belowOptAmount:', belowOptAmount.toNumber());
|
|
64
58
|
assert(belowOptAmount.eq(ans.div(new BN(2))));
|
|
65
59
|
|
|
66
|
-
const belowOptAmount2 =
|
|
67
|
-
mockSpot,
|
|
68
|
-
new BN(24900)
|
|
69
|
-
);
|
|
60
|
+
const { remainingCapacity: belowOptAmount2 } =
|
|
61
|
+
calculateSpotMarketBorrowCapacity(mockSpot, new BN(24900));
|
|
70
62
|
// console.log('belowOptAmount2:', belowOptAmount2.toNumber());
|
|
71
63
|
assert(belowOptAmount2.lt(ans.div(new BN(4))));
|
|
72
64
|
assert(belowOptAmount2.eq(new BN('17430000000000')));
|
|
73
65
|
|
|
74
|
-
const belowOptAmount3 =
|
|
75
|
-
mockSpot,
|
|
76
|
-
new BN(1)
|
|
77
|
-
);
|
|
66
|
+
const { remainingCapacity: belowOptAmount3 } =
|
|
67
|
+
calculateSpotMarketBorrowCapacity(mockSpot, new BN(1));
|
|
78
68
|
// console.log('belowOptAmount3:', belowOptAmount3.toNumber());
|
|
79
69
|
assert(belowOptAmount3.eq(new BN('700000000'))); //0.7
|
|
80
70
|
});
|
|
@@ -97,59 +87,47 @@ describe('Spot Tests', () => {
|
|
|
97
87
|
mockSpot.borrowBalance = new BN(7089.91675884 * 1e9);
|
|
98
88
|
|
|
99
89
|
// todo, should incorp all other spot market constraints?
|
|
100
|
-
const aboveMaxAmount =
|
|
101
|
-
mockSpot,
|
|
102
|
-
new BN(2000000)
|
|
103
|
-
);
|
|
90
|
+
const { remainingCapacity: aboveMaxAmount } =
|
|
91
|
+
calculateSpotMarketBorrowCapacity(mockSpot, new BN(2000000));
|
|
104
92
|
assert(aboveMaxAmount.eq(new BN('111498270939007')));
|
|
105
93
|
|
|
106
|
-
const maxAmount = calculateSpotMarketBorrowCapacity(
|
|
94
|
+
const { remainingCapacity: maxAmount } = calculateSpotMarketBorrowCapacity(
|
|
107
95
|
mockSpot,
|
|
108
96
|
new BN(1000000)
|
|
109
97
|
);
|
|
110
98
|
assert(maxAmount.eq(new BN('82502230374168')));
|
|
111
99
|
// console.log('aboveMaxAmount:', aboveMaxAmount.toNumber(), 'maxAmount:', maxAmount.toNumber());
|
|
112
|
-
const optAmount = calculateSpotMarketBorrowCapacity(
|
|
100
|
+
const { remainingCapacity: optAmount } = calculateSpotMarketBorrowCapacity(
|
|
113
101
|
mockSpot,
|
|
114
102
|
new BN(70000)
|
|
115
103
|
);
|
|
116
104
|
// console.log('optAmount:', optAmount.toNumber());
|
|
117
105
|
assert(optAmount.eq(new BN('55535858716123'))); // ~ 55535
|
|
118
106
|
|
|
119
|
-
const betweenOptMaxAmount =
|
|
120
|
-
mockSpot,
|
|
121
|
-
new BN(810000)
|
|
122
|
-
);
|
|
107
|
+
const { remainingCapacity: betweenOptMaxAmount } =
|
|
108
|
+
calculateSpotMarketBorrowCapacity(mockSpot, new BN(810000));
|
|
123
109
|
// console.log('betweenOptMaxAmount:', betweenOptMaxAmount.toNumber());
|
|
124
110
|
assert(betweenOptMaxAmount.lt(maxAmount));
|
|
125
111
|
assert(betweenOptMaxAmount.eq(new BN(76992910756523)));
|
|
126
112
|
assert(betweenOptMaxAmount.gt(optAmount));
|
|
127
113
|
|
|
128
|
-
const belowOptAmount =
|
|
129
|
-
mockSpot,
|
|
130
|
-
new BN(50000)
|
|
131
|
-
);
|
|
114
|
+
const { remainingCapacity: belowOptAmount } =
|
|
115
|
+
calculateSpotMarketBorrowCapacity(mockSpot, new BN(50000));
|
|
132
116
|
// console.log('belowOptAmount:', belowOptAmount.toNumber());
|
|
133
117
|
assert(belowOptAmount.eq(new BN('37558277610760')));
|
|
134
118
|
|
|
135
|
-
const belowOptAmount2 =
|
|
136
|
-
mockSpot,
|
|
137
|
-
new BN(24900)
|
|
138
|
-
);
|
|
119
|
+
const { remainingCapacity: belowOptAmount2 } =
|
|
120
|
+
calculateSpotMarketBorrowCapacity(mockSpot, new BN(24900));
|
|
139
121
|
// console.log('belowOptAmount2:', belowOptAmount2.toNumber());
|
|
140
122
|
assert(belowOptAmount2.eq(new BN('14996413323529')));
|
|
141
123
|
|
|
142
|
-
const belowOptAmount3 =
|
|
143
|
-
mockSpot,
|
|
144
|
-
new BN(4900)
|
|
145
|
-
);
|
|
124
|
+
const { remainingCapacity: belowOptAmount3 } =
|
|
125
|
+
calculateSpotMarketBorrowCapacity(mockSpot, new BN(4900));
|
|
146
126
|
// console.log('belowOptAmount2:', belowOptAmount3.toNumber());
|
|
147
127
|
assert(belowOptAmount3.eq(new BN('0')));
|
|
148
128
|
|
|
149
|
-
const belowOptAmount4 =
|
|
150
|
-
mockSpot,
|
|
151
|
-
new BN(1)
|
|
152
|
-
);
|
|
129
|
+
const { remainingCapacity: belowOptAmount4 } =
|
|
130
|
+
calculateSpotMarketBorrowCapacity(mockSpot, new BN(1));
|
|
153
131
|
// console.log('belowOptAmount3:', belowOptAmount4.toNumber());
|
|
154
132
|
assert(belowOptAmount4.eq(new BN('0')));
|
|
155
133
|
});
|