@drift-labs/sdk 2.14.0-beta.0 → 2.15.0-beta.0
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/accounts/bulkAccountLoader.d.ts +0 -1
- package/lib/accounts/bulkAccountLoader.js +3 -3
- package/lib/accounts/fetch.js +2 -2
- package/lib/accounts/pollingDriftClientAccountSubscriber.js +7 -7
- package/lib/accounts/pollingTokenAccountSubscriber.js +2 -2
- package/lib/accounts/pollingUserAccountSubscriber.js +2 -2
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +2 -2
- package/lib/accounts/types.d.ts +0 -1
- package/lib/accounts/webSocketAccountSubscriber.js +1 -1
- package/lib/accounts/webSocketDriftClientAccountSubscriber.js +3 -3
- package/lib/addresses/marketAddresses.js +1 -1
- package/lib/addresses/pda.js +1 -5
- package/lib/adminClient.js +57 -61
- package/lib/constants/numericConstants.d.ts +1 -0
- package/lib/constants/numericConstants.js +3 -2
- package/lib/constants/perpMarkets.js +10 -0
- package/lib/dlob/DLOB.js +68 -68
- package/lib/dlob/DLOBNode.js +7 -7
- package/lib/dlob/NodeList.js +2 -2
- package/lib/driftClient.js +81 -85
- package/lib/events/eventSubscriber.js +2 -2
- package/lib/events/pollingLogProvider.js +1 -1
- package/lib/examples/loadDlob.js +2 -2
- package/lib/examples/makeTradeExample.js +9 -9
- package/lib/factory/bigNum.js +9 -9
- package/lib/factory/oracleClient.js +2 -2
- package/lib/idl/drift.json +1 -1
- package/lib/index.js +1 -5
- package/lib/math/amm.js +23 -23
- package/lib/math/auction.js +6 -6
- package/lib/math/exchangeStatus.js +2 -2
- package/lib/math/funding.js +2 -2
- package/lib/math/margin.js +5 -5
- package/lib/math/market.js +13 -13
- package/lib/math/oracles.js +1 -1
- package/lib/math/orders.js +23 -23
- package/lib/math/position.js +5 -5
- package/lib/math/repeg.js +1 -1
- package/lib/math/spotBalance.js +8 -8
- package/lib/math/spotPosition.js +3 -3
- package/lib/math/trade.js +42 -42
- package/lib/oracles/oracleClientCache.js +1 -1
- package/lib/oracles/pythClient.js +1 -1
- package/lib/tokenFaucet.js +1 -5
- package/lib/tx/retryTxSender.js +1 -1
- package/lib/user.js +52 -52
- package/lib/userMap/userMap.js +1 -1
- package/lib/userMap/userStatsMap.js +3 -3
- package/lib/userStats.js +2 -2
- package/package.json +1 -1
- package/src/assert/assert.js +9 -0
- package/src/constants/numericConstants.ts +1 -0
- package/src/constants/perpMarkets.ts +10 -0
- package/src/dlob/DLOB.ts +1 -1
- package/src/idl/drift.json +1 -1
- package/src/token/index.js +38 -0
- package/src/tx/types.js +2 -0
- package/src/tx/utils.js +17 -0
- package/src/user.ts +2 -1
- package/src/util/computeUnits.js +27 -0
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
package/lib/math/orders.js
CHANGED
|
@@ -7,7 +7,7 @@ const anchor_1 = require("@project-serum/anchor");
|
|
|
7
7
|
const auction_1 = require("./auction");
|
|
8
8
|
const amm_1 = require("./amm");
|
|
9
9
|
function isOrderRiskIncreasing(user, order) {
|
|
10
|
-
if (
|
|
10
|
+
if (types_1.isVariant(order.status, 'init')) {
|
|
11
11
|
return false;
|
|
12
12
|
}
|
|
13
13
|
const position = user.getPerpPosition(order.marketIndex) ||
|
|
@@ -17,12 +17,12 @@ function isOrderRiskIncreasing(user, order) {
|
|
|
17
17
|
return true;
|
|
18
18
|
}
|
|
19
19
|
// if position is long and order is long
|
|
20
|
-
if (position.baseAssetAmount.gt(numericConstants_1.ZERO) &&
|
|
20
|
+
if (position.baseAssetAmount.gt(numericConstants_1.ZERO) && types_1.isVariant(order.direction, 'long')) {
|
|
21
21
|
return true;
|
|
22
22
|
}
|
|
23
23
|
// if position is short and order is short
|
|
24
24
|
if (position.baseAssetAmount.lt(numericConstants_1.ZERO) &&
|
|
25
|
-
|
|
25
|
+
types_1.isVariant(order.direction, 'short')) {
|
|
26
26
|
return true;
|
|
27
27
|
}
|
|
28
28
|
const baseAssetAmountToFill = order.baseAssetAmount.sub(order.baseAssetAmountFilled);
|
|
@@ -34,7 +34,7 @@ function isOrderRiskIncreasing(user, order) {
|
|
|
34
34
|
}
|
|
35
35
|
exports.isOrderRiskIncreasing = isOrderRiskIncreasing;
|
|
36
36
|
function isOrderRiskIncreasingInSameDirection(user, order) {
|
|
37
|
-
if (
|
|
37
|
+
if (types_1.isVariant(order.status, 'init')) {
|
|
38
38
|
return false;
|
|
39
39
|
}
|
|
40
40
|
const position = user.getPerpPosition(order.marketIndex) ||
|
|
@@ -44,31 +44,31 @@ function isOrderRiskIncreasingInSameDirection(user, order) {
|
|
|
44
44
|
return true;
|
|
45
45
|
}
|
|
46
46
|
// if position is long and order is long
|
|
47
|
-
if (position.baseAssetAmount.gt(numericConstants_1.ZERO) &&
|
|
47
|
+
if (position.baseAssetAmount.gt(numericConstants_1.ZERO) && types_1.isVariant(order.direction, 'long')) {
|
|
48
48
|
return true;
|
|
49
49
|
}
|
|
50
50
|
// if position is short and order is short
|
|
51
51
|
if (position.baseAssetAmount.lt(numericConstants_1.ZERO) &&
|
|
52
|
-
|
|
52
|
+
types_1.isVariant(order.direction, 'short')) {
|
|
53
53
|
return true;
|
|
54
54
|
}
|
|
55
55
|
return false;
|
|
56
56
|
}
|
|
57
57
|
exports.isOrderRiskIncreasingInSameDirection = isOrderRiskIncreasingInSameDirection;
|
|
58
58
|
function isOrderReduceOnly(user, order) {
|
|
59
|
-
if (
|
|
59
|
+
if (types_1.isVariant(order.status, 'init')) {
|
|
60
60
|
return false;
|
|
61
61
|
}
|
|
62
62
|
const position = user.getPerpPosition(order.marketIndex) ||
|
|
63
63
|
user.getEmptyPosition(order.marketIndex);
|
|
64
64
|
// if position is long and order is long
|
|
65
65
|
if (position.baseAssetAmount.gte(numericConstants_1.ZERO) &&
|
|
66
|
-
|
|
66
|
+
types_1.isVariant(order.direction, 'long')) {
|
|
67
67
|
return false;
|
|
68
68
|
}
|
|
69
69
|
// if position is short and order is short
|
|
70
70
|
if (position.baseAssetAmount.lte(numericConstants_1.ZERO) &&
|
|
71
|
-
|
|
71
|
+
types_1.isVariant(order.direction, 'short')) {
|
|
72
72
|
return false;
|
|
73
73
|
}
|
|
74
74
|
return true;
|
|
@@ -82,7 +82,7 @@ exports.standardizeBaseAssetAmount = standardizeBaseAssetAmount;
|
|
|
82
82
|
function getLimitPrice(order, oraclePriceData, slot, fallbackPrice) {
|
|
83
83
|
let limitPrice;
|
|
84
84
|
if (hasAuctionPrice(order, slot)) {
|
|
85
|
-
limitPrice =
|
|
85
|
+
limitPrice = auction_1.getAuctionPrice(order, slot, oraclePriceData.price);
|
|
86
86
|
}
|
|
87
87
|
else if (order.oraclePriceOffset !== 0) {
|
|
88
88
|
limitPrice = oraclePriceData.price.add(new anchor_1.BN(order.oraclePriceOffset));
|
|
@@ -99,15 +99,15 @@ exports.getLimitPrice = getLimitPrice;
|
|
|
99
99
|
function hasLimitPrice(order, slot) {
|
|
100
100
|
return (order.price.gt(numericConstants_1.ZERO) ||
|
|
101
101
|
order.oraclePriceOffset != 0 ||
|
|
102
|
-
!
|
|
102
|
+
!auction_1.isAuctionComplete(order, slot));
|
|
103
103
|
}
|
|
104
104
|
exports.hasLimitPrice = hasLimitPrice;
|
|
105
105
|
function hasAuctionPrice(order, slot) {
|
|
106
|
-
return isMarketOrder(order) && !
|
|
106
|
+
return isMarketOrder(order) && !auction_1.isAuctionComplete(order, slot);
|
|
107
107
|
}
|
|
108
108
|
exports.hasAuctionPrice = hasAuctionPrice;
|
|
109
109
|
function isFillableByVAMM(order, market, oraclePriceData, slot, ts) {
|
|
110
|
-
return ((
|
|
110
|
+
return ((auction_1.isAuctionComplete(order, slot) &&
|
|
111
111
|
calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData, slot).gte(market.amm.minOrderSize)) ||
|
|
112
112
|
isOrderExpired(order, ts));
|
|
113
113
|
}
|
|
@@ -118,19 +118,19 @@ function calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData,
|
|
|
118
118
|
}
|
|
119
119
|
const limitPrice = getLimitPrice(order, oraclePriceData, slot);
|
|
120
120
|
let baseAssetAmount;
|
|
121
|
-
const updatedAMM =
|
|
121
|
+
const updatedAMM = amm_1.calculateUpdatedAMM(market.amm, oraclePriceData);
|
|
122
122
|
if (limitPrice !== undefined) {
|
|
123
123
|
baseAssetAmount = calculateBaseAssetAmountToFillUpToLimitPrice(order, updatedAMM, limitPrice, oraclePriceData);
|
|
124
124
|
}
|
|
125
125
|
else {
|
|
126
126
|
baseAssetAmount = order.baseAssetAmount.sub(order.baseAssetAmountFilled);
|
|
127
127
|
}
|
|
128
|
-
const maxBaseAssetAmount =
|
|
128
|
+
const maxBaseAssetAmount = amm_1.calculateMaxBaseAssetAmountFillable(updatedAMM, order.direction);
|
|
129
129
|
return anchor_1.BN.min(maxBaseAssetAmount, baseAssetAmount);
|
|
130
130
|
}
|
|
131
131
|
exports.calculateBaseAssetAmountForAmmToFulfill = calculateBaseAssetAmountForAmmToFulfill;
|
|
132
132
|
function calculateBaseAssetAmountToFillUpToLimitPrice(order, amm, limitPrice, oraclePriceData) {
|
|
133
|
-
const [maxAmountToTrade, direction] =
|
|
133
|
+
const [maxAmountToTrade, direction] = amm_1.calculateMaxBaseAssetAmountToTrade(amm, limitPrice, order.direction, oraclePriceData);
|
|
134
134
|
const baseAssetAmount = standardizeBaseAssetAmount(maxAmountToTrade, amm.orderStepSize);
|
|
135
135
|
// Check that directions are the same
|
|
136
136
|
const sameDirection = isSameDirection(direction, order.direction);
|
|
@@ -144,12 +144,12 @@ function calculateBaseAssetAmountToFillUpToLimitPrice(order, amm, limitPrice, or
|
|
|
144
144
|
}
|
|
145
145
|
exports.calculateBaseAssetAmountToFillUpToLimitPrice = calculateBaseAssetAmountToFillUpToLimitPrice;
|
|
146
146
|
function isSameDirection(firstDirection, secondDirection) {
|
|
147
|
-
return ((
|
|
148
|
-
(
|
|
147
|
+
return ((types_1.isVariant(firstDirection, 'long') && types_1.isVariant(secondDirection, 'long')) ||
|
|
148
|
+
(types_1.isVariant(firstDirection, 'short') && types_1.isVariant(secondDirection, 'short')));
|
|
149
149
|
}
|
|
150
150
|
function isOrderExpired(order, ts) {
|
|
151
151
|
if (mustBeTriggered(order) ||
|
|
152
|
-
!
|
|
152
|
+
!types_1.isVariant(order.status, 'open') ||
|
|
153
153
|
order.maxTs.eq(numericConstants_1.ZERO)) {
|
|
154
154
|
return false;
|
|
155
155
|
}
|
|
@@ -157,19 +157,19 @@ function isOrderExpired(order, ts) {
|
|
|
157
157
|
}
|
|
158
158
|
exports.isOrderExpired = isOrderExpired;
|
|
159
159
|
function isMarketOrder(order) {
|
|
160
|
-
return
|
|
160
|
+
return types_1.isOneOfVariant(order.orderType, ['market', 'triggerMarket', 'oracle']);
|
|
161
161
|
}
|
|
162
162
|
exports.isMarketOrder = isMarketOrder;
|
|
163
163
|
function isLimitOrder(order) {
|
|
164
|
-
return
|
|
164
|
+
return types_1.isOneOfVariant(order.orderType, ['limit', 'triggerLimit']);
|
|
165
165
|
}
|
|
166
166
|
exports.isLimitOrder = isLimitOrder;
|
|
167
167
|
function mustBeTriggered(order) {
|
|
168
|
-
return
|
|
168
|
+
return types_1.isOneOfVariant(order.orderType, ['triggerMarket', 'triggerLimit']);
|
|
169
169
|
}
|
|
170
170
|
exports.mustBeTriggered = mustBeTriggered;
|
|
171
171
|
function isTriggered(order) {
|
|
172
|
-
return
|
|
172
|
+
return types_1.isOneOfVariant(order.triggerCondition, [
|
|
173
173
|
'triggeredAbove',
|
|
174
174
|
'triggeredBelow',
|
|
175
175
|
]);
|
package/lib/math/position.js
CHANGED
|
@@ -23,7 +23,7 @@ function calculateBaseAssetValue(market, userPosition, oraclePriceData, useSprea
|
|
|
23
23
|
let prepegAmm;
|
|
24
24
|
if (!skipUpdate) {
|
|
25
25
|
if (market.amm.baseSpread > 0 && useSpread) {
|
|
26
|
-
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } =
|
|
26
|
+
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = amm_1.calculateUpdatedAMMSpreadReserves(market.amm, directionToClose, oraclePriceData);
|
|
27
27
|
prepegAmm = {
|
|
28
28
|
baseAssetReserve,
|
|
29
29
|
quoteAssetReserve,
|
|
@@ -32,13 +32,13 @@ function calculateBaseAssetValue(market, userPosition, oraclePriceData, useSprea
|
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
34
|
else {
|
|
35
|
-
prepegAmm =
|
|
35
|
+
prepegAmm = amm_1.calculateUpdatedAMM(market.amm, oraclePriceData);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
else {
|
|
39
39
|
prepegAmm = market.amm;
|
|
40
40
|
}
|
|
41
|
-
const [newQuoteAssetReserve, _] =
|
|
41
|
+
const [newQuoteAssetReserve, _] = amm_1.calculateAmmReservesAfterSwap(prepegAmm, 'base', userPosition.baseAssetAmount.abs(), amm_1.getSwapDirection('base', directionToClose));
|
|
42
42
|
switch (directionToClose) {
|
|
43
43
|
case types_1.PositionDirection.SHORT:
|
|
44
44
|
return prepegAmm.quoteAssetReserve
|
|
@@ -67,7 +67,7 @@ function calculatePositionPNL(market, perpPosition, withFunding = false, oracleP
|
|
|
67
67
|
if (perpPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
68
68
|
return perpPosition.quoteAssetAmount;
|
|
69
69
|
}
|
|
70
|
-
const baseAssetValue =
|
|
70
|
+
const baseAssetValue = margin_1.calculateBaseAssetValueWithOracle(market, perpPosition, oraclePriceData);
|
|
71
71
|
const baseAssetValueSign = perpPosition.baseAssetAmount.isNeg()
|
|
72
72
|
? new __1.BN(-1)
|
|
73
73
|
: new __1.BN(1);
|
|
@@ -86,7 +86,7 @@ function calculateClaimablePnl(market, spotMarket, perpPosition, oraclePriceData
|
|
|
86
86
|
const fundingPnL = calculatePositionFundingPNL(market, perpPosition);
|
|
87
87
|
let unsettledPnl = unrealizedPnl.add(fundingPnL);
|
|
88
88
|
if (unrealizedPnl.gt(numericConstants_1.ZERO)) {
|
|
89
|
-
const excessPnlPool = __1.BN.max(numericConstants_1.ZERO,
|
|
89
|
+
const excessPnlPool = __1.BN.max(numericConstants_1.ZERO, market_1.calculateNetUserPnlImbalance(market, spotMarket, oraclePriceData).mul(new __1.BN(-1)));
|
|
90
90
|
const maxPositivePnl = __1.BN.max(perpPosition.quoteAssetAmount.sub(perpPosition.quoteEntryAmount), numericConstants_1.ZERO).add(excessPnlPool);
|
|
91
91
|
unsettledPnl = __1.BN.min(maxPositivePnl, unrealizedPnl);
|
|
92
92
|
}
|
package/lib/math/repeg.js
CHANGED
|
@@ -77,7 +77,7 @@ function calculateRepegCost(amm, newPeg) {
|
|
|
77
77
|
}
|
|
78
78
|
exports.calculateRepegCost = calculateRepegCost;
|
|
79
79
|
function calculateBudgetedKBN(x, y, budget, Q, d) {
|
|
80
|
-
|
|
80
|
+
assert_1.assert(Q.gt(new anchor_1.BN(0)));
|
|
81
81
|
const C = budget.mul(new anchor_1.BN(-1));
|
|
82
82
|
let dSign = new anchor_1.BN(1);
|
|
83
83
|
if (d.lt(new anchor_1.BN(0))) {
|
package/lib/math/spotBalance.js
CHANGED
|
@@ -8,11 +8,11 @@ const margin_1 = require("./margin");
|
|
|
8
8
|
const numericConstants_2 = require("../constants/numericConstants");
|
|
9
9
|
function getBalance(tokenAmount, spotMarket, balanceType) {
|
|
10
10
|
const precisionIncrease = numericConstants_1.TEN.pow(new anchor_1.BN(19 - spotMarket.decimals));
|
|
11
|
-
const cumulativeInterest =
|
|
11
|
+
const cumulativeInterest = types_1.isVariant(balanceType, 'deposit')
|
|
12
12
|
? spotMarket.cumulativeDepositInterest
|
|
13
13
|
: spotMarket.cumulativeBorrowInterest;
|
|
14
14
|
let balance = tokenAmount.mul(precisionIncrease).div(cumulativeInterest);
|
|
15
|
-
if (!balance.eq(numericConstants_1.ZERO) &&
|
|
15
|
+
if (!balance.eq(numericConstants_1.ZERO) && types_1.isVariant(balanceType, 'borrow')) {
|
|
16
16
|
balance = balance.add(numericConstants_1.ONE);
|
|
17
17
|
}
|
|
18
18
|
return balance;
|
|
@@ -20,14 +20,14 @@ function getBalance(tokenAmount, spotMarket, balanceType) {
|
|
|
20
20
|
exports.getBalance = getBalance;
|
|
21
21
|
function getTokenAmount(balanceAmount, spotMarket, balanceType) {
|
|
22
22
|
const precisionDecrease = numericConstants_1.TEN.pow(new anchor_1.BN(19 - spotMarket.decimals));
|
|
23
|
-
const cumulativeInterest =
|
|
23
|
+
const cumulativeInterest = types_1.isVariant(balanceType, 'deposit')
|
|
24
24
|
? spotMarket.cumulativeDepositInterest
|
|
25
25
|
: spotMarket.cumulativeBorrowInterest;
|
|
26
26
|
return balanceAmount.mul(cumulativeInterest).div(precisionDecrease);
|
|
27
27
|
}
|
|
28
28
|
exports.getTokenAmount = getTokenAmount;
|
|
29
29
|
function getSignedTokenAmount(tokenAmount, balanceType) {
|
|
30
|
-
if (
|
|
30
|
+
if (types_1.isVariant(balanceType, 'deposit')) {
|
|
31
31
|
return tokenAmount;
|
|
32
32
|
}
|
|
33
33
|
else {
|
|
@@ -72,10 +72,10 @@ function calculateAssetWeight(balanceAmount, spotMarket, marginCategory) {
|
|
|
72
72
|
let assetWeight;
|
|
73
73
|
switch (marginCategory) {
|
|
74
74
|
case 'Initial':
|
|
75
|
-
assetWeight =
|
|
75
|
+
assetWeight = margin_1.calculateSizeDiscountAssetWeight(sizeInAmmReservePrecision, new anchor_1.BN(spotMarket.imfFactor), new anchor_1.BN(spotMarket.initialAssetWeight));
|
|
76
76
|
break;
|
|
77
77
|
case 'Maintenance':
|
|
78
|
-
assetWeight =
|
|
78
|
+
assetWeight = margin_1.calculateSizeDiscountAssetWeight(sizeInAmmReservePrecision, new anchor_1.BN(spotMarket.imfFactor), new anchor_1.BN(spotMarket.maintenanceAssetWeight));
|
|
79
79
|
break;
|
|
80
80
|
default:
|
|
81
81
|
assetWeight = new anchor_1.BN(spotMarket.initialAssetWeight);
|
|
@@ -98,10 +98,10 @@ function calculateLiabilityWeight(balanceAmount, spotMarket, marginCategory) {
|
|
|
98
98
|
let assetWeight;
|
|
99
99
|
switch (marginCategory) {
|
|
100
100
|
case 'Initial':
|
|
101
|
-
assetWeight =
|
|
101
|
+
assetWeight = margin_1.calculateSizePremiumLiabilityWeight(sizeInAmmReservePrecision, new anchor_1.BN(spotMarket.imfFactor), new anchor_1.BN(spotMarket.initialLiabilityWeight), numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
102
102
|
break;
|
|
103
103
|
case 'Maintenance':
|
|
104
|
-
assetWeight =
|
|
104
|
+
assetWeight = margin_1.calculateSizePremiumLiabilityWeight(sizeInAmmReservePrecision, new anchor_1.BN(spotMarket.imfFactor), new anchor_1.BN(spotMarket.maintenanceLiabilityWeight), numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
105
105
|
break;
|
|
106
106
|
default:
|
|
107
107
|
assetWeight = spotMarket.initialLiabilityWeight;
|
package/lib/math/spotPosition.js
CHANGED
|
@@ -8,15 +8,15 @@ function isSpotPositionAvailable(position) {
|
|
|
8
8
|
}
|
|
9
9
|
exports.isSpotPositionAvailable = isSpotPositionAvailable;
|
|
10
10
|
function getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, oraclePriceData) {
|
|
11
|
-
const tokenAmount =
|
|
11
|
+
const tokenAmount = spotBalance_1.getSignedTokenAmount(spotBalance_1.getTokenAmount(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
|
|
12
12
|
const tokenAmountAllBidsFill = tokenAmount.add(spotPosition.openBids);
|
|
13
13
|
const tokenAmountAllAsksFill = tokenAmount.add(spotPosition.openAsks);
|
|
14
14
|
if (tokenAmountAllAsksFill.abs().gt(tokenAmountAllBidsFill.abs())) {
|
|
15
|
-
const worstCaseQuoteTokenAmount =
|
|
15
|
+
const worstCaseQuoteTokenAmount = spotBalance_1.getTokenValue(spotPosition.openAsks.neg(), spotMarketAccount.decimals, oraclePriceData);
|
|
16
16
|
return [tokenAmountAllBidsFill, worstCaseQuoteTokenAmount];
|
|
17
17
|
}
|
|
18
18
|
else {
|
|
19
|
-
const worstCaseQuoteTokenAmount =
|
|
19
|
+
const worstCaseQuoteTokenAmount = spotBalance_1.getTokenValue(spotPosition.openBids.neg(), spotMarketAccount.decimals, oraclePriceData);
|
|
20
20
|
return [tokenAmountAllAsksFill, worstCaseQuoteTokenAmount];
|
|
21
21
|
}
|
|
22
22
|
}
|
package/lib/math/trade.js
CHANGED
|
@@ -30,15 +30,15 @@ const MAXPCT = new anchor_1.BN(1000); //percentage units are [0,1000] => [0,1]
|
|
|
30
30
|
function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quote', oraclePriceData, useSpread = true) {
|
|
31
31
|
let oldPrice;
|
|
32
32
|
if (useSpread && market.amm.baseSpread > 0) {
|
|
33
|
-
if (
|
|
34
|
-
oldPrice =
|
|
33
|
+
if (types_2.isVariant(direction, 'long')) {
|
|
34
|
+
oldPrice = market_1.calculateAskPrice(market, oraclePriceData);
|
|
35
35
|
}
|
|
36
36
|
else {
|
|
37
|
-
oldPrice =
|
|
37
|
+
oldPrice = market_1.calculateBidPrice(market, oraclePriceData);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
else {
|
|
41
|
-
oldPrice =
|
|
41
|
+
oldPrice = market_1.calculateReservePrice(market, oraclePriceData);
|
|
42
42
|
}
|
|
43
43
|
if (amount.eq(numericConstants_1.ZERO)) {
|
|
44
44
|
return [numericConstants_1.ZERO, numericConstants_1.ZERO, oldPrice, oldPrice];
|
|
@@ -50,7 +50,7 @@ function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quo
|
|
|
50
50
|
.div(acquiredBaseReserve.abs());
|
|
51
51
|
let amm;
|
|
52
52
|
if (useSpread && market.amm.baseSpread > 0) {
|
|
53
|
-
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } =
|
|
53
|
+
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = amm_1.calculateUpdatedAMMSpreadReserves(market.amm, direction, oraclePriceData);
|
|
54
54
|
amm = {
|
|
55
55
|
baseAssetReserve,
|
|
56
56
|
quoteAssetReserve,
|
|
@@ -61,12 +61,12 @@ function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quo
|
|
|
61
61
|
else {
|
|
62
62
|
amm = market.amm;
|
|
63
63
|
}
|
|
64
|
-
const newPrice =
|
|
64
|
+
const newPrice = amm_1.calculatePrice(amm.baseAssetReserve.sub(acquiredBaseReserve), amm.quoteAssetReserve.sub(acquiredQuoteReserve), amm.pegMultiplier);
|
|
65
65
|
if (direction == types_1.PositionDirection.SHORT) {
|
|
66
|
-
|
|
66
|
+
assert_1.assert(newPrice.lte(oldPrice));
|
|
67
67
|
}
|
|
68
68
|
else {
|
|
69
|
-
|
|
69
|
+
assert_1.assert(oldPrice.lte(newPrice));
|
|
70
70
|
}
|
|
71
71
|
const pctMaxSlippage = newPrice
|
|
72
72
|
.sub(oldPrice)
|
|
@@ -96,10 +96,10 @@ function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType
|
|
|
96
96
|
if (amount.eq(numericConstants_1.ZERO)) {
|
|
97
97
|
return [numericConstants_1.ZERO, numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
98
98
|
}
|
|
99
|
-
const swapDirection =
|
|
99
|
+
const swapDirection = amm_1.getSwapDirection(inputAssetType, direction);
|
|
100
100
|
let amm;
|
|
101
101
|
if (useSpread && market.amm.baseSpread > 0) {
|
|
102
|
-
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } =
|
|
102
|
+
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = amm_1.calculateUpdatedAMMSpreadReserves(market.amm, direction, oraclePriceData);
|
|
103
103
|
amm = {
|
|
104
104
|
baseAssetReserve,
|
|
105
105
|
quoteAssetReserve,
|
|
@@ -110,10 +110,10 @@ function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType
|
|
|
110
110
|
else {
|
|
111
111
|
amm = market.amm;
|
|
112
112
|
}
|
|
113
|
-
const [newQuoteAssetReserve, newBaseAssetReserve] =
|
|
113
|
+
const [newQuoteAssetReserve, newBaseAssetReserve] = amm_1.calculateAmmReservesAfterSwap(amm, inputAssetType, amount, swapDirection);
|
|
114
114
|
const acquiredBase = amm.baseAssetReserve.sub(newBaseAssetReserve);
|
|
115
115
|
const acquiredQuote = amm.quoteAssetReserve.sub(newQuoteAssetReserve);
|
|
116
|
-
const acquiredQuoteAssetAmount =
|
|
116
|
+
const acquiredQuoteAssetAmount = amm_1.calculateQuoteAssetAmountSwapped(acquiredQuote.abs(), amm.pegMultiplier, swapDirection);
|
|
117
117
|
return [acquiredBase, acquiredQuote, acquiredQuoteAssetAmount];
|
|
118
118
|
}
|
|
119
119
|
exports.calculateTradeAcquiredAmounts = calculateTradeAcquiredAmounts;
|
|
@@ -135,12 +135,12 @@ exports.calculateTradeAcquiredAmounts = calculateTradeAcquiredAmounts;
|
|
|
135
135
|
* ]
|
|
136
136
|
*/
|
|
137
137
|
function calculateTargetPriceTrade(market, targetPrice, pct = MAXPCT, outputAssetType = 'quote', oraclePriceData, useSpread = true) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const reservePriceBefore =
|
|
142
|
-
const bidPriceBefore =
|
|
143
|
-
const askPriceBefore =
|
|
138
|
+
assert_1.assert(market.amm.baseAssetReserve.gt(numericConstants_1.ZERO));
|
|
139
|
+
assert_1.assert(targetPrice.gt(numericConstants_1.ZERO));
|
|
140
|
+
assert_1.assert(pct.lte(MAXPCT) && pct.gt(numericConstants_1.ZERO));
|
|
141
|
+
const reservePriceBefore = market_1.calculateReservePrice(market, oraclePriceData);
|
|
142
|
+
const bidPriceBefore = market_1.calculateBidPrice(market, oraclePriceData);
|
|
143
|
+
const askPriceBefore = market_1.calculateAskPrice(market, oraclePriceData);
|
|
144
144
|
let direction;
|
|
145
145
|
if (targetPrice.gt(reservePriceBefore)) {
|
|
146
146
|
const priceGap = targetPrice.sub(reservePriceBefore);
|
|
@@ -160,7 +160,7 @@ function calculateTargetPriceTrade(market, targetPrice, pct = MAXPCT, outputAsse
|
|
|
160
160
|
let quoteAssetReserveBefore;
|
|
161
161
|
let peg = market.amm.pegMultiplier;
|
|
162
162
|
if (useSpread && market.amm.baseSpread > 0) {
|
|
163
|
-
const { baseAssetReserve, quoteAssetReserve, newPeg } =
|
|
163
|
+
const { baseAssetReserve, quoteAssetReserve, newPeg } = amm_1.calculateUpdatedAMMSpreadReserves(market.amm, direction, oraclePriceData);
|
|
164
164
|
baseAssetReserveBefore = baseAssetReserve;
|
|
165
165
|
quoteAssetReserveBefore = quoteAssetReserve;
|
|
166
166
|
peg = newPeg;
|
|
@@ -190,9 +190,9 @@ function calculateTargetPriceTrade(market, targetPrice, pct = MAXPCT, outputAsse
|
|
|
190
190
|
}
|
|
191
191
|
else if (reservePriceBefore.gt(targetPrice)) {
|
|
192
192
|
// overestimate y2
|
|
193
|
-
baseAssetReserveAfter =
|
|
193
|
+
baseAssetReserveAfter = utils_1.squareRootBN(k.div(targetPrice).mul(peg).div(numericConstants_1.PEG_PRECISION).sub(biasModifier)).sub(new anchor_1.BN(1));
|
|
194
194
|
quoteAssetReserveAfter = k.div(numericConstants_1.PRICE_PRECISION).div(baseAssetReserveAfter);
|
|
195
|
-
markPriceAfter =
|
|
195
|
+
markPriceAfter = amm_1.calculatePrice(baseAssetReserveAfter, quoteAssetReserveAfter, peg);
|
|
196
196
|
direction = types_1.PositionDirection.SHORT;
|
|
197
197
|
tradeSize = quoteAssetReserveBefore
|
|
198
198
|
.sub(quoteAssetReserveAfter)
|
|
@@ -203,9 +203,9 @@ function calculateTargetPriceTrade(market, targetPrice, pct = MAXPCT, outputAsse
|
|
|
203
203
|
}
|
|
204
204
|
else if (reservePriceBefore.lt(targetPrice)) {
|
|
205
205
|
// underestimate y2
|
|
206
|
-
baseAssetReserveAfter =
|
|
206
|
+
baseAssetReserveAfter = utils_1.squareRootBN(k.div(targetPrice).mul(peg).div(numericConstants_1.PEG_PRECISION).add(biasModifier)).add(new anchor_1.BN(1));
|
|
207
207
|
quoteAssetReserveAfter = k.div(numericConstants_1.PRICE_PRECISION).div(baseAssetReserveAfter);
|
|
208
|
-
markPriceAfter =
|
|
208
|
+
markPriceAfter = amm_1.calculatePrice(baseAssetReserveAfter, quoteAssetReserveAfter, peg);
|
|
209
209
|
direction = types_1.PositionDirection.LONG;
|
|
210
210
|
tradeSize = quoteAssetReserveAfter
|
|
211
211
|
.sub(quoteAssetReserveBefore)
|
|
@@ -232,8 +232,8 @@ function calculateTargetPriceTrade(market, targetPrice, pct = MAXPCT, outputAsse
|
|
|
232
232
|
.mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
|
|
233
233
|
.mul(numericConstants_1.PRICE_PRECISION)
|
|
234
234
|
.div(baseSize.abs());
|
|
235
|
-
|
|
236
|
-
|
|
235
|
+
assert_1.assert(tp1.sub(tp2).lte(originalDiff), 'Target Price Calculation incorrect');
|
|
236
|
+
assert_1.assert(tp2.lte(tp1) || tp2.sub(tp1).abs() < 100000, 'Target Price Calculation incorrect' +
|
|
237
237
|
tp2.toString() +
|
|
238
238
|
'>=' +
|
|
239
239
|
tp1.toString() +
|
|
@@ -271,29 +271,29 @@ function calculateEstimatedPerpEntryPrice(assetType, amount, direction, market,
|
|
|
271
271
|
quoteFilled: numericConstants_1.ZERO,
|
|
272
272
|
};
|
|
273
273
|
}
|
|
274
|
-
const takerIsLong =
|
|
274
|
+
const takerIsLong = types_2.isVariant(direction, 'long');
|
|
275
275
|
const limitOrders = dlob[takerIsLong ? 'getMakerLimitAsks' : 'getMakerLimitBids'](market.marketIndex, slot, types_1.MarketType.PERP, oraclePriceData, takerIsLong
|
|
276
|
-
?
|
|
277
|
-
:
|
|
278
|
-
const swapDirection =
|
|
279
|
-
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } =
|
|
276
|
+
? market_1.calculateBidPrice(market, oraclePriceData)
|
|
277
|
+
: market_1.calculateAskPrice(market, oraclePriceData));
|
|
278
|
+
const swapDirection = amm_1.getSwapDirection(assetType, direction);
|
|
279
|
+
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = amm_1.calculateUpdatedAMMSpreadReserves(market.amm, direction, oraclePriceData);
|
|
280
280
|
const amm = {
|
|
281
281
|
baseAssetReserve,
|
|
282
282
|
quoteAssetReserve,
|
|
283
283
|
sqrtK: sqrtK,
|
|
284
284
|
pegMultiplier: newPeg,
|
|
285
285
|
};
|
|
286
|
-
const [ammBids, ammAsks] =
|
|
286
|
+
const [ammBids, ammAsks] = amm_1.calculateMarketOpenBidAsk(market.amm.baseAssetReserve, market.amm.minBaseAssetReserve, market.amm.maxBaseAssetReserve, market.amm.orderStepSize);
|
|
287
287
|
let ammLiquidity;
|
|
288
288
|
if (assetType === 'base') {
|
|
289
289
|
ammLiquidity = takerIsLong ? ammAsks.abs() : ammBids;
|
|
290
290
|
}
|
|
291
291
|
else {
|
|
292
|
-
const [afterSwapQuoteReserves, _] =
|
|
293
|
-
ammLiquidity =
|
|
292
|
+
const [afterSwapQuoteReserves, _] = amm_1.calculateAmmReservesAfterSwap(amm, 'base', takerIsLong ? ammAsks.abs() : ammBids, amm_1.getSwapDirection('base', direction));
|
|
293
|
+
ammLiquidity = amm_1.calculateQuoteAssetAmountSwapped(amm.quoteAssetReserve.sub(afterSwapQuoteReserves).abs(), amm.pegMultiplier, swapDirection);
|
|
294
294
|
}
|
|
295
295
|
const invariant = amm.sqrtK.mul(amm.sqrtK);
|
|
296
|
-
let bestPrice =
|
|
296
|
+
let bestPrice = amm_1.calculatePrice(amm.baseAssetReserve, amm.quoteAssetReserve, amm.pegMultiplier);
|
|
297
297
|
let cumulativeBaseFilled = numericConstants_1.ZERO;
|
|
298
298
|
let cumulativeQuoteFilled = numericConstants_1.ZERO;
|
|
299
299
|
let limitOrder = limitOrders.next().value;
|
|
@@ -310,7 +310,7 @@ function calculateEstimatedPerpEntryPrice(assetType, amount, direction, market,
|
|
|
310
310
|
const limitOrderPrice = limitOrder === null || limitOrder === void 0 ? void 0 : limitOrder.getPrice(oraclePriceData, slot);
|
|
311
311
|
let maxAmmFill;
|
|
312
312
|
if (limitOrderPrice) {
|
|
313
|
-
const newBaseReserves =
|
|
313
|
+
const newBaseReserves = utils_1.squareRootBN(invariant
|
|
314
314
|
.mul(numericConstants_1.PRICE_PRECISION)
|
|
315
315
|
.mul(amm.pegMultiplier)
|
|
316
316
|
.div(limitOrderPrice)
|
|
@@ -326,14 +326,14 @@ function calculateEstimatedPerpEntryPrice(assetType, amount, direction, market,
|
|
|
326
326
|
maxAmmFill = anchor_1.BN.min(maxAmmFill, ammLiquidity);
|
|
327
327
|
if (maxAmmFill.gt(numericConstants_1.ZERO)) {
|
|
328
328
|
const baseFilled = anchor_1.BN.min(amount.sub(cumulativeBaseFilled), maxAmmFill);
|
|
329
|
-
const [afterSwapQuoteReserves, afterSwapBaseReserves] =
|
|
329
|
+
const [afterSwapQuoteReserves, afterSwapBaseReserves] = amm_1.calculateAmmReservesAfterSwap(amm, 'base', baseFilled, swapDirection);
|
|
330
330
|
ammLiquidity = ammLiquidity.sub(baseFilled);
|
|
331
|
-
const quoteFilled =
|
|
331
|
+
const quoteFilled = amm_1.calculateQuoteAssetAmountSwapped(amm.quoteAssetReserve.sub(afterSwapQuoteReserves).abs(), amm.pegMultiplier, swapDirection);
|
|
332
332
|
cumulativeBaseFilled = cumulativeBaseFilled.add(baseFilled);
|
|
333
333
|
cumulativeQuoteFilled = cumulativeQuoteFilled.add(quoteFilled);
|
|
334
334
|
amm.baseAssetReserve = afterSwapBaseReserves;
|
|
335
335
|
amm.quoteAssetReserve = afterSwapQuoteReserves;
|
|
336
|
-
worstPrice =
|
|
336
|
+
worstPrice = amm_1.calculatePrice(amm.baseAssetReserve, amm.quoteAssetReserve, amm.pegMultiplier);
|
|
337
337
|
if (cumulativeBaseFilled.eq(amount)) {
|
|
338
338
|
break;
|
|
339
339
|
}
|
|
@@ -361,7 +361,7 @@ function calculateEstimatedPerpEntryPrice(assetType, amount, direction, market,
|
|
|
361
361
|
const limitOrderPrice = limitOrder === null || limitOrder === void 0 ? void 0 : limitOrder.getPrice(oraclePriceData, slot);
|
|
362
362
|
let maxAmmFill;
|
|
363
363
|
if (limitOrderPrice) {
|
|
364
|
-
const newQuoteReserves =
|
|
364
|
+
const newQuoteReserves = utils_1.squareRootBN(invariant
|
|
365
365
|
.mul(numericConstants_1.PEG_PRECISION)
|
|
366
366
|
.mul(limitOrderPrice)
|
|
367
367
|
.div(amm.pegMultiplier)
|
|
@@ -377,7 +377,7 @@ function calculateEstimatedPerpEntryPrice(assetType, amount, direction, market,
|
|
|
377
377
|
maxAmmFill = anchor_1.BN.min(maxAmmFill, ammLiquidity);
|
|
378
378
|
if (maxAmmFill.gt(numericConstants_1.ZERO)) {
|
|
379
379
|
const quoteFilled = anchor_1.BN.min(amount.sub(cumulativeQuoteFilled), maxAmmFill);
|
|
380
|
-
const [afterSwapQuoteReserves, afterSwapBaseReserves] =
|
|
380
|
+
const [afterSwapQuoteReserves, afterSwapBaseReserves] = amm_1.calculateAmmReservesAfterSwap(amm, 'quote', quoteFilled, swapDirection);
|
|
381
381
|
ammLiquidity = ammLiquidity.sub(quoteFilled);
|
|
382
382
|
const baseFilled = afterSwapBaseReserves
|
|
383
383
|
.sub(amm.baseAssetReserve)
|
|
@@ -386,7 +386,7 @@ function calculateEstimatedPerpEntryPrice(assetType, amount, direction, market,
|
|
|
386
386
|
cumulativeQuoteFilled = cumulativeQuoteFilled.add(quoteFilled);
|
|
387
387
|
amm.baseAssetReserve = afterSwapBaseReserves;
|
|
388
388
|
amm.quoteAssetReserve = afterSwapQuoteReserves;
|
|
389
|
-
worstPrice =
|
|
389
|
+
worstPrice = amm_1.calculatePrice(amm.baseAssetReserve, amm.quoteAssetReserve, amm.pegMultiplier);
|
|
390
390
|
if (cumulativeQuoteFilled.eq(amount)) {
|
|
391
391
|
break;
|
|
392
392
|
}
|
|
@@ -456,7 +456,7 @@ function calculateEstimatedSpotEntryPrice(assetType, amount, direction, market,
|
|
|
456
456
|
};
|
|
457
457
|
}
|
|
458
458
|
const basePrecision = new anchor_1.BN(Math.pow(10, market.decimals));
|
|
459
|
-
const takerIsLong =
|
|
459
|
+
const takerIsLong = types_2.isVariant(direction, 'long');
|
|
460
460
|
const dlobLimitOrders = dlob[takerIsLong ? 'getMakerLimitAsks' : 'getMakerLimitBids'](market.marketIndex, slot, types_1.MarketType.SPOT, oraclePriceData);
|
|
461
461
|
const serumLimitOrders = takerIsLong
|
|
462
462
|
? serumAsks.getL2(100)
|
|
@@ -11,7 +11,7 @@ class OracleClientCache {
|
|
|
11
11
|
if (this.cache.has(key)) {
|
|
12
12
|
return this.cache.get(key);
|
|
13
13
|
}
|
|
14
|
-
const client =
|
|
14
|
+
const client = oracleClient_1.getOracleClient(oracleSource, connection);
|
|
15
15
|
this.cache.set(key, client);
|
|
16
16
|
return client;
|
|
17
17
|
}
|
|
@@ -13,7 +13,7 @@ class PythClient {
|
|
|
13
13
|
return this.getOraclePriceDataFromBuffer(accountInfo.data);
|
|
14
14
|
}
|
|
15
15
|
getOraclePriceDataFromBuffer(buffer) {
|
|
16
|
-
const priceData =
|
|
16
|
+
const priceData = client_1.parsePriceData(buffer);
|
|
17
17
|
return {
|
|
18
18
|
price: convertPythPrice(priceData.aggregate.price, priceData.exponent),
|
|
19
19
|
slot: new anchor_1.BN(priceData.lastSlot.toString()),
|
package/lib/tokenFaucet.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
9
5
|
}) : (function(o, m, k, k2) {
|
|
10
6
|
if (k2 === undefined) k2 = k;
|
|
11
7
|
o[k2] = m[k];
|
package/lib/tx/retryTxSender.js
CHANGED
|
@@ -93,7 +93,7 @@ class RetryTxSender {
|
|
|
93
93
|
catch (err) {
|
|
94
94
|
throw new Error('signature must be base58 encoded: ' + signature);
|
|
95
95
|
}
|
|
96
|
-
|
|
96
|
+
assert_1.default(decodedSignature.length === 64, 'signature has invalid length');
|
|
97
97
|
const start = Date.now();
|
|
98
98
|
const subscriptionCommitment = commitment || this.provider.opts.commitment;
|
|
99
99
|
const subscriptionIds = new Array();
|