@drift-labs/sdk 2.34.1-beta.1 → 2.34.1-beta.3

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.34.1-beta.1
1
+ 2.34.1-beta.3
@@ -134,6 +134,16 @@ exports.DevnetPerpMarkets = [
134
134
  launchTs: 1687201081000,
135
135
  oracleSource: __1.OracleSource.PYTH,
136
136
  },
137
+ {
138
+ fullName: 'XRP',
139
+ category: ['Payments'],
140
+ symbol: 'XRP-PERP',
141
+ baseAssetSymbol: 'XRP',
142
+ marketIndex: 13,
143
+ oracle: new web3_js_1.PublicKey('DuG45Td6dgJBe64Ebymb1WjBys16L1VTQdoAURdsviqN'),
144
+ launchTs: 1689270550000,
145
+ oracleSource: __1.OracleSource.PYTH,
146
+ },
137
147
  ];
138
148
  exports.MainnetPerpMarkets = [
139
149
  {
@@ -266,6 +276,16 @@ exports.MainnetPerpMarkets = [
266
276
  launchTs: 1687201081000,
267
277
  oracleSource: __1.OracleSource.PYTH,
268
278
  },
279
+ {
280
+ fullName: 'XRP',
281
+ category: ['Payments'],
282
+ symbol: 'XRP-PERP',
283
+ baseAssetSymbol: 'XRP',
284
+ marketIndex: 13,
285
+ oracle: new web3_js_1.PublicKey('Guffb8DAAxNH6kdoawYjPXTbwUhjmveh8R4LM6uEqRV1'),
286
+ launchTs: 1689270550000,
287
+ oracleSource: __1.OracleSource.PYTH,
288
+ },
269
289
  ];
270
290
  exports.PerpMarkets = {
271
291
  devnet: exports.DevnetPerpMarkets,
@@ -8,16 +8,15 @@ import { OraclePriceData } from '../oracles/types';
8
8
  * @param periodAdjustment
9
9
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
10
10
  */
11
- export declare function calculateAllEstimatedFundingRate(market: PerpMarketAccount, oraclePriceData?: OraclePriceData, periodAdjustment?: BN, now?: BN): Promise<[BN, BN, BN, BN, BN]>;
11
+ export declare function calculateAllEstimatedFundingRate(market: PerpMarketAccount, oraclePriceData?: OraclePriceData, markPrice?: BN, now?: BN): Promise<[BN, BN, BN, BN, BN]>;
12
12
  /**
13
13
  *
14
14
  * @param market
15
15
  * @param oraclePriceData
16
16
  * @param periodAdjustment
17
- * @param estimationMethod
18
17
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
19
18
  */
20
- export declare function calculateEstimatedFundingRate(market: PerpMarketAccount, oraclePriceData?: OraclePriceData, periodAdjustment?: BN, estimationMethod?: 'interpolated' | 'lowerbound' | 'capped'): Promise<BN>;
19
+ export declare function calculateLongShortFundingRate(market: PerpMarketAccount, oraclePriceData?: OraclePriceData, markPrice?: BN, now?: BN): Promise<[BN, BN]>;
21
20
  /**
22
21
  *
23
22
  * @param market
@@ -25,15 +24,7 @@ export declare function calculateEstimatedFundingRate(market: PerpMarketAccount,
25
24
  * @param periodAdjustment
26
25
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
27
26
  */
28
- export declare function calculateLongShortFundingRate(market: PerpMarketAccount, oraclePriceData?: OraclePriceData, periodAdjustment?: BN): Promise<[BN, BN]>;
29
- /**
30
- *
31
- * @param market
32
- * @param oraclePriceData
33
- * @param periodAdjustment
34
- * @returns Estimated funding rate. : Precision //TODO-PRECISION
35
- */
36
- export declare function calculateLongShortFundingRateAndLiveTwaps(market: PerpMarketAccount, oraclePriceData?: OraclePriceData, periodAdjustment?: BN): Promise<[BN, BN, BN, BN]>;
27
+ export declare function calculateLongShortFundingRateAndLiveTwaps(market: PerpMarketAccount, oraclePriceData?: OraclePriceData, markPrice?: BN, now?: BN): Promise<[BN, BN, BN, BN]>;
37
28
  /**
38
29
  *
39
30
  * @param market
@@ -1,10 +1,53 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateFundingPool = exports.calculateLongShortFundingRateAndLiveTwaps = exports.calculateLongShortFundingRate = exports.calculateEstimatedFundingRate = exports.calculateAllEstimatedFundingRate = void 0;
3
+ exports.calculateFundingPool = exports.calculateLongShortFundingRateAndLiveTwaps = exports.calculateLongShortFundingRate = exports.calculateAllEstimatedFundingRate = void 0;
4
4
  const anchor_1 = require("@coral-xyz/anchor");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
6
  const types_1 = require("../types");
7
7
  const amm_1 = require("./amm");
8
+ const oracles_1 = require("./oracles");
9
+ function calculateLiveMarkTwap(market, oraclePriceData, markPrice, now, period = new anchor_1.BN(3600)) {
10
+ now = now || new anchor_1.BN((Date.now() / 1000).toFixed(0));
11
+ const lastMarkTwapWithMantissa = market.amm.lastMarkPriceTwap;
12
+ const lastMarkPriceTwapTs = market.amm.lastMarkPriceTwapTs;
13
+ const timeSinceLastMarkChange = now.sub(lastMarkPriceTwapTs);
14
+ const markTwapTimeSinceLastUpdate = anchor_1.BN.max(period, anchor_1.BN.max(numericConstants_1.ZERO, period.sub(timeSinceLastMarkChange)));
15
+ if (!markPrice) {
16
+ const [bid, ask] = (0, amm_1.calculateBidAskPrice)(market.amm, oraclePriceData);
17
+ markPrice = bid.add(ask).div(new anchor_1.BN(2));
18
+ }
19
+ const markTwapWithMantissa = markTwapTimeSinceLastUpdate
20
+ .mul(lastMarkTwapWithMantissa)
21
+ .add(timeSinceLastMarkChange.mul(markPrice))
22
+ .div(timeSinceLastMarkChange.add(markTwapTimeSinceLastUpdate));
23
+ return markTwapWithMantissa;
24
+ }
25
+ function shrinkStaleTwaps(market, markTwapWithMantissa, oracleTwapWithMantissa, now) {
26
+ now = now || new anchor_1.BN((Date.now() / 1000).toFixed(0));
27
+ let newMarkTwap = markTwapWithMantissa;
28
+ let newOracleTwap = oracleTwapWithMantissa;
29
+ if (market.amm.lastMarkPriceTwapTs.gt(market.amm.historicalOracleData.lastOraclePriceTwapTs)) {
30
+ // shrink oracle based on invalid intervals
31
+ const oracleInvalidDuration = anchor_1.BN.max(numericConstants_1.ZERO, market.amm.lastMarkPriceTwapTs.sub(market.amm.historicalOracleData.lastOraclePriceTwapTs));
32
+ const timeSinceLastOracleTwapUpdate = now.sub(market.amm.historicalOracleData.lastOraclePriceTwapTs);
33
+ const oracleTwapTimeSinceLastUpdate = anchor_1.BN.max(numericConstants_1.ONE, anchor_1.BN.min(market.amm.fundingPeriod, anchor_1.BN.max(numericConstants_1.ONE, market.amm.fundingPeriod.sub(timeSinceLastOracleTwapUpdate))));
34
+ newOracleTwap = oracleTwapTimeSinceLastUpdate
35
+ .mul(oracleTwapWithMantissa)
36
+ .add(oracleInvalidDuration.mul(markTwapWithMantissa))
37
+ .div(oracleTwapTimeSinceLastUpdate.add(oracleInvalidDuration));
38
+ }
39
+ else if (market.amm.lastMarkPriceTwapTs.lt(market.amm.historicalOracleData.lastOraclePriceTwapTs)) {
40
+ // shrink mark to oracle twap over tradless intervals
41
+ const tradelessDuration = anchor_1.BN.max(numericConstants_1.ZERO, market.amm.historicalOracleData.lastOraclePriceTwapTs.sub(market.amm.lastMarkPriceTwapTs));
42
+ const timeSinceLastMarkTwapUpdate = now.sub(market.amm.lastMarkPriceTwapTs);
43
+ const markTwapTimeSinceLastUpdate = anchor_1.BN.max(numericConstants_1.ONE, anchor_1.BN.min(market.amm.fundingPeriod, anchor_1.BN.max(numericConstants_1.ONE, market.amm.fundingPeriod.sub(timeSinceLastMarkTwapUpdate))));
44
+ newMarkTwap = markTwapTimeSinceLastUpdate
45
+ .mul(markTwapWithMantissa)
46
+ .add(tradelessDuration.mul(oracleTwapWithMantissa))
47
+ .div(markTwapTimeSinceLastUpdate.add(tradelessDuration));
48
+ }
49
+ return [newMarkTwap, newOracleTwap];
50
+ }
8
51
  /**
9
52
  *
10
53
  * @param market
@@ -12,76 +55,38 @@ const amm_1 = require("./amm");
12
55
  * @param periodAdjustment
13
56
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
14
57
  */
15
- async function calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustment = new anchor_1.BN(1), now) {
16
- // periodAdjustment
17
- // 1: hourly
18
- // 24: daily
19
- // 24 * 365.25: annualized
20
- const secondsInHour = new anchor_1.BN(3600);
21
- const hoursInDay = new anchor_1.BN(24);
22
- const ONE = new anchor_1.BN(1);
58
+ async function calculateAllEstimatedFundingRate(market, oraclePriceData, markPrice, now) {
23
59
  if ((0, types_1.isVariant)(market.status, 'uninitialized')) {
24
60
  return [numericConstants_1.ZERO, numericConstants_1.ZERO, numericConstants_1.ZERO, numericConstants_1.ZERO, numericConstants_1.ZERO];
25
61
  }
26
- const payFreq = new anchor_1.BN(market.amm.fundingPeriod);
27
62
  // todo: sufficiently differs from blockchain timestamp?
28
63
  now = now || new anchor_1.BN((Date.now() / 1000).toFixed(0));
29
- const timeSinceLastUpdate = now.sub(market.amm.lastFundingRateTs);
30
- // calculate real-time mark twap
31
- const lastMarkTwapWithMantissa = market.amm.lastMarkPriceTwap;
32
- const lastMarkPriceTwapTs = market.amm.lastMarkPriceTwapTs;
33
- const timeSinceLastMarkChange = now.sub(lastMarkPriceTwapTs);
34
- const markTwapTimeSinceLastUpdate = anchor_1.BN.max(secondsInHour, anchor_1.BN.max(numericConstants_1.ZERO, secondsInHour.sub(timeSinceLastMarkChange)));
35
- const [bid, ask] = (0, amm_1.calculateBidAskPrice)(market.amm, oraclePriceData);
36
- const baseAssetPriceWithMantissa = bid.add(ask).div(new anchor_1.BN(2));
37
- const markTwapWithMantissa = markTwapTimeSinceLastUpdate
38
- .mul(lastMarkTwapWithMantissa)
39
- .add(timeSinceLastMarkChange.mul(baseAssetPriceWithMantissa))
40
- .div(timeSinceLastMarkChange.add(markTwapTimeSinceLastUpdate));
41
- // calculate real-time (predicted) oracle twap
42
- // note: oracle twap depends on `when the chord is struck` (market is trade)
43
- const lastOracleTwapWithMantissa = market.amm.historicalOracleData.lastOraclePriceTwap;
44
- const lastOraclePriceTwapTs = market.amm.historicalOracleData.lastOraclePriceTwapTs;
45
- const oracleInvalidDuration = anchor_1.BN.max(numericConstants_1.ZERO, lastMarkPriceTwapTs.sub(lastOraclePriceTwapTs));
46
- const timeSinceLastOracleTwapUpdate = now.sub(lastOraclePriceTwapTs);
47
- const oracleTwapTimeSinceLastUpdate = anchor_1.BN.max(ONE, anchor_1.BN.min(secondsInHour, anchor_1.BN.max(ONE, secondsInHour.sub(timeSinceLastOracleTwapUpdate))));
48
- let oracleTwapWithMantissa = lastOracleTwapWithMantissa;
49
- // if passing live oracle data, improve predicted calc estimate
50
- if (oraclePriceData) {
51
- const oraclePrice = oraclePriceData.price;
52
- const oracleLiveVsTwap = oraclePrice
53
- .sub(lastOracleTwapWithMantissa)
54
- .abs()
55
- .mul(numericConstants_1.PRICE_PRECISION)
56
- .mul(new anchor_1.BN(100))
57
- .div(lastOracleTwapWithMantissa);
58
- // verify pyth live input is within 20% of last twap for live update
59
- if (oracleLiveVsTwap.lte(numericConstants_1.PRICE_PRECISION.mul(new anchor_1.BN(20)))) {
60
- oracleTwapWithMantissa = oracleTwapTimeSinceLastUpdate
61
- .mul(lastOracleTwapWithMantissa)
62
- .add(timeSinceLastMarkChange.mul(oraclePrice))
63
- .div(timeSinceLastMarkChange.add(oracleTwapTimeSinceLastUpdate));
64
- }
65
- }
66
- const shrunkLastOracleTwapwithMantissa = oracleTwapTimeSinceLastUpdate
67
- .mul(oracleTwapWithMantissa)
68
- .add(oracleInvalidDuration.mul(lastMarkTwapWithMantissa))
69
- .div(oracleTwapTimeSinceLastUpdate.add(oracleInvalidDuration));
70
- const twapSpread = markTwapWithMantissa.sub(shrunkLastOracleTwapwithMantissa);
64
+ // calculate real-time mark and oracle twap
65
+ const liveMarkTwap = calculateLiveMarkTwap(market, oraclePriceData, markPrice, now, market.amm.fundingPeriod);
66
+ const liveOracleTwap = (0, oracles_1.calculateLiveOracleTwap)(market.amm.historicalOracleData, oraclePriceData, now, market.amm.fundingPeriod);
67
+ const [markTwap, oracleTwap] = shrinkStaleTwaps(market, liveMarkTwap, liveOracleTwap, now);
68
+ // if(!markTwap.eq(liveMarkTwap)){
69
+ // console.log('shrink mark:', liveMarkTwap.toString(), '->', markTwap.toString());
70
+ // }
71
+ // if(!oracleTwap.eq(liveOracleTwap)){
72
+ // console.log('shrink orac:', liveOracleTwap.toString(), '->', oracleTwap.toString());
73
+ // }
74
+ const twapSpread = markTwap.sub(oracleTwap);
71
75
  const twapSpreadPct = twapSpread
72
76
  .mul(numericConstants_1.PRICE_PRECISION)
73
77
  .mul(new anchor_1.BN(100))
74
- .div(shrunkLastOracleTwapwithMantissa);
78
+ .div(oracleTwap);
79
+ const secondsInHour = new anchor_1.BN(3600);
80
+ const hoursInDay = new anchor_1.BN(24);
81
+ const timeSinceLastUpdate = now.sub(market.amm.lastFundingRateTs);
75
82
  const lowerboundEst = twapSpreadPct
76
- .mul(payFreq)
83
+ .mul(market.amm.fundingPeriod)
77
84
  .mul(anchor_1.BN.min(secondsInHour, timeSinceLastUpdate))
78
- .mul(periodAdjustment)
79
85
  .div(secondsInHour)
80
86
  .div(secondsInHour)
81
87
  .div(hoursInDay);
82
- const interpEst = twapSpreadPct.mul(periodAdjustment).div(hoursInDay);
88
+ const interpEst = twapSpreadPct.div(hoursInDay);
83
89
  const interpRateQuote = twapSpreadPct
84
- .mul(periodAdjustment)
85
90
  .div(hoursInDay)
86
91
  .div(numericConstants_1.PRICE_PRECISION.div(numericConstants_1.QUOTE_PRECISION));
87
92
  let feePoolSize = calculateFundingPool(market);
@@ -95,36 +100,18 @@ async function calculateAllEstimatedFundingRate(market, oraclePriceData, periodA
95
100
  largerSide = market.amm.baseAssetAmountLong.abs();
96
101
  smallerSide = market.amm.baseAssetAmountShort.abs();
97
102
  if (twapSpread.gt(new anchor_1.BN(0))) {
98
- return [
99
- markTwapWithMantissa,
100
- oracleTwapWithMantissa,
101
- lowerboundEst,
102
- interpEst,
103
- interpEst,
104
- ];
103
+ return [markTwap, oracleTwap, lowerboundEst, interpEst, interpEst];
105
104
  }
106
105
  }
107
106
  else if (market.amm.baseAssetAmountLong.lt(market.amm.baseAssetAmountShort.abs())) {
108
107
  largerSide = market.amm.baseAssetAmountShort.abs();
109
108
  smallerSide = market.amm.baseAssetAmountLong.abs();
110
109
  if (twapSpread.lt(new anchor_1.BN(0))) {
111
- return [
112
- markTwapWithMantissa,
113
- oracleTwapWithMantissa,
114
- lowerboundEst,
115
- interpEst,
116
- interpEst,
117
- ];
110
+ return [markTwap, oracleTwap, lowerboundEst, interpEst, interpEst];
118
111
  }
119
112
  }
120
113
  else {
121
- return [
122
- markTwapWithMantissa,
123
- oracleTwapWithMantissa,
124
- lowerboundEst,
125
- interpEst,
126
- interpEst,
127
- ];
114
+ return [markTwap, oracleTwap, lowerboundEst, interpEst, interpEst];
128
115
  }
129
116
  if (largerSide.gt(numericConstants_1.ZERO)) {
130
117
  // funding smaller flow
@@ -136,8 +123,7 @@ async function calculateAllEstimatedFundingRate(market, oraclePriceData, periodA
136
123
  cappedAltEst = cappedAltEst
137
124
  .mul(numericConstants_1.PRICE_PRECISION)
138
125
  .mul(new anchor_1.BN(100))
139
- .div(oracleTwapWithMantissa)
140
- .mul(periodAdjustment);
126
+ .div(oracleTwap);
141
127
  if (cappedAltEst.abs().gte(interpEst.abs())) {
142
128
  cappedAltEst = interpEst;
143
129
  }
@@ -145,37 +131,9 @@ async function calculateAllEstimatedFundingRate(market, oraclePriceData, periodA
145
131
  else {
146
132
  cappedAltEst = interpEst;
147
133
  }
148
- return [
149
- markTwapWithMantissa,
150
- oracleTwapWithMantissa,
151
- lowerboundEst,
152
- cappedAltEst,
153
- interpEst,
154
- ];
134
+ return [markTwap, oracleTwap, lowerboundEst, cappedAltEst, interpEst];
155
135
  }
156
136
  exports.calculateAllEstimatedFundingRate = calculateAllEstimatedFundingRate;
157
- /**
158
- *
159
- * @param market
160
- * @param oraclePriceData
161
- * @param periodAdjustment
162
- * @param estimationMethod
163
- * @returns Estimated funding rate. : Precision //TODO-PRECISION
164
- */
165
- async function calculateEstimatedFundingRate(market, oraclePriceData, periodAdjustment = new anchor_1.BN(1), estimationMethod) {
166
- const [_1, _2, lowerboundEst, cappedAltEst, interpEst] = await calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustment);
167
- if (estimationMethod == 'lowerbound') {
168
- //assuming remaining funding period has no gap
169
- return lowerboundEst;
170
- }
171
- else if (estimationMethod == 'capped') {
172
- return cappedAltEst;
173
- }
174
- else {
175
- return interpEst;
176
- }
177
- }
178
- exports.calculateEstimatedFundingRate = calculateEstimatedFundingRate;
179
137
  /**
180
138
  *
181
139
  * @param market
@@ -183,8 +141,8 @@ exports.calculateEstimatedFundingRate = calculateEstimatedFundingRate;
183
141
  * @param periodAdjustment
184
142
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
185
143
  */
186
- async function calculateLongShortFundingRate(market, oraclePriceData, periodAdjustment = new anchor_1.BN(1)) {
187
- const [_1, _2, _, cappedAltEst, interpEst] = await calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustment);
144
+ async function calculateLongShortFundingRate(market, oraclePriceData, markPrice, now) {
145
+ const [_1, _2, _, cappedAltEst, interpEst] = await calculateAllEstimatedFundingRate(market, oraclePriceData, markPrice, now);
188
146
  if (market.amm.baseAssetAmountLong.gt(market.amm.baseAssetAmountShort)) {
189
147
  return [cappedAltEst, interpEst];
190
148
  }
@@ -203,8 +161,8 @@ exports.calculateLongShortFundingRate = calculateLongShortFundingRate;
203
161
  * @param periodAdjustment
204
162
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
205
163
  */
206
- async function calculateLongShortFundingRateAndLiveTwaps(market, oraclePriceData, periodAdjustment = new anchor_1.BN(1)) {
207
- const [markTwapLive, oracleTwapLive, _2, cappedAltEst, interpEst] = await calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustment);
164
+ async function calculateLongShortFundingRateAndLiveTwaps(market, oraclePriceData, markPrice, now) {
165
+ const [markTwapLive, oracleTwapLive, _2, cappedAltEst, interpEst] = await calculateAllEstimatedFundingRate(market, oraclePriceData, markPrice, now);
208
166
  if (market.amm.baseAssetAmountLong.gt(market.amm.baseAssetAmountShort.abs())) {
209
167
  return [markTwapLive, oracleTwapLive, cappedAltEst, interpEst];
210
168
  }
package/lib/user.d.ts CHANGED
@@ -190,10 +190,11 @@ export declare class User {
190
190
  getTotalAssetValue(marginCategory?: MarginCategory): BN;
191
191
  /**
192
192
  * calculates max allowable leverage exceeding hitting requirement category
193
+ * for large sizes where imf factor activates, result is a lower bound
193
194
  * @params category {Initial, Maintenance}
194
195
  * @returns : Precision TEN_THOUSAND
195
196
  */
196
- getMaxLeverageForPerp(perpMarketIndex: number, category?: MarginCategory): BN;
197
+ getMaxLeverageForPerp(perpMarketIndex: number, marginCategory?: MarginCategory): BN;
197
198
  /**
198
199
  * calculates max allowable leverage exceeding hitting requirement category
199
200
  * @param spotMarketIndex
package/lib/user.js CHANGED
@@ -791,11 +791,13 @@ class User {
791
791
  }
792
792
  /**
793
793
  * calculates max allowable leverage exceeding hitting requirement category
794
+ * for large sizes where imf factor activates, result is a lower bound
794
795
  * @params category {Initial, Maintenance}
795
796
  * @returns : Precision TEN_THOUSAND
796
797
  */
797
- getMaxLeverageForPerp(perpMarketIndex, category = 'Initial') {
798
+ getMaxLeverageForPerp(perpMarketIndex, marginCategory = 'Initial') {
798
799
  const market = this.driftClient.getPerpMarketAccount(perpMarketIndex);
800
+ const marketPrice = this.driftClient.getOracleDataForPerpMarket(perpMarketIndex).price;
799
801
  const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
800
802
  const totalAssetValue = spotAssetValue.add(perpPnl);
801
803
  const netAssetValue = totalAssetValue.sub(spotLiabilityValue);
@@ -803,9 +805,40 @@ class User {
803
805
  return numericConstants_1.ZERO;
804
806
  }
805
807
  const totalLiabilityValue = perpLiabilityValue.add(spotLiabilityValue);
806
- const marginRatio = (0, _1.calculateMarketMarginRatio)(market, numericConstants_1.ZERO, // todo
807
- category);
808
808
  const freeCollateral = this.getFreeCollateral();
809
+ let rawMarginRatio;
810
+ switch (marginCategory) {
811
+ case 'Initial':
812
+ rawMarginRatio = market.marginRatioInitial;
813
+ break;
814
+ case 'Maintenance':
815
+ rawMarginRatio = market.marginRatioMaintenance;
816
+ break;
817
+ default:
818
+ rawMarginRatio = market.marginRatioInitial;
819
+ break;
820
+ }
821
+ // absolute max fesible size (upper bound)
822
+ const maxSize = _1.BN.max(numericConstants_1.ZERO, freeCollateral
823
+ .mul(numericConstants_1.MARGIN_PRECISION)
824
+ .div(new _1.BN(rawMarginRatio))
825
+ .mul(numericConstants_1.PRICE_PRECISION)
826
+ .div(marketPrice));
827
+ // margin ratio incorporting upper bound on size
828
+ let marginRatio = (0, _1.calculateMarketMarginRatio)(market, maxSize, marginCategory);
829
+ // use more fesible size since imf factor activated
830
+ let attempts = 0;
831
+ while (marginRatio > rawMarginRatio + 1e-4 && attempts < 10) {
832
+ // more fesible size (upper bound)
833
+ const targetSize = _1.BN.max(numericConstants_1.ZERO, freeCollateral
834
+ .mul(numericConstants_1.MARGIN_PRECISION)
835
+ .div(new _1.BN(marginRatio))
836
+ .mul(numericConstants_1.PRICE_PRECISION)
837
+ .div(marketPrice));
838
+ // margin ratio incorporting more fesible target size
839
+ marginRatio = (0, _1.calculateMarketMarginRatio)(market, targetSize, marginCategory);
840
+ attempts += 1;
841
+ }
809
842
  // how much more liabilities can be opened w remaining free collateral
810
843
  const additionalLiabilities = freeCollateral
811
844
  .mul(numericConstants_1.MARGIN_PRECISION)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.34.1-beta.1",
3
+ "version": "2.34.1-beta.3",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -53,6 +53,7 @@
53
53
  "eslint": "^7.29.0",
54
54
  "eslint-config-prettier": "^8.3.0",
55
55
  "eslint-plugin-prettier": "^3.4.0",
56
+ "lodash": "^4.17.21",
56
57
  "mocha": "^10.0.0",
57
58
  "prettier": "^2.4.1",
58
59
  "ts-node": "^10.8.0",
@@ -144,6 +144,16 @@ export const DevnetPerpMarkets: PerpMarketConfig[] = [
144
144
  launchTs: 1687201081000,
145
145
  oracleSource: OracleSource.PYTH,
146
146
  },
147
+ {
148
+ fullName: 'XRP',
149
+ category: ['Payments'],
150
+ symbol: 'XRP-PERP',
151
+ baseAssetSymbol: 'XRP',
152
+ marketIndex: 13,
153
+ oracle: new PublicKey('DuG45Td6dgJBe64Ebymb1WjBys16L1VTQdoAURdsviqN'),
154
+ launchTs: 1689270550000,
155
+ oracleSource: OracleSource.PYTH,
156
+ },
147
157
  ];
148
158
 
149
159
  export const MainnetPerpMarkets: PerpMarketConfig[] = [
@@ -277,6 +287,16 @@ export const MainnetPerpMarkets: PerpMarketConfig[] = [
277
287
  launchTs: 1687201081000,
278
288
  oracleSource: OracleSource.PYTH,
279
289
  },
290
+ {
291
+ fullName: 'XRP',
292
+ category: ['Payments'],
293
+ symbol: 'XRP-PERP',
294
+ baseAssetSymbol: 'XRP',
295
+ marketIndex: 13,
296
+ oracle: new PublicKey('Guffb8DAAxNH6kdoawYjPXTbwUhjmveh8R4LM6uEqRV1'),
297
+ launchTs: 1689270550000,
298
+ oracleSource: OracleSource.PYTH,
299
+ },
280
300
  ];
281
301
 
282
302
  export const PerpMarkets: { [key in DriftEnv]: PerpMarketConfig[] } = {