@drift-labs/sdk 0.2.0-master.3 → 0.2.0-master.31
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/README.md +13 -13
- package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
- package/lib/accounts/bulkUserStatsSubscription.js +21 -0
- package/lib/accounts/bulkUserSubscription.js +0 -1
- package/lib/accounts/fetch.d.ts +2 -1
- package/lib/accounts/fetch.js +9 -1
- package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +16 -16
- package/lib/accounts/pollingClearingHouseAccountSubscriber.js +31 -28
- package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
- package/lib/accounts/types.d.ts +22 -11
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +17 -17
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +37 -35
- package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
- package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
- package/lib/addresses/marketAddresses.d.ts +1 -3
- package/lib/addresses/pda.d.ts +10 -4
- package/lib/addresses/pda.js +51 -14
- package/lib/admin.d.ts +42 -26
- package/lib/admin.js +228 -81
- package/lib/clearingHouse.d.ts +130 -49
- package/lib/clearingHouse.js +1256 -367
- package/lib/clearingHouseConfig.d.ts +4 -4
- package/lib/clearingHouseUser.d.ts +51 -39
- package/lib/clearingHouseUser.js +408 -191
- package/lib/clearingHouseUserStats.d.ts +18 -0
- package/lib/clearingHouseUserStats.js +49 -0
- package/lib/clearingHouseUserStatsConfig.d.ts +14 -0
- package/lib/clearingHouseUserStatsConfig.js +2 -0
- package/lib/config.d.ts +7 -9
- package/lib/config.js +21 -21
- package/lib/constants/numericConstants.d.ts +25 -12
- package/lib/constants/numericConstants.js +35 -21
- package/lib/constants/perpMarkets.d.ts +18 -0
- package/lib/constants/{markets.js → perpMarkets.js} +7 -7
- package/lib/constants/spotMarkets.d.ts +19 -0
- package/lib/constants/spotMarkets.js +53 -0
- package/lib/dlob/DLOB.d.ts +74 -0
- package/lib/dlob/DLOB.js +595 -0
- package/lib/dlob/DLOBNode.d.ts +54 -0
- package/lib/dlob/DLOBNode.js +85 -0
- package/lib/dlob/NodeList.d.ts +26 -0
- package/lib/dlob/NodeList.js +139 -0
- package/lib/events/eventList.js +3 -0
- package/lib/events/eventSubscriber.d.ts +4 -2
- package/lib/events/eventSubscriber.js +16 -9
- package/lib/events/fetchLogs.d.ts +10 -1
- package/lib/events/fetchLogs.js +27 -7
- package/lib/events/pollingLogProvider.d.ts +2 -1
- package/lib/events/pollingLogProvider.js +6 -2
- package/lib/events/sort.js +8 -11
- package/lib/events/types.d.ts +8 -2
- package/lib/events/types.js +6 -0
- package/lib/examples/makeTradeExample.js +20 -8
- package/lib/factory/bigNum.d.ts +2 -0
- package/lib/factory/bigNum.js +48 -10
- package/lib/idl/clearing_house.json +4889 -1529
- package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/lib/index.d.ts +21 -6
- package/lib/index.js +25 -6
- package/lib/math/amm.d.ts +9 -6
- package/lib/math/amm.js +91 -66
- package/lib/math/auction.js +4 -1
- package/lib/math/conversion.js +1 -1
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +11 -10
- package/lib/math/insurance.d.ts +4 -0
- package/lib/math/insurance.js +27 -0
- package/lib/math/margin.d.ts +11 -0
- package/lib/math/margin.js +77 -0
- package/lib/math/market.d.ts +14 -9
- package/lib/math/market.js +72 -10
- package/lib/math/oracles.d.ts +4 -0
- package/lib/math/oracles.js +36 -8
- package/lib/math/orders.d.ts +6 -2
- package/lib/math/orders.js +78 -3
- package/lib/math/position.d.ts +21 -13
- package/lib/math/position.js +76 -36
- package/lib/math/repeg.js +14 -5
- package/lib/math/spotBalance.d.ts +22 -0
- package/lib/math/spotBalance.js +192 -0
- package/lib/math/spotMarket.d.ts +4 -0
- package/lib/math/spotMarket.js +8 -0
- package/lib/math/spotPosition.d.ts +6 -0
- package/lib/math/spotPosition.js +23 -0
- package/lib/math/trade.d.ts +10 -10
- package/lib/math/trade.js +32 -39
- package/lib/oracles/pythClient.js +1 -1
- package/lib/oracles/quoteAssetOracleClient.js +1 -1
- package/lib/oracles/switchboardClient.js +1 -1
- package/lib/orderParams.d.ts +14 -5
- package/lib/orderParams.js +12 -92
- package/lib/serum/serumSubscriber.d.ts +23 -0
- package/lib/serum/serumSubscriber.js +41 -0
- package/lib/serum/types.d.ts +11 -0
- package/lib/serum/types.js +2 -0
- package/lib/slot/SlotSubscriber.d.ts +7 -0
- package/lib/slot/SlotSubscriber.js +3 -0
- package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
- package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
- package/lib/tx/retryTxSender.d.ts +1 -1
- package/lib/tx/retryTxSender.js +13 -4
- package/lib/tx/types.d.ts +1 -1
- package/lib/tx/utils.js +1 -1
- package/lib/types.d.ts +566 -138
- package/lib/types.js +129 -5
- package/lib/userMap/userMap.d.ts +25 -0
- package/lib/userMap/userMap.js +73 -0
- package/lib/userMap/userStatsMap.d.ts +19 -0
- package/lib/userMap/userStatsMap.js +68 -0
- package/lib/util/computeUnits.js +1 -1
- package/lib/util/getTokenAddress.d.ts +2 -0
- package/lib/util/getTokenAddress.js +9 -0
- package/package.json +12 -6
- package/src/accounts/bulkUserStatsSubscription.ts +33 -0
- package/src/accounts/bulkUserSubscription.ts +0 -1
- package/src/accounts/fetch.ts +27 -2
- package/src/accounts/pollingClearingHouseAccountSubscriber.ts +46 -42
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
- package/src/accounts/types.ts +31 -11
- package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +64 -59
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
- package/src/addresses/marketAddresses.ts +1 -2
- package/src/addresses/pda.ts +88 -14
- package/src/admin.ts +452 -147
- package/src/assert/assert.js +9 -0
- package/src/clearingHouse.ts +2066 -467
- package/src/clearingHouseConfig.ts +4 -3
- package/src/clearingHouseUser.ts +747 -294
- package/src/clearingHouseUserStats.ts +75 -0
- package/src/clearingHouseUserStatsConfig.ts +18 -0
- package/src/config.ts +30 -31
- package/src/constants/numericConstants.ts +48 -25
- package/src/constants/{markets.ts → perpMarkets.ts} +10 -10
- package/src/constants/spotMarkets.ts +73 -0
- package/src/dlob/DLOB.ts +953 -0
- package/src/dlob/DLOBNode.ts +167 -0
- package/src/dlob/NodeList.ts +189 -0
- package/src/events/eventList.js +77 -0
- package/src/events/eventList.ts +3 -0
- package/src/events/eventSubscriber.ts +20 -12
- package/src/events/fetchLogs.ts +35 -8
- package/src/events/pollingLogProvider.ts +10 -2
- package/src/events/sort.ts +11 -15
- package/src/events/types.ts +19 -1
- package/src/examples/makeTradeExample.js +157 -0
- package/src/examples/makeTradeExample.ts +32 -14
- package/src/factory/bigNum.ts +65 -13
- package/src/idl/clearing_house.json +4889 -1529
- package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/src/index.ts +21 -6
- package/src/math/amm.ts +171 -88
- package/src/math/auction.ts +5 -1
- package/src/math/conversion.ts +2 -2
- package/src/math/funding.ts +20 -18
- package/src/math/insurance.ts +35 -0
- package/src/math/margin.ts +127 -0
- package/src/math/market.ts +145 -14
- package/src/math/oracles.ts +63 -9
- package/src/math/orders.ts +138 -4
- package/src/math/position.ts +119 -58
- package/src/math/repeg.ts +16 -6
- package/src/math/spotBalance.ts +319 -0
- package/src/math/spotMarket.ts +9 -0
- package/src/math/spotPosition.ts +47 -0
- package/src/math/trade.ts +53 -59
- package/src/oracles/pythClient.ts +2 -2
- package/src/oracles/quoteAssetOracleClient.ts +2 -2
- package/src/oracles/switchboardClient.ts +2 -2
- package/src/orderParams.ts +24 -137
- package/src/serum/serumSubscriber.ts +80 -0
- package/src/serum/types.ts +13 -0
- package/src/slot/SlotSubscriber.ts +11 -1
- package/src/token/index.js +38 -0
- package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
- package/src/tx/retryTxSender.ts +16 -5
- package/src/tx/types.js +2 -0
- package/src/tx/types.ts +2 -1
- package/src/tx/utils.js +17 -0
- package/src/tx/utils.ts +1 -1
- package/src/types.ts +533 -140
- package/src/userMap/userMap.ts +100 -0
- package/src/userMap/userStatsMap.ts +110 -0
- package/src/util/computeUnits.js +21 -11
- package/src/util/computeUnits.ts +1 -1
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/getTokenAddress.ts +18 -0
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
- package/tests/bn/test.ts +24 -10
- package/tests/dlob/helpers.ts +397 -0
- package/tests/dlob/test.ts +3688 -0
- package/lib/constants/banks.d.ts +0 -16
- package/lib/constants/banks.js +0 -34
- package/lib/constants/markets.d.ts +0 -19
- package/lib/math/bankBalance.d.ts +0 -9
- package/lib/math/bankBalance.js +0 -75
- package/lib/math/state.d.ts +0 -8
- package/lib/math/state.js +0 -15
- package/lib/orders.d.ts +0 -8
- package/lib/orders.js +0 -134
- package/src/constants/banks.ts +0 -43
- package/src/math/bankBalance.ts +0 -112
- package/src/math/state.ts +0 -14
- package/src/math/utils.js +0 -27
- package/src/math/utils.js.map +0 -1
- package/src/orders.ts +0 -244
- package/src/util/computeUnits.js.map +0 -1
package/src/math/orders.ts
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import { ClearingHouseUser } from '../clearingHouseUser';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
isOneOfVariant,
|
|
4
|
+
isVariant,
|
|
5
|
+
PerpMarketAccount,
|
|
6
|
+
Order,
|
|
7
|
+
PositionDirection,
|
|
8
|
+
} from '../types';
|
|
3
9
|
import { ZERO, TWO } from '../constants/numericConstants';
|
|
4
10
|
import { BN } from '@project-serum/anchor';
|
|
5
11
|
import { OraclePriceData } from '../oracles/types';
|
|
6
|
-
import { getAuctionPrice } from './auction';
|
|
12
|
+
import { getAuctionPrice, isAuctionComplete } from './auction';
|
|
13
|
+
import { calculateAskPrice, calculateBidPrice } from './market';
|
|
14
|
+
import {
|
|
15
|
+
calculateMaxBaseAssetAmountFillable,
|
|
16
|
+
calculateMaxBaseAssetAmountToTrade,
|
|
17
|
+
} from './amm';
|
|
7
18
|
|
|
8
19
|
export function isOrderRiskIncreasing(
|
|
9
20
|
user: ClearingHouseUser,
|
|
@@ -121,16 +132,139 @@ export function standardizeBaseAssetAmount(
|
|
|
121
132
|
export function getLimitPrice(
|
|
122
133
|
order: Order,
|
|
123
134
|
oraclePriceData: OraclePriceData,
|
|
124
|
-
slot: number
|
|
135
|
+
slot: number,
|
|
136
|
+
perpMarket?: PerpMarketAccount
|
|
125
137
|
): BN {
|
|
126
138
|
let limitPrice;
|
|
127
139
|
if (!order.oraclePriceOffset.eq(ZERO)) {
|
|
128
140
|
limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
|
|
129
141
|
} else if (isOneOfVariant(order.orderType, ['market', 'triggerMarket'])) {
|
|
130
|
-
|
|
142
|
+
if (!isAuctionComplete(order, slot)) {
|
|
143
|
+
limitPrice = getAuctionPrice(order, slot);
|
|
144
|
+
} else if (!order.price.eq(ZERO)) {
|
|
145
|
+
limitPrice = order.price;
|
|
146
|
+
} else {
|
|
147
|
+
if (perpMarket) {
|
|
148
|
+
if (isVariant(order.direction, 'long')) {
|
|
149
|
+
const askPrice = calculateAskPrice(perpMarket, oraclePriceData);
|
|
150
|
+
const delta = askPrice.div(new BN(perpMarket.amm.maxSlippageRatio));
|
|
151
|
+
limitPrice = askPrice.add(delta);
|
|
152
|
+
} else {
|
|
153
|
+
const bidPrice = calculateBidPrice(perpMarket, oraclePriceData);
|
|
154
|
+
const delta = bidPrice.div(new BN(perpMarket.amm.maxSlippageRatio));
|
|
155
|
+
limitPrice = bidPrice.sub(delta);
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
// check oracle validity?
|
|
159
|
+
const oraclePrice1Pct = oraclePriceData.price.div(new BN(100));
|
|
160
|
+
if (isVariant(order.direction, 'long')) {
|
|
161
|
+
limitPrice = oraclePriceData.price.add(oraclePrice1Pct);
|
|
162
|
+
} else {
|
|
163
|
+
limitPrice = oraclePriceData.price.sub(oraclePrice1Pct);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
131
167
|
} else {
|
|
132
168
|
limitPrice = order.price;
|
|
133
169
|
}
|
|
134
170
|
|
|
135
171
|
return limitPrice;
|
|
136
172
|
}
|
|
173
|
+
|
|
174
|
+
export function isFillableByVAMM(
|
|
175
|
+
order: Order,
|
|
176
|
+
market: PerpMarketAccount,
|
|
177
|
+
oraclePriceData: OraclePriceData,
|
|
178
|
+
slot: number
|
|
179
|
+
): boolean {
|
|
180
|
+
return (
|
|
181
|
+
(isAuctionComplete(order, slot) &&
|
|
182
|
+
!calculateBaseAssetAmountForAmmToFulfill(
|
|
183
|
+
order,
|
|
184
|
+
market,
|
|
185
|
+
oraclePriceData,
|
|
186
|
+
slot
|
|
187
|
+
).eq(ZERO)) ||
|
|
188
|
+
isOrderExpired(order, slot)
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export function calculateBaseAssetAmountForAmmToFulfill(
|
|
193
|
+
order: Order,
|
|
194
|
+
market: PerpMarketAccount,
|
|
195
|
+
oraclePriceData: OraclePriceData,
|
|
196
|
+
slot: number
|
|
197
|
+
): BN {
|
|
198
|
+
if (
|
|
199
|
+
isOneOfVariant(order.orderType, ['triggerMarket', 'triggerLimit']) &&
|
|
200
|
+
order.triggered === false
|
|
201
|
+
) {
|
|
202
|
+
return ZERO;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const limitPrice = getLimitPrice(order, oraclePriceData, slot, market);
|
|
206
|
+
const baseAssetAmount = calculateBaseAssetAmountToFillUpToLimitPrice(
|
|
207
|
+
order,
|
|
208
|
+
market,
|
|
209
|
+
limitPrice,
|
|
210
|
+
oraclePriceData
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
const maxBaseAssetAmount = calculateMaxBaseAssetAmountFillable(
|
|
214
|
+
market.amm,
|
|
215
|
+
order.direction
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
return BN.min(maxBaseAssetAmount, baseAssetAmount);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export function calculateBaseAssetAmountToFillUpToLimitPrice(
|
|
222
|
+
order: Order,
|
|
223
|
+
market: PerpMarketAccount,
|
|
224
|
+
limitPrice: BN,
|
|
225
|
+
oraclePriceData: OraclePriceData
|
|
226
|
+
): BN {
|
|
227
|
+
const [maxAmountToTrade, direction] = calculateMaxBaseAssetAmountToTrade(
|
|
228
|
+
market.amm,
|
|
229
|
+
limitPrice,
|
|
230
|
+
order.direction,
|
|
231
|
+
oraclePriceData
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
const baseAssetAmount = standardizeBaseAssetAmount(
|
|
235
|
+
maxAmountToTrade,
|
|
236
|
+
market.amm.baseAssetAmountStepSize
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
// Check that directions are the same
|
|
240
|
+
const sameDirection = isSameDirection(direction, order.direction);
|
|
241
|
+
if (!sameDirection) {
|
|
242
|
+
return ZERO;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return baseAssetAmount.gt(order.baseAssetAmount)
|
|
246
|
+
? order.baseAssetAmount
|
|
247
|
+
: baseAssetAmount;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function isSameDirection(
|
|
251
|
+
firstDirection: PositionDirection,
|
|
252
|
+
secondDirection: PositionDirection
|
|
253
|
+
): boolean {
|
|
254
|
+
return (
|
|
255
|
+
(isVariant(firstDirection, 'long') && isVariant(secondDirection, 'long')) ||
|
|
256
|
+
(isVariant(firstDirection, 'short') && isVariant(secondDirection, 'short'))
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export function isOrderExpired(order: Order, slot: number): boolean {
|
|
261
|
+
if (
|
|
262
|
+
isOneOfVariant(order.orderType, ['triggerMarket', 'triggerLimit']) ||
|
|
263
|
+
!isVariant(order.status, 'open') ||
|
|
264
|
+
order.timeInForce === 0
|
|
265
|
+
) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return new BN(slot).sub(order.slot).gt(new BN(order.timeInForce));
|
|
270
|
+
}
|
package/src/math/position.ts
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
import { BN } from '../';
|
|
1
|
+
import { BN, SpotMarketAccount } from '../';
|
|
2
2
|
import {
|
|
3
3
|
AMM_RESERVE_PRECISION,
|
|
4
4
|
AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO,
|
|
5
5
|
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
FUNDING_RATE_BUFFER_PRECISION,
|
|
7
|
+
PRICE_PRECISION,
|
|
8
8
|
ONE,
|
|
9
|
-
PRICE_TO_QUOTE_PRECISION,
|
|
10
9
|
ZERO,
|
|
11
10
|
} from '../constants/numericConstants';
|
|
12
11
|
import { OraclePriceData } from '../oracles/types';
|
|
13
|
-
import {
|
|
12
|
+
import { PerpMarketAccount, PositionDirection, PerpPosition } from '../types';
|
|
14
13
|
import {
|
|
15
14
|
calculateUpdatedAMM,
|
|
16
15
|
calculateUpdatedAMMSpreadReserves,
|
|
17
16
|
calculateAmmReservesAfterSwap,
|
|
18
17
|
getSwapDirection,
|
|
19
18
|
} from './amm';
|
|
19
|
+
import { calculateBaseAssetValueWithOracle } from './margin';
|
|
20
|
+
import { calculateNetUserPnlImbalance } from './market';
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* calculateBaseAssetValue
|
|
@@ -27,9 +28,11 @@ import {
|
|
|
27
28
|
* @returns Base Asset Value. : Precision QUOTE_PRECISION
|
|
28
29
|
*/
|
|
29
30
|
export function calculateBaseAssetValue(
|
|
30
|
-
market:
|
|
31
|
-
userPosition:
|
|
32
|
-
oraclePriceData: OraclePriceData
|
|
31
|
+
market: PerpMarketAccount,
|
|
32
|
+
userPosition: PerpPosition,
|
|
33
|
+
oraclePriceData: OraclePriceData,
|
|
34
|
+
useSpread = true,
|
|
35
|
+
skipUpdate = false
|
|
33
36
|
): BN {
|
|
34
37
|
if (userPosition.baseAssetAmount.eq(ZERO)) {
|
|
35
38
|
return ZERO;
|
|
@@ -38,21 +41,25 @@ export function calculateBaseAssetValue(
|
|
|
38
41
|
const directionToClose = findDirectionToClose(userPosition);
|
|
39
42
|
let prepegAmm: Parameters<typeof calculateAmmReservesAfterSwap>[0];
|
|
40
43
|
|
|
41
|
-
if (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
44
|
+
if (!skipUpdate) {
|
|
45
|
+
if (market.amm.baseSpread > 0 && useSpread) {
|
|
46
|
+
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } =
|
|
47
|
+
calculateUpdatedAMMSpreadReserves(
|
|
48
|
+
market.amm,
|
|
49
|
+
directionToClose,
|
|
50
|
+
oraclePriceData
|
|
51
|
+
);
|
|
52
|
+
prepegAmm = {
|
|
53
|
+
baseAssetReserve,
|
|
54
|
+
quoteAssetReserve,
|
|
55
|
+
sqrtK: sqrtK,
|
|
56
|
+
pegMultiplier: newPeg,
|
|
57
|
+
};
|
|
58
|
+
} else {
|
|
59
|
+
prepegAmm = calculateUpdatedAMM(market.amm, oraclePriceData);
|
|
60
|
+
}
|
|
54
61
|
} else {
|
|
55
|
-
prepegAmm =
|
|
62
|
+
prepegAmm = market.amm;
|
|
56
63
|
}
|
|
57
64
|
|
|
58
65
|
const [newQuoteAssetReserve, _] = calculateAmmReservesAfterSwap(
|
|
@@ -82,38 +89,36 @@ export function calculateBaseAssetValue(
|
|
|
82
89
|
* calculatePositionPNL
|
|
83
90
|
* = BaseAssetAmount * (Avg Exit Price - Avg Entry Price)
|
|
84
91
|
* @param market
|
|
85
|
-
* @param
|
|
92
|
+
* @param PerpPosition
|
|
86
93
|
* @param withFunding (adds unrealized funding payment pnl to result)
|
|
94
|
+
* @param oraclePriceData
|
|
87
95
|
* @returns BaseAssetAmount : Precision QUOTE_PRECISION
|
|
88
96
|
*/
|
|
89
97
|
export function calculatePositionPNL(
|
|
90
|
-
market:
|
|
91
|
-
|
|
98
|
+
market: PerpMarketAccount,
|
|
99
|
+
perpPosition: PerpPosition,
|
|
92
100
|
withFunding = false,
|
|
93
101
|
oraclePriceData: OraclePriceData
|
|
94
102
|
): BN {
|
|
95
|
-
if (
|
|
96
|
-
return
|
|
103
|
+
if (perpPosition.baseAssetAmount.eq(ZERO)) {
|
|
104
|
+
return perpPosition.quoteAssetAmount;
|
|
97
105
|
}
|
|
98
106
|
|
|
99
|
-
const baseAssetValue =
|
|
107
|
+
const baseAssetValue = calculateBaseAssetValueWithOracle(
|
|
100
108
|
market,
|
|
101
|
-
|
|
109
|
+
perpPosition,
|
|
102
110
|
oraclePriceData
|
|
103
111
|
);
|
|
104
112
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
const baseAssetValueSign = perpPosition.baseAssetAmount.isNeg()
|
|
114
|
+
? new BN(-1)
|
|
115
|
+
: new BN(1);
|
|
116
|
+
let pnl = baseAssetValue
|
|
117
|
+
.mul(baseAssetValueSign)
|
|
118
|
+
.add(perpPosition.quoteAssetAmount);
|
|
111
119
|
|
|
112
120
|
if (withFunding) {
|
|
113
|
-
const fundingRatePnL = calculatePositionFundingPNL(
|
|
114
|
-
market,
|
|
115
|
-
marketPosition
|
|
116
|
-
).div(PRICE_TO_QUOTE_PRECISION);
|
|
121
|
+
const fundingRatePnL = calculatePositionFundingPNL(market, perpPosition);
|
|
117
122
|
|
|
118
123
|
pnl = pnl.add(fundingRatePnL);
|
|
119
124
|
}
|
|
@@ -121,60 +126,118 @@ export function calculatePositionPNL(
|
|
|
121
126
|
return pnl;
|
|
122
127
|
}
|
|
123
128
|
|
|
129
|
+
export function calculateClaimablePnl(
|
|
130
|
+
market: PerpMarketAccount,
|
|
131
|
+
spotMarket: SpotMarketAccount,
|
|
132
|
+
perpPosition: PerpPosition,
|
|
133
|
+
oraclePriceData: OraclePriceData
|
|
134
|
+
): BN {
|
|
135
|
+
const unrealizedPnl = calculatePositionPNL(
|
|
136
|
+
market,
|
|
137
|
+
perpPosition,
|
|
138
|
+
true,
|
|
139
|
+
oraclePriceData
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
const fundingPnL = calculatePositionFundingPNL(market, perpPosition);
|
|
143
|
+
|
|
144
|
+
let unsettledPnl = unrealizedPnl.add(fundingPnL);
|
|
145
|
+
if (unrealizedPnl.gt(ZERO)) {
|
|
146
|
+
const excessPnlPool = BN.max(
|
|
147
|
+
ZERO,
|
|
148
|
+
calculateNetUserPnlImbalance(market, spotMarket, oraclePriceData).mul(
|
|
149
|
+
new BN(-1)
|
|
150
|
+
)
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
const maxPositivePnl = BN.max(
|
|
154
|
+
perpPosition.quoteAssetAmount
|
|
155
|
+
.sub(perpPosition.quoteEntryAmount)
|
|
156
|
+
.add(excessPnlPool),
|
|
157
|
+
ZERO
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
unsettledPnl = BN.min(maxPositivePnl, unrealizedPnl);
|
|
161
|
+
}
|
|
162
|
+
return unsettledPnl;
|
|
163
|
+
}
|
|
164
|
+
|
|
124
165
|
/**
|
|
125
166
|
*
|
|
126
167
|
* @param market
|
|
127
|
-
* @param
|
|
168
|
+
* @param PerpPosition
|
|
128
169
|
* @returns // TODO-PRECISION
|
|
129
170
|
*/
|
|
130
171
|
export function calculatePositionFundingPNL(
|
|
131
|
-
market:
|
|
132
|
-
|
|
172
|
+
market: PerpMarketAccount,
|
|
173
|
+
perpPosition: PerpPosition
|
|
133
174
|
): BN {
|
|
134
|
-
if (
|
|
175
|
+
if (perpPosition.baseAssetAmount.eq(ZERO)) {
|
|
135
176
|
return ZERO;
|
|
136
177
|
}
|
|
137
178
|
|
|
138
179
|
let ammCumulativeFundingRate: BN;
|
|
139
|
-
if (
|
|
180
|
+
if (perpPosition.baseAssetAmount.gt(ZERO)) {
|
|
140
181
|
ammCumulativeFundingRate = market.amm.cumulativeFundingRateLong;
|
|
141
182
|
} else {
|
|
142
183
|
ammCumulativeFundingRate = market.amm.cumulativeFundingRateShort;
|
|
143
184
|
}
|
|
144
185
|
|
|
145
186
|
const perPositionFundingRate = ammCumulativeFundingRate
|
|
146
|
-
.sub(
|
|
147
|
-
.mul(
|
|
187
|
+
.sub(perpPosition.lastCumulativeFundingRate)
|
|
188
|
+
.mul(perpPosition.baseAssetAmount)
|
|
148
189
|
.div(AMM_RESERVE_PRECISION)
|
|
149
|
-
.div(
|
|
190
|
+
.div(FUNDING_RATE_BUFFER_PRECISION)
|
|
150
191
|
.mul(new BN(-1));
|
|
151
192
|
|
|
152
193
|
return perPositionFundingRate;
|
|
153
194
|
}
|
|
154
195
|
|
|
155
|
-
export function positionIsAvailable(position:
|
|
156
|
-
return
|
|
196
|
+
export function positionIsAvailable(position: PerpPosition): boolean {
|
|
197
|
+
return (
|
|
198
|
+
position.baseAssetAmount.eq(ZERO) &&
|
|
199
|
+
position.openOrders === 0 &&
|
|
200
|
+
position.quoteAssetAmount.eq(ZERO) &&
|
|
201
|
+
position.lpShares.eq(ZERO)
|
|
202
|
+
);
|
|
157
203
|
}
|
|
158
204
|
|
|
159
205
|
/**
|
|
160
206
|
*
|
|
161
207
|
* @param userPosition
|
|
162
|
-
* @returns Precision:
|
|
208
|
+
* @returns Precision: PRICE_PRECISION (10^10)
|
|
163
209
|
*/
|
|
164
|
-
export function calculateEntryPrice(userPosition:
|
|
210
|
+
export function calculateEntryPrice(userPosition: PerpPosition): BN {
|
|
211
|
+
if (userPosition.baseAssetAmount.eq(ZERO)) {
|
|
212
|
+
return ZERO;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return userPosition.quoteEntryAmount
|
|
216
|
+
.mul(PRICE_PRECISION)
|
|
217
|
+
.mul(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
218
|
+
.div(userPosition.baseAssetAmount)
|
|
219
|
+
.abs();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
*
|
|
224
|
+
* @param userPosition
|
|
225
|
+
* @returns Precision: PRICE_PRECISION (10^10)
|
|
226
|
+
*/
|
|
227
|
+
export function calculateCostBasis(userPosition: PerpPosition): BN {
|
|
165
228
|
if (userPosition.baseAssetAmount.eq(ZERO)) {
|
|
166
229
|
return ZERO;
|
|
167
230
|
}
|
|
168
231
|
|
|
169
232
|
return userPosition.quoteAssetAmount
|
|
170
|
-
.mul(
|
|
233
|
+
.mul(PRICE_PRECISION)
|
|
171
234
|
.mul(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
172
235
|
.div(userPosition.baseAssetAmount)
|
|
173
236
|
.abs();
|
|
174
237
|
}
|
|
175
238
|
|
|
176
239
|
export function findDirectionToClose(
|
|
177
|
-
userPosition:
|
|
240
|
+
userPosition: PerpPosition
|
|
178
241
|
): PositionDirection {
|
|
179
242
|
return userPosition.baseAssetAmount.gt(ZERO)
|
|
180
243
|
? PositionDirection.SHORT
|
|
@@ -182,15 +245,13 @@ export function findDirectionToClose(
|
|
|
182
245
|
}
|
|
183
246
|
|
|
184
247
|
export function positionCurrentDirection(
|
|
185
|
-
userPosition:
|
|
248
|
+
userPosition: PerpPosition
|
|
186
249
|
): PositionDirection {
|
|
187
250
|
return userPosition.baseAssetAmount.gte(ZERO)
|
|
188
251
|
? PositionDirection.LONG
|
|
189
252
|
: PositionDirection.SHORT;
|
|
190
253
|
}
|
|
191
254
|
|
|
192
|
-
export function isEmptyPosition(userPosition:
|
|
193
|
-
return (
|
|
194
|
-
userPosition.baseAssetAmount.eq(ZERO) && userPosition.openOrders.eq(ZERO)
|
|
195
|
-
);
|
|
255
|
+
export function isEmptyPosition(userPosition: PerpPosition): boolean {
|
|
256
|
+
return userPosition.baseAssetAmount.eq(ZERO) && userPosition.openOrders === 0;
|
|
196
257
|
}
|
package/src/math/repeg.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BN } from '@project-serum/anchor';
|
|
2
2
|
import { assert } from '../assert/assert';
|
|
3
3
|
import {
|
|
4
|
-
|
|
4
|
+
PRICE_PRECISION,
|
|
5
5
|
AMM_RESERVE_PRECISION,
|
|
6
6
|
PEG_PRECISION,
|
|
7
7
|
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
@@ -31,15 +31,15 @@ export function calculateAdjustKCost(
|
|
|
31
31
|
|
|
32
32
|
const quoteScale = y.mul(d).mul(Q); //.div(AMM_RESERVE_PRECISION);
|
|
33
33
|
|
|
34
|
-
const p = numerator.mul(
|
|
34
|
+
const p = numerator.mul(PRICE_PRECISION).div(denomenator);
|
|
35
35
|
|
|
36
36
|
const cost = quoteScale
|
|
37
37
|
.div(x.add(d))
|
|
38
38
|
.sub(
|
|
39
39
|
quoteScale
|
|
40
40
|
.mul(p)
|
|
41
|
-
.div(
|
|
42
|
-
.div(x.mul(p).div(
|
|
41
|
+
.div(PRICE_PRECISION)
|
|
42
|
+
.div(x.mul(p).div(PRICE_PRECISION).add(d))
|
|
43
43
|
)
|
|
44
44
|
.div(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
45
45
|
.div(PEG_PRECISION);
|
|
@@ -98,6 +98,16 @@ export function calculateBudgetedKBN(
|
|
|
98
98
|
.div(QUOTE_PRECISION);
|
|
99
99
|
const denom2 = pegged_y_d_d;
|
|
100
100
|
|
|
101
|
+
// protocol is spending to increase k
|
|
102
|
+
if (C.lt(ZERO)) {
|
|
103
|
+
// thus denom1 is negative and solution is unstable
|
|
104
|
+
if (denom1.abs().gt(denom2.abs())) {
|
|
105
|
+
console.log('denom1 > denom2', denom1.toString(), denom2.toString());
|
|
106
|
+
console.log('budget cost exceeds stable K solution');
|
|
107
|
+
return [new BN(10000), new BN(1)];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
101
111
|
const numerator = numer1.sub(numer2).div(AMM_TO_QUOTE_PRECISION_RATIO);
|
|
102
112
|
const denominator = denom1.add(denom2).div(AMM_TO_QUOTE_PRECISION_RATIO);
|
|
103
113
|
|
|
@@ -165,11 +175,11 @@ export function calculateBudgetedPeg(amm: AMM, cost: BN, targetPrice: BN): BN {
|
|
|
165
175
|
return targetPeg;
|
|
166
176
|
}
|
|
167
177
|
|
|
168
|
-
const deltaPegMultiplier = C.mul(
|
|
178
|
+
const deltaPegMultiplier = C.mul(PRICE_PRECISION).div(
|
|
169
179
|
deltaQuoteAssetReserves.div(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
170
180
|
);
|
|
171
181
|
const newPeg = Q.sub(
|
|
172
|
-
deltaPegMultiplier.mul(PEG_PRECISION).div(
|
|
182
|
+
deltaPegMultiplier.mul(PEG_PRECISION).div(PRICE_PRECISION)
|
|
173
183
|
);
|
|
174
184
|
|
|
175
185
|
return newPeg;
|