@drift-labs/sdk 2.41.0-beta.0 → 2.41.0-beta.1

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.
Files changed (81) hide show
  1. package/README.md +0 -1
  2. package/VERSION +1 -1
  3. package/bun.lockb +0 -0
  4. package/lib/accounts/types.d.ts +5 -1
  5. package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -1
  6. package/lib/accounts/webSocketAccountSubscriber.js +28 -2
  7. package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +2 -1
  8. package/lib/accounts/webSocketDriftClientAccountSubscriber.js +6 -5
  9. package/lib/accounts/webSocketProgramAccountSubscriber.d.ts +32 -0
  10. package/lib/accounts/webSocketProgramAccountSubscriber.js +99 -0
  11. package/lib/accounts/webSocketUserAccountSubscriber.d.ts +2 -1
  12. package/lib/accounts/webSocketUserAccountSubscriber.js +3 -2
  13. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +2 -1
  14. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +3 -2
  15. package/lib/addresses/pda.d.ts +1 -0
  16. package/lib/addresses/pda.js +5 -1
  17. package/lib/adminClient.d.ts +2 -0
  18. package/lib/adminClient.js +20 -0
  19. package/lib/auctionSubscriber/auctionSubscriber.d.ts +3 -2
  20. package/lib/auctionSubscriber/auctionSubscriber.js +15 -7
  21. package/lib/auctionSubscriber/types.d.ts +1 -0
  22. package/lib/dlob/DLOB.d.ts +2 -6
  23. package/lib/dlob/DLOB.js +9 -11
  24. package/lib/dlob/DLOBSubscriber.js +4 -7
  25. package/lib/dlob/orderBookLevels.d.ts +4 -2
  26. package/lib/dlob/orderBookLevels.js +79 -16
  27. package/lib/driftClient.d.ts +2 -1
  28. package/lib/driftClient.js +5 -4
  29. package/lib/driftClientConfig.d.ts +1 -0
  30. package/lib/factory/bigNum.js +4 -2
  31. package/lib/idl/drift.json +222 -2
  32. package/lib/jupiter/jupiterClient.d.ts +4 -1
  33. package/lib/jupiter/jupiterClient.js +4 -1
  34. package/lib/math/amm.js +7 -2
  35. package/lib/math/auction.d.ts +12 -1
  36. package/lib/math/auction.js +22 -1
  37. package/lib/math/market.js +2 -4
  38. package/lib/math/superStake.d.ts +51 -4
  39. package/lib/math/superStake.js +173 -21
  40. package/lib/math/trade.js +2 -4
  41. package/lib/math/utils.d.ts +1 -0
  42. package/lib/math/utils.js +10 -1
  43. package/lib/orderSubscriber/OrderSubscriber.d.ts +1 -3
  44. package/lib/orderSubscriber/OrderSubscriber.js +4 -3
  45. package/lib/orderSubscriber/WebsocketSubscription.d.ts +4 -2
  46. package/lib/orderSubscriber/WebsocketSubscription.js +15 -12
  47. package/lib/orderSubscriber/types.d.ts +1 -0
  48. package/lib/user.d.ts +2 -2
  49. package/lib/user.js +5 -5
  50. package/package.json +2 -1
  51. package/src/accounts/types.ts +8 -1
  52. package/src/accounts/webSocketAccountSubscriber.ts +36 -2
  53. package/src/accounts/webSocketDriftClientAccountSubscriber.ts +15 -5
  54. package/src/accounts/webSocketProgramAccountSubscriber.ts +152 -0
  55. package/src/accounts/webSocketUserAccountSubscriber.ts +10 -2
  56. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +10 -2
  57. package/src/addresses/pda.ts +9 -0
  58. package/src/adminClient.ts +32 -0
  59. package/src/auctionSubscriber/auctionSubscriber.ts +30 -21
  60. package/src/auctionSubscriber/types.ts +1 -0
  61. package/src/dlob/DLOB.ts +9 -32
  62. package/src/dlob/DLOBSubscriber.ts +8 -7
  63. package/src/dlob/orderBookLevels.ts +133 -32
  64. package/src/driftClient.ts +5 -1
  65. package/src/driftClientConfig.ts +1 -0
  66. package/src/factory/bigNum.ts +2 -0
  67. package/src/idl/drift.json +222 -2
  68. package/src/jupiter/jupiterClient.ts +6 -0
  69. package/src/math/amm.ts +9 -2
  70. package/src/math/auction.ts +36 -2
  71. package/src/math/market.ts +4 -9
  72. package/src/math/superStake.ts +247 -23
  73. package/src/math/trade.ts +3 -11
  74. package/src/math/utils.ts +12 -0
  75. package/src/orderSubscriber/OrderSubscriber.ts +12 -7
  76. package/src/orderSubscriber/WebsocketSubscription.ts +34 -23
  77. package/src/orderSubscriber/types.ts +1 -0
  78. package/src/user.ts +7 -5
  79. package/tests/amm/test.ts +402 -0
  80. package/tests/auctions/test.ts +66 -0
  81. package/tests/dlob/test.ts +1 -73
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getAuctionPriceForOracleOffsetAuction = exports.getAuctionPriceForFixedAuction = exports.getAuctionPrice = exports.isFallbackAvailableLiquiditySource = exports.isAuctionComplete = void 0;
3
+ exports.deriveOracleAuctionParams = exports.getAuctionPriceForOracleOffsetAuction = exports.getAuctionPriceForFixedAuction = exports.getAuctionPrice = exports.isFallbackAvailableLiquiditySource = exports.isAuctionComplete = void 0;
4
4
  const types_1 = require("../types");
