@drift-labs/sdk 2.49.0-beta.10 → 2.49.0-beta.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.
- package/VERSION +1 -1
- package/lib/math/superStake.d.ts +43 -0
- package/lib/math/superStake.js +64 -22
- package/package.json +1 -1
- package/src/math/superStake.ts +108 -20
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.49.0-beta.
|
|
1
|
+
2.49.0-beta.11
|
package/lib/math/superStake.d.ts
CHANGED
|
@@ -5,6 +5,30 @@ import { DriftClient } from '../driftClient';
|
|
|
5
5
|
import { BN } from '@coral-xyz/anchor';
|
|
6
6
|
import { User } from '../user';
|
|
7
7
|
import { DepositRecord } from '../types';
|
|
8
|
+
export type BSOL_STATS_API_RESPONSE = {
|
|
9
|
+
success: boolean;
|
|
10
|
+
stats?: {
|
|
11
|
+
conversion: {
|
|
12
|
+
bsol_to_sol: number;
|
|
13
|
+
sol_to_bsol: number;
|
|
14
|
+
};
|
|
15
|
+
apy: {
|
|
16
|
+
base: number;
|
|
17
|
+
blze: number;
|
|
18
|
+
total: number;
|
|
19
|
+
lending: number;
|
|
20
|
+
liquidity: number;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export type BSOL_EMISSIONS_API_RESPONSE = {
|
|
25
|
+
success: boolean;
|
|
26
|
+
emissions?: {
|
|
27
|
+
lend: number;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export declare function fetchBSolMetrics(): Promise<any>;
|
|
31
|
+
export declare function fetchBSolDriftEmissions(): Promise<any>;
|
|
8
32
|
export declare function findBestSuperStakeIxs({ marketIndex, amount, jupiterClient, driftClient, userAccountPublicKey, price, forceMarinade, onlyDirectRoutes, }: {
|
|
9
33
|
marketIndex: number;
|
|
10
34
|
amount: BN;
|
|
@@ -46,6 +70,25 @@ export declare function findBestJitoSolSuperStakeIxs({ amount, jupiterClient, dr
|
|
|
46
70
|
method: 'jupiter' | 'marinade';
|
|
47
71
|
price: number;
|
|
48
72
|
}>;
|
|
73
|
+
/**
|
|
74
|
+
* Finds best Jupiter Swap instructions for a generic lstMint
|
|
75
|
+
*
|
|
76
|
+
* Without doing any extra steps like checking if you can get a better rate by staking directly with that LST platform
|
|
77
|
+
*/
|
|
78
|
+
export declare function findBestLstSuperStakeIxs({ amount, lstMint, jupiterClient, driftClient, userAccountPublicKey, onlyDirectRoutes, lstMarketIndex, }: {
|
|
79
|
+
amount: BN;
|
|
80
|
+
lstMint: PublicKey;
|
|
81
|
+
lstMarketIndex: number;
|
|
82
|
+
jupiterClient: JupiterClient;
|
|
83
|
+
driftClient: DriftClient;
|
|
84
|
+
userAccountPublicKey?: PublicKey;
|
|
85
|
+
onlyDirectRoutes?: boolean;
|
|
86
|
+
}): Promise<{
|
|
87
|
+
ixs: TransactionInstruction[];
|
|
88
|
+
lookupTables: AddressLookupTableAccount[];
|
|
89
|
+
method: 'jupiter' | 'marinade';
|
|
90
|
+
price: number;
|
|
91
|
+
}>;
|
|
49
92
|
export type JITO_SOL_METRICS_ENDPOINT_RESPONSE = {
|
|
50
93
|
data: {
|
|
51
94
|
getStakePoolStats: {
|
package/lib/math/superStake.js
CHANGED
|
@@ -3,7 +3,7 @@ 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.calculateEstimatedSuperStakeLiquidationPrice = exports.calculateSolEarned = exports.fetchJitoSolMetrics = exports.findBestJitoSolSuperStakeIxs = exports.findBestMSolSuperStakeIxs = exports.findBestSuperStakeIxs = void 0;
|
|
6
|
+
exports.calculateEstimatedSuperStakeLiquidationPrice = exports.calculateSolEarned = exports.fetchJitoSolMetrics = exports.findBestLstSuperStakeIxs = exports.findBestJitoSolSuperStakeIxs = exports.findBestMSolSuperStakeIxs = exports.findBestSuperStakeIxs = exports.fetchBSolDriftEmissions = exports.fetchBSolMetrics = void 0;
|
|
7
7
|
const web3_js_1 = require("@solana/web3.js");
|
|
8
8
|
const marinade_1 = require("../marinade");
|
|
9
9
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
@@ -11,6 +11,14 @@ const types_1 = require("../types");
|
|
|
11
11
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
12
12
|
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
13
13
|
const utils_1 = require("./utils");
|
|
14
|
+
async function fetchBSolMetrics() {
|
|
15
|
+
return await (0, node_fetch_1.default)('https://stake.solblaze.org/api/v1/stats');
|
|
16
|
+
}
|
|
17
|
+
exports.fetchBSolMetrics = fetchBSolMetrics;
|
|
18
|
+
async function fetchBSolDriftEmissions() {
|
|
19
|
+
return await (0, node_fetch_1.default)('https://stake.solblaze.org/api/v1/drift_emissions');
|
|
20
|
+
}
|
|
21
|
+
exports.fetchBSolDriftEmissions = fetchBSolDriftEmissions;
|
|
14
22
|
async function findBestSuperStakeIxs({ marketIndex, amount, jupiterClient, driftClient, userAccountPublicKey, price, forceMarinade, onlyDirectRoutes, }) {
|
|
15
23
|
if (marketIndex === 2) {
|
|
16
24
|
return findBestMSolSuperStakeIxs({
|
|
@@ -32,6 +40,17 @@ async function findBestSuperStakeIxs({ marketIndex, amount, jupiterClient, drift
|
|
|
32
40
|
onlyDirectRoutes,
|
|
33
41
|
});
|
|
34
42
|
}
|
|
43
|
+
else if (marketIndex === 8) {
|
|
44
|
+
return findBestLstSuperStakeIxs({
|
|
45
|
+
amount,
|
|
46
|
+
lstMint: driftClient.getSpotMarketAccount(8).mint,
|
|
47
|
+
lstMarketIndex: 8,
|
|
48
|
+
jupiterClient,
|
|
49
|
+
driftClient,
|
|
50
|
+
userAccountPublicKey,
|
|
51
|
+
onlyDirectRoutes,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
35
54
|
else {
|
|
36
55
|
throw new Error(`Unsupported superstake market index: ${marketIndex}`);
|
|
37
56
|
}
|
|
@@ -90,14 +109,30 @@ async function findBestMSolSuperStakeIxs({ amount, jupiterClient, driftClient, u
|
|
|
90
109
|
}
|
|
91
110
|
exports.findBestMSolSuperStakeIxs = findBestMSolSuperStakeIxs;
|
|
92
111
|
async function findBestJitoSolSuperStakeIxs({ amount, jupiterClient, driftClient, userAccountPublicKey, onlyDirectRoutes, }) {
|
|
112
|
+
return await findBestLstSuperStakeIxs({
|
|
113
|
+
amount,
|
|
114
|
+
jupiterClient,
|
|
115
|
+
driftClient,
|
|
116
|
+
userAccountPublicKey,
|
|
117
|
+
onlyDirectRoutes,
|
|
118
|
+
lstMint: driftClient.getSpotMarketAccount(6).mint,
|
|
119
|
+
lstMarketIndex: 6,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
exports.findBestJitoSolSuperStakeIxs = findBestJitoSolSuperStakeIxs;
|
|
123
|
+
/**
|
|
124
|
+
* Finds best Jupiter Swap instructions for a generic lstMint
|
|
125
|
+
*
|
|
126
|
+
* Without doing any extra steps like checking if you can get a better rate by staking directly with that LST platform
|
|
127
|
+
*/
|
|
128
|
+
async function findBestLstSuperStakeIxs({ amount, lstMint, jupiterClient, driftClient, userAccountPublicKey, onlyDirectRoutes, lstMarketIndex, }) {
|
|
93
129
|
const solMint = driftClient.getSpotMarketAccount(1).mint;
|
|
94
|
-
const JitoSolMint = driftClient.getSpotMarketAccount(6).mint;
|
|
95
130
|
let jupiterPrice;
|
|
96
131
|
let bestRoute;
|
|
97
132
|
try {
|
|
98
133
|
const jupiterRoutes = await jupiterClient.getRoutes({
|
|
99
134
|
inputMint: solMint,
|
|
100
|
-
outputMint:
|
|
135
|
+
outputMint: lstMint,
|
|
101
136
|
amount,
|
|
102
137
|
onlyDirectRoutes,
|
|
103
138
|
});
|
|
@@ -110,7 +145,7 @@ async function findBestJitoSolSuperStakeIxs({ amount, jupiterClient, driftClient
|
|
|
110
145
|
}
|
|
111
146
|
const { ixs, lookupTables } = await driftClient.getJupiterSwapIx({
|
|
112
147
|
inMarketIndex: 1,
|
|
113
|
-
outMarketIndex:
|
|
148
|
+
outMarketIndex: lstMarketIndex,
|
|
114
149
|
route: bestRoute,
|
|
115
150
|
jupiterClient,
|
|
116
151
|
amount,
|
|
@@ -123,7 +158,7 @@ async function findBestJitoSolSuperStakeIxs({ amount, jupiterClient, driftClient
|
|
|
123
158
|
price: jupiterPrice,
|
|
124
159
|
};
|
|
125
160
|
}
|
|
126
|
-
exports.
|
|
161
|
+
exports.findBestLstSuperStakeIxs = findBestLstSuperStakeIxs;
|
|
127
162
|
const JITO_SOL_START_DATE = '2022-10-31T00:00:00Z';
|
|
128
163
|
async function fetchJitoSolMetrics() {
|
|
129
164
|
const res = await (0, node_fetch_1.default)('https://kobe.mainnet.jito.network/', {
|
|
@@ -213,12 +248,30 @@ async function calculateSolEarned({ marketIndex, user, depositRecords, }) {
|
|
|
213
248
|
lstRatios.set(timestamp, data);
|
|
214
249
|
}
|
|
215
250
|
};
|
|
251
|
+
const getBSolPrice = async (timestamps) => {
|
|
252
|
+
var _a, _b;
|
|
253
|
+
// Currently there's only one bSOL price, no timestamped data
|
|
254
|
+
// So just use the same price for every timestamp for now
|
|
255
|
+
const response = await fetchBSolMetrics();
|
|
256
|
+
if (response.status === 200) {
|
|
257
|
+
const data = (await response.json());
|
|
258
|
+
const bSolRatio = (_b = (_a = data === null || data === void 0 ? void 0 : data.stats) === null || _a === void 0 ? void 0 : _a.conversion) === null || _b === void 0 ? void 0 : _b.bsol_to_sol;
|
|
259
|
+
if (bSolRatio) {
|
|
260
|
+
timestamps.forEach((timestamp) => lstRatios.set(timestamp, bSolRatio));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
// This block kind of assumes the record are all from the same market
|
|
265
|
+
// Otherwise the following code that checks the record.marketIndex would break
|
|
216
266
|
if (marketIndex === 2) {
|
|
217
267
|
await Promise.all(timestamps.map(getMsolPrice));
|
|
218
268
|
}
|
|
219
269
|
else if (marketIndex === 6) {
|
|
220
270
|
lstRatios = await getJitoSolHistoricalPriceMap(timestamps);
|
|
221
271
|
}
|
|
272
|
+
else if (marketIndex === 8) {
|
|
273
|
+
await getBSolPrice(timestamps);
|
|
274
|
+
}
|
|
222
275
|
let solEarned = numericConstants_1.ZERO;
|
|
223
276
|
for (const record of depositRecords) {
|
|
224
277
|
if (record.marketIndex === 1) {
|
|
@@ -229,23 +282,12 @@ async function calculateSolEarned({ marketIndex, user, depositRecords, }) {
|
|
|
229
282
|
solEarned = solEarned.add(record.amount);
|
|
230
283
|
}
|
|
231
284
|
}
|
|
232
|
-
else if (record.marketIndex === 2
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
else {
|
|
240
|
-
solEarned = solEarned.add(solAmount);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
else if (record.marketIndex === 6) {
|
|
244
|
-
const jitoSolRatio = lstRatios.get(record.ts.toNumber());
|
|
245
|
-
const jitoSolRatioBN = new anchor_1.BN(jitoSolRatio * web3_js_1.LAMPORTS_PER_SOL);
|
|
246
|
-
const solAmount = record.amount
|
|
247
|
-
.mul(jitoSolRatioBN)
|
|
248
|
-
.div(numericConstants_1.LAMPORTS_PRECISION);
|
|
285
|
+
else if (record.marketIndex === 2 ||
|
|
286
|
+
record.marketIndex === 6 ||
|
|
287
|
+
record.marketIndex === 8) {
|
|
288
|
+
const lstRatio = lstRatios.get(record.ts.toNumber());
|
|
289
|
+
const lstRatioBN = new anchor_1.BN(lstRatio * web3_js_1.LAMPORTS_PER_SOL);
|
|
290
|
+
const solAmount = record.amount.mul(lstRatioBN).div(numericConstants_1.LAMPORTS_PRECISION);
|
|
249
291
|
if ((0, types_1.isVariant)(record.direction, 'deposit')) {
|
|
250
292
|
solEarned = solEarned.sub(solAmount);
|
|
251
293
|
}
|
package/package.json
CHANGED
package/src/math/superStake.ts
CHANGED
|
@@ -14,6 +14,38 @@ import { LAMPORTS_PRECISION, ZERO } from '../constants/numericConstants';
|
|
|
14
14
|
import fetch from 'node-fetch';
|
|
15
15
|
import { checkSameDate } from './utils';
|
|
16
16
|
|
|
17
|
+
export type BSOL_STATS_API_RESPONSE = {
|
|
18
|
+
success: boolean;
|
|
19
|
+
stats?: {
|
|
20
|
+
conversion: {
|
|
21
|
+
bsol_to_sol: number;
|
|
22
|
+
sol_to_bsol: number;
|
|
23
|
+
};
|
|
24
|
+
apy: {
|
|
25
|
+
base: number;
|
|
26
|
+
blze: number;
|
|
27
|
+
total: number;
|
|
28
|
+
lending: number;
|
|
29
|
+
liquidity: number;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type BSOL_EMISSIONS_API_RESPONSE = {
|
|
35
|
+
success: boolean;
|
|
36
|
+
emissions?: {
|
|
37
|
+
lend: number;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export async function fetchBSolMetrics() {
|
|
42
|
+
return await fetch('https://stake.solblaze.org/api/v1/stats');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function fetchBSolDriftEmissions() {
|
|
46
|
+
return await fetch('https://stake.solblaze.org/api/v1/drift_emissions');
|
|
47
|
+
}
|
|
48
|
+
|
|
17
49
|
export async function findBestSuperStakeIxs({
|
|
18
50
|
marketIndex,
|
|
19
51
|
amount,
|
|
@@ -56,6 +88,16 @@ export async function findBestSuperStakeIxs({
|
|
|
56
88
|
userAccountPublicKey,
|
|
57
89
|
onlyDirectRoutes,
|
|
58
90
|
});
|
|
91
|
+
} else if (marketIndex === 8) {
|
|
92
|
+
return findBestLstSuperStakeIxs({
|
|
93
|
+
amount,
|
|
94
|
+
lstMint: driftClient.getSpotMarketAccount(8).mint,
|
|
95
|
+
lstMarketIndex: 8,
|
|
96
|
+
jupiterClient,
|
|
97
|
+
driftClient,
|
|
98
|
+
userAccountPublicKey,
|
|
99
|
+
onlyDirectRoutes,
|
|
100
|
+
});
|
|
59
101
|
} else {
|
|
60
102
|
throw new Error(`Unsupported superstake market index: ${marketIndex}`);
|
|
61
103
|
}
|
|
@@ -153,16 +195,53 @@ export async function findBestJitoSolSuperStakeIxs({
|
|
|
153
195
|
lookupTables: AddressLookupTableAccount[];
|
|
154
196
|
method: 'jupiter' | 'marinade';
|
|
155
197
|
price: number;
|
|
198
|
+
}> {
|
|
199
|
+
return await findBestLstSuperStakeIxs({
|
|
200
|
+
amount,
|
|
201
|
+
jupiterClient,
|
|
202
|
+
driftClient,
|
|
203
|
+
userAccountPublicKey,
|
|
204
|
+
onlyDirectRoutes,
|
|
205
|
+
lstMint: driftClient.getSpotMarketAccount(6).mint,
|
|
206
|
+
lstMarketIndex: 6,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Finds best Jupiter Swap instructions for a generic lstMint
|
|
212
|
+
*
|
|
213
|
+
* Without doing any extra steps like checking if you can get a better rate by staking directly with that LST platform
|
|
214
|
+
*/
|
|
215
|
+
export async function findBestLstSuperStakeIxs({
|
|
216
|
+
amount,
|
|
217
|
+
lstMint,
|
|
218
|
+
jupiterClient,
|
|
219
|
+
driftClient,
|
|
220
|
+
userAccountPublicKey,
|
|
221
|
+
onlyDirectRoutes,
|
|
222
|
+
lstMarketIndex,
|
|
223
|
+
}: {
|
|
224
|
+
amount: BN;
|
|
225
|
+
lstMint: PublicKey;
|
|
226
|
+
lstMarketIndex: number;
|
|
227
|
+
jupiterClient: JupiterClient;
|
|
228
|
+
driftClient: DriftClient;
|
|
229
|
+
userAccountPublicKey?: PublicKey;
|
|
230
|
+
onlyDirectRoutes?: boolean;
|
|
231
|
+
}): Promise<{
|
|
232
|
+
ixs: TransactionInstruction[];
|
|
233
|
+
lookupTables: AddressLookupTableAccount[];
|
|
234
|
+
method: 'jupiter' | 'marinade';
|
|
235
|
+
price: number;
|
|
156
236
|
}> {
|
|
157
237
|
const solMint = driftClient.getSpotMarketAccount(1).mint;
|
|
158
|
-
const JitoSolMint = driftClient.getSpotMarketAccount(6).mint;
|
|
159
238
|
|
|
160
239
|
let jupiterPrice;
|
|
161
240
|
let bestRoute;
|
|
162
241
|
try {
|
|
163
242
|
const jupiterRoutes = await jupiterClient.getRoutes({
|
|
164
243
|
inputMint: solMint,
|
|
165
|
-
outputMint:
|
|
244
|
+
outputMint: lstMint,
|
|
166
245
|
amount,
|
|
167
246
|
onlyDirectRoutes,
|
|
168
247
|
});
|
|
@@ -176,7 +255,7 @@ export async function findBestJitoSolSuperStakeIxs({
|
|
|
176
255
|
|
|
177
256
|
const { ixs, lookupTables } = await driftClient.getJupiterSwapIx({
|
|
178
257
|
inMarketIndex: 1,
|
|
179
|
-
outMarketIndex:
|
|
258
|
+
outMarketIndex: lstMarketIndex,
|
|
180
259
|
route: bestRoute,
|
|
181
260
|
jupiterClient,
|
|
182
261
|
amount,
|
|
@@ -322,10 +401,27 @@ export async function calculateSolEarned({
|
|
|
322
401
|
}
|
|
323
402
|
};
|
|
324
403
|
|
|
404
|
+
const getBSolPrice = async (timestamps: number[]) => {
|
|
405
|
+
// Currently there's only one bSOL price, no timestamped data
|
|
406
|
+
// So just use the same price for every timestamp for now
|
|
407
|
+
const response = await fetchBSolMetrics();
|
|
408
|
+
if (response.status === 200) {
|
|
409
|
+
const data = (await response.json()) as BSOL_STATS_API_RESPONSE;
|
|
410
|
+
const bSolRatio = data?.stats?.conversion?.bsol_to_sol;
|
|
411
|
+
if (bSolRatio) {
|
|
412
|
+
timestamps.forEach((timestamp) => lstRatios.set(timestamp, bSolRatio));
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
// This block kind of assumes the record are all from the same market
|
|
418
|
+
// Otherwise the following code that checks the record.marketIndex would break
|
|
325
419
|
if (marketIndex === 2) {
|
|
326
420
|
await Promise.all(timestamps.map(getMsolPrice));
|
|
327
421
|
} else if (marketIndex === 6) {
|
|
328
422
|
lstRatios = await getJitoSolHistoricalPriceMap(timestamps);
|
|
423
|
+
} else if (marketIndex === 8) {
|
|
424
|
+
await getBSolPrice(timestamps);
|
|
329
425
|
}
|
|
330
426
|
|
|
331
427
|
let solEarned = ZERO;
|
|
@@ -336,23 +432,15 @@ export async function calculateSolEarned({
|
|
|
336
432
|
} else {
|
|
337
433
|
solEarned = solEarned.add(record.amount);
|
|
338
434
|
}
|
|
339
|
-
} else if (
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
}
|
|
349
|
-
} else if (record.marketIndex === 6) {
|
|
350
|
-
const jitoSolRatio = lstRatios.get(record.ts.toNumber());
|
|
351
|
-
const jitoSolRatioBN = new BN(jitoSolRatio * LAMPORTS_PER_SOL);
|
|
352
|
-
|
|
353
|
-
const solAmount = record.amount
|
|
354
|
-
.mul(jitoSolRatioBN)
|
|
355
|
-
.div(LAMPORTS_PRECISION);
|
|
435
|
+
} else if (
|
|
436
|
+
record.marketIndex === 2 ||
|
|
437
|
+
record.marketIndex === 6 ||
|
|
438
|
+
record.marketIndex === 8
|
|
439
|
+
) {
|
|
440
|
+
const lstRatio = lstRatios.get(record.ts.toNumber());
|
|
441
|
+
const lstRatioBN = new BN(lstRatio * LAMPORTS_PER_SOL);
|
|
442
|
+
|
|
443
|
+
const solAmount = record.amount.mul(lstRatioBN).div(LAMPORTS_PRECISION);
|
|
356
444
|
if (isVariant(record.direction, 'deposit')) {
|
|
357
445
|
solEarned = solEarned.sub(solAmount);
|
|
358
446
|
} else {
|