@drift-labs/sdk 2.38.1-beta.1 → 2.38.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.
Files changed (54) hide show
  1. package/VERSION +1 -1
  2. package/lib/accounts/fetch.js +2 -2
  3. package/lib/accounts/pollingDriftClientAccountSubscriber.js +2 -14
  4. package/lib/accounts/pollingUserStatsAccountSubscriber.js +2 -2
  5. package/lib/adminClient.d.ts +1 -0
  6. package/lib/adminClient.js +11 -0
  7. package/lib/config.d.ts +1 -0
  8. package/lib/config.js +2 -0
  9. package/lib/driftClient.d.ts +22 -2
  10. package/lib/driftClient.js +101 -15
  11. package/lib/examples/loadDlob.js +3 -1
  12. package/lib/examples/makeTradeExample.js +3 -1
  13. package/lib/idl/drift.json +36 -1
  14. package/lib/index.d.ts +3 -0
  15. package/lib/index.js +3 -0
  16. package/lib/jupiter/jupiterClient.d.ts +197 -0
  17. package/lib/jupiter/jupiterClient.js +48 -3
  18. package/lib/math/spotBalance.d.ts +6 -5
  19. package/lib/math/spotBalance.js +28 -11
  20. package/lib/math/spotMarket.d.ts +1 -1
  21. package/lib/math/spotMarket.js +2 -2
  22. package/lib/math/spotPosition.d.ts +16 -3
  23. package/lib/math/spotPosition.js +53 -9
  24. package/lib/oracles/strictOraclePrice.d.ts +8 -0
  25. package/lib/oracles/strictOraclePrice.js +17 -0
  26. package/lib/priorityFee/priorityFeeSubscriber.d.ts +22 -0
  27. package/lib/priorityFee/priorityFeeSubscriber.js +46 -0
  28. package/lib/tokenFaucet.js +1 -0
  29. package/lib/types.d.ts +4 -0
  30. package/lib/types.js +3 -0
  31. package/lib/user.d.ts +5 -4
  32. package/lib/user.js +71 -105
  33. package/package.json +2 -2
  34. package/src/accounts/fetch.ts +2 -2
  35. package/src/accounts/pollingDriftClientAccountSubscriber.ts +5 -23
  36. package/src/accounts/pollingUserStatsAccountSubscriber.ts +10 -8
  37. package/src/adminClient.ts +23 -0
  38. package/src/config.ts +3 -0
  39. package/src/driftClient.ts +173 -13
  40. package/src/examples/loadDlob.ts +1 -0
  41. package/src/examples/makeTradeExample.ts +1 -0
  42. package/src/idl/drift.json +36 -1
  43. package/src/index.ts +3 -0
  44. package/src/jupiter/jupiterClient.ts +246 -3
  45. package/src/math/spotBalance.ts +37 -11
  46. package/src/math/spotMarket.ts +7 -1
  47. package/src/math/spotPosition.ts +133 -18
  48. package/src/oracles/strictOraclePrice.ts +19 -0
  49. package/src/priorityFee/priorityFeeSubscriber.ts +75 -0
  50. package/src/tokenFaucet.ts +1 -0
  51. package/src/types.ts +4 -0
  52. package/src/user.ts +171 -228
  53. package/tests/dlob/helpers.ts +10 -7
  54. package/tests/user/test.ts +77 -4
@@ -28,6 +28,173 @@ export interface Route {
28
28
  slippageBps: number;
29
29
  swapMode: SwapMode;
30
30
  }
