@drift-labs/sdk 2.49.0-beta.10 → 2.49.0-beta.12

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.49.0-beta.10
1
+ 2.49.0-beta.12
@@ -194,6 +194,16 @@ exports.DevnetPerpMarkets = [
194
194
  launchTs: 1700542800000,
195
195
  oracleSource: __1.OracleSource.PYTH,
196
196
  },
197
+ {
198
+ fullName: 'Celestia',
199
+ category: ['Data'],
200
+ symbol: 'TIA-PERP',
201
+ baseAssetSymbol: 'TIA',
202
+ marketIndex: 19,
203
+ oracle: new web3_js_1.PublicKey('4GiL1Y6u6JkPb7ckakzJgc414h6P7qoYnEKFcd1YtSB9'),
204
+ launchTs: 1701880540000,
205
+ oracleSource: __1.OracleSource.PYTH,
206
+ },
197
207
  ];
198
208
  exports.MainnetPerpMarkets = [
199
209
  {
@@ -386,6 +396,16 @@ exports.MainnetPerpMarkets = [
386
396
  launchTs: 1700542800000,
387
397
  oracleSource: __1.OracleSource.PYTH,
388
398
  },
399
+ {
400
+ fullName: 'Celestia',
401
+ category: ['Data'],
402
+ symbol: 'TIA-PERP',
403
+ baseAssetSymbol: 'TIA',
404
+ marketIndex: 19,
405
+ oracle: new web3_js_1.PublicKey('funeUsHgi2QKkLdUPASRLuYkaK8JaazCEz3HikbkhVt'),
406
+ launchTs: 1701880540000,
407
+ oracleSource: __1.OracleSource.PYTH,
408
+ },
389
409
  ];
390
410
  exports.PerpMarkets = {
391
411
  devnet: exports.DevnetPerpMarkets,
@@ -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: {
@@ -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: JitoSolMint,
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: 6,
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.findBestJitoSolSuperStakeIxs = findBestJitoSolSuperStakeIxs;
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
- const msolRatio = lstRatios.get(record.ts.toNumber());
234
- const msolRatioBN = new anchor_1.BN(msolRatio * web3_js_1.LAMPORTS_PER_SOL);
235
- const solAmount = record.amount.mul(msolRatioBN).div(numericConstants_1.LAMPORTS_PRECISION);
236
- if ((0, types_1.isVariant)(record.direction, 'deposit')) {
237
- solEarned = solEarned.sub(solAmount);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.49.0-beta.10",
3
+ "version": "2.49.0-beta.12",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -204,6 +204,16 @@ export const DevnetPerpMarkets: PerpMarketConfig[] = [
204
204
  launchTs: 1700542800000,
205
205
  oracleSource: OracleSource.PYTH,
206
206
  },
207
+ {
208
+ fullName: 'Celestia',
209
+ category: ['Data'],
210
+ symbol: 'TIA-PERP',
211
+ baseAssetSymbol: 'TIA',
212
+ marketIndex: 19,
213
+ oracle: new PublicKey('4GiL1Y6u6JkPb7ckakzJgc414h6P7qoYnEKFcd1YtSB9'),
214
+ launchTs: 1701880540000,
215
+ oracleSource: OracleSource.PYTH,
216
+ },
207
217
  ];
208
218
 
209
219
  export const MainnetPerpMarkets: PerpMarketConfig[] = [
@@ -397,6 +407,16 @@ export const MainnetPerpMarkets: PerpMarketConfig[] = [
397
407
  launchTs: 1700542800000,
398
408
  oracleSource: OracleSource.PYTH,
399
409
  },
410
+ {
411
+ fullName: 'Celestia',
412
+ category: ['Data'],
413
+ symbol: 'TIA-PERP',
414
+ baseAssetSymbol: 'TIA',
415
+ marketIndex: 19,
416
+ oracle: new PublicKey('funeUsHgi2QKkLdUPASRLuYkaK8JaazCEz3HikbkhVt'),
417
+ launchTs: 1701880540000,
418
+ oracleSource: OracleSource.PYTH,
419
+ },
400
420
  ];
401
421
 
402
422
  export const PerpMarkets: { [key in DriftEnv]: PerpMarketConfig[] } = {
@@ -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: JitoSolMint,
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: 6,
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 (record.marketIndex === 2) {
340
- const msolRatio = lstRatios.get(record.ts.toNumber());
341
- const msolRatioBN = new BN(msolRatio * LAMPORTS_PER_SOL);
342
-
343
- const solAmount = record.amount.mul(msolRatioBN).div(LAMPORTS_PRECISION);
344
- if (isVariant(record.direction, 'deposit')) {
345
- solEarned = solEarned.sub(solAmount);
346
- } else {
347
- solEarned = solEarned.add(solAmount);
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 {