5
5
  const _1 = require("../.");
6
6
  function isAuctionComplete(order, slot) {
@@ -89,3 +89,24 @@ function getAuctionPriceForOracleOffsetAuction(order, slot, oraclePrice) {
89
89
  return oraclePrice.add(priceOffset);
90
90
  }
91
91
  exports.getAuctionPriceForOracleOffsetAuction = getAuctionPriceForOracleOffsetAuction;
92
+ function deriveOracleAuctionParams({ direction, oraclePrice, auctionStartPrice, auctionEndPrice, limitPrice, }) {
93
+ let oraclePriceOffset = limitPrice.sub(oraclePrice);
94
+ if (oraclePriceOffset.eq(_1.ZERO)) {
95
+ oraclePriceOffset = (0, types_1.isVariant)(direction, 'long')
96
+ ? auctionEndPrice.sub(oraclePrice).add(_1.ONE)
97
+ : auctionEndPrice.sub(oraclePrice).sub(_1.ONE);
98
+ }
99
+ let oraclePriceOffsetNum;
100
+ try {
101
+ oraclePriceOffsetNum = oraclePriceOffset.toNumber();
102
+ }
103
+ catch (e) {
104
+ oraclePriceOffsetNum = 0;
105
+ }
106
+ return {
107
+ auctionStartPrice: auctionStartPrice.sub(oraclePrice),
108
+ auctionEndPrice: auctionEndPrice.sub(oraclePrice),
109
+ oraclePriceOffset: oraclePriceOffsetNum,
110
+ };
111
+ }
112
+ exports.deriveOracleAuctionParams = deriveOracleAuctionParams;
@@ -130,12 +130,10 @@ exports.calculateNetUserPnlImbalance = calculateNetUserPnlImbalance;
130
130
  function calculateAvailablePerpLiquidity(market, oraclePriceData, dlob, slot) {
131
131
  let [bids, asks] = (0, amm_1.calculateMarketOpenBidAsk)(market.amm.baseAssetReserve, market.amm.minBaseAssetReserve, market.amm.maxBaseAssetReserve, market.amm.orderStepSize);
132
132
  asks = asks.abs();
133
- const bidPrice = calculateBidPrice(market, oraclePriceData);
134
- const askPrice = calculateAskPrice(market, oraclePriceData);
135
- for (const bid of dlob.getMakerLimitBids(market.marketIndex, slot, types_1.MarketType.PERP, oraclePriceData, askPrice)) {
133
+ for (const bid of dlob.getRestingLimitBids(market.marketIndex, slot, types_1.MarketType.PERP, oraclePriceData)) {
136
134
  bids = bids.add(bid.order.baseAssetAmount.sub(bid.order.baseAssetAmountFilled));
137
135
  }
138
- for (const ask of dlob.getMakerLimitAsks(market.marketIndex, slot, types_1.MarketType.PERP, oraclePriceData, bidPrice)) {
136
+ for (const ask of dlob.getRestingLimitAsks(market.marketIndex, slot, types_1.MarketType.PERP, oraclePriceData)) {
139
137
  asks = asks.add(ask.order.baseAssetAmount.sub(ask.order.baseAssetAmountFilled));
140
138
  }
141
139
  return {
@@ -4,11 +4,12 @@ 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, marinadePrice, forceMarinade, onlyDirectRoutes, }: {
7
+ export declare function findBestSuperStakeIxs({ marketIndex, amount, jupiterClient, driftClient, userAccountPublicKey, price, forceMarinade, onlyDirectRoutes, }: {
8
+ marketIndex: number;
8
9
  amount: BN;
9
10
  jupiterClient: JupiterClient;
10
11
  driftClient: DriftClient;
11
- marinadePrice?: number;
12
+ price?: number;
12
13
  userAccountPublicKey?: PublicKey;
13
14
  forceMarinade?: boolean;
14
15
  onlyDirectRoutes?: boolean;
@@ -18,8 +19,54 @@ export declare function findBestSuperStakeIxs({ amount, jupiterClient, driftClie
18
19
  method: 'jupiter' | 'marinade';
19
20
  price: number;
20
21
  }>;
21
- export declare function calculateSolEarned({ user, depositRecords, }: {
22
+ export declare function findBestMSolSuperStakeIxs({ amount, jupiterClient, driftClient, userAccountPublicKey, price, forceMarinade, onlyDirectRoutes, }: {
23
+ amount: BN;
24
+ jupiterClient: JupiterClient;
25
+ driftClient: DriftClient;
26
+ price?: number;
27
+ userAccountPublicKey?: PublicKey;
28
+ forceMarinade?: boolean;
29
+ onlyDirectRoutes?: boolean;
30
+ }): Promise<{
31
+ ixs: TransactionInstruction[];
32
+ lookupTables: AddressLookupTableAccount[];
33
+ method: 'jupiter' | 'marinade';
34
+ price: number;
35
+ }>;
36
+ export declare function findBestJitoSolSuperStakeIxs({ amount, jupiterClient, driftClient, userAccountPublicKey, onlyDirectRoutes, }: {
37
+ amount: BN;
38
+ jupiterClient: JupiterClient;
39
+ driftClient: DriftClient;
40
+ userAccountPublicKey?: PublicKey;
41
+ onlyDirectRoutes?: boolean;
42
+ }): Promise<{
43
+ ixs: TransactionInstruction[];
44
+ lookupTables: AddressLookupTableAccount[];
45
+ method: 'jupiter' | 'marinade';
46
+ price: number;
47
+ }>;
48
+ export type JITO_SOL_METRICS_ENDPOINT_RESPONSE = {
49
+ data: {
50
+ getStakePoolStats: {
51
+ tvl: {
52
+ data: number;
53
+ date: string;
54
+ }[];
55
+ supply: {
56
+ data: number;
57
+ date: string;
58
+ }[];
59
+ apy: {
60
+ data: number;
61
+ date: string;
62
+ }[];
63
+ };
64
+ };
65
+ };
66
+ export declare function fetchJitoSolMetrics(): Promise<JITO_SOL_METRICS_ENDPOINT_RESPONSE>;
67
+ export declare function calculateSolEarned({ marketIndex, user, depositRecords, }: {
68
+ marketIndex: number;
22
69
  user: User;
23
70
  depositRecords: DepositRecord[];
24
71
  }): Promise<BN>;
25
- export declare function calculateEstimatedSuperStakeLiquidationPrice(msolDepositAmount: number, msolMaintenanceAssetWeight: number, solBorrowAmount: number, solMaintenanceLiabilityWeight: number, msolPriceRatio: number): number;
72
+ export declare function calculateEstimatedSuperStakeLiquidationPrice(lstDepositAmount: number, lstMaintenanceAssetWeight: number, solBorrowAmount: number, solMaintenanceLiabilityWeight: number, lstPriceRatio: number): number;
@@ -3,17 +3,44 @@ 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.findBestSuperStakeIxs = void 0;
6
+ exports.calculateEstimatedSuperStakeLiquidationPrice = exports.calculateSolEarned = exports.fetchJitoSolMetrics = exports.findBestJitoSolSuperStakeIxs = exports.findBestMSolSuperStakeIxs = exports.findBestSuperStakeIxs = 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");
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, marinadePrice, forceMarinade, onlyDirectRoutes, }) {
14
- if (!marinadePrice) {
13
+ const utils_1 = require("./utils");
14
+ async function findBestSuperStakeIxs({ marketIndex, amount, jupiterClient, driftClient, userAccountPublicKey, price, forceMarinade, onlyDirectRoutes, }) {
15
+ if (marketIndex === 2) {
16
+ return findBestMSolSuperStakeIxs({
17
+ amount,
18
+ jupiterClient,
19
+ driftClient,
20
+ userAccountPublicKey,
21
+ price,
22
+ forceMarinade,
23
+ onlyDirectRoutes,
24
+ });
25
+ }
26
+ else if (marketIndex === 6) {
27
+ return findBestJitoSolSuperStakeIxs({
28
+ amount,
29
+ jupiterClient,
30
+ driftClient,
31
+ userAccountPublicKey,
32
+ onlyDirectRoutes,
33
+ });
34
+ }
35
+ else {
36
+ throw new Error(`Unsupported superstake market index: ${marketIndex}`);
37
+ }
38
+ }
39
+ exports.findBestSuperStakeIxs = findBestSuperStakeIxs;
40
+ async function findBestMSolSuperStakeIxs({ amount, jupiterClient, driftClient, userAccountPublicKey, price, forceMarinade, onlyDirectRoutes, }) {
41
+ if (!price) {
15
42
  const marinadeProgram = (0, marinade_1.getMarinadeFinanceProgram)(driftClient.provider);
16
- marinadePrice = await (0, marinade_1.getMarinadeMSolPrice)(marinadeProgram);
43
+ price = await (0, marinade_1.getMarinadeMSolPrice)(marinadeProgram);
17
44
  }
18
45
  const solMint = driftClient.getSpotMarketAccount(1).mint;
19
46
  const mSOLMint = driftClient.getSpotMarketAccount(2).mint;
@@ -32,7 +59,7 @@ async function findBestSuperStakeIxs({ amount, jupiterClient, driftClient, userA
32
59
  catch (e) {
33
60
  console.error('Error getting jupiter price', e);
34
61
  }
35
- if (!jupiterPrice || marinadePrice <= jupiterPrice || forceMarinade) {
62
+ if (!jupiterPrice || price <= jupiterPrice || forceMarinade) {
36
63
  const ixs = await driftClient.getStakeForMSOLIx({
37
64
  amount,
38
65
  userAccountPublicKey,
@@ -41,7 +68,7 @@ async function findBestSuperStakeIxs({ amount, jupiterClient, driftClient, userA
41
68
  method: 'marinade',
42
69
  ixs,
43
70
  lookupTables: [],
44
- price: marinadePrice,
71
+ price: price,
45
72
  };
46
73
  }
47
74
  else {
@@ -61,25 +88,137 @@ async function findBestSuperStakeIxs({ amount, jupiterClient, driftClient, userA
61
88
  };
62
89
  }
63
90
  }
64
- exports.findBestSuperStakeIxs = findBestSuperStakeIxs;
65
- async function calculateSolEarned({ user, depositRecords, }) {
91
+ exports.findBestMSolSuperStakeIxs = findBestMSolSuperStakeIxs;
92
+ async function findBestJitoSolSuperStakeIxs({ amount, jupiterClient, driftClient, userAccountPublicKey, onlyDirectRoutes, }) {
93
+ const solMint = driftClient.getSpotMarketAccount(1).mint;
94
+ const JitoSolMint = driftClient.getSpotMarketAccount(6).mint;
95
+ let jupiterPrice;
96
+ let bestRoute;
97
+ try {
98
+ const jupiterRoutes = await jupiterClient.getRoutes({
99
+ inputMint: solMint,
100
+ outputMint: JitoSolMint,
101
+ amount,
102
+ onlyDirectRoutes,
103
+ });
104
+ bestRoute = jupiterRoutes[0];
105
+ jupiterPrice = bestRoute.inAmount / bestRoute.outAmount;
106
+ }
107
+ catch (e) {
108
+ console.error('Error getting jupiter price', e);
109
+ throw e;
110
+ }
111
+ const { ixs, lookupTables } = await driftClient.getJupiterSwapIx({
112
+ inMarketIndex: 1,
113
+ outMarketIndex: 6,
114
+ route: bestRoute,
115
+ jupiterClient,
116
+ amount,
117
+ userAccountPublicKey,
118
+ });
119
+ return {
120
+ method: 'jupiter',
121
+ ixs,
122
+ lookupTables,
123
+ price: jupiterPrice,
124
+ };
125
+ }
126
+ exports.findBestJitoSolSuperStakeIxs = findBestJitoSolSuperStakeIxs;
127
+ const JITO_SOL_START_DATE = '2022-10-31T00:00:00Z';
128
+ async function fetchJitoSolMetrics() {
129
+ const res = await (0, node_fetch_1.default)('https://kobe.mainnet.jito.network/', {
130
+ body: JSON.stringify({
131
+ operationName: 'QueryRoot',
132
+ variables: {
133
+ request: {
134
+ bucketType: 'DAILY',
135
+ rangeFilter: {
136
+ start: JITO_SOL_START_DATE,
137
+ end: new Date().toISOString(),
138
+ },
139
+ sortBy: {
140
+ order: 'ASC',
141
+ field: 'BLOCK_TIME',
142
+ },
143
+ },
144
+ },
145
+ query: `
146
+ query QueryRoot($request: GetStakePoolStatsRequest!) {
147
+ getStakePoolStats(req: $request) {
148
+ tvl {
149
+ data
150
+ date
151
+ }
152
+ apy {
153
+ data
154
+ date
155
+ }
156
+ supply {
157
+ data
158
+ date
159
+ }
160
+ }
161
+ }
162
+ `,
163
+ }),
164
+ method: 'POST',
165
+ });
166
+ const data = await res.json();
167
+ return data;
168
+ }
169
+ exports.fetchJitoSolMetrics = fetchJitoSolMetrics;
170
+ const getJitoSolHistoricalPriceMap = async (timestamps) => {
171
+ try {
172
+ const data = await fetchJitoSolMetrics();
173
+ const jitoSolHistoricalPriceMap = new Map();
174
+ const jitoSolHistoricalPriceInSol = [];
175
+ for (let i = 0; i < data.data.getStakePoolStats.supply.length; i++) {
176
+ const priceInSol = data.data.getStakePoolStats.tvl[i].data /
177
+ 10 ** 9 /
178
+ data.data.getStakePoolStats.supply[i].data;
179
+ jitoSolHistoricalPriceInSol.push({
180
+ price: priceInSol,
181
+ ts: data.data.getStakePoolStats.tvl[i].date,
182
+ });
183
+ }
184
+ for (const timestamp of timestamps) {
185
+ const date = new Date(timestamp * 1000);
186
+ const dateString = date.toISOString();
187
+ const price = jitoSolHistoricalPriceInSol.find((p) => (0, utils_1.checkSameDate)(p.ts, dateString));
188
+ if (price) {
189
+ jitoSolHistoricalPriceMap.set(timestamp, price.price);
190
+ }
191
+ }
192
+ return jitoSolHistoricalPriceMap;
193
+ }
194
+ catch (err) {
195
+ console.error(err);
196
+ return undefined;
197
+ }
198
+ };
199
+ async function calculateSolEarned({ marketIndex, user, depositRecords, }) {
66
200
  const now = Date.now() / 1000;
67
201
  const timestamps = [
68
202
  now,
69
203
  ...depositRecords.map((r) => r.ts.toNumber()),
70
204
  ];
71
- const msolRatios = new Map();
72
- const getPrice = async (timestamp) => {
205
+ let lstRatios = new Map();
206
+ const getMsolPrice = async (timestamp) => {
73
207
  const date = new Date(timestamp * 1000); // Convert Unix timestamp to milliseconds
74
208
  const swaggerApiDateTime = date.toISOString(); // Format date as swagger API date-time
75
209
  const url = `https://api.marinade.finance/msol/price_sol?time=${swaggerApiDateTime}`;
76
210
  const response = await (0, node_fetch_1.default)(url);
77
211
  if (response.status === 200) {
78
212
  const data = await response.json();
79
- msolRatios.set(timestamp, data);
213
+ lstRatios.set(timestamp, data);
80
214
  }
81
215
  };
82
- await Promise.all(timestamps.map(getPrice));
216
+ if (marketIndex === 2) {
217
+ await Promise.all(timestamps.map(getMsolPrice));
218
+ }
219
+ else if (marketIndex === 6) {
220
+ lstRatios = await getJitoSolHistoricalPriceMap(timestamps);
221
+ }
83
222
  let solEarned = numericConstants_1.ZERO;
84
223
  for (const record of depositRecords) {
85
224
  if (record.marketIndex === 1) {
@@ -91,7 +230,7 @@ async function calculateSolEarned({ user, depositRecords, }) {
91
230
  }
92
231
  }
93
232
  else if (record.marketIndex === 2) {
94
- const msolRatio = msolRatios.get(record.ts.toNumber());
233
+ const msolRatio = lstRatios.get(record.ts.toNumber());
95
234
  const msolRatioBN = new anchor_1.BN(msolRatio * web3_js_1.LAMPORTS_PER_SOL);
96
235
  const solAmount = record.amount.mul(msolRatioBN).div(numericConstants_1.LAMPORTS_PRECISION);
97
236
  if ((0, types_1.isVariant)(record.direction, 'deposit')) {
@@ -101,21 +240,34 @@ async function calculateSolEarned({ user, depositRecords, }) {
101
240
  solEarned = solEarned.add(solAmount);
102
241
  }
103
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);
249
+ if ((0, types_1.isVariant)(record.direction, 'deposit')) {
250
+ solEarned = solEarned.sub(solAmount);
251
+ }
252
+ else {
253
+ solEarned = solEarned.add(solAmount);
254
+ }
255
+ }
104
256
  }
105
- const currentMSOLTokenAmount = await user.getTokenAmount(2);
257
+ const currentLstTokenAmount = await user.getTokenAmount(marketIndex);
258
+ const currentLstRatio = lstRatios.get(now);
259
+ const currentLstRatioBN = new anchor_1.BN(currentLstRatio * web3_js_1.LAMPORTS_PER_SOL);
260
+ solEarned = solEarned.add(currentLstTokenAmount.mul(currentLstRatioBN).div(numericConstants_1.LAMPORTS_PRECISION));
106
261
  const currentSOLTokenAmount = await user.getTokenAmount(1);
107
- const currentMSOLRatio = msolRatios.get(now);
108
- const currentMSOLRatioBN = new anchor_1.BN(currentMSOLRatio * web3_js_1.LAMPORTS_PER_SOL);
109
- solEarned = solEarned.add(currentMSOLTokenAmount.mul(currentMSOLRatioBN).div(numericConstants_1.LAMPORTS_PRECISION));
110
262
  solEarned = solEarned.add(currentSOLTokenAmount);
111
263
  return solEarned;
112
264
  }
113
265
  exports.calculateSolEarned = calculateSolEarned;
114
- // calculate estimated liquidation price (in mSOL/SOL) based on target amounts
115
- function calculateEstimatedSuperStakeLiquidationPrice(msolDepositAmount, msolMaintenanceAssetWeight, solBorrowAmount, solMaintenanceLiabilityWeight, msolPriceRatio) {
266
+ // calculate estimated liquidation price (in LST/SOL) based on target amounts
267
+ function calculateEstimatedSuperStakeLiquidationPrice(lstDepositAmount, lstMaintenanceAssetWeight, solBorrowAmount, solMaintenanceLiabilityWeight, lstPriceRatio) {
116
268
  const liquidationDivergence = (solMaintenanceLiabilityWeight * solBorrowAmount) /
117
- (msolMaintenanceAssetWeight * msolDepositAmount * msolPriceRatio);
118
- const liquidationPrice = msolPriceRatio * liquidationDivergence;
269
+ (lstMaintenanceAssetWeight * lstDepositAmount * lstPriceRatio);
270
+ const liquidationPrice = lstPriceRatio * liquidationDivergence;
119
271
  return liquidationPrice;
120
272
  }
121
273
  exports.calculateEstimatedSuperStakeLiquidationPrice = calculateEstimatedSuperStakeLiquidationPrice;
package/lib/math/trade.js CHANGED
@@ -278,9 +278,7 @@ function calculateEstimatedPerpEntryPrice(assetType, amount, direction, market,
278
278
  };
279
279
  }
280
280
  const takerIsLong = (0, types_2.isVariant)(direction, 'long');
281
- const limitOrders = dlob[takerIsLong ? 'getMakerLimitAsks' : 'getMakerLimitBids'](market.marketIndex, slot, types_1.MarketType.PERP, oraclePriceData, takerIsLong
282
- ? (0, market_1.calculateBidPrice)(market, oraclePriceData)
283
- : (0, market_1.calculateAskPrice)(market, oraclePriceData));
281
+ const limitOrders = dlob[takerIsLong ? 'getRestingLimitAsks' : 'getRestingLimitBids'](market.marketIndex, slot, types_1.MarketType.PERP, oraclePriceData);
284
282
  const swapDirection = (0, amm_1.getSwapDirection)(assetType, direction);
285
283
  const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, direction, oraclePriceData);
286
284
  const amm = {
@@ -463,7 +461,7 @@ function calculateEstimatedSpotEntryPrice(assetType, amount, direction, market,
463
461
  }
464
462
  const basePrecision = new anchor_1.BN(Math.pow(10, market.decimals));
465
463
  const takerIsLong = (0, types_2.isVariant)(direction, 'long');
466
- const dlobLimitOrders = dlob[takerIsLong ? 'getMakerLimitAsks' : 'getMakerLimitBids'](market.marketIndex, slot, types_1.MarketType.SPOT, oraclePriceData);
464
+ const dlobLimitOrders = dlob[takerIsLong ? 'getRestingLimitAsks' : 'getRestingLimitBids'](market.marketIndex, slot, types_1.MarketType.SPOT, oraclePriceData);
467
465
  const serumLimitOrders = takerIsLong
468
466
  ? serumAsks.getL2(100)
469
467
  : serumBids.getL2(100);
@@ -12,3 +12,4 @@ export declare const sigNum: (x: BN) => BN;
12
12
  * @returns: timeRemainingUntilUpdate (in seconds)
13
13
  */
14
14
  export declare function timeRemainingUntilUpdate(now: BN, lastUpdateTs: BN, updatePeriod: BN): BN;
15
+ export declare const checkSameDate: (dateString1: string, dateString2: string) => boolean;
package/lib/math/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.timeRemainingUntilUpdate = exports.sigNum = exports.divCeil = exports.squareRootBN = exports.clampBN = void 0;
3
+ exports.checkSameDate = exports.timeRemainingUntilUpdate = exports.sigNum = exports.divCeil = exports.squareRootBN = exports.clampBN = void 0;
4
4
  const __1 = require("../");
5
5
  function clampBN(x, min, max) {
6
6
  return __1.BN.max(min, __1.BN.min(x, max));
@@ -76,3 +76,12 @@ function timeRemainingUntilUpdate(now, lastUpdateTs, updatePeriod) {
76
76
  return timeRemainingUntilUpdate;
77
77
  }
78
78
  exports.timeRemainingUntilUpdate = timeRemainingUntilUpdate;
79
+ const checkSameDate = (dateString1, dateString2) => {
80
+ const date1 = new Date(dateString1);
81
+ const date2 = new Date(dateString2);
82
+ const isSameDate = date1.getDate() === date2.getDate() &&
83
+ date1.getMonth() === date2.getMonth() &&
84
+ date1.getFullYear() === date2.getFullYear();
85
+ return isSameDate;
86
+ };
87
+ exports.checkSameDate = checkSameDate;
@@ -1,8 +1,6 @@
1
1
  /// <reference types="node" />
2
- /// <reference types="node" />
3
2
  import { DriftClient } from '../driftClient';
4
3
  import { UserAccount } from '../types';
5
- import { Buffer } from 'buffer';
6
4
  import { DLOB } from '../dlob/DLOB';
7
5
  import { OrderSubscriberConfig, OrderSubscriberEvents } from './types';
8
6
  import { PollingSubscription } from './PollingSubscription';
@@ -22,7 +20,7 @@ export declare class OrderSubscriber {
22
20
  constructor(config: OrderSubscriberConfig);
23
21
  subscribe(): Promise<void>;
24
22
  fetch(): Promise<void>;
25
- tryUpdateUserAccount(key: string, buffer: Buffer, slot: number): void;
23
+ tryUpdateUserAccount(key: string, userAccount: UserAccount, slot: number): void;
26
24
  getDLOB(slot: number): Promise<DLOB>;
27
25
  unsubscribe(): Promise<void>;
28
26
  }
@@ -22,6 +22,7 @@ class OrderSubscriber {
22
22
  this.subscription = new WebsocketSubscription_1.WebsocketSubscription({
23
23
  orderSubscriber: this,
24
24
  skipInitialLoad: config.subscriptionConfig.skipInitialLoad,
25
+ resubTimeoutMs: config.subscriptionConfig.resubTimeoutMs,
25
26
  });
26
27
  }
27
28
  this.eventEmitter = new events_1.EventEmitter();
@@ -57,7 +58,8 @@ class OrderSubscriber {
57
58
  // @ts-ignore
58
59
  const buffer = buffer_1.Buffer.from(programAccount.account.data[0], programAccount.account.data[1]);
59
60
  programAccountSet.add(key);
60
- this.tryUpdateUserAccount(key, buffer, slot);
61
+ const userAccount = this.driftClient.program.account.user.coder.accounts.decode('User', buffer);
62
+ this.tryUpdateUserAccount(key, userAccount, slot);
61
63
  }
62
64
  for (const key of this.usersAccounts.keys()) {
63
65
  if (!programAccountSet.has(key)) {
@@ -73,10 +75,9 @@ class OrderSubscriber {
73
75
  this.fetchPromise = undefined;
74
76
  }
75
77
  }
76
- tryUpdateUserAccount(key, buffer, slot) {
78
+ tryUpdateUserAccount(key, userAccount, slot) {
77
79
  const slotAndUserAccount = this.usersAccounts.get(key);
78
80
  if (!slotAndUserAccount || slotAndUserAccount.slot < slot) {
79
- const userAccount = this.driftClient.program.account.user.coder.accounts.decode('User', buffer);
80
81
  const newOrders = userAccount.orders.filter((order) => {
81
82
  var _a;
82
83
  return order.slot.toNumber() > ((_a = slotAndUserAccount === null || slotAndUserAccount === void 0 ? void 0 : slotAndUserAccount.slot) !== null && _a !== void 0 ? _a : 0) &&
@@ -2,10 +2,12 @@ import { OrderSubscriber } from './OrderSubscriber';
2
2
  export declare class WebsocketSubscription {
3
3
  private orderSubscriber;
4
4
  private skipInitialLoad;
5
- private websocketId;
6
- constructor({ orderSubscriber, skipInitialLoad, }: {
5
+ private resubTimeoutMs?;
6
+ private subscriber;
7
+ constructor({ orderSubscriber, skipInitialLoad, resubTimeoutMs, }: {
7
8
  orderSubscriber: OrderSubscriber;
8
9
  skipInitialLoad?: boolean;
10
+ resubTimeoutMs?: number;
9
11
  });
10
12
  subscribe(): Promise<void>;
11
13
  unsubscribe(): Promise<void>;
@@ -2,29 +2,32 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WebsocketSubscription = void 0;
4
4
  const memcmp_1 = require("../memcmp");
5
+ const webSocketProgramAccountSubscriber_1 = require("../accounts/webSocketProgramAccountSubscriber");
5
6
  class WebsocketSubscription {
6
- constructor({ orderSubscriber, skipInitialLoad = false, }) {
7
+ constructor({ orderSubscriber, skipInitialLoad = false, resubTimeoutMs, }) {
7
8
  this.orderSubscriber = orderSubscriber;
8
9
  this.skipInitialLoad = skipInitialLoad;
10
+ this.resubTimeoutMs = resubTimeoutMs;
9
11
  }
10
12
  async subscribe() {
11
- if (this.websocketId) {
12
- return;
13
+ if (!this.subscriber) {
14
+ this.subscriber = new webSocketProgramAccountSubscriber_1.WebSocketProgramAccountSubscriber('OrderSubscriber', 'User', this.orderSubscriber.driftClient.program, this.orderSubscriber.driftClient.program.account.user.coder.accounts.decode.bind(this.orderSubscriber.driftClient.program.account.user.coder.accounts), {
15
+ filters: [(0, memcmp_1.getUserFilter)(), (0, memcmp_1.getNonIdleUserFilter)()],
16
+ commitment: this.orderSubscriber.driftClient.opts.commitment,
17
+ }, this.resubTimeoutMs);
13
18
  }
14
- this.websocketId =
15
- this.orderSubscriber.driftClient.connection.onProgramAccountChange(this.orderSubscriber.driftClient.program.programId, (keyAccountInfo, context) => {
16
- const userKey = keyAccountInfo.accountId.toBase58();
17
- this.orderSubscriber.tryUpdateUserAccount(userKey, keyAccountInfo.accountInfo.data, context.slot);
18
- }, this.orderSubscriber.driftClient.opts.commitment, [(0, memcmp_1.getUserFilter)(), (0, memcmp_1.getNonIdleUserFilter)()]);
19
+ await this.subscriber.subscribe((accountId, account, context) => {
20
+ const userKey = accountId.toBase58();
21
+ this.orderSubscriber.tryUpdateUserAccount(userKey, account, context.slot);
22
+ });
19
23
  if (!this.skipInitialLoad) {
20
24
  await this.orderSubscriber.fetch();
21
25
  }
22
26
  }
23
27
  async unsubscribe() {
24
- if (this.websocketId) {
25
- await this.orderSubscriber.driftClient.connection.removeProgramAccountChangeListener(this.websocketId);
26
- this.websocketId = undefined;
27
- }
28
+ if (!this.subscriber)
29
+ return;
30
+ this.subscriber.unsubscribe();
28
31
  }
29
32
  }
30
33
  exports.WebsocketSubscription = WebsocketSubscription;
@@ -9,6 +9,7 @@ export type OrderSubscriberConfig = {
9
9
  } | {
10
10
  type: 'websocket';
11
11
  skipInitialLoad?: boolean;
12
+ resubTimeoutMs?: number;
12
13
  };
13
14
  };
14
15
  export interface OrderSubscriberEvents {
package/lib/user.d.ts CHANGED
@@ -180,14 +180,14 @@ export declare class User {
180
180
  * calculates current user leverage which is (total liability size) / (net asset value)
181
181
  * @returns : Precision TEN_THOUSAND
182
182
  */
183
- getLeverage(): BN;
183
+ getLeverage(includeOpenOrders?: boolean): BN;
184
184
  calculateLeverageFromComponents({ perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue, }: {
185
185
  perpLiabilityValue: BN;
186
186
  perpPnl: BN;
187
187
  spotAssetValue: BN;
188
188
  spotLiabilityValue: BN;
189
189
  }): BN;
190
- getLeverageComponents(): {
190
+ getLeverageComponents(includeOpenOrders?: boolean): {
191
191
  perpLiabilityValue: BN;
192
192
  perpPnl: BN;
193
193
  spotAssetValue: BN;
package/lib/user.js CHANGED
@@ -822,8 +822,8 @@ class User {
822
822
  * calculates current user leverage which is (total liability size) / (net asset value)
823
823
  * @returns : Precision TEN_THOUSAND
824
824
  */
825
- getLeverage() {
826
- return this.calculateLeverageFromComponents(this.getLeverageComponents());
825
+ getLeverage(includeOpenOrders = true) {
826
+ return this.calculateLeverageFromComponents(this.getLeverageComponents(includeOpenOrders));
827
827
  }
828
828
  calculateLeverageFromComponents({ perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue, }) {
829
829
  const totalLiabilityValue = perpLiabilityValue.add(spotLiabilityValue);
@@ -834,10 +834,10 @@ class User {
834
834
  }
835
835
  return totalLiabilityValue.mul(numericConstants_1.TEN_THOUSAND).div(netAssetValue);
836
836
  }
837
- getLeverageComponents() {
838
- const perpLiability = this.getTotalPerpPositionValue(undefined, undefined, true);
837
+ getLeverageComponents(includeOpenOrders = true) {
838
+ const perpLiability = this.getTotalPerpPositionValue(undefined, undefined, includeOpenOrders);
839
839
  const perpPnl = this.getUnrealizedPNL(true);
840
- const { totalAssetValue: spotAssetValue, totalLiabilityValue: spotLiabilityValue, } = this.getSpotMarketAssetAndLiabilityValue(undefined, undefined, undefined, true);
840
+ const { totalAssetValue: spotAssetValue, totalLiabilityValue: spotLiabilityValue, } = this.getSpotMarketAssetAndLiabilityValue(undefined, undefined, undefined, includeOpenOrders);
841
841
  return {
842
842
  perpLiabilityValue: perpLiability,
843
843
  perpPnl,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.41.0-beta.0",
3
+ "version": "2.41.0-beta.1",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -44,6 +44,7 @@
44
44
  "uuid": "^8.3.2"
45
45
  },
46
46
  "devDependencies": {
47
+ "@types/big.js": "^6.2.0",
47
48
  "@types/chai": "^4.3.1",
48
49
  "@types/jest": "^28.1.3",
49
50
  "@types/mocha": "^9.1.1",
@@ -8,7 +8,7 @@ import {
8
8
  } from '../types';
9
9
  import StrictEventEmitter from 'strict-event-emitter-types';
10
10
  import { EventEmitter } from 'events';
11
- import { PublicKey } from '@solana/web3.js';
11
+ import { Context, PublicKey } from '@solana/web3.js';
12
12
  import { Account } from '@solana/spl-token';
13
13
  import { OracleInfo, OraclePriceData } from '..';
14
14
 
@@ -21,6 +21,13 @@ export interface AccountSubscriber<T> {
21
21
  setData(userAccount: T, slot?: number): void;
22
22
  }
23
23
 
24
+ export interface ProgramAccountSubscriber<T> {
25
+ subscribe(
26
+ onChange: (accountId: PublicKey, data: T, context: Context) => void
27
+ ): Promise<void>;
28
+ unsubscribe(): Promise<void>;
29
+ }
30
+
24
31
  export class NotSubscribedError extends Error {
25
32
  name = 'NotSubscribedError';
26
33
  }