31
+ /**
32
+ *
33
+ * @export
34
+ * @interface RoutePlanStep
35
+ */
36
+ export interface RoutePlanStep {
37
+ /**
38
+ *
39
+ * @type {SwapInfo}
40
+ * @memberof RoutePlanStep
41
+ */
42
+ swapInfo: SwapInfo;
43
+ /**
44
+ *
45
+ * @type {number}
46
+ * @memberof RoutePlanStep
47
+ */
48
+ percent: number;
49
+ }
50
+ export interface SwapInfo {
51
+ /**
52
+ *
53
+ * @type {string}
54
+ * @memberof SwapInfo
55
+ */
56
+ ammKey: string;
57
+ /**
58
+ *
59
+ * @type {string}
60
+ * @memberof SwapInfo
61
+ */
62
+ label?: string;
63
+ /**
64
+ *
65
+ * @type {string}
66
+ * @memberof SwapInfo
67
+ */
68
+ inputMint: string;
69
+ /**
70
+ *
71
+ * @type {string}
72
+ * @memberof SwapInfo
73
+ */
74
+ outputMint: string;
75
+ /**
76
+ *
77
+ * @type {string}
78
+ * @memberof SwapInfo
79
+ */
80
+ inAmount: string;
81
+ /**
82
+ *
83
+ * @type {string}
84
+ * @memberof SwapInfo
85
+ */
86
+ outAmount: string;
87
+ /**
88
+ *
89
+ * @type {string}
90
+ * @memberof SwapInfo
91
+ */
92
+ feeAmount: string;
93
+ /**
94
+ *
95
+ * @type {string}
96
+ * @memberof SwapInfo
97
+ */
98
+ feeMint: string;
99
+ }
100
+ /**
101
+ *
102
+ * @export
103
+ * @interface PlatformFee
104
+ */
105
+ export interface PlatformFee {
106
+ /**
107
+ *
108
+ * @type {string}
109
+ * @memberof PlatformFee
110
+ */
111
+ amount?: string;
112
+ /**
113
+ *
114
+ * @type {number}
115
+ * @memberof PlatformFee
116
+ */
117
+ feeBps?: number;
118
+ }
119
+ /**
120
+ *
121
+ * @export
122
+ * @interface QuoteResponse
123
+ */
124
+ export interface QuoteResponse {
125
+ /**
126
+ *
127
+ * @type {string}
128
+ * @memberof QuoteResponse
129
+ */
130
+ inputMint: string;
131
+ /**
132
+ *
133
+ * @type {string}
134
+ * @memberof QuoteResponse
135
+ */
136
+ inAmount: string;
137
+ /**
138
+ *
139
+ * @type {string}
140
+ * @memberof QuoteResponse
141
+ */
142
+ outputMint: string;
143
+ /**
144
+ *
145
+ * @type {string}
146
+ * @memberof QuoteResponse
147
+ */
148
+ outAmount: string;
149
+ /**
150
+ *
151
+ * @type {string}
152
+ * @memberof QuoteResponse
153
+ */
154
+ otherAmountThreshold: string;
155
+ /**
156
+ *
157
+ * @type {SwapMode}
158
+ * @memberof QuoteResponse
159
+ */
160
+ swapMode: SwapMode;
161
+ /**
162
+ *
163
+ * @type {number}
164
+ * @memberof QuoteResponse
165
+ */
166
+ slippageBps: number;
167
+ /**
168
+ *
169
+ * @type {PlatformFee}
170
+ * @memberof QuoteResponse
171
+ */
172
+ platformFee?: PlatformFee;
173
+ /**
174
+ *
175
+ * @type {string}
176
+ * @memberof QuoteResponse
177
+ */
178
+ priceImpactPct: string;
179
+ /**
180
+ *
181
+ * @type {Array<RoutePlanStep>}
182
+ * @memberof QuoteResponse
183
+ */
184
+ routePlan: Array<RoutePlanStep>;
185
+ /**
186
+ *
187
+ * @type {number}
188
+ * @memberof QuoteResponse
189
+ */
190
+ contextSlot?: number;
191
+ /**
192
+ *
193
+ * @type {number}
194
+ * @memberof QuoteResponse
195
+ */
196
+ timeTaken?: number;
197
+ }
31
198
  export declare class JupiterClient {
32
199
  url: string;
33
200
  connection: Connection;
@@ -36,6 +203,7 @@ export declare class JupiterClient {
36
203
  connection: Connection;
37
204
  });
