@drift-labs/sdk 0.2.0-master.0 → 0.2.0-master.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/lib/admin.d.ts +1 -0
- package/lib/admin.js +9 -0
- package/lib/clearingHouse.d.ts +5 -9
- package/lib/clearingHouse.js +53 -70
- package/lib/config.js +1 -1
- package/lib/constants/numericConstants.d.ts +1 -0
- package/lib/constants/numericConstants.js +2 -1
- package/lib/factory/bigNum.d.ts +8 -2
- package/lib/factory/bigNum.js +14 -6
- package/lib/idl/clearing_house.json +106 -39
- package/lib/math/amm.d.ts +6 -1
- package/lib/math/amm.js +127 -16
- package/lib/math/orders.js +2 -12
- package/lib/math/repeg.js +1 -1
- package/lib/orders.d.ts +1 -2
- package/lib/orders.js +6 -85
- package/lib/types.d.ts +5 -0
- package/lib/types.js +1 -0
- package/package.json +2 -2
- package/src/admin.ts +13 -0
- package/src/clearingHouse.ts +75 -126
- package/src/config.ts +1 -1
- package/src/constants/numericConstants.ts +1 -0
- package/src/factory/bigNum.ts +26 -9
- package/src/idl/clearing_house.json +106 -39
- package/src/math/amm.ts +202 -17
- package/src/math/orders.ts +3 -13
- package/src/math/repeg.ts +2 -1
- package/src/orders.ts +7 -131
- package/src/types.ts +4 -1
package/lib/math/amm.js
CHANGED
|
@@ -1,25 +1,58 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.calculateQuoteAssetAmountSwapped = exports.calculateMaxBaseAssetAmountToTrade = exports.calculateTerminalPrice = exports.getSwapDirection = exports.calculateSwapOutput = exports.calculateSpreadReserves = exports.calculateSpread = exports.calculateAmmReservesAfterSwap = exports.calculatePrice = exports.calculateBidAskPrice = exports.calculateUpdatedAMMSpreadReserves = exports.calculateUpdatedAMM = exports.calculateNewAmm = void 0;
|
|
3
|
+
exports.calculateQuoteAssetAmountSwapped = exports.calculateMaxBaseAssetAmountToTrade = exports.calculateTerminalPrice = exports.getSwapDirection = exports.calculateSwapOutput = exports.calculateSpreadReserves = exports.calculateSpread = exports.calculateSpreadBN = exports.calculateMaxSpread = exports.calculateEffectiveLeverage = exports.calculateAmmReservesAfterSwap = exports.calculatePrice = exports.calculateBidAskPrice = exports.calculateUpdatedAMMSpreadReserves = exports.calculateUpdatedAMM = exports.calculateNewAmm = exports.calculateOptimalPegAndBudget = exports.calculatePegFromTargetPrice = void 0;
|
|
4
4
|
const anchor_1 = require("@project-serum/anchor");
|
|
5
5
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
6
6
|
const types_1 = require("../types");
|
|
7
7
|
const assert_1 = require("../assert/assert");
|
|
8
8
|
const __1 = require("..");
|
|
9
9
|
const repeg_1 = require("./repeg");
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
function calculatePegFromTargetPrice(targetPrice, baseAssetReserve, quoteAssetReserve) {
|
|
11
|
+
return targetPrice
|
|
12
|
+
.mul(baseAssetReserve)
|
|
13
|
+
.div(quoteAssetReserve)
|
|
14
|
+
.add(numericConstants_1.PRICE_DIV_PEG.div(new anchor_1.BN(2)))
|
|
15
|
+
.div(numericConstants_1.PRICE_DIV_PEG);
|
|
16
|
+
}
|
|
17
|
+
exports.calculatePegFromTargetPrice = calculatePegFromTargetPrice;
|
|
18
|
+
function calculateOptimalPegAndBudget(amm, oraclePriceData) {
|
|
19
|
+
const markPriceBefore = calculatePrice(amm.baseAssetReserve, amm.quoteAssetReserve, amm.pegMultiplier);
|
|
13
20
|
const targetPrice = oraclePriceData.price;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
.div(amm.quoteAssetReserve)
|
|
17
|
-
.add(numericConstants_1.MARK_PRICE_PRECISION.div(numericConstants_1.PEG_PRECISION).div(new anchor_1.BN(2)))
|
|
18
|
-
.div(numericConstants_1.MARK_PRICE_PRECISION.div(numericConstants_1.PEG_PRECISION));
|
|
19
|
-
let prePegCost = (0, repeg_1.calculateRepegCost)(amm, newPeg);
|
|
21
|
+
const newPeg = calculatePegFromTargetPrice(targetPrice, amm.baseAssetReserve, amm.quoteAssetReserve);
|
|
22
|
+
const prePegCost = (0, repeg_1.calculateRepegCost)(amm, newPeg);
|
|
20
23
|
const totalFeeLB = amm.totalExchangeFee.div(new anchor_1.BN(2));
|
|
21
24
|
const budget = anchor_1.BN.max(numericConstants_1.ZERO, amm.totalFeeMinusDistributions.sub(totalFeeLB));
|
|
22
|
-
if (
|
|
25
|
+
if (budget.lt(prePegCost)) {
|
|
26
|
+
const maxPriceSpread = new anchor_1.BN(amm.maxSpread)
|
|
27
|
+
.mul(targetPrice)
|
|
28
|
+
.div(numericConstants_1.BID_ASK_SPREAD_PRECISION);
|
|
29
|
+
let newTargetPrice;
|
|
30
|
+
let newOptimalPeg;
|
|
31
|
+
let newBudget;
|
|
32
|
+
const targetPriceGap = markPriceBefore.sub(targetPrice);
|
|
33
|
+
if (targetPriceGap.abs().gt(maxPriceSpread)) {
|
|
34
|
+
const markAdj = targetPriceGap.abs().sub(maxPriceSpread);
|
|
35
|
+
if (targetPriceGap.lt(new anchor_1.BN(0))) {
|
|
36
|
+
newTargetPrice = markPriceBefore.add(markAdj);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
newTargetPrice = markPriceBefore.sub(markAdj);
|
|
40
|
+
}
|
|
41
|
+
newOptimalPeg = calculatePegFromTargetPrice(newTargetPrice, amm.baseAssetReserve, amm.quoteAssetReserve);
|
|
42
|
+
newBudget = (0, repeg_1.calculateRepegCost)(amm, newOptimalPeg);
|
|
43
|
+
return [newTargetPrice, newOptimalPeg, newBudget, false];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return [targetPrice, newPeg, budget, true];
|
|
47
|
+
}
|
|
48
|
+
exports.calculateOptimalPegAndBudget = calculateOptimalPegAndBudget;
|
|
49
|
+
function calculateNewAmm(amm, oraclePriceData) {
|
|
50
|
+
let pKNumer = new anchor_1.BN(1);
|
|
51
|
+
let pKDenom = new anchor_1.BN(1);
|
|
52
|
+
const [targetPrice, _newPeg, budget, checkLowerBound] = calculateOptimalPegAndBudget(amm, oraclePriceData);
|
|
53
|
+
let prePegCost = (0, repeg_1.calculateRepegCost)(amm, _newPeg);
|
|
54
|
+
let newPeg = _newPeg;
|
|
55
|
+
if (prePegCost.gt(budget) && checkLowerBound) {
|
|
23
56
|
[pKNumer, pKDenom] = [new anchor_1.BN(999), new anchor_1.BN(1000)];
|
|
24
57
|
const deficitMadeup = (0, repeg_1.calculateAdjustKCost)(amm, pKNumer, pKDenom);
|
|
25
58
|
(0, assert_1.assert)(deficitMadeup.lte(new anchor_1.BN(0)));
|
|
@@ -73,8 +106,14 @@ function calculateUpdatedAMMSpreadReserves(amm, direction, oraclePriceData) {
|
|
|
73
106
|
return result;
|
|
74
107
|
}
|
|
75
108
|
exports.calculateUpdatedAMMSpreadReserves = calculateUpdatedAMMSpreadReserves;
|
|
76
|
-
function calculateBidAskPrice(amm, oraclePriceData) {
|
|
77
|
-
|
|
109
|
+
function calculateBidAskPrice(amm, oraclePriceData, withUpdate = true) {
|
|
110
|
+
let newAmm;
|
|
111
|
+
if (withUpdate) {
|
|
112
|
+
newAmm = calculateUpdatedAMM(amm, oraclePriceData);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
newAmm = amm;
|
|
116
|
+
}
|
|
78
117
|
const askReserves = calculateSpreadReserves(newAmm, types_1.PositionDirection.LONG, oraclePriceData);
|
|
79
118
|
const bidReserves = calculateSpreadReserves(newAmm, types_1.PositionDirection.SHORT, oraclePriceData);
|
|
80
119
|
const askPrice = calculatePrice(askReserves.baseAssetReserve, askReserves.quoteAssetReserve, newAmm.pegMultiplier);
|
|
@@ -126,6 +165,67 @@ function calculateAmmReservesAfterSwap(amm, inputAssetType, swapAmount, swapDire
|
|
|
126
165
|
return [newQuoteAssetReserve, newBaseAssetReserve];
|
|
127
166
|
}
|
|
128
167
|
exports.calculateAmmReservesAfterSwap = calculateAmmReservesAfterSwap;
|
|
168
|
+
function calculateEffectiveLeverage(baseSpread, quoteAssetReserve, terminalQuoteAssetReserve, pegMultiplier, netBaseAssetAmount, markPrice, totalFeeMinusDistributions) {
|
|
169
|
+
// inventory skew
|
|
170
|
+
const netBaseAssetValue = quoteAssetReserve
|
|
171
|
+
.sub(terminalQuoteAssetReserve)
|
|
172
|
+
.mul(pegMultiplier)
|
|
173
|
+
.div(numericConstants_1.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
|
|
174
|
+
const localBaseAssetValue = netBaseAssetAmount
|
|
175
|
+
.mul(markPrice)
|
|
176
|
+
.div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO.mul(numericConstants_1.MARK_PRICE_PRECISION));
|
|
177
|
+
const effectiveLeverage = localBaseAssetValue.sub(netBaseAssetValue).toNumber() /
|
|
178
|
+
(Math.max(0, totalFeeMinusDistributions.toNumber()) + 1) +
|
|
179
|
+
1 / numericConstants_1.QUOTE_PRECISION.toNumber();
|
|
180
|
+
return effectiveLeverage;
|
|
181
|
+
}
|
|
182
|
+
exports.calculateEffectiveLeverage = calculateEffectiveLeverage;
|
|
183
|
+
function calculateMaxSpread(marginRatioInitial) {
|
|
184
|
+
const maxTargetSpread = new anchor_1.BN(marginRatioInitial)
|
|
185
|
+
.mul(numericConstants_1.BID_ASK_SPREAD_PRECISION.div(numericConstants_1.MARGIN_PRECISION))
|
|
186
|
+
.toNumber();
|
|
187
|
+
return maxTargetSpread;
|
|
188
|
+
}
|
|
189
|
+
exports.calculateMaxSpread = calculateMaxSpread;
|
|
190
|
+
function calculateSpreadBN(baseSpread, lastOracleMarkSpreadPct, lastOracleConfPct, maxSpread, quoteAssetReserve, terminalQuoteAssetReserve, pegMultiplier, netBaseAssetAmount, markPrice, totalFeeMinusDistributions) {
|
|
191
|
+
let longSpread = baseSpread / 2;
|
|
192
|
+
let shortSpread = baseSpread / 2;
|
|
193
|
+
if (lastOracleMarkSpreadPct.gt(numericConstants_1.ZERO)) {
|
|
194
|
+
shortSpread = Math.max(shortSpread, lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber());
|
|
195
|
+
}
|
|
196
|
+
else if (lastOracleMarkSpreadPct.lt(numericConstants_1.ZERO)) {
|
|
197
|
+
longSpread = Math.max(longSpread, lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber());
|
|
198
|
+
}
|
|
199
|
+
const maxTargetSpread = maxSpread;
|
|
200
|
+
const MAX_INVENTORY_SKEW = 5;
|
|
201
|
+
const effectiveLeverage = calculateEffectiveLeverage(baseSpread, quoteAssetReserve, terminalQuoteAssetReserve, pegMultiplier, netBaseAssetAmount, markPrice, totalFeeMinusDistributions);
|
|
202
|
+
if (totalFeeMinusDistributions.gt(numericConstants_1.ZERO)) {
|
|
203
|
+
const spreadScale = Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
|
|
204
|
+
if (netBaseAssetAmount.gt(numericConstants_1.ZERO)) {
|
|
205
|
+
longSpread *= spreadScale;
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
shortSpread *= spreadScale;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
longSpread *= MAX_INVENTORY_SKEW;
|
|
213
|
+
shortSpread *= MAX_INVENTORY_SKEW;
|
|
214
|
+
}
|
|
215
|
+
const totalSpread = longSpread + shortSpread;
|
|
216
|
+
if (totalSpread > maxTargetSpread) {
|
|
217
|
+
if (longSpread > shortSpread) {
|
|
218
|
+
longSpread = Math.min(longSpread, maxTargetSpread);
|
|
219
|
+
shortSpread = maxTargetSpread - longSpread;
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
shortSpread = Math.min(shortSpread, maxTargetSpread);
|
|
223
|
+
longSpread = maxTargetSpread - shortSpread;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return [longSpread, shortSpread];
|
|
227
|
+
}
|
|
228
|
+
exports.calculateSpreadBN = calculateSpreadBN;
|
|
129
229
|
function calculateSpread(amm, direction, oraclePriceData) {
|
|
130
230
|
let spread = amm.baseSpread / 2;
|
|
131
231
|
if (amm.baseSpread == 0 || amm.curveUpdateIntensity == 0) {
|
|
@@ -133,14 +233,18 @@ function calculateSpread(amm, direction, oraclePriceData) {
|
|
|
133
233
|
}
|
|
134
234
|
const markPrice = calculatePrice(amm.baseAssetReserve, amm.quoteAssetReserve, amm.pegMultiplier);
|
|
135
235
|
const targetPrice = (oraclePriceData === null || oraclePriceData === void 0 ? void 0 : oraclePriceData.price) || markPrice;
|
|
236
|
+
const confInterval = oraclePriceData.confidence || numericConstants_1.ZERO;
|
|
136
237
|
const targetMarkSpreadPct = markPrice
|
|
137
238
|
.sub(targetPrice)
|
|
138
239
|
.mul(numericConstants_1.BID_ASK_SPREAD_PRECISION)
|
|
139
240
|
.div(markPrice);
|
|
241
|
+
const confIntervalPct = confInterval
|
|
242
|
+
.mul(numericConstants_1.BID_ASK_SPREAD_PRECISION)
|
|
243
|
+
.div(markPrice);
|
|
140
244
|
// oracle retreat
|
|
141
245
|
if (((0, types_1.isVariant)(direction, 'long') && targetMarkSpreadPct.lt(numericConstants_1.ZERO)) ||
|
|
142
246
|
((0, types_1.isVariant)(direction, 'short') && targetMarkSpreadPct.gt(numericConstants_1.ZERO))) {
|
|
143
|
-
spread = Math.max(spread, targetMarkSpreadPct.abs().toNumber());
|
|
247
|
+
spread = Math.max(spread, targetMarkSpreadPct.abs().toNumber() + confIntervalPct.abs().toNumber());
|
|
144
248
|
}
|
|
145
249
|
// inventory skew
|
|
146
250
|
const MAX_INVENTORY_SKEW = 5;
|
|
@@ -161,9 +265,16 @@ function calculateSpread(amm, direction, oraclePriceData) {
|
|
|
161
265
|
if (amm.totalFeeMinusDistributions.gt(numericConstants_1.ZERO)) {
|
|
162
266
|
effectiveLeverage =
|
|
163
267
|
localPnl.sub(netPnl).toNumber() /
|
|
164
|
-
amm.totalFeeMinusDistributions.toNumber();
|
|
268
|
+
(amm.totalFeeMinusDistributions.toNumber() + 1);
|
|
269
|
+
}
|
|
270
|
+
let spreadScale = Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
|
|
271
|
+
const maxTargetSpread = numericConstants_1.BID_ASK_SPREAD_PRECISION.toNumber() / 50; // 2%
|
|
272
|
+
// cap the scale to attempt to only scale up to maxTargetSpread
|
|
273
|
+
// always let the oracle retreat methods go through 100%
|
|
274
|
+
if (spreadScale * spread > maxTargetSpread) {
|
|
275
|
+
spreadScale = Math.max(1.05, maxTargetSpread / spread);
|
|
165
276
|
}
|
|
166
|
-
spread *=
|
|
277
|
+
spread *= spreadScale;
|
|
167
278
|
}
|
|
168
279
|
return spread;
|
|
169
280
|
}
|
package/lib/math/orders.js
CHANGED
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getLimitPrice = exports.standardizeBaseAssetAmount = exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
|
|
4
4
|
const types_1 = require("../types");
|
|
5
5
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
6
|
-
const anchor_1 = require("@project-serum/anchor");
|
|
7
6
|
const auction_1 = require("./auction");
|
|
8
7
|
function isOrderRiskIncreasing(user, order) {
|
|
9
8
|
if ((0, types_1.isVariant)(order.status, 'init')) {
|
|
@@ -81,18 +80,9 @@ exports.standardizeBaseAssetAmount = standardizeBaseAssetAmount;
|
|
|
81
80
|
function getLimitPrice(order, oraclePriceData, slot) {
|
|
82
81
|
let limitPrice;
|
|
83
82
|
if (!order.oraclePriceOffset.eq(numericConstants_1.ZERO)) {
|
|
84
|
-
|
|
85
|
-
if (order.postOnly) {
|
|
86
|
-
limitPrice = (0, types_1.isVariant)(order.direction, 'long')
|
|
87
|
-
? anchor_1.BN.min(order.price, floatingPrice)
|
|
88
|
-
: anchor_1.BN.max(order.price, floatingPrice);
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
limitPrice = floatingPrice;
|
|
92
|
-
}
|
|
83
|
+
limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
|
|
93
84
|
}
|
|
94
|
-
else if ((0, types_1.
|
|
95
|
-
(0, types_1.isVariant)(order.orderType, 'triggerMarket')) {
|
|
85
|
+
else if ((0, types_1.isOneOfVariant)(order.orderType, ['market', 'triggerMarket'])) {
|
|
96
86
|
limitPrice = (0, auction_1.getAuctionPrice)(order, slot);
|
|
97
87
|
}
|
|
98
88
|
else {
|
package/lib/math/repeg.js
CHANGED
|
@@ -107,7 +107,7 @@ function calculateBudgetedPeg(amm, cost, targetPrice) {
|
|
|
107
107
|
const targetPeg = targetPrice
|
|
108
108
|
.mul(amm.baseAssetReserve)
|
|
109
109
|
.div(amm.quoteAssetReserve)
|
|
110
|
-
.div(numericConstants_1.
|
|
110
|
+
.div(numericConstants_1.PRICE_DIV_PEG);
|
|
111
111
|
const k = amm.sqrtK.mul(amm.sqrtK);
|
|
112
112
|
const x = amm.baseAssetReserve;
|
|
113
113
|
const y = amm.quoteAssetReserve;
|
package/lib/orders.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
2
|
import { MarketAccount, Order, UserAccount, UserPosition } from './types';
|
|
3
|
-
import { BN
|
|
3
|
+
import { BN } from '.';
|
|
4
4
|
import { OraclePriceData } from '.';
|
|
5
5
|
export declare function calculateNewStateAfterOrder(userAccount: UserAccount, userPosition: UserPosition, market: MarketAccount, order: Order): [UserAccount, UserPosition, MarketAccount] | null;
|
|
6
6
|
export declare function calculateBaseAssetAmountMarketCanExecute(market: MarketAccount, order: Order, oraclePriceData?: OraclePriceData): BN;
|
|
7
7
|
export declare function calculateAmountToTradeForLimit(market: MarketAccount, order: Order, oraclePriceData?: OraclePriceData): BN;
|
|
8
8
|
export declare function calculateAmountToTradeForTriggerLimit(market: MarketAccount, order: Order): BN;
|
|
9
|
-
export declare function calculateBaseAssetAmountUserCanExecute(market: MarketAccount, order: Order, user: ClearingHouseUser, oraclePriceData?: OraclePriceData): BN;
|
package/lib/orders.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.calculateAmountToTradeForTriggerLimit = exports.calculateAmountToTradeForLimit = exports.calculateBaseAssetAmountMarketCanExecute = exports.calculateNewStateAfterOrder = void 0;
|
|
4
4
|
const types_1 = require("./types");
|
|
5
5
|
const _1 = require(".");
|
|
6
6
|
const market_1 = require("./math/market");
|
|
@@ -88,7 +88,6 @@ function calculateBaseAssetAmountMarketCanExecute(market, order, oraclePriceData
|
|
|
88
88
|
return calculateAmountToTradeForTriggerLimit(market, order);
|
|
89
89
|
}
|
|
90
90
|
else if ((0, types_1.isVariant)(order.orderType, 'market')) {
|
|
91
|
-
// should never be a market order queued
|
|
92
91
|
return numericConstants_1.ZERO;
|
|
93
92
|
}
|
|
94
93
|
else {
|
|
@@ -102,15 +101,7 @@ function calculateAmountToTradeForLimit(market, order, oraclePriceData) {
|
|
|
102
101
|
if (!oraclePriceData) {
|
|
103
102
|
throw Error('Cant calculate limit price for oracle offset oracle without OraclePriceData');
|
|
104
103
|
}
|
|
105
|
-
|
|
106
|
-
if (order.postOnly) {
|
|
107
|
-
limitPrice = (0, types_1.isVariant)(order.direction, 'long')
|
|
108
|
-
? _1.BN.min(order.price, floatingPrice)
|
|
109
|
-
: _1.BN.max(order.price, floatingPrice);
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
limitPrice = floatingPrice;
|
|
113
|
-
}
|
|
104
|
+
limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
|
|
114
105
|
}
|
|
115
106
|
const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice, order.direction);
|
|
116
107
|
const baseAssetAmount = (0, _1.standardizeBaseAssetAmount)(maxAmountToTrade, market.amm.baseAssetAmountStepSize);
|
|
@@ -125,11 +116,8 @@ function calculateAmountToTradeForLimit(market, order, oraclePriceData) {
|
|
|
125
116
|
}
|
|
126
117
|
exports.calculateAmountToTradeForLimit = calculateAmountToTradeForLimit;
|
|
127
118
|
function calculateAmountToTradeForTriggerLimit(market, order) {
|
|
128
|
-
if (order.
|
|
129
|
-
|
|
130
|
-
if (baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
131
|
-
return numericConstants_1.ZERO;
|
|
132
|
-
}
|
|
119
|
+
if (!order.triggered) {
|
|
120
|
+
return numericConstants_1.ZERO;
|
|
133
121
|
}
|
|
134
122
|
return calculateAmountToTradeForLimit(market, order);
|
|
135
123
|
}
|
|
@@ -139,75 +127,8 @@ function isSameDirection(firstDirection, secondDirection) {
|
|
|
139
127
|
((0, types_1.isVariant)(firstDirection, 'short') && (0, types_1.isVariant)(secondDirection, 'short')));
|
|
140
128
|
}
|
|
141
129
|
function calculateAmountToTradeForTriggerMarket(market, order) {
|
|
142
|
-
|
|
143
|
-
? order.baseAssetAmount
|
|
144
|
-
: numericConstants_1.ZERO;
|
|
145
|
-
}
|
|
146
|
-
function isTriggerConditionSatisfied(market, order, oraclePriceData) {
|
|
147
|
-
const markPrice = (0, market_1.calculateMarkPrice)(market, oraclePriceData);
|
|
148
|
-
if ((0, types_1.isVariant)(order.triggerCondition, 'above')) {
|
|
149
|
-
return markPrice.gt(order.triggerPrice);
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
return markPrice.lt(order.triggerPrice);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
function calculateBaseAssetAmountUserCanExecute(market, order, user, oraclePriceData) {
|
|
156
|
-
const maxLeverage = user.getMaxLeverage(order.marketIndex, 'Initial');
|
|
157
|
-
const freeCollateral = user.getFreeCollateral();
|
|
158
|
-
let quoteAssetAmount;
|
|
159
|
-
if ((0, _1.isOrderRiskIncreasingInSameDirection)(user, order)) {
|
|
160
|
-
quoteAssetAmount = freeCollateral.mul(maxLeverage).div(_1.TEN_THOUSAND);
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
const position = user.getUserPosition(order.marketIndex) ||
|
|
164
|
-
user.getEmptyPosition(order.marketIndex);
|
|
165
|
-
const positionValue = (0, _1.calculateBaseAssetValue)(market, position, oraclePriceData);
|
|
166
|
-
quoteAssetAmount = freeCollateral
|
|
167
|
-
.mul(maxLeverage)
|
|
168
|
-
.div(_1.TEN_THOUSAND)
|
|
169
|
-
.add(positionValue.mul(numericConstants_1.TWO));
|
|
170
|
-
}
|
|
171
|
-
if (quoteAssetAmount.lte(numericConstants_1.ZERO)) {
|
|
130
|
+
if (!order.triggered) {
|
|
172
131
|
return numericConstants_1.ZERO;
|
|
173
132
|
}
|
|
174
|
-
|
|
175
|
-
? types_1.SwapDirection.ADD
|
|
176
|
-
: types_1.SwapDirection.REMOVE;
|
|
177
|
-
const useSpread = !order.postOnly;
|
|
178
|
-
let amm;
|
|
179
|
-
if (useSpread) {
|
|
180
|
-
const { baseAssetReserve, quoteAssetReserve } = (0, _1.calculateSpreadReserves)(market.amm, order.direction, oraclePriceData);
|
|
181
|
-
amm = {
|
|
182
|
-
baseAssetReserve,
|
|
183
|
-
quoteAssetReserve,
|
|
184
|
-
sqrtK: market.amm.sqrtK,
|
|
185
|
-
pegMultiplier: market.amm.pegMultiplier,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
amm = market.amm;
|
|
190
|
-
}
|
|
191
|
-
const baseAssetReservesBefore = amm.baseAssetReserve;
|
|
192
|
-
const [_, baseAssetReservesAfter] = (0, _1.calculateAmmReservesAfterSwap)(amm, 'quote', quoteAssetAmount, swapDirection);
|
|
193
|
-
let baseAssetAmount = baseAssetReservesBefore
|
|
194
|
-
.sub(baseAssetReservesAfter)
|
|
195
|
-
.abs();
|
|
196
|
-
if (order.reduceOnly) {
|
|
197
|
-
const position = user.getUserPosition(order.marketIndex) ||
|
|
198
|
-
user.getEmptyPosition(order.marketIndex);
|
|
199
|
-
if ((0, types_1.isVariant)(order.direction, 'long') &&
|
|
200
|
-
position.baseAssetAmount.gte(numericConstants_1.ZERO)) {
|
|
201
|
-
baseAssetAmount = numericConstants_1.ZERO;
|
|
202
|
-
}
|
|
203
|
-
else if ((0, types_1.isVariant)(order.direction, 'short') &&
|
|
204
|
-
position.baseAssetAmount.lte(numericConstants_1.ZERO)) {
|
|
205
|
-
baseAssetAmount = numericConstants_1.ZERO;
|
|
206
|
-
}
|
|
207
|
-
else {
|
|
208
|
-
_1.BN.min(baseAssetAmount, position.baseAssetAmount.abs());
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
return baseAssetAmount;
|
|
133
|
+
return order.baseAssetAmount;
|
|
212
134
|
}
|
|
213
|
-
exports.calculateBaseAssetAmountUserCanExecute = calculateBaseAssetAmountUserCanExecute;
|
package/lib/types.d.ts
CHANGED
|
@@ -88,6 +88,9 @@ export declare class OrderAction {
|
|
|
88
88
|
static readonly FILL: {
|
|
89
89
|
fill: {};
|
|
90
90
|
};
|
|
91
|
+
static readonly TRIGGER: {
|
|
92
|
+
trigger: {};
|
|
93
|
+
};
|
|
91
94
|
}
|
|
92
95
|
export declare class OrderTriggerCondition {
|
|
93
96
|
static readonly ABOVE: {
|
|
@@ -304,6 +307,7 @@ export declare type AMM = {
|
|
|
304
307
|
lastAskPriceTwap: BN;
|
|
305
308
|
longSpread: BN;
|
|
306
309
|
shortSpread: BN;
|
|
310
|
+
maxSpread: number;
|
|
307
311
|
};
|
|
308
312
|
export declare type UserPosition = {
|
|
309
313
|
baseAssetAmount: BN;
|
|
@@ -356,6 +360,7 @@ export declare type Order = {
|
|
|
356
360
|
reduceOnly: boolean;
|
|
357
361
|
triggerPrice: BN;
|
|
358
362
|
triggerCondition: OrderTriggerCondition;
|
|
363
|
+
triggered: boolean;
|
|
359
364
|
discountTier: OrderDiscountTier;
|
|
360
365
|
existingPositionDirection: PositionDirection;
|
|
361
366
|
referrer: PublicKey;
|
package/lib/types.js
CHANGED
|
@@ -50,6 +50,7 @@ OrderAction.PLACE = { place: {} };
|
|
|
50
50
|
OrderAction.CANCEL = { cancel: {} };
|
|
51
51
|
OrderAction.EXPIRE = { expire: {} };
|
|
52
52
|
OrderAction.FILL = { fill: {} };
|
|
53
|
+
OrderAction.TRIGGER = { trigger: {} };
|
|
53
54
|
class OrderTriggerCondition {
|
|
54
55
|
}
|
|
55
56
|
exports.OrderTriggerCondition = OrderTriggerCondition;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "0.2.0-master.
|
|
3
|
+
"version": "0.2.0-master.3",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@project-serum/anchor": "0.24.2",
|
|
33
|
-
"@pythnetwork/client": "
|
|
33
|
+
"@pythnetwork/client": "2.5.1",
|
|
34
34
|
"@solana/spl-token": "^0.1.6",
|
|
35
35
|
"@solana/web3.js": "1.41.0",
|
|
36
36
|
"@switchboard-xyz/switchboard-v2": "^0.0.67",
|
package/src/admin.ts
CHANGED
|
@@ -444,6 +444,19 @@ export class Admin extends ClearingHouse {
|
|
|
444
444
|
});
|
|
445
445
|
}
|
|
446
446
|
|
|
447
|
+
public async updateMarketMaxSpread(
|
|
448
|
+
marketIndex: BN,
|
|
449
|
+
maxSpread: number
|
|
450
|
+
): Promise<TransactionSignature> {
|
|
451
|
+
return await this.program.rpc.updateMarketMaxSpread(maxSpread, {
|
|
452
|
+
accounts: {
|
|
453
|
+
admin: this.wallet.publicKey,
|
|
454
|
+
state: await this.getStatePublicKey(),
|
|
455
|
+
market: await getMarketPublicKey(this.program.programId, marketIndex),
|
|
456
|
+
},
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
|
|
447
460
|
public async updatePartialLiquidationClosePercentage(
|
|
448
461
|
numerator: BN,
|
|
449
462
|
denominator: BN
|