@drift-labs/sdk 0.2.0-master.2 → 0.2.0-master.20
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/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/pollingUserStatsAccountSubscriber.d.ts +27 -0
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
- package/lib/accounts/types.d.ts +14 -1
- package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
- package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
- package/lib/addresses/pda.d.ts +1 -0
- package/lib/addresses/pda.js +8 -1
- package/lib/admin.d.ts +9 -5
- package/lib/admin.js +52 -11
- package/lib/clearingHouse.d.ts +52 -23
- package/lib/clearingHouse.js +727 -197
- package/lib/clearingHouseConfig.d.ts +1 -0
- package/lib/clearingHouseUser.d.ts +17 -17
- package/lib/clearingHouseUser.js +186 -101
- 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.js +1 -1
- package/lib/constants/banks.d.ts +2 -2
- package/lib/constants/banks.js +12 -4
- package/lib/constants/numericConstants.d.ts +5 -0
- package/lib/constants/numericConstants.js +8 -3
- package/lib/events/eventList.js +3 -0
- package/lib/events/types.d.ts +3 -1
- package/lib/events/types.js +2 -0
- package/lib/factory/bigNum.d.ts +1 -0
- package/lib/factory/bigNum.js +34 -10
- package/lib/idl/clearing_house.json +1609 -388
- package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/lib/index.d.ts +9 -3
- package/lib/index.js +13 -3
- package/lib/math/amm.d.ts +1 -0
- package/lib/math/amm.js +22 -38
- package/lib/math/auction.js +4 -1
- package/lib/math/bankBalance.d.ts +7 -1
- package/lib/math/bankBalance.js +77 -2
- package/lib/math/margin.d.ts +11 -0
- package/lib/math/margin.js +72 -0
- package/lib/math/market.d.ts +4 -1
- package/lib/math/market.js +35 -1
- package/lib/math/oracles.d.ts +3 -0
- package/lib/math/oracles.js +25 -5
- package/lib/math/orders.d.ts +5 -2
- package/lib/math/orders.js +53 -12
- package/lib/math/position.d.ts +8 -0
- package/lib/math/position.js +45 -12
- package/lib/math/trade.d.ts +1 -1
- package/lib/math/trade.js +7 -10
- package/lib/orderParams.d.ts +14 -5
- package/lib/orderParams.js +8 -96
- 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.js +9 -2
- package/lib/tx/utils.js +1 -1
- package/lib/types.d.ts +233 -26
- package/lib/types.js +64 -1
- 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 +3 -3
- package/src/accounts/bulkUserStatsSubscription.ts +33 -0
- package/src/accounts/bulkUserSubscription.ts +0 -1
- package/src/accounts/fetch.ts +27 -2
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
- package/src/accounts/types.ts +18 -0
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
- package/src/addresses/marketAddresses.js +26 -0
- package/src/addresses/pda.ts +13 -0
- package/src/admin.ts +82 -15
- package/src/assert/assert.js +9 -0
- package/src/clearingHouse.ts +1224 -319
- package/src/clearingHouseConfig.ts +1 -0
- package/src/clearingHouseUser.ts +311 -148
- package/src/clearingHouseUserStats.ts +75 -0
- package/src/clearingHouseUserStatsConfig.ts +18 -0
- package/src/config.ts +1 -1
- package/src/constants/banks.js +42 -0
- package/src/constants/banks.ts +14 -4
- package/src/constants/markets.js +42 -0
- package/src/constants/numericConstants.js +41 -0
- package/src/constants/numericConstants.ts +14 -2
- package/src/events/eventList.js +77 -0
- package/src/events/eventList.ts +3 -0
- package/src/events/eventSubscriber.js +139 -0
- package/src/events/fetchLogs.js +50 -0
- package/src/events/pollingLogProvider.js +64 -0
- package/src/events/sort.js +44 -0
- package/src/events/txEventCache.js +71 -0
- package/src/events/types.ts +6 -0
- package/src/events/webSocketLogProvider.js +41 -0
- package/src/examples/makeTradeExample.js +80 -0
- package/src/factory/bigNum.js +390 -0
- package/src/factory/bigNum.ts +42 -13
- package/src/factory/oracleClient.js +20 -0
- package/src/idl/clearing_house.json +1609 -388
- package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/src/index.ts +9 -3
- package/src/math/amm.ts +54 -55
- package/src/math/auction.js +42 -0
- package/src/math/auction.ts +5 -1
- package/src/math/bankBalance.ts +148 -2
- package/src/math/conversion.js +11 -0
- package/src/math/funding.js +248 -0
- package/src/math/margin.ts +124 -0
- package/src/math/market.ts +66 -1
- package/src/math/oracles.js +26 -0
- package/src/math/oracles.ts +42 -5
- package/src/math/orders.ts +112 -13
- package/src/math/position.ts +64 -9
- package/src/math/repeg.js +128 -0
- package/src/math/state.js +15 -0
- package/src/math/trade.js +253 -0
- package/src/math/trade.ts +23 -25
- package/src/math/utils.js +0 -1
- package/src/oracles/oracleClientCache.js +19 -0
- package/src/oracles/pythClient.js +46 -0
- package/src/oracles/quoteAssetOracleClient.js +32 -0
- package/src/oracles/switchboardClient.js +69 -0
- package/src/oracles/types.js +2 -0
- package/src/orderParams.js +20 -0
- package/src/orderParams.ts +20 -141
- package/src/slot/SlotSubscriber.js +39 -0
- package/src/slot/SlotSubscriber.ts +11 -1
- package/src/token/index.js +38 -0
- package/src/tokenFaucet.js +189 -0
- package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
- package/src/tx/retryTxSender.ts +11 -3
- package/src/tx/types.js +2 -0
- package/src/tx/utils.js +17 -0
- package/src/tx/utils.ts +1 -1
- package/src/types.ts +236 -27
- package/src/userName.js +20 -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/src/wallet.js +35 -0
- package/tests/bn/test.ts +10 -0
- package/lib/orders.d.ts +0 -8
- package/lib/orders.js +0 -142
- package/src/orders.ts +0 -251
- package/src/util/computeUnits.js.map +0 -1
package/lib/math/oracles.js
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isOracleValid = void 0;
|
|
3
|
+
exports.isOracleTooDivergent = exports.isOracleValid = void 0;
|
|
4
4
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
5
5
|
const index_1 = require("../index");
|
|
6
6
|
function isOracleValid(amm, oraclePriceData, oracleGuardRails, slot) {
|
|
7
|
-
const isOraclePriceNonPositive = oraclePriceData.price.
|
|
7
|
+
const isOraclePriceNonPositive = oraclePriceData.price.lte(numericConstants_1.ZERO);
|
|
8
8
|
const isOraclePriceTooVolatile = oraclePriceData.price
|
|
9
9
|
.div(index_1.BN.max(numericConstants_1.ONE, amm.lastOraclePriceTwap))
|
|
10
10
|
.gt(oracleGuardRails.validity.tooVolatileRatio) ||
|
|
11
11
|
amm.lastOraclePriceTwap
|
|
12
12
|
.div(index_1.BN.max(numericConstants_1.ONE, oraclePriceData.price))
|
|
13
13
|
.gt(oracleGuardRails.validity.tooVolatileRatio);
|
|
14
|
-
const isConfidenceTooLarge =
|
|
15
|
-
.
|
|
16
|
-
.
|
|
14
|
+
const isConfidenceTooLarge = new index_1.BN(amm.baseSpread)
|
|
15
|
+
.add(index_1.BN.max(numericConstants_1.ONE, oraclePriceData.confidence))
|
|
16
|
+
.mul(numericConstants_1.BID_ASK_SPREAD_PRECISION)
|
|
17
|
+
.div(oraclePriceData.price)
|
|
18
|
+
.gt(new index_1.BN(amm.maxSpread));
|
|
17
19
|
const oracleIsStale = oraclePriceData.slot
|
|
18
20
|
.sub(new index_1.BN(slot))
|
|
19
21
|
.gt(oracleGuardRails.validity.slotsBeforeStale);
|
|
@@ -24,3 +26,21 @@ function isOracleValid(amm, oraclePriceData, oracleGuardRails, slot) {
|
|
|
24
26
|
isConfidenceTooLarge);
|
|
25
27
|
}
|
|
26
28
|
exports.isOracleValid = isOracleValid;
|
|
29
|
+
function isOracleTooDivergent(amm, oraclePriceData, oracleGuardRails, now) {
|
|
30
|
+
const sinceLastUpdate = now.sub(amm.lastOraclePriceTwapTs);
|
|
31
|
+
const sinceStart = index_1.BN.max(numericConstants_1.ZERO, new index_1.BN(60 * 5).sub(sinceLastUpdate));
|
|
32
|
+
const oracleTwap5min = amm.lastOraclePriceTwap5min
|
|
33
|
+
.mul(sinceStart)
|
|
34
|
+
.add(oraclePriceData.price)
|
|
35
|
+
.mul(sinceLastUpdate)
|
|
36
|
+
.div(sinceStart.add(sinceLastUpdate));
|
|
37
|
+
const oracleSpread = oracleTwap5min.sub(oraclePriceData.price);
|
|
38
|
+
const oracleSpreadPct = oracleSpread
|
|
39
|
+
.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
40
|
+
.div(oracleTwap5min);
|
|
41
|
+
const tooDivergent = oracleSpreadPct
|
|
42
|
+
.abs()
|
|
43
|
+
.gte(numericConstants_1.BID_ASK_SPREAD_PRECISION.mul(oracleGuardRails.priceDivergence.markOracleDivergenceNumerator).div(oracleGuardRails.priceDivergence.markOracleDivergenceDenominator));
|
|
44
|
+
return tooDivergent;
|
|
45
|
+
}
|
|
46
|
+
exports.isOracleTooDivergent = isOracleTooDivergent;
|
package/lib/math/orders.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
2
|
import { ClearingHouseUser } from '../clearingHouseUser';
|
|
3
|
-
import { Order } from '../types';
|
|
3
|
+
import { MarketAccount, Order } from '../types';
|
|
4
4
|
import { BN } from '@project-serum/anchor';
|
|
5
5
|
import { OraclePriceData } from '../oracles/types';
|
|
6
6
|
export declare function isOrderRiskIncreasing(user: ClearingHouseUser, order: Order): boolean;
|
|
7
7
|
export declare function isOrderRiskIncreasingInSameDirection(user: ClearingHouseUser, order: Order): boolean;
|
|
8
8
|
export declare function isOrderReduceOnly(user: ClearingHouseUser, order: Order): boolean;
|
|
9
9
|
export declare function standardizeBaseAssetAmount(baseAssetAmount: BN, stepSize: BN): BN;
|
|
10
|
-
export declare function getLimitPrice(order: Order, oraclePriceData: OraclePriceData, slot: number): BN;
|
|
10
|
+
export declare function getLimitPrice(order: Order, market: MarketAccount, oraclePriceData: OraclePriceData, slot: number): BN;
|
|
11
|
+
export declare function isFillableByVAMM(order: Order, market: MarketAccount, oraclePriceData: OraclePriceData, slot: number): boolean;
|
|
12
|
+
export declare function calculateBaseAssetAmountForAmmToFulfill(order: Order, market: MarketAccount, oraclePriceData: OraclePriceData, slot: number): BN;
|
|
13
|
+
export declare function calculateBaseAssetAmountToFillUpToLimitPrice(order: Order, market: MarketAccount, limitPrice: BN, oraclePriceData: OraclePriceData): BN;
|
package/lib/math/orders.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getLimitPrice = exports.standardizeBaseAssetAmount = exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
|
|
3
|
+
exports.calculateBaseAssetAmountToFillUpToLimitPrice = exports.calculateBaseAssetAmountForAmmToFulfill = exports.isFillableByVAMM = 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
6
|
const anchor_1 = require("@project-serum/anchor");
|
|
7
7
|
const auction_1 = require("./auction");
|
|
8
|
+
const market_1 = require("./market");
|
|
9
|
+
const amm_1 = require("./amm");
|
|
8
10
|
function isOrderRiskIncreasing(user, order) {
|
|
9
11
|
if ((0, types_1.isVariant)(order.status, 'init')) {
|
|
10
12
|
return false;
|
|
@@ -78,26 +80,65 @@ function standardizeBaseAssetAmount(baseAssetAmount, stepSize) {
|
|
|
78
80
|
return baseAssetAmount.sub(remainder);
|
|
79
81
|
}
|
|
80
82
|
exports.standardizeBaseAssetAmount = standardizeBaseAssetAmount;
|
|
81
|
-
function getLimitPrice(order, oraclePriceData, slot) {
|
|
83
|
+
function getLimitPrice(order, market, oraclePriceData, slot) {
|
|
82
84
|
let limitPrice;
|
|
83
85
|
if (!order.oraclePriceOffset.eq(numericConstants_1.ZERO)) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
|
|
87
|
+
}
|
|
88
|
+
else if ((0, types_1.isOneOfVariant)(order.orderType, ['market', 'triggerMarket'])) {
|
|
89
|
+
if ((0, auction_1.isAuctionComplete)(order, slot)) {
|
|
90
|
+
limitPrice = (0, auction_1.getAuctionPrice)(order, slot);
|
|
91
|
+
}
|
|
92
|
+
else if (!order.price.eq(numericConstants_1.ZERO)) {
|
|
93
|
+
limitPrice = order.price;
|
|
94
|
+
}
|
|
95
|
+
else if ((0, types_1.isVariant)(order.direction, 'long')) {
|
|
96
|
+
const askPrice = (0, market_1.calculateAskPrice)(market, oraclePriceData);
|
|
97
|
+
const delta = askPrice.div(new anchor_1.BN(market.amm.maxSlippageRatio));
|
|
98
|
+
limitPrice = askPrice.add(delta);
|
|
89
99
|
}
|
|
90
100
|
else {
|
|
91
|
-
|
|
101
|
+
const bidPrice = (0, market_1.calculateBidPrice)(market, oraclePriceData);
|
|
102
|
+
const delta = bidPrice.div(new anchor_1.BN(market.amm.maxSlippageRatio));
|
|
103
|
+
limitPrice = bidPrice.sub(delta);
|
|
92
104
|
}
|
|
93
105
|
}
|
|
94
|
-
else if ((0, types_1.isVariant)(order.orderType, 'market') ||
|
|
95
|
-
(0, types_1.isVariant)(order.orderType, 'triggerMarket')) {
|
|
96
|
-
limitPrice = (0, auction_1.getAuctionPrice)(order, slot);
|
|
97
|
-
}
|
|
98
106
|
else {
|
|
99
107
|
limitPrice = order.price;
|
|
100
108
|
}
|
|
101
109
|
return limitPrice;
|
|
102
110
|
}
|
|
103
111
|
exports.getLimitPrice = getLimitPrice;
|
|
112
|
+
function isFillableByVAMM(order, market, oraclePriceData, slot) {
|
|
113
|
+
return ((0, auction_1.isAuctionComplete)(order, slot) &&
|
|
114
|
+
!calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData, slot).eq(numericConstants_1.ZERO));
|
|
115
|
+
}
|
|
116
|
+
exports.isFillableByVAMM = isFillableByVAMM;
|
|
117
|
+
function calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData, slot) {
|
|
118
|
+
if ((0, types_1.isOneOfVariant)(order.orderType, ['triggerMarket', 'triggerLimit']) &&
|
|
119
|
+
order.triggered === false) {
|
|
120
|
+
return numericConstants_1.ZERO;
|
|
121
|
+
}
|
|
122
|
+
const limitPrice = getLimitPrice(order, market, oraclePriceData, slot);
|
|
123
|
+
const baseAssetAmount = calculateBaseAssetAmountToFillUpToLimitPrice(order, market, limitPrice, oraclePriceData);
|
|
124
|
+
const maxBaseAssetAmount = (0, amm_1.calculateMaxBaseAssetAmountFillable)(market.amm, order.direction);
|
|
125
|
+
return anchor_1.BN.min(maxBaseAssetAmount, baseAssetAmount);
|
|
126
|
+
}
|
|
127
|
+
exports.calculateBaseAssetAmountForAmmToFulfill = calculateBaseAssetAmountForAmmToFulfill;
|
|
128
|
+
function calculateBaseAssetAmountToFillUpToLimitPrice(order, market, limitPrice, oraclePriceData) {
|
|
129
|
+
const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice, order.direction, oraclePriceData);
|
|
130
|
+
const baseAssetAmount = standardizeBaseAssetAmount(maxAmountToTrade, market.amm.baseAssetAmountStepSize);
|
|
131
|
+
// Check that directions are the same
|
|
132
|
+
const sameDirection = isSameDirection(direction, order.direction);
|
|
133
|
+
if (!sameDirection) {
|
|
134
|
+
return numericConstants_1.ZERO;
|
|
135
|
+
}
|
|
136
|
+
return baseAssetAmount.gt(order.baseAssetAmount)
|
|
137
|
+
? order.baseAssetAmount
|
|
138
|
+
: baseAssetAmount;
|
|
139
|
+
}
|
|
140
|
+
exports.calculateBaseAssetAmountToFillUpToLimitPrice = calculateBaseAssetAmountToFillUpToLimitPrice;
|
|
141
|
+
function isSameDirection(firstDirection, secondDirection) {
|
|
142
|
+
return (((0, types_1.isVariant)(firstDirection, 'long') && (0, types_1.isVariant)(secondDirection, 'long')) ||
|
|
143
|
+
((0, types_1.isVariant)(firstDirection, 'short') && (0, types_1.isVariant)(secondDirection, 'short')));
|
|
144
|
+
}
|
package/lib/math/position.d.ts
CHANGED
|
@@ -17,9 +17,11 @@ export declare function calculateBaseAssetValue(market: MarketAccount, userPosit
|
|
|
17
17
|
* @param market
|
|
18
18
|
* @param marketPosition
|
|
19
19
|
* @param withFunding (adds unrealized funding payment pnl to result)
|
|
20
|
+
* @param oraclePriceData
|
|
20
21
|
* @returns BaseAssetAmount : Precision QUOTE_PRECISION
|
|
21
22
|
*/
|
|
22
23
|
export declare function calculatePositionPNL(market: MarketAccount, marketPosition: UserPosition, withFunding: boolean, oraclePriceData: OraclePriceData): BN;
|
|
24
|
+
export declare function calculateUnsettledPnl(market: MarketAccount, marketPosition: UserPosition, oraclePriceData: OraclePriceData): BN;
|
|
23
25
|
/**
|
|
24
26
|
*
|
|
25
27
|
* @param market
|
|
@@ -34,6 +36,12 @@ export declare function positionIsAvailable(position: UserPosition): boolean;
|
|
|
34
36
|
* @returns Precision: MARK_PRICE_PRECISION (10^10)
|
|
35
37
|
*/
|
|
36
38
|
export declare function calculateEntryPrice(userPosition: UserPosition): BN;
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
* @param userPosition
|
|
42
|
+
* @returns Precision: MARK_PRICE_PRECISION (10^10)
|
|
43
|
+
*/
|
|
44
|
+
export declare function calculateCostBasis(userPosition: UserPosition): BN;
|
|
37
45
|
export declare function findDirectionToClose(userPosition: UserPosition): PositionDirection;
|
|
38
46
|
export declare function positionCurrentDirection(userPosition: UserPosition): PositionDirection;
|
|
39
47
|
export declare function isEmptyPosition(userPosition: UserPosition): boolean;
|
package/lib/math/position.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
|
|
3
|
+
exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateCostBasis = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculateUnsettledPnl = 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
|
+
const margin_1 = require("./margin");
|
|
8
9
|
/**
|
|
9
10
|
* calculateBaseAssetValue
|
|
10
11
|
* = market value of closing entire position
|
|
@@ -53,20 +54,20 @@ exports.calculateBaseAssetValue = calculateBaseAssetValue;
|
|
|
53
54
|
* @param market
|
|
54
55
|
* @param marketPosition
|
|
55
56
|
* @param withFunding (adds unrealized funding payment pnl to result)
|
|
57
|
+
* @param oraclePriceData
|
|
56
58
|
* @returns BaseAssetAmount : Precision QUOTE_PRECISION
|
|
57
59
|
*/
|
|
58
60
|
function calculatePositionPNL(market, marketPosition, withFunding = false, oraclePriceData) {
|
|
59
61
|
if (marketPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
60
|
-
return
|
|
61
|
-
}
|
|
62
|
-
const baseAssetValue = calculateBaseAssetValue(market, marketPosition, oraclePriceData);
|
|
63
|
-
let pnl;
|
|
64
|
-
if (marketPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
|
|
65
|
-
pnl = baseAssetValue.sub(marketPosition.quoteAssetAmount);
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
pnl = marketPosition.quoteAssetAmount.sub(baseAssetValue);
|
|
62
|
+
return marketPosition.quoteAssetAmount;
|
|
69
63
|
}
|
|
64
|
+
const baseAssetValue = (0, margin_1.calculateMarginBaseAssetValue)(market, marketPosition, oraclePriceData);
|
|
65
|
+
const baseAssetValueSign = marketPosition.baseAssetAmount.isNeg()
|
|
66
|
+
? new __1.BN(-1)
|
|
67
|
+
: new __1.BN(1);
|
|
68
|
+
let pnl = baseAssetValue
|
|
69
|
+
.mul(baseAssetValueSign)
|
|
70
|
+
.add(marketPosition.quoteAssetAmount);
|
|
70
71
|
if (withFunding) {
|
|
71
72
|
const fundingRatePnL = calculatePositionFundingPNL(market, marketPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
|
|
72
73
|
pnl = pnl.add(fundingRatePnL);
|
|
@@ -74,6 +75,19 @@ function calculatePositionPNL(market, marketPosition, withFunding = false, oracl
|
|
|
74
75
|
return pnl;
|
|
75
76
|
}
|
|
76
77
|
exports.calculatePositionPNL = calculatePositionPNL;
|
|
78
|
+
function calculateUnsettledPnl(market, marketPosition, oraclePriceData) {
|
|
79
|
+
const unrealizedPnl = calculatePositionPNL(market, marketPosition, true, oraclePriceData);
|
|
80
|
+
let unsettledPnl = unrealizedPnl;
|
|
81
|
+
if (unrealizedPnl.gt(numericConstants_1.ZERO)) {
|
|
82
|
+
const fundingPnL = calculatePositionFundingPNL(market, marketPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
|
|
83
|
+
const maxPositivePnl = __1.BN.max(marketPosition.quoteAssetAmount
|
|
84
|
+
.sub(marketPosition.quoteEntryAmount)
|
|
85
|
+
.add(fundingPnL), numericConstants_1.ZERO);
|
|
86
|
+
unsettledPnl = __1.BN.min(maxPositivePnl, unrealizedPnl);
|
|
87
|
+
}
|
|
88
|
+
return unsettledPnl;
|
|
89
|
+
}
|
|
90
|
+
exports.calculateUnsettledPnl = calculateUnsettledPnl;
|
|
77
91
|
/**
|
|
78
92
|
*
|
|
79
93
|
* @param market
|
|
@@ -101,7 +115,10 @@ function calculatePositionFundingPNL(market, marketPosition) {
|
|
|
101
115
|
}
|
|
102
116
|
exports.calculatePositionFundingPNL = calculatePositionFundingPNL;
|
|
103
117
|
function positionIsAvailable(position) {
|
|
104
|
-
return position.baseAssetAmount.eq(numericConstants_1.ZERO) &&
|
|
118
|
+
return (position.baseAssetAmount.eq(numericConstants_1.ZERO) &&
|
|
119
|
+
position.openOrders.eq(numericConstants_1.ZERO) &&
|
|
120
|
+
position.quoteAssetAmount.eq(numericConstants_1.ZERO) &&
|
|
121
|
+
position.lpShares.eq(numericConstants_1.ZERO));
|
|
105
122
|
}
|
|
106
123
|
exports.positionIsAvailable = positionIsAvailable;
|
|
107
124
|
/**
|
|
@@ -113,13 +130,29 @@ function calculateEntryPrice(userPosition) {
|
|
|
113
130
|
if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
114
131
|
return numericConstants_1.ZERO;
|
|
115
132
|
}
|
|
116
|
-
return userPosition.
|
|
133
|
+
return userPosition.quoteEntryAmount
|
|
117
134
|
.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
118
135
|
.mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
|
|
119
136
|
.div(userPosition.baseAssetAmount)
|
|
120
137
|
.abs();
|
|
121
138
|
}
|
|
122
139
|
exports.calculateEntryPrice = calculateEntryPrice;
|
|
140
|
+
/**
|
|
141
|
+
*
|
|
142
|
+
* @param userPosition
|
|
143
|
+
* @returns Precision: MARK_PRICE_PRECISION (10^10)
|
|
144
|
+
*/
|
|
145
|
+
function calculateCostBasis(userPosition) {
|
|
146
|
+
if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
147
|
+
return numericConstants_1.ZERO;
|
|
148
|
+
}
|
|
149
|
+
return userPosition.quoteAssetAmount
|
|
150
|
+
.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
151
|
+
.mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
|
|
152
|
+
.div(userPosition.baseAssetAmount)
|
|
153
|
+
.abs();
|
|
154
|
+
}
|
|
155
|
+
exports.calculateCostBasis = calculateCostBasis;
|
|
123
156
|
function findDirectionToClose(userPosition) {
|
|
124
157
|
return userPosition.baseAssetAmount.gt(numericConstants_1.ZERO)
|
|
125
158
|
? types_1.PositionDirection.SHORT
|
package/lib/math/trade.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export declare function calculateTradeSlippage(direction: PositionDirection, amo
|
|
|
33
33
|
* | 'acquiredBase' => positive/negative change in user's base : BN AMM_RESERVE_PRECISION
|
|
34
34
|
* | 'acquiredQuote' => positive/negative change in user's quote : BN TODO-PRECISION
|
|
35
35
|
*/
|
|
36
|
-
export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market: MarketAccount, inputAssetType: AssetType, oraclePriceData: OraclePriceData, useSpread?: boolean): [BN, BN];
|
|
36
|
+
export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market: MarketAccount, inputAssetType: AssetType, oraclePriceData: OraclePriceData, useSpread?: boolean): [BN, BN, BN];
|
|
37
37
|
/**
|
|
38
38
|
* calculateTargetPriceTrade
|
|
39
39
|
* simple function for finding arbitraging trades
|
package/lib/math/trade.js
CHANGED
|
@@ -43,15 +43,11 @@ function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quo
|
|
|
43
43
|
if (amount.eq(numericConstants_1.ZERO)) {
|
|
44
44
|
return [numericConstants_1.ZERO, numericConstants_1.ZERO, oldPrice, oldPrice];
|
|
45
45
|
}
|
|
46
|
-
const [
|
|
47
|
-
const
|
|
48
|
-
? types_1.SwapDirection.REMOVE
|
|
49
|
-
: types_1.SwapDirection.ADD;
|
|
50
|
-
const quoteAssetAmountAcquired = (0, amm_1.calculateQuoteAssetAmountSwapped)(acquiredQuote.abs(), market.amm.pegMultiplier, swapDirection);
|
|
51
|
-
const entryPrice = quoteAssetAmountAcquired
|
|
46
|
+
const [acquiredBaseReserve, acquiredQuoteReserve, acquiredQuoteAssetAmount] = calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType, oraclePriceData, useSpread);
|
|
47
|
+
const entryPrice = acquiredQuoteAssetAmount
|
|
52
48
|
.mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
|
|
53
49
|
.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
54
|
-
.div(
|
|
50
|
+
.div(acquiredBaseReserve.abs());
|
|
55
51
|
let amm;
|
|
56
52
|
if (useSpread && market.amm.baseSpread > 0) {
|
|
57
53
|
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, direction, oraclePriceData);
|
|
@@ -65,7 +61,7 @@ function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quo
|
|
|
65
61
|
else {
|
|
66
62
|
amm = market.amm;
|
|
67
63
|
}
|
|
68
|
-
const newPrice = (0, amm_1.calculatePrice)(amm.baseAssetReserve.sub(
|
|
64
|
+
const newPrice = (0, amm_1.calculatePrice)(amm.baseAssetReserve.sub(acquiredBaseReserve), amm.quoteAssetReserve.sub(acquiredQuoteReserve), amm.pegMultiplier);
|
|
69
65
|
if (direction == types_1.PositionDirection.SHORT) {
|
|
70
66
|
(0, assert_1.assert)(newPrice.lte(oldPrice));
|
|
71
67
|
}
|
|
@@ -98,7 +94,7 @@ exports.calculateTradeSlippage = calculateTradeSlippage;
|
|
|
98
94
|
*/
|
|
99
95
|
function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType = 'quote', oraclePriceData, useSpread = true) {
|
|
100
96
|
if (amount.eq(numericConstants_1.ZERO)) {
|
|
101
|
-
return [numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
97
|
+
return [numericConstants_1.ZERO, numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
102
98
|
}
|
|
103
99
|
const swapDirection = (0, amm_1.getSwapDirection)(inputAssetType, direction);
|
|
104
100
|
let amm;
|
|
@@ -117,7 +113,8 @@ function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType
|
|
|
117
113
|
const [newQuoteAssetReserve, newBaseAssetReserve] = (0, amm_1.calculateAmmReservesAfterSwap)(amm, inputAssetType, amount, swapDirection);
|
|
118
114
|
const acquiredBase = amm.baseAssetReserve.sub(newBaseAssetReserve);
|
|
119
115
|
const acquiredQuote = amm.quoteAssetReserve.sub(newQuoteAssetReserve);
|
|
120
|
-
|
|
116
|
+
const acquiredQuoteAssetAmount = (0, amm_1.calculateQuoteAssetAmountSwapped)(acquiredQuote.abs(), amm.pegMultiplier, swapDirection);
|
|
117
|
+
return [acquiredBase, acquiredQuote, acquiredQuoteAssetAmount];
|
|
121
118
|
}
|
|
122
119
|
exports.calculateTradeAcquiredAmounts = calculateTradeAcquiredAmounts;
|
|
123
120
|
/**
|
package/lib/orderParams.d.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
|
-
import {
|
|
2
|
+
import { OptionalOrderParams, OrderTriggerCondition } from './types';
|
|
3
3
|
import { BN } from '@project-serum/anchor';
|
|
4
|
-
export declare function getLimitOrderParams(
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export declare function
|
|
4
|
+
export declare function getLimitOrderParams(params: Omit<OptionalOrderParams, 'orderType'> & {
|
|
5
|
+
price: BN;
|
|
6
|
+
}): OptionalOrderParams;
|
|
7
|
+
export declare function getTriggerMarketOrderParams(params: Omit<OptionalOrderParams, 'orderType'> & {
|
|
8
|
+
triggerCondition: OrderTriggerCondition;
|
|
9
|
+
triggerPrice: BN;
|
|
10
|
+
}): OptionalOrderParams;
|
|
11
|
+
export declare function getTriggerLimitOrderParams(params: Omit<OptionalOrderParams, 'orderType'> & {
|
|
12
|
+
triggerCondition: OrderTriggerCondition;
|
|
13
|
+
triggerPrice: BN;
|
|
14
|
+
price: BN;
|
|
15
|
+
}): OptionalOrderParams;
|
|
16
|
+
export declare function getMarketOrderParams(params: Omit<OptionalOrderParams, 'orderType'>): OptionalOrderParams;
|
package/lib/orderParams.js
CHANGED
|
@@ -2,107 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getMarketOrderParams = exports.getTriggerLimitOrderParams = exports.getTriggerMarketOrderParams = exports.getLimitOrderParams = void 0;
|
|
4
4
|
const types_1 = require("./types");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return {
|
|
8
|
-
orderType: types_1.OrderType.LIMIT,
|
|
9
|
-
userOrderId,
|
|
10
|
-
marketIndex,
|
|
11
|
-
direction,
|
|
12
|
-
quoteAssetAmount: numericConstants_1.ZERO,
|
|
13
|
-
baseAssetAmount,
|
|
14
|
-
price,
|
|
15
|
-
reduceOnly,
|
|
16
|
-
postOnly,
|
|
17
|
-
immediateOrCancel,
|
|
18
|
-
positionLimit: numericConstants_1.ZERO,
|
|
19
|
-
padding0: true,
|
|
20
|
-
padding1: numericConstants_1.ZERO,
|
|
21
|
-
optionalAccounts: {
|
|
22
|
-
discountToken,
|
|
23
|
-
referrer,
|
|
24
|
-
},
|
|
25
|
-
triggerCondition: types_1.OrderTriggerCondition.ABOVE,
|
|
26
|
-
triggerPrice: numericConstants_1.ZERO,
|
|
27
|
-
oraclePriceOffset,
|
|
28
|
-
};
|
|
5
|
+
function getLimitOrderParams(params) {
|
|
6
|
+
return Object.assign({}, params, { orderType: types_1.OrderType.LIMIT });
|
|
29
7
|
}
|
|
30
8
|
exports.getLimitOrderParams = getLimitOrderParams;
|
|
31
|
-
function getTriggerMarketOrderParams(
|
|
32
|
-
return {
|
|
33
|
-
orderType: types_1.OrderType.TRIGGER_MARKET,
|
|
34
|
-
userOrderId,
|
|
35
|
-
marketIndex,
|
|
36
|
-
direction,
|
|
37
|
-
quoteAssetAmount: numericConstants_1.ZERO,
|
|
38
|
-
baseAssetAmount,
|
|
39
|
-
price: numericConstants_1.ZERO,
|
|
40
|
-
reduceOnly,
|
|
41
|
-
postOnly: false,
|
|
42
|
-
immediateOrCancel: false,
|
|
43
|
-
positionLimit: numericConstants_1.ZERO,
|
|
44
|
-
padding0: true,
|
|
45
|
-
padding1: numericConstants_1.ZERO,
|
|
46
|
-
optionalAccounts: {
|
|
47
|
-
discountToken,
|
|
48
|
-
referrer,
|
|
49
|
-
},
|
|
50
|
-
triggerCondition,
|
|
51
|
-
triggerPrice,
|
|
52
|
-
oraclePriceOffset: numericConstants_1.ZERO,
|
|
53
|
-
};
|
|
9
|
+
function getTriggerMarketOrderParams(params) {
|
|
10
|
+
return Object.assign({}, params, { orderType: types_1.OrderType.TRIGGER_MARKET });
|
|
54
11
|
}
|
|
55
12
|
exports.getTriggerMarketOrderParams = getTriggerMarketOrderParams;
|
|
56
|
-
function getTriggerLimitOrderParams(
|
|
57
|
-
return {
|
|
58
|
-
orderType: types_1.OrderType.TRIGGER_LIMIT,
|
|
59
|
-
userOrderId,
|
|
60
|
-
marketIndex,
|
|
61
|
-
direction,
|
|
62
|
-
quoteAssetAmount: numericConstants_1.ZERO,
|
|
63
|
-
baseAssetAmount,
|
|
64
|
-
price,
|
|
65
|
-
reduceOnly,
|
|
66
|
-
postOnly: false,
|
|
67
|
-
immediateOrCancel: false,
|
|
68
|
-
positionLimit: numericConstants_1.ZERO,
|
|
69
|
-
padding0: true,
|
|
70
|
-
padding1: numericConstants_1.ZERO,
|
|
71
|
-
optionalAccounts: {
|
|
72
|
-
discountToken,
|
|
73
|
-
referrer,
|
|
74
|
-
},
|
|
75
|
-
triggerCondition,
|
|
76
|
-
triggerPrice,
|
|
77
|
-
oraclePriceOffset: numericConstants_1.ZERO,
|
|
78
|
-
};
|
|
13
|
+
function getTriggerLimitOrderParams(params) {
|
|
14
|
+
return Object.assign({}, params, { orderType: types_1.OrderType.TRIGGER_LIMIT });
|
|
79
15
|
}
|
|
80
16
|
exports.getTriggerLimitOrderParams = getTriggerLimitOrderParams;
|
|
81
|
-
function getMarketOrderParams(
|
|
82
|
-
|
|
83
|
-
throw Error('baseAssetAmount or quoteAssetAmount must be zero');
|
|
84
|
-
}
|
|
85
|
-
return {
|
|
86
|
-
orderType: types_1.OrderType.MARKET,
|
|
87
|
-
userOrderId: 0,
|
|
88
|
-
marketIndex,
|
|
89
|
-
direction,
|
|
90
|
-
quoteAssetAmount,
|
|
91
|
-
baseAssetAmount,
|
|
92
|
-
price,
|
|
93
|
-
reduceOnly,
|
|
94
|
-
postOnly: false,
|
|
95
|
-
immediateOrCancel: false,
|
|
96
|
-
positionLimit: numericConstants_1.ZERO,
|
|
97
|
-
padding0: true,
|
|
98
|
-
padding1: numericConstants_1.ZERO,
|
|
99
|
-
optionalAccounts: {
|
|
100
|
-
discountToken,
|
|
101
|
-
referrer,
|
|
102
|
-
},
|
|
103
|
-
triggerCondition: types_1.OrderTriggerCondition.ABOVE,
|
|
104
|
-
triggerPrice: numericConstants_1.ZERO,
|
|
105
|
-
oraclePriceOffset: numericConstants_1.ZERO,
|
|
106
|
-
};
|
|
17
|
+
function getMarketOrderParams(params) {
|
|
18
|
+
return Object.assign({}, params, { orderType: types_1.OrderType.MARKET });
|
|
107
19
|
}
|
|
108
20
|
exports.getMarketOrderParams = getMarketOrderParams;
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import { Connection } from '@solana/web3.js';
|
|
3
|
+
import { EventEmitter } from 'events';
|
|
4
|
+
import StrictEventEmitter from 'strict-event-emitter-types/types/src';
|
|
2
5
|
declare type SlotSubscriberConfig = {};
|
|
6
|
+
export interface SlotSubscriberEvents {
|
|
7
|
+
newSlot: (newSlot: number) => void;
|
|
8
|
+
}
|
|
3
9
|
export declare class SlotSubscriber {
|
|
4
10
|
private connection;
|
|
5
11
|
currentSlot: number;
|
|
6
12
|
subscriptionId: number;
|
|
13
|
+
eventEmitter: StrictEventEmitter<EventEmitter, SlotSubscriberEvents>;
|
|
7
14
|
constructor(connection: Connection, _config?: SlotSubscriberConfig);
|
|
8
15
|
subscribe(): Promise<void>;
|
|
9
16
|
getSlot(): number;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SlotSubscriber = void 0;
|
|
4
|
+
const events_1 = require("events");
|
|
4
5
|
class SlotSubscriber {
|
|
5
6
|
constructor(connection, _config) {
|
|
6
7
|
this.connection = connection;
|
|
8
|
+
this.eventEmitter = new events_1.EventEmitter();
|
|
7
9
|
}
|
|
8
10
|
async subscribe() {
|
|
9
11
|
this.currentSlot = await this.connection.getSlot('confirmed');
|
|
10
12
|
this.subscriptionId = this.connection.onSlotChange((slotInfo) => {
|
|
11
13
|
this.currentSlot = slotInfo.slot;
|
|
14
|
+
this.eventEmitter.emit('newSlot', slotInfo.slot);
|
|
12
15
|
});
|
|
13
16
|
}
|
|
14
17
|
getSlot() {
|
|
@@ -5,22 +5,25 @@ import { AccountInfo } from '@solana/spl-token';
|
|
|
5
5
|
import { ConfirmOptions, Connection, PublicKey, TransactionInstruction, TransactionSignature } from '@solana/web3.js';
|
|
6
6
|
import { BN } from '.';
|
|
7
7
|
import { IWallet } from './types';
|
|
8
|
-
export declare class
|
|
8
|
+
export declare class TokenFaucet {
|
|
9
9
|
connection: Connection;
|
|
10
10
|
wallet: IWallet;
|
|
11
11
|
program: Program;
|
|
12
12
|
provider: AnchorProvider;
|
|
13
|
+
mint: PublicKey;
|
|
13
14
|
opts?: ConfirmOptions;
|
|
14
|
-
constructor(connection: Connection, wallet: IWallet, programId: PublicKey, opts?: ConfirmOptions);
|
|
15
|
-
|
|
15
|
+
constructor(connection: Connection, wallet: IWallet, programId: PublicKey, mint: PublicKey, opts?: ConfirmOptions);
|
|
16
|
+
getFaucetConfigPublicKeyAndNonce(): Promise<[
|
|
16
17
|
PublicKey,
|
|
17
18
|
number
|
|
18
19
|
]>;
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
getMintAuthority(): Promise<PublicKey>;
|
|
21
|
+
getFaucetConfigPublicKey(): Promise<PublicKey>;
|
|
21
22
|
initialize(): Promise<TransactionSignature>;
|
|
22
23
|
fetchState(): Promise<any>;
|
|
24
|
+
private mintToUserIx;
|
|
23
25
|
mintToUser(userTokenAccount: PublicKey, amount: BN): Promise<TransactionSignature>;
|
|
26
|
+
transferMintAuthority(): Promise<TransactionSignature>;
|
|
24
27
|
createAssociatedTokenAccountAndMintTo(userPublicKey: PublicKey, amount: BN): Promise<[PublicKey, TransactionSignature]>;
|
|
25
28
|
createAssociatedTokenAccountAndMintToInstructions(userPublicKey: PublicKey, amount: BN): Promise<[PublicKey, TransactionInstruction, TransactionInstruction]>;
|
|
26
29
|
getAssosciatedMockUSDMintAddress(props: {
|