38
205
  /**
206
+ * ** @deprecated - use getQuote
39
207
  * Get routes for a swap
40
208
  * @param inputMint the mint of the input token
41
209
  * @param outputMint the mint of the output token
@@ -53,6 +221,35 @@ export declare class JupiterClient {
53
221
  onlyDirectRoutes?: boolean;
54
222
  }): Promise<Route[]>;
55
223
  /**
224
+ * Get routes for a swap
225
+ * @param inputMint the mint of the input token
226
+ * @param outputMint the mint of the output token
227
+ * @param amount the amount of the input token
228
+ * @param slippageBps the slippage tolerance in basis points
229
+ * @param swapMode the swap mode (ExactIn or ExactOut)
230
+ * @param onlyDirectRoutes whether to only return direct routes
231
+ */
232
+ getQuote({ inputMint, outputMint, amount, slippageBps, swapMode, onlyDirectRoutes, }: {
233
+ inputMint: PublicKey;
234
+ outputMint: PublicKey;
235
+ amount: BN;
236
+ slippageBps?: number;
237
+ swapMode?: SwapMode;
238
+ onlyDirectRoutes?: boolean;
239
+ }): Promise<QuoteResponse>;
240
+ /**
241
+ * Get a swap transaction for quote
242
+ * @param quoteResponse quote to perform swap
243
+ * @param userPublicKey the signer's wallet public key
244
+ * @param slippageBps the slippage tolerance in basis points
245
+ */
246
+ getSwap({ quote, userPublicKey, slippageBps, }: {
247
+ quote: QuoteResponse;
248
+ userPublicKey: PublicKey;
249
+ slippageBps?: number;
250
+ }): Promise<VersionedTransaction>;
251
+ /**
252
+ * ** @deprecated - use getSwap
56
253
  * Get a swap transaction for a route
57
254
  * @param route the route to perform swap
58
255
  * @param userPublicKey the signer's wallet public key
@@ -8,11 +8,12 @@ const web3_js_1 = require("@solana/web3.js");
8
8
  const node_fetch_1 = __importDefault(require("node-fetch"));
9
9
  class JupiterClient {
10
10
  constructor({ connection }) {
11
- this.url = 'https://quote-api.jup.ag/v4';
11
+ this.url = 'https://quote-api.jup.ag';
12
12
  this.lookupTableCahce = new Map();
13
13
  this.connection = connection;
14
14
  }
15
15
  /**
16
+ * ** @deprecated - use getQuote
16
17
  * Get routes for a swap
17
18
  * @param inputMint the mint of the input token
18
19
  * @param outputMint the mint of the output token
@@ -30,17 +31,61 @@ class JupiterClient {
30
31
  swapMode,
31
32
  onlyDirectRoutes: onlyDirectRoutes.toString(),
32
33
  }).toString();
33
- const { data: routes } = await (await (0, node_fetch_1.default)(`https://quote-api.jup.ag/v4/quote?${params}`)).json();
34
+ const { data: routes } = await (await (0, node_fetch_1.default)(`${this.url}/v4/quote?${params}`)).json();
34
35
  return routes;
35
36
  }
36
37
  /**
38
+ * Get routes for a swap
39
+ * @param inputMint the mint of the input token
40
+ * @param outputMint the mint of the output token
41
+ * @param amount the amount of the input token
42
+ * @param slippageBps the slippage tolerance in basis points
43
+ * @param swapMode the swap mode (ExactIn or ExactOut)
44
+ * @param onlyDirectRoutes whether to only return direct routes
45
+ */
46
+ async getQuote({ inputMint, outputMint, amount, slippageBps = 50, swapMode = 'ExactIn', onlyDirectRoutes = false, }) {
47
+ const params = new URLSearchParams({
48
+ inputMint: inputMint.toString(),
49
+ outputMint: outputMint.toString(),
50
+ amount: amount.toString(),
51
+ slippageBps: slippageBps.toString(),
52
+ swapMode,
53
+ onlyDirectRoutes: onlyDirectRoutes.toString(),
54
+ }).toString();
55
+ const quote = await (await (0, node_fetch_1.default)(`${this.url}/v6/quote?${params}`)).json();
56
+ return quote;
57
+ }
58
+ /**
59
+ * Get a swap transaction for quote
60
+ * @param quoteResponse quote to perform swap
61
+ * @param userPublicKey the signer's wallet public key
62
+ * @param slippageBps the slippage tolerance in basis points
63
+ */
64
+ async getSwap({ quote, userPublicKey, slippageBps = 50, }) {
65
+ const resp = await (await (0, node_fetch_1.default)(`${this.url}/v6/swap`, {
66
+ method: 'POST',
67
+ headers: {
68
+ 'Content-Type': 'application/json',
69
+ },
70
+ body: JSON.stringify({
71
+ quoteResponse: quote,
72
+ userPublicKey,
73
+ slippageBps,
74
+ }),
75
+ })).json();
76
+ const { swapTransaction } = resp;
77
+ const swapTransactionBuf = Buffer.from(swapTransaction, 'base64');
78
+ return web3_js_1.VersionedTransaction.deserialize(swapTransactionBuf);
79
+ }
80
+ /**
81
+ * ** @deprecated - use getSwap
37
82
  * Get a swap transaction for a route
38
83
  * @param route the route to perform swap
39
84
  * @param userPublicKey the signer's wallet public key
40
85
  * @param slippageBps the slippage tolerance in basis points
41
86
  */
