@drift-labs/sdk 0.2.0-master.27 → 0.2.0-master.28
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/types.d.ts +1 -0
- package/lib/clearingHouse.d.ts +1 -0
- package/lib/clearingHouse.js +5 -0
- package/lib/clearingHouseUser.js +2 -2
- package/lib/idl/clearing_house.json +1 -1
- package/lib/math/market.d.ts +2 -1
- package/lib/math/market.js +16 -11
- package/lib/math/position.d.ts +3 -3
- package/lib/math/position.js +23 -16
- package/lib/math/repeg.js +8 -0
- package/lib/types.d.ts +1 -1
- package/package.json +1 -1
- package/src/clearingHouse.ts +7 -0
- package/src/clearingHouseUser.ts +2 -2
- package/src/idl/clearing_house.json +1 -1
- package/src/math/market.ts +21 -12
- package/src/math/position.ts +36 -22
- package/src/math/repeg.ts +9 -0
- package/src/types.ts +1 -1
- package/tests/dlob/helpers.ts +1 -1
- package/src/addresses/marketAddresses.js +0 -26
- package/src/assert/assert.js +0 -9
- package/src/constants/banks.js +0 -42
- package/src/constants/markets.js +0 -42
- package/src/events/eventList.js +0 -77
- package/src/events/txEventCache.js +0 -71
- package/src/examples/makeTradeExample.js +0 -157
- package/src/factory/bigNum.js +0 -390
- package/src/factory/oracleClient.js +0 -20
- package/src/math/auction.js +0 -42
- package/src/math/conversion.js +0 -11
- package/src/math/funding.js +0 -248
- package/src/math/repeg.js +0 -128
- package/src/math/trade.js +0 -253
- package/src/math/utils.js +0 -26
- package/src/math/utils.js.map +0 -1
- package/src/oracles/oracleClientCache.js +0 -19
- package/src/oracles/pythClient.js +0 -46
- package/src/oracles/quoteAssetOracleClient.js +0 -32
- package/src/oracles/switchboardClient.js +0 -69
- package/src/oracles/types.js +0 -2
- package/src/token/index.js +0 -38
- package/src/tx/types.js +0 -2
- package/src/tx/utils.js +0 -17
- package/src/userName.js +0 -20
- package/src/util/computeUnits.js +0 -27
- package/src/util/getTokenAddress.js +0 -9
- package/src/util/promiseTimeout.js +0 -14
- package/src/util/tps.js +0 -27
- package/src/wallet.js +0 -35
package/lib/accounts/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
/// <reference types="bn.js" />
|
|
3
|
+
/// <reference types="node" />
|
|
3
4
|
import { SpotMarketAccount, PerpMarketAccount, OracleSource, StateAccount, UserAccount, UserStatsAccount } from '../types';
|
|
4
5
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
5
6
|
import { EventEmitter } from 'events';
|
package/lib/clearingHouse.d.ts
CHANGED
|
@@ -193,6 +193,7 @@ export declare class ClearingHouse {
|
|
|
193
193
|
getSettleFundingPaymentIx(userAccount: PublicKey): Promise<TransactionInstruction>;
|
|
194
194
|
triggerEvent(eventName: keyof ClearingHouseAccountEvents, data?: any): void;
|
|
195
195
|
getOracleDataForMarket(marketIndex: BN): OraclePriceData;
|
|
196
|
+
getOracleDataForSpotMarket(marketIndex: BN): OraclePriceData;
|
|
196
197
|
initializeInsuranceFundStake(marketIndex: BN): Promise<TransactionSignature>;
|
|
197
198
|
getInitializeInsuranceFundStakeIx(marketIndex: BN): Promise<TransactionInstruction>;
|
|
198
199
|
addInsuranceFundStake(marketIndex: BN, amount: BN, collateralAccountPublicKey: PublicKey): Promise<TransactionSignature>;
|
package/lib/clearingHouse.js
CHANGED
|
@@ -2002,6 +2002,11 @@ class ClearingHouse {
|
|
|
2002
2002
|
const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
|
|
2003
2003
|
return oracleData;
|
|
2004
2004
|
}
|
|
2005
|
+
getOracleDataForSpotMarket(marketIndex) {
|
|
2006
|
+
const oracleKey = this.getSpotMarketAccount(marketIndex).oracle;
|
|
2007
|
+
const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
|
|
2008
|
+
return oracleData;
|
|
2009
|
+
}
|
|
2005
2010
|
async initializeInsuranceFundStake(marketIndex) {
|
|
2006
2011
|
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getInitializeInsuranceFundStakeIx(marketIndex)), [], this.opts);
|
|
2007
2012
|
return txSig;
|
package/lib/clearingHouseUser.js
CHANGED
|
@@ -73,7 +73,7 @@ class ClearingHouseUser {
|
|
|
73
73
|
openOrders: numericConstants_1.ZERO,
|
|
74
74
|
openBids: numericConstants_1.ZERO,
|
|
75
75
|
openAsks: numericConstants_1.ZERO,
|
|
76
|
-
|
|
76
|
+
settledPnl: numericConstants_1.ZERO,
|
|
77
77
|
lpShares: numericConstants_1.ZERO,
|
|
78
78
|
lastFeePerLp: numericConstants_1.ZERO,
|
|
79
79
|
lastNetBaseAssetAmountPerLp: numericConstants_1.ZERO,
|
|
@@ -622,7 +622,7 @@ class ClearingHouseUser {
|
|
|
622
622
|
openOrders: new _1.BN(0),
|
|
623
623
|
openBids: new _1.BN(0),
|
|
624
624
|
openAsks: new _1.BN(0),
|
|
625
|
-
|
|
625
|
+
settledPnl: numericConstants_1.ZERO,
|
|
626
626
|
lpShares: numericConstants_1.ZERO,
|
|
627
627
|
lastFeePerLp: numericConstants_1.ZERO,
|
|
628
628
|
lastNetBaseAssetAmountPerLp: numericConstants_1.ZERO,
|
package/lib/math/market.d.ts
CHANGED
|
@@ -29,4 +29,5 @@ export declare function calculateOracleSpread(price: BN, oraclePriceData: Oracle
|
|
|
29
29
|
export declare function calculateMarketMarginRatio(market: PerpMarketAccount, size: BN, marginCategory: MarginCategory): number;
|
|
30
30
|
export declare function calculateUnrealizedAssetWeight(market: PerpMarketAccount, quoteSpotMarket: SpotMarketAccount, unrealizedPnl: BN, marginCategory: MarginCategory, oraclePriceData: OraclePriceData): BN;
|
|
31
31
|
export declare function calculateMarketAvailablePNL(perpMarket: PerpMarketAccount, spotMarket: SpotMarketAccount): BN;
|
|
32
|
-
export declare function
|
|
32
|
+
export declare function calculateNetUserPnl(perpMarket: PerpMarketAccount, oraclePriceData: OraclePriceData): BN;
|
|
33
|
+
export declare function calculateNetUserPnlImbalance(perpMarket: PerpMarketAccount, spotMarket: SpotMarketAccount, oraclePriceData: OraclePriceData): BN;
|
package/lib/math/market.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.calculateNetUserPnlImbalance = exports.calculateNetUserPnl = exports.calculateMarketAvailablePNL = exports.calculateUnrealizedAssetWeight = exports.calculateMarketMarginRatio = exports.calculateOracleSpread = exports.calculateMarkOracleSpread = exports.calculateNewMarketAfterTrade = exports.calculateAskPrice = exports.calculateBidPrice = exports.calculateMarkPrice = void 0;
|
|
4
4
|
const anchor_1 = require("@project-serum/anchor");
|
|
5
5
|
const types_1 = require("../types");
|
|
6
6
|
const amm_1 = require("./amm");
|
|
@@ -78,7 +78,7 @@ function calculateUnrealizedAssetWeight(market, quoteSpotMarket, unrealizedPnl,
|
|
|
78
78
|
case 'Initial':
|
|
79
79
|
assetWeight = new anchor_1.BN(market.unrealizedInitialAssetWeight);
|
|
80
80
|
if (market.unrealizedMaxImbalance.gt(numericConstants_1.ZERO)) {
|
|
81
|
-
const netUnsettledPnl =
|
|
81
|
+
const netUnsettledPnl = calculateNetUserPnlImbalance(market, quoteSpotMarket, oraclePriceData);
|
|
82
82
|
if (netUnsettledPnl.gt(market.unrealizedMaxImbalance)) {
|
|
83
83
|
assetWeight = assetWeight
|
|
84
84
|
.mul(market.unrealizedMaxImbalance)
|
|
@@ -98,17 +98,22 @@ function calculateMarketAvailablePNL(perpMarket, spotMarket) {
|
|
|
98
98
|
return (0, spotBalance_1.getTokenAmount)(perpMarket.pnlPool.balance, spotMarket, types_1.SpotBalanceType.DEPOSIT);
|
|
99
99
|
}
|
|
100
100
|
exports.calculateMarketAvailablePNL = calculateMarketAvailablePNL;
|
|
101
|
-
function
|
|
102
|
-
const netUserPositionValue =
|
|
101
|
+
function calculateNetUserPnl(perpMarket, oraclePriceData) {
|
|
102
|
+
const netUserPositionValue = perpMarket.amm.netBaseAssetAmount
|
|
103
103
|
.mul(oraclePriceData.price)
|
|
104
104
|
.div(numericConstants_1.BASE_PRECISION)
|
|
105
105
|
.div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
|
|
106
|
-
const netUserCostBasis =
|
|
107
|
-
.add(
|
|
108
|
-
.sub(
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
106
|
+
const netUserCostBasis = perpMarket.amm.quoteAssetAmountLong
|
|
107
|
+
.add(perpMarket.amm.quoteAssetAmountShort)
|
|
108
|
+
.sub(perpMarket.amm.cumulativeSocialLoss);
|
|
109
|
+
const netUserPnl = netUserPositionValue.add(netUserCostBasis);
|
|
110
|
+
return netUserPnl;
|
|
111
|
+
}
|
|
112
|
+
exports.calculateNetUserPnl = calculateNetUserPnl;
|
|
113
|
+
function calculateNetUserPnlImbalance(perpMarket, spotMarket, oraclePriceData) {
|
|
114
|
+
const netUserPnl = calculateNetUserPnl(perpMarket, oraclePriceData);
|
|
115
|
+
const pnlPool = (0, spotBalance_1.getTokenAmount)(perpMarket.pnlPool.balance, spotMarket, types_1.SpotBalanceType.DEPOSIT);
|
|
116
|
+
const imbalance = netUserPnl.sub(pnlPool);
|
|
112
117
|
return imbalance;
|
|
113
118
|
}
|
|
114
|
-
exports.
|
|
119
|
+
exports.calculateNetUserPnlImbalance = calculateNetUserPnlImbalance;
|
package/lib/math/position.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
|
-
import { BN } from '../';
|
|
2
|
+
import { BN, SpotMarketAccount } from '../';
|
|
3
3
|
import { OraclePriceData } from '../oracles/types';
|
|
4
4
|
import { PerpMarketAccount, PositionDirection, PerpPosition } from '../types';
|
|
5
5
|
/**
|
|
@@ -10,7 +10,7 @@ import { PerpMarketAccount, PositionDirection, PerpPosition } from '../types';
|
|
|
10
10
|
* @param oraclePriceData
|
|
11
11
|
* @returns Base Asset Value. : Precision QUOTE_PRECISION
|
|
12
12
|
*/
|
|
13
|
-
export declare function calculateBaseAssetValue(market: PerpMarketAccount, userPosition: PerpPosition, oraclePriceData: OraclePriceData): BN;
|
|
13
|
+
export declare function calculateBaseAssetValue(market: PerpMarketAccount, userPosition: PerpPosition, oraclePriceData: OraclePriceData, useSpread?: boolean, skipUpdate?: boolean): BN;
|
|
14
14
|
/**
|
|
15
15
|
* calculatePositionPNL
|
|
16
16
|
* = BaseAssetAmount * (Avg Exit Price - Avg Entry Price)
|
|
@@ -21,7 +21,7 @@ export declare function calculateBaseAssetValue(market: PerpMarketAccount, userP
|
|
|
21
21
|
* @returns BaseAssetAmount : Precision QUOTE_PRECISION
|
|
22
22
|
*/
|
|
23
23
|
export declare function calculatePositionPNL(market: PerpMarketAccount, perpPosition: PerpPosition, withFunding: boolean, oraclePriceData: OraclePriceData): BN;
|
|
24
|
-
export declare function
|
|
24
|
+
export declare function calculateClaimablePnl(market: PerpMarketAccount, spotMarket: SpotMarketAccount, perpPosition: PerpPosition, oraclePriceData: OraclePriceData): BN;
|
|
25
25
|
/**
|
|
26
26
|
*
|
|
27
27
|
* @param market
|
package/lib/math/position.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateCostBasis = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.
|
|
3
|
+
exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateCostBasis = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculateClaimablePnl = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
|
|
4
4
|
const __1 = require("../");
|
|
5
5
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
6
6
|
const types_1 = require("../types");
|
|
7
7
|
const amm_1 = require("./amm");
|
|
8
8
|
const margin_1 = require("./margin");
|
|
9
|
+
const market_1 = require("./market");
|
|
9
10
|
/**
|
|
10
11
|
* calculateBaseAssetValue
|
|
11
12
|
* = market value of closing entire position
|
|
@@ -14,23 +15,28 @@ const margin_1 = require("./margin");
|
|
|
14
15
|
* @param oraclePriceData
|
|
15
16
|
* @returns Base Asset Value. : Precision QUOTE_PRECISION
|
|
16
17
|
*/
|
|
17
|
-
function calculateBaseAssetValue(market, userPosition, oraclePriceData) {
|
|
18
|
+
function calculateBaseAssetValue(market, userPosition, oraclePriceData, useSpread = true, skipUpdate = false) {
|
|
18
19
|
if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
19
20
|
return numericConstants_1.ZERO;
|
|
20
21
|
}
|
|
21
22
|
const directionToClose = findDirectionToClose(userPosition);
|
|
22
23
|
let prepegAmm;
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
if (!skipUpdate) {
|
|
25
|
+
if (market.amm.baseSpread > 0 && useSpread) {
|
|
26
|
+
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, directionToClose, oraclePriceData);
|
|
27
|
+
prepegAmm = {
|
|
28
|
+
baseAssetReserve,
|
|
29
|
+
quoteAssetReserve,
|
|
30
|
+
sqrtK: sqrtK,
|
|
31
|
+
pegMultiplier: newPeg,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
prepegAmm = (0, amm_1.calculateUpdatedAMM)(market.amm, oraclePriceData);
|
|
36
|
+
}
|
|
31
37
|
}
|
|
32
38
|
else {
|
|
33
|
-
prepegAmm =
|
|
39
|
+
prepegAmm = market.amm;
|
|
34
40
|
}
|
|
35
41
|
const [newQuoteAssetReserve, _] = (0, amm_1.calculateAmmReservesAfterSwap)(prepegAmm, 'base', userPosition.baseAssetAmount.abs(), (0, amm_1.getSwapDirection)('base', directionToClose));
|
|
36
42
|
switch (directionToClose) {
|
|
@@ -75,19 +81,20 @@ function calculatePositionPNL(market, perpPosition, withFunding = false, oracleP
|
|
|
75
81
|
return pnl;
|
|
76
82
|
}
|
|
77
83
|
exports.calculatePositionPNL = calculatePositionPNL;
|
|
78
|
-
function
|
|
84
|
+
function calculateClaimablePnl(market, spotMarket, perpPosition, oraclePriceData) {
|
|
79
85
|
const unrealizedPnl = calculatePositionPNL(market, perpPosition, true, oraclePriceData);
|
|
80
|
-
|
|
86
|
+
const fundingPnL = calculatePositionFundingPNL(market, perpPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
|
|
87
|
+
let unsettledPnl = unrealizedPnl.add(fundingPnL);
|
|
81
88
|
if (unrealizedPnl.gt(numericConstants_1.ZERO)) {
|
|
82
|
-
const
|
|
89
|
+
const excessPnlPool = __1.BN.max(numericConstants_1.ZERO, (0, market_1.calculateNetUserPnlImbalance)(market, spotMarket, oraclePriceData).mul(new __1.BN(-1)));
|
|
83
90
|
const maxPositivePnl = __1.BN.max(perpPosition.quoteAssetAmount
|
|
84
91
|
.sub(perpPosition.quoteEntryAmount)
|
|
85
|
-
.add(
|
|
92
|
+
.add(excessPnlPool), numericConstants_1.ZERO);
|
|
86
93
|
unsettledPnl = __1.BN.min(maxPositivePnl, unrealizedPnl);
|
|
87
94
|
}
|
|
88
95
|
return unsettledPnl;
|
|
89
96
|
}
|
|
90
|
-
exports.
|
|
97
|
+
exports.calculateClaimablePnl = calculateClaimablePnl;
|
|
91
98
|
/**
|
|
92
99
|
*
|
|
93
100
|
* @param market
|
package/lib/math/repeg.js
CHANGED
|
@@ -71,6 +71,14 @@ function calculateBudgetedKBN(x, y, budget, Q, d) {
|
|
|
71
71
|
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
72
72
|
.div(numericConstants_1.QUOTE_PRECISION);
|
|
73
73
|
const denom2 = pegged_y_d_d;
|
|
74
|
+
// protocol is spending to increase k
|
|
75
|
+
if (C.lt(numericConstants_1.ZERO)) {
|
|
76
|
+
// thus denom1 is negative and solution is unstable
|
|
77
|
+
if (denom1.lt(pegged_y_d_d.abs())) {
|
|
78
|
+
console.log('budget cost exceeds stable K solution');
|
|
79
|
+
return [new anchor_1.BN(10000), new anchor_1.BN(1)];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
74
82
|
const numerator = numer1.sub(numer2).div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO);
|
|
75
83
|
const denominator = denom1.add(denom2).div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO);
|
|
76
84
|
return [numerator, denominator];
|
package/lib/types.d.ts
CHANGED
package/package.json
CHANGED
package/src/clearingHouse.ts
CHANGED
|
@@ -3199,6 +3199,13 @@ export class ClearingHouse {
|
|
|
3199
3199
|
return oracleData;
|
|
3200
3200
|
}
|
|
3201
3201
|
|
|
3202
|
+
public getOracleDataForSpotMarket(marketIndex: BN): OraclePriceData {
|
|
3203
|
+
const oracleKey = this.getSpotMarketAccount(marketIndex).oracle;
|
|
3204
|
+
const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
|
|
3205
|
+
|
|
3206
|
+
return oracleData;
|
|
3207
|
+
}
|
|
3208
|
+
|
|
3202
3209
|
public async initializeInsuranceFundStake(
|
|
3203
3210
|
marketIndex: BN
|
|
3204
3211
|
): Promise<TransactionSignature> {
|
package/src/clearingHouseUser.ts
CHANGED
|
@@ -142,7 +142,7 @@ export class ClearingHouseUser {
|
|
|
142
142
|
openOrders: ZERO,
|
|
143
143
|
openBids: ZERO,
|
|
144
144
|
openAsks: ZERO,
|
|
145
|
-
|
|
145
|
+
settledPnl: ZERO,
|
|
146
146
|
lpShares: ZERO,
|
|
147
147
|
lastFeePerLp: ZERO,
|
|
148
148
|
lastNetBaseAssetAmountPerLp: ZERO,
|
|
@@ -1071,7 +1071,7 @@ export class ClearingHouseUser {
|
|
|
1071
1071
|
openOrders: new BN(0),
|
|
1072
1072
|
openBids: new BN(0),
|
|
1073
1073
|
openAsks: new BN(0),
|
|
1074
|
-
|
|
1074
|
+
settledPnl: ZERO,
|
|
1075
1075
|
lpShares: ZERO,
|
|
1076
1076
|
lastFeePerLp: ZERO,
|
|
1077
1077
|
lastNetBaseAssetAmountPerLp: ZERO,
|
package/src/math/market.ts
CHANGED
|
@@ -157,7 +157,7 @@ export function calculateUnrealizedAssetWeight(
|
|
|
157
157
|
assetWeight = new BN(market.unrealizedInitialAssetWeight);
|
|
158
158
|
|
|
159
159
|
if (market.unrealizedMaxImbalance.gt(ZERO)) {
|
|
160
|
-
const netUnsettledPnl =
|
|
160
|
+
const netUnsettledPnl = calculateNetUserPnlImbalance(
|
|
161
161
|
market,
|
|
162
162
|
quoteSpotMarket,
|
|
163
163
|
oraclePriceData
|
|
@@ -194,29 +194,38 @@ export function calculateMarketAvailablePNL(
|
|
|
194
194
|
);
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
export function
|
|
198
|
-
|
|
199
|
-
bank: SpotMarketAccount,
|
|
197
|
+
export function calculateNetUserPnl(
|
|
198
|
+
perpMarket: PerpMarketAccount,
|
|
200
199
|
oraclePriceData: OraclePriceData
|
|
201
200
|
): BN {
|
|
202
|
-
const netUserPositionValue =
|
|
201
|
+
const netUserPositionValue = perpMarket.amm.netBaseAssetAmount
|
|
203
202
|
.mul(oraclePriceData.price)
|
|
204
203
|
.div(BASE_PRECISION)
|
|
205
204
|
.div(PRICE_TO_QUOTE_PRECISION);
|
|
206
205
|
|
|
207
|
-
const netUserCostBasis =
|
|
208
|
-
.add(
|
|
209
|
-
.sub(
|
|
206
|
+
const netUserCostBasis = perpMarket.amm.quoteAssetAmountLong
|
|
207
|
+
.add(perpMarket.amm.quoteAssetAmountShort)
|
|
208
|
+
.sub(perpMarket.amm.cumulativeSocialLoss);
|
|
209
|
+
|
|
210
|
+
const netUserPnl = netUserPositionValue.add(netUserCostBasis);
|
|
211
|
+
|
|
212
|
+
return netUserPnl;
|
|
213
|
+
}
|
|
210
214
|
|
|
211
|
-
|
|
215
|
+
export function calculateNetUserPnlImbalance(
|
|
216
|
+
perpMarket: PerpMarketAccount,
|
|
217
|
+
spotMarket: SpotMarketAccount,
|
|
218
|
+
oraclePriceData: OraclePriceData
|
|
219
|
+
): BN {
|
|
220
|
+
const netUserPnl = calculateNetUserPnl(perpMarket, oraclePriceData);
|
|
212
221
|
|
|
213
222
|
const pnlPool = getTokenAmount(
|
|
214
|
-
|
|
215
|
-
|
|
223
|
+
perpMarket.pnlPool.balance,
|
|
224
|
+
spotMarket,
|
|
216
225
|
SpotBalanceType.DEPOSIT
|
|
217
226
|
);
|
|
218
227
|
|
|
219
|
-
const imbalance =
|
|
228
|
+
const imbalance = netUserPnl.sub(pnlPool);
|
|
220
229
|
|
|
221
230
|
return imbalance;
|
|
222
231
|
}
|
package/src/math/position.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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,
|
|
@@ -17,8 +17,8 @@ import {
|
|
|
17
17
|
calculateAmmReservesAfterSwap,
|
|
18
18
|
getSwapDirection,
|
|
19
19
|
} from './amm';
|
|
20
|
-
|
|
21
20
|
import { calculateBaseAssetValueWithOracle } from './margin';
|
|
21
|
+
import { calculateNetUserPnlImbalance } from './market';
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* calculateBaseAssetValue
|
|
@@ -31,7 +31,9 @@ import { calculateBaseAssetValueWithOracle } from './margin';
|
|
|
31
31
|
export function calculateBaseAssetValue(
|
|
32
32
|
market: PerpMarketAccount,
|
|
33
33
|
userPosition: PerpPosition,
|
|
34
|
-
oraclePriceData: OraclePriceData
|
|
34
|
+
oraclePriceData: OraclePriceData,
|
|
35
|
+
useSpread = true,
|
|
36
|
+
skipUpdate = false
|
|
35
37
|
): BN {
|
|
36
38
|
if (userPosition.baseAssetAmount.eq(ZERO)) {
|
|
37
39
|
return ZERO;
|
|
@@ -40,21 +42,25 @@ export function calculateBaseAssetValue(
|
|
|
40
42
|
const directionToClose = findDirectionToClose(userPosition);
|
|
41
43
|
let prepegAmm: Parameters<typeof calculateAmmReservesAfterSwap>[0];
|
|
42
44
|
|
|
43
|
-
if (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
if (!skipUpdate) {
|
|
46
|
+
if (market.amm.baseSpread > 0 && useSpread) {
|
|
47
|
+
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } =
|
|
48
|
+
calculateUpdatedAMMSpreadReserves(
|
|
49
|
+
market.amm,
|
|
50
|
+
directionToClose,
|
|
51
|
+
oraclePriceData
|
|
52
|
+
);
|
|
53
|
+
prepegAmm = {
|
|
54
|
+
baseAssetReserve,
|
|
55
|
+
quoteAssetReserve,
|
|
56
|
+
sqrtK: sqrtK,
|
|
57
|
+
pegMultiplier: newPeg,
|
|
58
|
+
};
|
|
59
|
+
} else {
|
|
60
|
+
prepegAmm = calculateUpdatedAMM(market.amm, oraclePriceData);
|
|
61
|
+
}
|
|
56
62
|
} else {
|
|
57
|
-
prepegAmm =
|
|
63
|
+
prepegAmm = market.amm;
|
|
58
64
|
}
|
|
59
65
|
|
|
60
66
|
const [newQuoteAssetReserve, _] = calculateAmmReservesAfterSwap(
|
|
@@ -124,8 +130,9 @@ export function calculatePositionPNL(
|
|
|
124
130
|
return pnl;
|
|
125
131
|
}
|
|
126
132
|
|
|
127
|
-
export function
|
|
133
|
+
export function calculateClaimablePnl(
|
|
128
134
|
market: PerpMarketAccount,
|
|
135
|
+
spotMarket: SpotMarketAccount,
|
|
129
136
|
perpPosition: PerpPosition,
|
|
130
137
|
oraclePriceData: OraclePriceData
|
|
131
138
|
): BN {
|
|
@@ -136,16 +143,23 @@ export function calculateUnsettledPnl(
|
|
|
136
143
|
oraclePriceData
|
|
137
144
|
);
|
|
138
145
|
|
|
139
|
-
|
|
146
|
+
const fundingPnL = calculatePositionFundingPNL(market, perpPosition).div(
|
|
147
|
+
PRICE_TO_QUOTE_PRECISION
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
let unsettledPnl = unrealizedPnl.add(fundingPnL);
|
|
140
151
|
if (unrealizedPnl.gt(ZERO)) {
|
|
141
|
-
const
|
|
142
|
-
|
|
152
|
+
const excessPnlPool = BN.max(
|
|
153
|
+
ZERO,
|
|
154
|
+
calculateNetUserPnlImbalance(market, spotMarket, oraclePriceData).mul(
|
|
155
|
+
new BN(-1)
|
|
156
|
+
)
|
|
143
157
|
);
|
|
144
158
|
|
|
145
159
|
const maxPositivePnl = BN.max(
|
|
146
160
|
perpPosition.quoteAssetAmount
|
|
147
161
|
.sub(perpPosition.quoteEntryAmount)
|
|
148
|
-
.add(
|
|
162
|
+
.add(excessPnlPool),
|
|
149
163
|
ZERO
|
|
150
164
|
);
|
|
151
165
|
|
package/src/math/repeg.ts
CHANGED
|
@@ -98,6 +98,15 @@ 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.lt(pegged_y_d_d.abs())) {
|
|
105
|
+
console.log('budget cost exceeds stable K solution');
|
|
106
|
+
return [new BN(10000), new BN(1)];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
101
110
|
const numerator = numer1.sub(numer2).div(AMM_TO_QUOTE_PRECISION_RATIO);
|
|
102
111
|
const denominator = denom1.add(denom2).div(AMM_TO_QUOTE_PRECISION_RATIO);
|
|
103
112
|
|
package/src/types.ts
CHANGED
package/tests/dlob/helpers.ts
CHANGED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.getMarketAddress = void 0;
|
|
13
|
-
const pda_1 = require("./pda");
|
|
14
|
-
const CACHE = new Map();
|
|
15
|
-
function getMarketAddress(programId, marketIndex) {
|
|
16
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
-
const cacheKey = `${programId.toString()}-${marketIndex.toString()}`;
|
|
18
|
-
if (CACHE.has(cacheKey)) {
|
|
19
|
-
return CACHE.get(cacheKey);
|
|
20
|
-
}
|
|
21
|
-
const publicKey = yield pda_1.getMarketPublicKey(programId, marketIndex);
|
|
22
|
-
CACHE.set(cacheKey, publicKey);
|
|
23
|
-
return publicKey;
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
exports.getMarketAddress = getMarketAddress;
|
package/src/assert/assert.js
DELETED
package/src/constants/banks.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Banks = exports.MainnetBanks = exports.DevnetBanks = exports.WRAPPED_SOL_MINT = void 0;
|
|
4
|
-
const web3_js_1 = require("@solana/web3.js");
|
|
5
|
-
const __1 = require("../");
|
|
6
|
-
exports.WRAPPED_SOL_MINT = new web3_js_1.PublicKey('So11111111111111111111111111111111111111112');
|
|
7
|
-
exports.DevnetBanks = [
|
|
8
|
-
{
|
|
9
|
-
symbol: 'USDC',
|
|
10
|
-
bankIndex: new __1.BN(0),
|
|
11
|
-
oracle: web3_js_1.PublicKey.default,
|
|
12
|
-
oracleSource: __1.OracleSource.QUOTE_ASSET,
|
|
13
|
-
mint: new web3_js_1.PublicKey('8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2'),
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
symbol: 'SOL',
|
|
17
|
-
bankIndex: new __1.BN(1),
|
|
18
|
-
oracle: new web3_js_1.PublicKey('J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix'),
|
|
19
|
-
oracleSource: __1.OracleSource.PYTH,
|
|
20
|
-
mint: new web3_js_1.PublicKey(exports.WRAPPED_SOL_MINT),
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
symbol: 'BTC',
|
|
24
|
-
bankIndex: new __1.BN(2),
|
|
25
|
-
oracle: new web3_js_1.PublicKey('HovQMDrbAgAYPCmHVSrezcSmkMtXSSUsLDFANExrZh2J'),
|
|
26
|
-
oracleSource: __1.OracleSource.PYTH,
|
|
27
|
-
mint: new web3_js_1.PublicKey('3BZPwbcqB5kKScF3TEXxwNfx5ipV13kbRVDvfVp5c6fv'),
|
|
28
|
-
},
|
|
29
|
-
];
|
|
30
|
-
exports.MainnetBanks = [
|
|
31
|
-
{
|
|
32
|
-
symbol: 'USDC',
|
|
33
|
-
bankIndex: new __1.BN(0),
|
|
34
|
-
oracle: web3_js_1.PublicKey.default,
|
|
35
|
-
oracleSource: __1.OracleSource.QUOTE_ASSET,
|
|
36
|
-
mint: new web3_js_1.PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'),
|
|
37
|
-
},
|
|
38
|
-
];
|
|
39
|
-
exports.Banks = {
|
|
40
|
-
devnet: exports.DevnetBanks,
|
|
41
|
-
'mainnet-beta': exports.MainnetBanks,
|
|
42
|
-
};
|
package/src/constants/markets.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Markets = exports.MainnetMarkets = exports.DevnetMarkets = void 0;
|
|
4
|
-
const __1 = require("../");
|
|
5
|
-
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
-
exports.DevnetMarkets = [
|
|
7
|
-
{
|
|
8
|
-
fullName: 'Solana',
|
|
9
|
-
category: ['L1', 'Infra'],
|
|
10
|
-
symbol: 'SOL-PERP',
|
|
11
|
-
baseAssetSymbol: 'SOL',
|
|
12
|
-
marketIndex: new __1.BN(0),
|
|
13
|
-
oracle: new web3_js_1.PublicKey('J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix'),
|
|
14
|
-
launchTs: 1655751353000,
|
|
15
|
-
oracleSource: __1.OracleSource.PYTH,
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
fullName: 'Bitcoin',
|
|
19
|
-
category: ['L1', 'Payment'],
|
|
20
|
-
symbol: 'BTC-PERP',
|
|
21
|
-
baseAssetSymbol: 'BTC',
|
|
22
|
-
marketIndex: new __1.BN(1),
|
|
23
|
-
oracle: new web3_js_1.PublicKey('HovQMDrbAgAYPCmHVSrezcSmkMtXSSUsLDFANExrZh2J'),
|
|
24
|
-
launchTs: 1655751353000,
|
|
25
|
-
oracleSource: __1.OracleSource.PYTH,
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
fullName: 'Ethereum',
|
|
29
|
-
category: ['L1', 'Infra'],
|
|
30
|
-
symbol: 'ETH-PERP',
|
|
31
|
-
baseAssetSymbol: 'ETH',
|
|
32
|
-
marketIndex: new __1.BN(2),
|
|
33
|
-
oracle: new web3_js_1.PublicKey('EdVCmQ9FSPcVe5YySXDPCRmc8aDQLKJ9xvYBMZPie1Vw'),
|
|
34
|
-
launchTs: 1637691133472,
|
|
35
|
-
oracleSource: __1.OracleSource.PYTH,
|
|
36
|
-
},
|
|
37
|
-
];
|
|
38
|
-
exports.MainnetMarkets = [];
|
|
39
|
-
exports.Markets = {
|
|
40
|
-
devnet: exports.DevnetMarkets,
|
|
41
|
-
'mainnet-beta': [],
|
|
42
|
-
};
|