42
87
  async getSwapTransaction({ route, userPublicKey, slippageBps = 50, }) {
43
- const resp = await (await (0, node_fetch_1.default)(`${this.url}/swap`, {
88
+ const resp = await (await (0, node_fetch_1.default)(`${this.url}/v4/swap`, {
44
89
  method: 'POST',
45
90
  headers: {
46
91
  'Content-Type': 'application/json',
@@ -1,6 +1,7 @@
1
1
  import { SpotMarketAccount, SpotBalanceType, MarginCategory } from '../types';
2
2
  import { BN } from '@coral-xyz/anchor';
3
3
  import { OraclePriceData } from '../oracles/types';
4
+ import { StrictOraclePrice } from '../oracles/strictOraclePrice';
4
5
  /**
5
6
  * Calculates the balance of a given token amount including any accumulated interest. This
6
7
  * is the same as `SpotPosition.scaledBalance`.
@@ -33,11 +34,10 @@ export declare function getSignedTokenAmount(tokenAmount: BN, balanceType: SpotB
33
34
  *
34
35
  * @param {BN} tokenAmount - The amount of tokens to calculate the value for (from `getTokenAmount`)
35
36
  * @param {number} spotDecimals - The number of decimals in the token.
36
- * @param {OraclePriceData} oraclePriceData - The oracle price data (typically a token/USD oracle).
37
- * @param {BN} oraclePriceTwap - The Time-Weighted Average Price of the oracle.
37
+ * @param {StrictOraclePrice} strictOraclePrice - Contains oracle price and 5min twap.
38
38
  * @return {BN} The calculated value of the given token amount, scaled by `PRICE_PRECISION`
39
39
  */
40
- export declare function getStrictTokenValue(tokenAmount: BN, spotDecimals: number, oraclePriceData: OraclePriceData, oraclePriceTwap: BN): BN;
40
+ export declare function getStrictTokenValue(tokenAmount: BN, spotDecimals: number, strictOraclePrice: StrictOraclePrice): BN;
41
41
  /**
42
42
  * Calculates the value of a given token amount in relation to an oracle price data
43
43
  *
@@ -46,8 +46,9 @@ export declare function getStrictTokenValue(tokenAmount: BN, spotDecimals: numbe
46
46
  * @param {OraclePriceData} oraclePriceData - The oracle price data (typically a token/USD oracle).
47
47
  * @return {BN} The value of the token based on the oracle, scaled by `PRICE_PRECISION`
48
48
  */
49
- export declare function getTokenValue(tokenAmount: BN, spotDecimals: number, oraclePriceData: OraclePriceData): BN;
50
- export declare function calculateAssetWeight(balanceAmount: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
49
+ export declare function getTokenValue(tokenAmount: BN, spotDecimals: number, oraclePriceData: Pick<OraclePriceData, 'price'>): BN;
50
+ export declare function calculateAssetWeight(balanceAmount: BN, oraclePrice: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
51
+ export declare function calculateScaledInitialAssetWeight(spotMarket: SpotMarketAccount, oraclePrice: BN): BN;
51
52
  export declare function calculateLiabilityWeight(size: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
52
53
  export declare function calculateUtilization(bank: SpotMarketAccount, delta?: any): BN;
53
54
  /**
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateWithdrawLimit = exports.calculateTokenUtilizationLimits = exports.calculateInterestAccumulated = exports.calculateBorrowRate = exports.calculateDepositRate = exports.calculateInterestRate = exports.calculateSpotMarketBorrowCapacity = exports.calculateUtilization = exports.calculateLiabilityWeight = exports.calculateAssetWeight = exports.getTokenValue = exports.getStrictTokenValue = exports.getSignedTokenAmount = exports.getTokenAmount = exports.getBalance = void 0;
3
+ exports.calculateWithdrawLimit = exports.calculateTokenUtilizationLimits = exports.calculateInterestAccumulated = exports.calculateBorrowRate = exports.calculateDepositRate = exports.calculateInterestRate = exports.calculateSpotMarketBorrowCapacity = exports.calculateUtilization = exports.calculateLiabilityWeight = exports.calculateScaledInitialAssetWeight = exports.calculateAssetWeight = exports.getTokenValue = exports.getStrictTokenValue = exports.getSignedTokenAmount = exports.getTokenAmount = exports.getBalance = void 0;
4
4
  const types_1 = require("../types");
5
5
  const anchor_1 = require("@coral-xyz/anchor");
6
6
  const numericConstants_1 = require("../constants/numericConstants");
@@ -69,20 +69,19 @@ exports.getSignedTokenAmount = getSignedTokenAmount;
69
69
  *
70
70
  * @param {BN} tokenAmount - The amount of tokens to calculate the value for (from `getTokenAmount`)
71
71
  * @param {number} spotDecimals - The number of decimals in the token.
72
- * @param {OraclePriceData} oraclePriceData - The oracle price data (typically a token/USD oracle).
73
- * @param {BN} oraclePriceTwap - The Time-Weighted Average Price of the oracle.
72
+ * @param {StrictOraclePrice} strictOraclePrice - Contains oracle price and 5min twap.
74
73
  * @return {BN} The calculated value of the given token amount, scaled by `PRICE_PRECISION`
75
74
  */
76
- function getStrictTokenValue(tokenAmount, spotDecimals, oraclePriceData, oraclePriceTwap) {
75
+ function getStrictTokenValue(tokenAmount, spotDecimals, strictOraclePrice) {
77
76
  if (tokenAmount.eq(numericConstants_1.ZERO)) {
78
77
  return numericConstants_1.ZERO;
79
78
  }
80
- let price = oraclePriceData.price;
81
- if (tokenAmount.gt(numericConstants_1.ZERO)) {
82
- price = anchor_1.BN.min(oraclePriceData.price, oraclePriceTwap);
79
+ let price;
80
+ if (tokenAmount.gte(numericConstants_1.ZERO)) {
81
+ price = strictOraclePrice.min();
83
82
  }
84
83
  else {
85
- price = anchor_1.BN.max(oraclePriceData.price, oraclePriceTwap);
84
+ price = strictOraclePrice.max();
86
85
  }
87
86
  const precisionDecrease = numericConstants_1.TEN.pow(new anchor_1.BN(spotDecimals));
88
87
  return tokenAmount.mul(price).div(precisionDecrease);
@@ -104,7 +103,7 @@ function getTokenValue(tokenAmount, spotDecimals, oraclePriceData) {
104
103
  return tokenAmount.mul(oraclePriceData.price).div(precisionDecrease);
105
104
  }
106
105
  exports.getTokenValue = getTokenValue;
107
- function calculateAssetWeight(balanceAmount, spotMarket, marginCategory) {
106
+ function calculateAssetWeight(balanceAmount, oraclePrice, spotMarket, marginCategory) {
108
107
  const sizePrecision = numericConstants_1.TEN.pow(new anchor_1.BN(spotMarket.decimals));
109
108
  let sizeInAmmReservePrecision;
110
109
  if (sizePrecision.gt(numericConstants_1.AMM_RESERVE_PRECISION)) {
@@ -118,18 +117,36 @@ function calculateAssetWeight(balanceAmount, spotMarket, marginCategory) {
118
117
  let assetWeight;
119
118
  switch (marginCategory) {
120
119
  case 'Initial':
121
- assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(sizeInAmmReservePrecision, new anchor_1.BN(spotMarket.imfFactor), new anchor_1.BN(spotMarket.initialAssetWeight));
120
+ assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(sizeInAmmReservePrecision, new anchor_1.BN(spotMarket.imfFactor), calculateScaledInitialAssetWeight(spotMarket, oraclePrice));
122
121
  break;
123
122
  case 'Maintenance':
124
123
  assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(sizeInAmmReservePrecision, new anchor_1.BN(spotMarket.imfFactor), new anchor_1.BN(spotMarket.maintenanceAssetWeight));
125
124
  break;
126
125
  default:
127
- assetWeight = new anchor_1.BN(spotMarket.initialAssetWeight);
126
+ assetWeight = calculateScaledInitialAssetWeight(spotMarket, oraclePrice);
128
127
  break;
129
128
  }
130
129
  return assetWeight;
131
130
  }
132
131
  exports.calculateAssetWeight = calculateAssetWeight;
132
+ function calculateScaledInitialAssetWeight(spotMarket, oraclePrice) {
133
+ if (spotMarket.scaleInitialAssetWeightStart.eq(numericConstants_1.ZERO)) {
134
+ return new anchor_1.BN(spotMarket.initialAssetWeight);
135
+ }
136
+ const deposits = getTokenAmount(spotMarket.depositBalance, spotMarket, types_1.SpotBalanceType.DEPOSIT);
137
+ const depositsValue = getTokenValue(deposits, spotMarket.decimals, {
138
+ price: oraclePrice,
139
+ });
140
+ if (depositsValue.lt(spotMarket.scaleInitialAssetWeightStart)) {
141
+ return new anchor_1.BN(spotMarket.initialAssetWeight);
142
+ }
143
+ else {
144
+ return new anchor_1.BN(spotMarket.initialAssetWeight)
145
+ .mul(spotMarket.scaleInitialAssetWeightStart)
146
+ .div(depositsValue);
147
+ }
148
+ }
149
+ exports.calculateScaledInitialAssetWeight = calculateScaledInitialAssetWeight;
133
150
  function calculateLiabilityWeight(size, spotMarket, marginCategory) {
134
151
  const sizePrecision = numericConstants_1.TEN.pow(new anchor_1.BN(spotMarket.decimals));
135
152
  let sizeInAmmReservePrecision;
@@ -1,4 +1,4 @@
1
1
  import { BN } from '@coral-xyz/anchor';
2
2
  import { MarginCategory, SpotBalanceType, SpotMarketAccount } from '../types';
3
3
  export declare function castNumberToSpotPrecision(value: number | BN, spotMarket: SpotMarketAccount): BN;
4
- export declare function calculateSpotMarketMarginRatio(market: SpotMarketAccount, marginCategory: MarginCategory, size: BN, balanceType: SpotBalanceType): number;
4
+ export declare function calculateSpotMarketMarginRatio(market: SpotMarketAccount, oraclePrice: BN, marginCategory: MarginCategory, size: BN, balanceType: SpotBalanceType): number;
@@ -14,9 +14,9 @@ function castNumberToSpotPrecision(value, spotMarket) {
14
14
  }
15
15
  }
16
16
  exports.castNumberToSpotPrecision = castNumberToSpotPrecision;
17
- function calculateSpotMarketMarginRatio(market, marginCategory, size, balanceType) {
17
+ function calculateSpotMarketMarginRatio(market, oraclePrice, marginCategory, size, balanceType) {
18
18
  if ((0, types_1.isVariant)(balanceType, 'deposit')) {
19
- const assetWeight = (0, spotBalance_1.calculateAssetWeight)(size, market, marginCategory);
19
+ const assetWeight = (0, spotBalance_1.calculateAssetWeight)(size, oraclePrice, market, marginCategory);
20
20
  return numericConstants_1.MARGIN_PRECISION.sub(assetWeight).toNumber();
21
21
  }
22
22
  else {
@@ -1,5 +1,18 @@
1
- import { SpotMarketAccount, SpotPosition } from '../types';
1
+ import { MarginCategory, SpotMarketAccount, SpotPosition } from '../types';
2
2
  import { BN } from '@coral-xyz/anchor';
3
- import { OraclePriceData } from '../oracles/types';
3
+ import { StrictOraclePrice } from '../oracles/strictOraclePrice';
4
4
  export declare function isSpotPositionAvailable(position: SpotPosition): boolean;
5
- export declare function getWorstCaseTokenAmounts(spotPosition: SpotPosition, spotMarketAccount: SpotMarketAccount, oraclePriceData: OraclePriceData): [BN, BN];
5
+ export type OrderFillSimulation = {
6
+ tokenAmount: BN;
7
+ ordersValue: BN;
8
+ tokenValue: BN;
9
+ weight: BN;
10
+ weightedTokenValue: BN;
11
+ freeCollateralContribution: any;
12
+ };
13
+ export declare function getWorstCaseTokenAmounts(spotPosition: SpotPosition, spotMarketAccount: SpotMarketAccount, strictOraclePrice: StrictOraclePrice, marginCategory: MarginCategory): OrderFillSimulation;
14
+ export declare function calculateWeightedTokenValue(tokenAmount: BN, tokenValue: BN, oraclePrice: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): {
15
+ weight: BN;
16
+ weightedTokenValue: BN;
17
+ };
18
+ export declare function simulateOrderFill(tokenAmount: BN, tokenValue: BN, openOrders: BN, strictOraclePrice: StrictOraclePrice, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): OrderFillSimulation;
@@ -1,23 +1,67 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getWorstCaseTokenAmounts = exports.isSpotPositionAvailable = void 0;
3
+ exports.simulateOrderFill = exports.calculateWeightedTokenValue = exports.getWorstCaseTokenAmounts = exports.isSpotPositionAvailable = void 0;
4
4
  const numericConstants_1 = require("../constants/numericConstants");
5
5
  const spotBalance_1 = require("./spotBalance");
6
6
  function isSpotPositionAvailable(position) {
7
7
  return position.scaledBalance.eq(numericConstants_1.ZERO) && position.openOrders === 0;
8
8
  }
9
9
  exports.isSpotPositionAvailable = isSpotPositionAvailable;
10
- function getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, oraclePriceData) {
10
+ function getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory) {
11
11
  const tokenAmount = (0, spotBalance_1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
12
- const tokenAmountAllBidsFill = tokenAmount.add(spotPosition.openBids);
13
- const tokenAmountAllAsksFill = tokenAmount.add(spotPosition.openAsks);
14
- if (tokenAmountAllBidsFill.abs().gt(tokenAmountAllAsksFill.abs())) {
15
- const worstCaseQuoteTokenAmount = (0, spotBalance_1.getTokenValue)(spotPosition.openBids.neg(), spotMarketAccount.decimals, oraclePriceData);
16
- return [tokenAmountAllBidsFill, worstCaseQuoteTokenAmount];
12
+ const tokenValue = (0, spotBalance_1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice);
13
+ if (spotPosition.openBids.eq(numericConstants_1.ZERO) && spotPosition.openAsks.eq(numericConstants_1.ZERO)) {
14
+ const { weight, weightedTokenValue } = calculateWeightedTokenValue(tokenAmount, tokenValue, strictOraclePrice.current, spotMarketAccount, marginCategory);
15
+ return {
16
+ tokenAmount,
17
+ ordersValue: numericConstants_1.ZERO,
18
+ tokenValue,
19
+ weight,
20
+ weightedTokenValue,
21
+ freeCollateralContribution: weightedTokenValue,
22
+ };
23
+ }
24
+ const bidsSimulation = simulateOrderFill(tokenAmount, tokenValue, spotPosition.openBids, strictOraclePrice, spotMarketAccount, marginCategory);
25
+ const asksSimulation = simulateOrderFill(tokenAmount, tokenValue, spotPosition.openAsks, strictOraclePrice, spotMarketAccount, marginCategory);
26
+ if (asksSimulation.freeCollateralContribution.lt(bidsSimulation.freeCollateralContribution)) {
27
+ return asksSimulation;
17
28
  }
18
29
  else {
19
- const worstCaseQuoteTokenAmount = (0, spotBalance_1.getTokenValue)(spotPosition.openAsks.neg(), spotMarketAccount.decimals, oraclePriceData);
20
- return [tokenAmountAllAsksFill, worstCaseQuoteTokenAmount];
30
+ return bidsSimulation;
21
31
  }
22
32
  }
23
33
  exports.getWorstCaseTokenAmounts = getWorstCaseTokenAmounts;
34
+ function calculateWeightedTokenValue(tokenAmount, tokenValue, oraclePrice, spotMarket, marginCategory) {
35
+ let weight;
36
+ if (tokenValue.gte(numericConstants_1.ZERO)) {
37
+ weight = (0, spotBalance_1.calculateAssetWeight)(tokenAmount, oraclePrice, spotMarket, marginCategory);
38
+ }
39
+ else {
40
+ weight = (0, spotBalance_1.calculateLiabilityWeight)(tokenAmount.abs(), spotMarket, marginCategory);
41
+ }
42
+ return {
43
+ weight: weight,
44
+ weightedTokenValue: tokenValue
45
+ .mul(weight)
46
+ .div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION),
47
+ };
48
+ }
49
+ exports.calculateWeightedTokenValue = calculateWeightedTokenValue;
50
+ function simulateOrderFill(tokenAmount, tokenValue, openOrders, strictOraclePrice, spotMarket, marginCategory) {
51
+ const ordersValue = (0, spotBalance_1.getTokenValue)(openOrders.neg(), spotMarket.decimals, {
52
+ price: strictOraclePrice.max(),
53
+ });
54
+ const tokenAmountAfterFill = tokenAmount.add(openOrders);
55
+ const tokenValueAfterFill = tokenValue.add(ordersValue.neg());
56
+ const { weight, weightedTokenValue: weightedTokenValueAfterFill } = calculateWeightedTokenValue(tokenAmountAfterFill, tokenValueAfterFill, strictOraclePrice.current, spotMarket, marginCategory);
57
+ const freeCollateralContribution = weightedTokenValueAfterFill.add(ordersValue);
58
+ return {
59
+ tokenAmount: tokenAmountAfterFill,
60
+ ordersValue: ordersValue,
61
+ tokenValue: tokenValueAfterFill,
62
+ weight,
63
+ weightedTokenValue: weightedTokenValueAfterFill,
64
+ freeCollateralContribution,
65
+ };
66
+ }
67
+ exports.simulateOrderFill = simulateOrderFill;
@@ -0,0 +1,8 @@
1
+ import { BN } from '@coral-xyz/anchor';
2
+ export declare class StrictOraclePrice {
3
+ current: BN;
4
+ twap?: BN;
5
+ constructor(current: BN, twap?: BN);
6
+ max(): BN;
7
+ min(): BN;
8
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StrictOraclePrice = void 0;
4
+ const anchor_1 = require("@coral-xyz/anchor");
5
+ class StrictOraclePrice {
6
+ constructor(current, twap) {
7
+ this.current = current;
8
+ this.twap = twap;
9
+ }
10
+ max() {
11
+ return this.twap ? anchor_1.BN.max(this.twap, this.current) : this.current;
12
+ }
13
+ min() {
14
+ return this.twap ? anchor_1.BN.min(this.twap, this.current) : this.current;
15
+ }
16
+ }
17
+ exports.StrictOraclePrice = StrictOraclePrice;
@@ -0,0 +1,22 @@
1
+ /// <reference types="node" />
2
+ import { Connection, PublicKey } from '@solana/web3.js';
3
+ export declare class PriorityFeeSubscriber {
4
+ connection: Connection;
5
+ frequencyMs: number;
6
+ addresses: PublicKey[];
7
+ slotsToCheck: number;
8
+ intervalId?: NodeJS.Timer;
9
+ latestPriorityFee: number;
10
+ avgPriorityFee: number;
11
+ maxPriorityFee: number;
12
+ lastSlotSeen: number;
13
+ constructor({ connection, frequencyMs, addresses, slotsToCheck, }: {
14
+ connection: Connection;
15
+ frequencyMs: number;
16
+ addresses: PublicKey[];
17
+ slotsToCheck?: number;
18
+ });
19
+ subscribe(): Promise<void>;
20
+ load(): Promise<void>;
21
+ unsubscribe(): Promise<void>;
22
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PriorityFeeSubscriber = void 0;
4
+ class PriorityFeeSubscriber {
5
+ constructor({ connection, frequencyMs, addresses, slotsToCheck = 10, }) {
6
+ this.latestPriorityFee = 0;
7
+ // avg of last {slotsToCheck} slots
8
+ this.avgPriorityFee = 0;
9
+ // max of last {slotsToCheck} slots
10
+ this.maxPriorityFee = 0;
11
+ this.lastSlotSeen = 0;
12
+ this.connection = connection;
13
+ this.frequencyMs = frequencyMs;
14
+ this.addresses = addresses;
15
+ this.slotsToCheck = slotsToCheck;
16
+ }
17
+ async subscribe() {
18
+ if (this.intervalId) {
19
+ return;
20
+ }
21
+ this.intervalId = setInterval(this.load.bind(this), this.frequencyMs);
22
+ }
23
+ async load() {
24
+ var _a, _b, _c;
25
+ // @ts-ignore
26
+ const rpcJSONResponse = await this.connection._rpcRequest('getRecentPrioritizationFees', [this.addresses]);
27
+ const descResults = (_c = (_b = (_a = rpcJSONResponse === null || rpcJSONResponse === void 0 ? void 0 : rpcJSONResponse.result) === null || _a === void 0 ? void 0 : _a.sort((a, b) => b.slot - a.slot)) === null || _b === void 0 ? void 0 : _b.slice(0, this.slotsToCheck)) !== null && _c !== void 0 ? _c : [];
28
+ if (!(descResults === null || descResults === void 0 ? void 0 : descResults.length))
29
+ return;
30
+ const mostRecentResult = descResults[0];
31
+ this.latestPriorityFee = mostRecentResult.prioritizationFee;
32
+ this.lastSlotSeen = mostRecentResult.slot;
33
+ this.avgPriorityFee =
34
+ descResults.reduce((a, b) => {
35
+ return a + b.prioritizationFee;
36
+ }, 0) / descResults.length;
37
+ this.maxPriorityFee = Math.max(...descResults.map((result) => result.prioritizationFee));
38
+ }
39
+ async unsubscribe() {
40
+ if (this.intervalId) {
41
+ clearInterval(this.intervalId);
42
+ this.intervalId = undefined;
43
+ }
44
+ }
45
+ }
46
+ exports.PriorityFeeSubscriber = PriorityFeeSubscriber;
@@ -37,6 +37,7 @@ class TokenFaucet {
37
37
  this.connection = connection;
38
38
  this.wallet = wallet;
39
39
  this.opts = opts || anchor_1.AnchorProvider.defaultOptions();
40
+ // @ts-ignore
40
41
  const provider = new anchor_1.AnchorProvider(connection, wallet, this.opts);
41
42
  this.provider = provider;
42
43
  this.program = new anchor_1.Program(token_faucet_json_1.default, programId, provider);
package/lib/types.d.ts CHANGED
@@ -242,6 +242,9 @@ export declare class OrderActionExplanation {
242
242
  static readonly ORDER_FILLED_WITH_SERUM: {
243
243
  orderFillWithSerum: {};
244
244
  };
245
+ static readonly ORDER_FILLED_WITH_PHOENIX: {
246
+ orderFillWithPhoenix: {};
247
+ };
245
248
  static readonly REDUCE_ONLY_ORDER_INCREASED_POSITION: {
246
249
  reduceOnlyOrderIncreasedPosition: {};
247
250
  };
@@ -721,6 +724,7 @@ export type SpotMarketAccount = {
721
724
  maintenanceLiabilityWeight: number;
722
725
  liquidatorFee: number;
723
726
  imfFactor: number;
727
+ scaleInitialAssetWeightStart: BN;
724
728
  withdrawGuardThreshold: BN;
725
729
  depositTokenTwap: BN;
726
730
  borrowTokenTwap: BN;
package/lib/types.js CHANGED
@@ -156,6 +156,9 @@ OrderActionExplanation.RISK_INCREASING_ORDER = {
156
156
  OrderActionExplanation.ORDER_FILLED_WITH_SERUM = {
157
157
  orderFillWithSerum: {},
158
158
  };
159
+ OrderActionExplanation.ORDER_FILLED_WITH_PHOENIX = {
160
+ orderFillWithPhoenix: {},
161
+ };
159
162
  OrderActionExplanation.REDUCE_ONLY_ORDER_INCREASED_POSITION = {
160
163
  reduceOnlyOrderIncreasedPosition: {},
161
164
  };