@drift-labs/sdk 0.2.0-temp.2 → 2.0.1
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 +27 -29
- package/lib/accounts/bulkAccountLoader.d.ts +2 -0
- package/lib/accounts/bulkAccountLoader.js +36 -29
- package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
- package/lib/accounts/bulkUserStatsSubscription.js +21 -0
- package/lib/accounts/bulkUserSubscription.d.ts +2 -2
- 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 → pollingDriftClientAccountSubscriber.d.ts} +20 -25
- package/lib/accounts/{pollingClearingHouseAccountSubscriber.js → pollingDriftClientAccountSubscriber.js} +45 -49
- package/lib/accounts/{pollingOracleSubscriber.d.ts → pollingOracleAccountSubscriber.d.ts} +2 -2
- package/lib/accounts/{pollingOracleSubscriber.js → pollingOracleAccountSubscriber.js} +3 -3
- package/lib/accounts/pollingUserAccountSubscriber.d.ts +1 -1
- package/lib/accounts/pollingUserAccountSubscriber.js +5 -11
- package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +107 -0
- package/lib/accounts/types.d.ts +26 -15
- package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +49 -0
- package/lib/accounts/{webSocketClearingHouseAccountSubscriber.js → webSocketDriftClientAccountSubscriber.js} +47 -45
- 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/marketAddresses.js +1 -1
- package/lib/addresses/pda.d.ts +15 -9
- package/lib/addresses/pda.js +73 -35
- package/lib/adminClient.d.ts +65 -0
- package/lib/adminClient.js +637 -0
- package/lib/config.d.ts +10 -10
- package/lib/config.js +26 -22
- package/lib/constants/numericConstants.d.ts +29 -12
- package/lib/constants/numericConstants.js +40 -21
- package/lib/constants/perpMarkets.d.ts +18 -0
- package/lib/constants/{markets.js → perpMarkets.js} +20 -9
- package/lib/constants/spotMarkets.d.ts +19 -0
- package/lib/constants/spotMarkets.js +63 -0
- package/lib/dlob/DLOB.d.ts +82 -0
- package/lib/dlob/DLOB.js +694 -0
- package/lib/dlob/DLOBNode.d.ts +54 -0
- package/lib/dlob/DLOBNode.js +77 -0
- package/lib/dlob/NodeList.d.ts +27 -0
- package/lib/dlob/NodeList.js +144 -0
- package/lib/driftClient.d.ts +234 -0
- package/lib/driftClient.js +2108 -0
- package/lib/{clearingHouseConfig.d.ts → driftClientConfig.d.ts} +9 -9
- package/lib/{clearingHouseConfig.js → driftClientConfig.js} +0 -0
- package/lib/events/eventList.d.ts +0 -1
- package/lib/events/eventList.js +0 -7
- package/lib/events/eventSubscriber.d.ts +5 -2
- package/lib/events/eventSubscriber.js +25 -11
- package/lib/events/fetchLogs.d.ts +13 -2
- package/lib/events/fetchLogs.js +45 -14
- package/lib/events/pollingLogProvider.d.ts +2 -1
- package/lib/events/pollingLogProvider.js +7 -3
- package/lib/events/sort.js +8 -11
- package/lib/events/txEventCache.d.ts +0 -2
- package/lib/events/txEventCache.js +0 -14
- package/lib/events/types.d.ts +11 -3
- package/lib/events/types.js +8 -0
- package/lib/events/webSocketLogProvider.js +1 -1
- package/lib/examples/makeTradeExample.js +30 -18
- package/lib/factory/bigNum.d.ts +8 -4
- package/lib/factory/bigNum.js +109 -19
- package/lib/idl/drift.json +8392 -0
- package/lib/index.d.ts +29 -12
- package/lib/index.js +29 -12
- package/lib/math/amm.d.ts +9 -6
- package/lib/math/amm.js +91 -38
- package/lib/math/conversion.js +1 -1
- package/lib/math/exchangeStatus.d.ts +4 -0
- package/lib/math/exchangeStatus.js +18 -0
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +23 -21
- 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 +82 -0
- package/lib/math/market.d.ts +14 -9
- package/lib/math/market.js +70 -10
- package/lib/math/oracles.d.ts +4 -0
- package/lib/math/oracles.js +36 -8
- package/lib/math/orders.d.ts +16 -6
- package/lib/math/orders.js +97 -17
- package/lib/math/position.d.ts +27 -13
- package/lib/math/position.js +91 -37
- package/lib/math/repeg.js +17 -8
- 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 +27 -31
- 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 +4 -4
- package/lib/orderParams.js +12 -4
- package/lib/serum/serumFulfillmentConfigMap.d.ts +10 -0
- package/lib/serum/serumFulfillmentConfigMap.js +17 -0
- package/lib/serum/serumSubscriber.d.ts +27 -0
- package/lib/serum/serumSubscriber.js +56 -0
- package/lib/serum/types.d.ts +11 -0
- package/{src/oracles → lib/serum}/types.js +0 -0
- package/lib/tokenFaucet.d.ts +1 -0
- package/lib/tokenFaucet.js +23 -12
- 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/types.d.ts +631 -222
- package/lib/types.js +137 -24
- package/lib/user.d.ts +228 -0
- package/lib/user.js +959 -0
- package/lib/userConfig.d.ts +14 -0
- package/lib/{clearingHouseUserConfig.js → userConfig.js} +0 -0
- package/lib/userMap/userMap.d.ts +41 -0
- package/lib/userMap/userMap.js +85 -0
- package/lib/userMap/userStatsMap.d.ts +19 -0
- package/lib/userMap/userStatsMap.js +68 -0
- package/lib/userName.d.ts +1 -0
- package/lib/userName.js +3 -2
- package/lib/userStats.d.ts +18 -0
- package/lib/userStats.js +49 -0
- package/lib/userStatsConfig.d.ts +14 -0
- package/{src/clearingHouseConfig.js → lib/userStatsConfig.js} +0 -0
- package/lib/util/getTokenAddress.d.ts +2 -0
- package/lib/util/getTokenAddress.js +9 -0
- package/package.json +12 -5
- package/src/accounts/bulkAccountLoader.ts +44 -34
- package/src/accounts/bulkUserStatsSubscription.ts +33 -0
- package/src/accounts/bulkUserSubscription.ts +2 -3
- package/src/accounts/fetch.ts +27 -2
- package/src/accounts/{pollingClearingHouseAccountSubscriber.ts → pollingDriftClientAccountSubscriber.ts} +65 -75
- package/src/accounts/{pollingOracleSubscriber.ts → pollingOracleAccountSubscriber.ts} +2 -2
- package/src/accounts/pollingUserAccountSubscriber.ts +5 -12
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +166 -0
- package/src/accounts/types.ts +35 -15
- package/src/accounts/{webSocketClearingHouseAccountSubscriber.ts → webSocketDriftClientAccountSubscriber.ts} +78 -73
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
- package/src/addresses/marketAddresses.ts +3 -4
- package/src/addresses/pda.ts +105 -33
- package/src/adminClient.ts +1207 -0
- package/src/config.ts +41 -34
- package/src/constants/numericConstants.ts +59 -26
- package/src/constants/{markets.ts → perpMarkets.ts} +22 -11
- package/src/constants/spotMarkets.ts +83 -0
- package/src/dlob/DLOB.ts +1120 -0
- package/src/dlob/DLOBNode.ts +155 -0
- package/src/dlob/NodeList.ts +195 -0
- package/src/driftClient.ts +3594 -0
- package/src/{clearingHouseConfig.ts → driftClientConfig.ts} +9 -8
- package/src/events/eventList.ts +1 -8
- package/src/events/eventSubscriber.ts +36 -14
- package/src/events/fetchLogs.ts +60 -15
- package/src/events/pollingLogProvider.ts +11 -3
- package/src/events/sort.ts +11 -15
- package/src/events/txEventCache.ts +0 -16
- package/src/events/types.ts +27 -2
- package/src/events/webSocketLogProvider.ts +1 -1
- package/src/examples/makeTradeExample.js +152 -75
- package/src/examples/makeTradeExample.ts +44 -28
- package/src/factory/bigNum.ts +150 -22
- package/src/idl/drift.json +8392 -0
- package/src/idl/pyth.json +98 -2
- package/src/index.ts +29 -12
- package/src/math/amm.ts +161 -48
- package/src/math/conversion.ts +2 -2
- package/src/math/exchangeStatus.ts +31 -0
- package/src/math/funding.ts +41 -31
- package/src/math/insurance.ts +35 -0
- package/src/math/margin.ts +133 -0
- package/src/math/market.ts +143 -14
- package/src/math/oracles.ts +63 -9
- package/src/math/orders.ts +168 -26
- package/src/math/position.ts +133 -59
- package/src/math/repeg.ts +19 -9
- 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 +33 -37
- 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 +16 -8
- package/src/serum/serumFulfillmentConfigMap.ts +26 -0
- package/src/serum/serumSubscriber.ts +99 -0
- package/src/serum/types.ts +13 -0
- package/src/tokenFaucet.ts +38 -15
- package/src/tx/retryTxSender.ts +16 -5
- package/src/tx/types.ts +2 -1
- package/src/types.ts +594 -195
- package/src/user.ts +1599 -0
- package/src/{clearingHouseUserConfig.ts → userConfig.ts} +5 -5
- package/src/userMap/userMap.ts +124 -0
- package/src/userMap/userStatsMap.ts +108 -0
- package/src/userName.ts +2 -1
- package/src/userStats.ts +75 -0
- package/src/userStatsConfig.ts +18 -0
- package/src/util/getTokenAddress.ts +18 -0
- package/tests/bn/test.ts +46 -11
- package/tests/dlob/helpers.ts +619 -0
- package/tests/dlob/test.ts +4586 -0
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +0 -49
- package/lib/admin.d.ts +0 -44
- package/lib/admin.js +0 -438
- package/lib/clearingHouse.d.ts +0 -146
- package/lib/clearingHouse.js +0 -1154
- package/lib/clearingHouseUser.d.ts +0 -187
- package/lib/clearingHouseUser.js +0 -634
- package/lib/clearingHouseUserConfig.d.ts +0 -14
- package/lib/constants/banks.d.ts +0 -16
- package/lib/constants/banks.js +0 -41
- package/lib/constants/markets.d.ts +0 -19
- package/lib/idl/clearing_house.json +0 -4464
- 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/accounts/bulkAccountLoader.js +0 -197
- package/src/accounts/bulkUserSubscription.js +0 -33
- package/src/accounts/pollingClearingHouseAccountSubscriber.js +0 -311
- package/src/accounts/pollingOracleSubscriber.js +0 -93
- package/src/accounts/pollingTokenAccountSubscriber.js +0 -90
- package/src/accounts/pollingUserAccountSubscriber.js +0 -132
- package/src/accounts/types.js +0 -10
- package/src/accounts/utils.js +0 -7
- package/src/accounts/webSocketAccountSubscriber.js +0 -93
- package/src/accounts/webSocketClearingHouseAccountSubscriber.js +0 -233
- package/src/accounts/webSocketUserAccountSubscriber.js +0 -62
- package/src/addresses/marketAddresses.js +0 -26
- package/src/admin.js +0 -517
- package/src/admin.ts +0 -730
- package/src/clearingHouse.ts +0 -1828
- package/src/clearingHouseUser.ts +0 -978
- package/src/clearingHouseUserConfig.js +0 -2
- package/src/config.js +0 -67
- package/src/constants/banks.js +0 -42
- package/src/constants/banks.ts +0 -50
- package/src/constants/markets.js +0 -42
- package/src/constants/numericConstants.js +0 -41
- package/src/events/eventSubscriber.js +0 -139
- package/src/events/fetchLogs.js +0 -50
- package/src/events/pollingLogProvider.js +0 -64
- package/src/events/sort.js +0 -44
- package/src/events/txEventCache.js +0 -71
- package/src/events/types.js +0 -20
- package/src/events/webSocketLogProvider.js +0 -41
- package/src/factory/bigNum.js +0 -390
- package/src/factory/oracleClient.js +0 -20
- package/src/idl/clearing_house.json +0 -4464
- package/src/index.js +0 -69
- package/src/math/amm.js +0 -369
- package/src/math/auction.js +0 -42
- package/src/math/bankBalance.ts +0 -112
- package/src/math/conversion.js +0 -11
- package/src/math/funding.js +0 -248
- package/src/math/oracles.js +0 -26
- package/src/math/repeg.js +0 -128
- package/src/math/state.js +0 -15
- package/src/math/state.ts +0 -14
- package/src/math/trade.js +0 -253
- package/src/math/utils.js +0 -26
- package/src/math/utils.js.map +0 -1
- package/src/mockUSDCFaucet.js +0 -280
- 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/orderParams.js +0 -20
- package/src/orders.ts +0 -245
- package/src/slot/SlotSubscriber.js +0 -39
- package/src/tokenFaucet.js +0 -189
- package/src/types.js +0 -125
- package/src/userName.js +0 -20
- package/src/wallet.js +0 -35
package/src/math/orders.ts
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { User } from '../user';
|
|
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
12
|
import { getAuctionPrice, isAuctionComplete } from './auction';
|
|
7
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
calculateMaxBaseAssetAmountFillable,
|
|
15
|
+
calculateMaxBaseAssetAmountToTrade,
|
|
16
|
+
} from './amm';
|
|
8
17
|
|
|
9
|
-
export function isOrderRiskIncreasing(
|
|
10
|
-
user: ClearingHouseUser,
|
|
11
|
-
order: Order
|
|
12
|
-
): boolean {
|
|
18
|
+
export function isOrderRiskIncreasing(user: User, order: Order): boolean {
|
|
13
19
|
if (isVariant(order.status, 'init')) {
|
|
14
20
|
return false;
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
const position =
|
|
18
|
-
user.
|
|
24
|
+
user.getPerpPosition(order.marketIndex) ||
|
|
19
25
|
user.getEmptyPosition(order.marketIndex);
|
|
20
26
|
|
|
21
27
|
// if no position exists, it's risk increasing
|
|
@@ -48,7 +54,7 @@ export function isOrderRiskIncreasing(
|
|
|
48
54
|
}
|
|
49
55
|
|
|
50
56
|
export function isOrderRiskIncreasingInSameDirection(
|
|
51
|
-
user:
|
|
57
|
+
user: User,
|
|
52
58
|
order: Order
|
|
53
59
|
): boolean {
|
|
54
60
|
if (isVariant(order.status, 'init')) {
|
|
@@ -56,7 +62,7 @@ export function isOrderRiskIncreasingInSameDirection(
|
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
const position =
|
|
59
|
-
user.
|
|
65
|
+
user.getPerpPosition(order.marketIndex) ||
|
|
60
66
|
user.getEmptyPosition(order.marketIndex);
|
|
61
67
|
|
|
62
68
|
// if no position exists, it's risk increasing
|
|
@@ -80,16 +86,13 @@ export function isOrderRiskIncreasingInSameDirection(
|
|
|
80
86
|
return false;
|
|
81
87
|
}
|
|
82
88
|
|
|
83
|
-
export function isOrderReduceOnly(
|
|
84
|
-
user: ClearingHouseUser,
|
|
85
|
-
order: Order
|
|
86
|
-
): boolean {
|
|
89
|
+
export function isOrderReduceOnly(user: User, order: Order): boolean {
|
|
87
90
|
if (isVariant(order.status, 'init')) {
|
|
88
91
|
return false;
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
const position =
|
|
92
|
-
user.
|
|
95
|
+
user.getPerpPosition(order.marketIndex) ||
|
|
93
96
|
user.getEmptyPosition(order.marketIndex);
|
|
94
97
|
|
|
95
98
|
// if position is long and order is long
|
|
@@ -121,26 +124,25 @@ export function standardizeBaseAssetAmount(
|
|
|
121
124
|
|
|
122
125
|
export function getLimitPrice(
|
|
123
126
|
order: Order,
|
|
124
|
-
market: MarketAccount,
|
|
125
127
|
oraclePriceData: OraclePriceData,
|
|
126
128
|
slot: number
|
|
127
129
|
): BN {
|
|
128
130
|
let limitPrice;
|
|
129
|
-
if (
|
|
130
|
-
limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
|
|
131
|
+
if (order.oraclePriceOffset !== 0) {
|
|
132
|
+
limitPrice = oraclePriceData.price.add(new BN(order.oraclePriceOffset));
|
|
131
133
|
} else if (isOneOfVariant(order.orderType, ['market', 'triggerMarket'])) {
|
|
132
|
-
if (isAuctionComplete(order, slot)) {
|
|
134
|
+
if (!isAuctionComplete(order, slot)) {
|
|
133
135
|
limitPrice = getAuctionPrice(order, slot);
|
|
134
136
|
} else if (!order.price.eq(ZERO)) {
|
|
135
137
|
limitPrice = order.price;
|
|
136
|
-
} else if (isVariant(order.direction, 'long')) {
|
|
137
|
-
const askPrice = calculateAskPrice(market, oraclePriceData);
|
|
138
|
-
const delta = askPrice.div(new BN(market.amm.maxSlippageRatio));
|
|
139
|
-
limitPrice = askPrice.add(delta);
|
|
140
138
|
} else {
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
|
|
139
|
+
// check oracle validity?
|
|
140
|
+
const oraclePrice1Pct = oraclePriceData.price.div(new BN(100));
|
|
141
|
+
if (isVariant(order.direction, 'long')) {
|
|
142
|
+
limitPrice = oraclePriceData.price.add(oraclePrice1Pct);
|
|
143
|
+
} else {
|
|
144
|
+
limitPrice = oraclePriceData.price.sub(oraclePrice1Pct);
|
|
145
|
+
}
|
|
144
146
|
}
|
|
145
147
|
} else {
|
|
146
148
|
limitPrice = order.price;
|
|
@@ -148,3 +150,143 @@ export function getLimitPrice(
|
|
|
148
150
|
|
|
149
151
|
return limitPrice;
|
|
150
152
|
}
|
|
153
|
+
|
|
154
|
+
export function getOptionalLimitPrice(
|
|
155
|
+
order: Order,
|
|
156
|
+
oraclePriceData: OraclePriceData,
|
|
157
|
+
slot: number
|
|
158
|
+
): BN | undefined {
|
|
159
|
+
if (hasLimitPrice(order, slot)) {
|
|
160
|
+
return getLimitPrice(order, oraclePriceData, slot);
|
|
161
|
+
} else {
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function hasLimitPrice(order: Order, slot: number): boolean {
|
|
167
|
+
return (
|
|
168
|
+
order.price.gt(ZERO) ||
|
|
169
|
+
order.oraclePriceOffset != 0 ||
|
|
170
|
+
!isAuctionComplete(order, slot)
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function isFillableByVAMM(
|
|
175
|
+
order: Order,
|
|
176
|
+
market: PerpMarketAccount,
|
|
177
|
+
oraclePriceData: OraclePriceData,
|
|
178
|
+
slot: number,
|
|
179
|
+
ts: number
|
|
180
|
+
): boolean {
|
|
181
|
+
return (
|
|
182
|
+
(isAuctionComplete(order, slot) &&
|
|
183
|
+
!calculateBaseAssetAmountForAmmToFulfill(
|
|
184
|
+
order,
|
|
185
|
+
market,
|
|
186
|
+
oraclePriceData,
|
|
187
|
+
slot
|
|
188
|
+
).eq(ZERO)) ||
|
|
189
|
+
isOrderExpired(order, ts)
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function calculateBaseAssetAmountForAmmToFulfill(
|
|
194
|
+
order: Order,
|
|
195
|
+
market: PerpMarketAccount,
|
|
196
|
+
oraclePriceData: OraclePriceData,
|
|
197
|
+
slot: number
|
|
198
|
+
): BN {
|
|
199
|
+
if (mustBeTriggered(order) && !isTriggered(order)) {
|
|
200
|
+
return ZERO;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const limitPrice = getOptionalLimitPrice(order, oraclePriceData, slot);
|
|
204
|
+
let baseAssetAmount;
|
|
205
|
+
if (limitPrice !== undefined) {
|
|
206
|
+
baseAssetAmount = calculateBaseAssetAmountToFillUpToLimitPrice(
|
|
207
|
+
order,
|
|
208
|
+
market,
|
|
209
|
+
limitPrice,
|
|
210
|
+
oraclePriceData
|
|
211
|
+
);
|
|
212
|
+
} else {
|
|
213
|
+
baseAssetAmount = order.baseAssetAmount.sub(order.baseAssetAmountFilled);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const maxBaseAssetAmount = calculateMaxBaseAssetAmountFillable(
|
|
217
|
+
market.amm,
|
|
218
|
+
order.direction
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
return BN.min(maxBaseAssetAmount, baseAssetAmount);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export function calculateBaseAssetAmountToFillUpToLimitPrice(
|
|
225
|
+
order: Order,
|
|
226
|
+
market: PerpMarketAccount,
|
|
227
|
+
limitPrice: BN,
|
|
228
|
+
oraclePriceData: OraclePriceData
|
|
229
|
+
): BN {
|
|
230
|
+
const [maxAmountToTrade, direction] = calculateMaxBaseAssetAmountToTrade(
|
|
231
|
+
market.amm,
|
|
232
|
+
limitPrice,
|
|
233
|
+
order.direction,
|
|
234
|
+
oraclePriceData
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
const baseAssetAmount = standardizeBaseAssetAmount(
|
|
238
|
+
maxAmountToTrade,
|
|
239
|
+
market.amm.orderStepSize
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
// Check that directions are the same
|
|
243
|
+
const sameDirection = isSameDirection(direction, order.direction);
|
|
244
|
+
if (!sameDirection) {
|
|
245
|
+
return ZERO;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const baseAssetAmountUnfilled = order.baseAssetAmount.sub(
|
|
249
|
+
order.baseAssetAmountFilled
|
|
250
|
+
);
|
|
251
|
+
return baseAssetAmount.gt(baseAssetAmountUnfilled)
|
|
252
|
+
? baseAssetAmountUnfilled
|
|
253
|
+
: baseAssetAmount;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function isSameDirection(
|
|
257
|
+
firstDirection: PositionDirection,
|
|
258
|
+
secondDirection: PositionDirection
|
|
259
|
+
): boolean {
|
|
260
|
+
return (
|
|
261
|
+
(isVariant(firstDirection, 'long') && isVariant(secondDirection, 'long')) ||
|
|
262
|
+
(isVariant(firstDirection, 'short') && isVariant(secondDirection, 'short'))
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function isOrderExpired(order: Order, ts: number): boolean {
|
|
267
|
+
if (
|
|
268
|
+
isOneOfVariant(order.orderType, ['triggerMarket', 'triggerLimit']) ||
|
|
269
|
+
!isVariant(order.status, 'open') ||
|
|
270
|
+
order.maxTs.eq(ZERO)
|
|
271
|
+
) {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return new BN(ts).gt(order.maxTs);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export function isMarketOrder(order: Order): boolean {
|
|
279
|
+
return isOneOfVariant(order.orderType, ['market', 'triggerMarket']);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export function isLimitOrder(order: Order): boolean {
|
|
283
|
+
return isOneOfVariant(order.orderType, ['limit', 'triggerLimit']);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export function mustBeTriggered(order: Order): boolean {
|
|
287
|
+
return isOneOfVariant(order.orderType, ['triggerMarket', 'triggerLimit']);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export function isTriggered(order: Order): boolean {
|
|
291
|
+
return isOneOfVariant(order.orderType, ['triggeredAbove', 'triggeredBelow']);
|
|
292
|
+
}
|
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,64 +126,135 @@ 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:
|
|
196
|
+
export function positionIsAvailable(position: PerpPosition): boolean {
|
|
156
197
|
return (
|
|
157
198
|
position.baseAssetAmount.eq(ZERO) &&
|
|
158
|
-
position.openOrders
|
|
159
|
-
position.
|
|
199
|
+
position.openOrders === 0 &&
|
|
200
|
+
position.quoteAssetAmount.eq(ZERO) &&
|
|
201
|
+
position.lpShares.eq(ZERO)
|
|
160
202
|
);
|
|
161
203
|
}
|
|
162
204
|
|
|
163
205
|
/**
|
|
164
206
|
*
|
|
165
207
|
* @param userPosition
|
|
166
|
-
* @returns Precision:
|
|
208
|
+
* @returns Precision: PRICE_PRECISION (10^6)
|
|
167
209
|
*/
|
|
168
|
-
export function
|
|
210
|
+
export function calculateBreakEvenPrice(userPosition: PerpPosition): BN {
|
|
211
|
+
if (userPosition.baseAssetAmount.eq(ZERO)) {
|
|
212
|
+
return ZERO;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return userPosition.quoteBreakEvenAmount
|
|
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^6)
|
|
226
|
+
*/
|
|
227
|
+
export function calculateEntryPrice(userPosition: PerpPosition): BN {
|
|
228
|
+
if (userPosition.baseAssetAmount.eq(ZERO)) {
|
|
229
|
+
return ZERO;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return userPosition.quoteEntryAmount
|
|
233
|
+
.mul(PRICE_PRECISION)
|
|
234
|
+
.mul(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
235
|
+
.div(userPosition.baseAssetAmount)
|
|
236
|
+
.abs();
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
*
|
|
241
|
+
* @param userPosition
|
|
242
|
+
* @returns Precision: PRICE_PRECISION (10^10)
|
|
243
|
+
*/
|
|
244
|
+
export function calculateCostBasis(userPosition: PerpPosition): BN {
|
|
169
245
|
if (userPosition.baseAssetAmount.eq(ZERO)) {
|
|
170
246
|
return ZERO;
|
|
171
247
|
}
|
|
172
248
|
|
|
173
249
|
return userPosition.quoteAssetAmount
|
|
174
|
-
.mul(
|
|
250
|
+
.mul(PRICE_PRECISION)
|
|
175
251
|
.mul(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
176
252
|
.div(userPosition.baseAssetAmount)
|
|
177
253
|
.abs();
|
|
178
254
|
}
|
|
179
255
|
|
|
180
256
|
export function findDirectionToClose(
|
|
181
|
-
userPosition:
|
|
257
|
+
userPosition: PerpPosition
|
|
182
258
|
): PositionDirection {
|
|
183
259
|
return userPosition.baseAssetAmount.gt(ZERO)
|
|
184
260
|
? PositionDirection.SHORT
|
|
@@ -186,15 +262,13 @@ export function findDirectionToClose(
|
|
|
186
262
|
}
|
|
187
263
|
|
|
188
264
|
export function positionCurrentDirection(
|
|
189
|
-
userPosition:
|
|
265
|
+
userPosition: PerpPosition
|
|
190
266
|
): PositionDirection {
|
|
191
267
|
return userPosition.baseAssetAmount.gte(ZERO)
|
|
192
268
|
? PositionDirection.LONG
|
|
193
269
|
: PositionDirection.SHORT;
|
|
194
270
|
}
|
|
195
271
|
|
|
196
|
-
export function isEmptyPosition(userPosition:
|
|
197
|
-
return (
|
|
198
|
-
userPosition.baseAssetAmount.eq(ZERO) && userPosition.openOrders.eq(ZERO)
|
|
199
|
-
);
|
|
272
|
+
export function isEmptyPosition(userPosition: PerpPosition): boolean {
|
|
273
|
+
return userPosition.baseAssetAmount.eq(ZERO) && userPosition.openOrders === 0;
|
|
200
274
|
}
|
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,
|
|
@@ -26,20 +26,20 @@ export function calculateAdjustKCost(
|
|
|
26
26
|
const x = amm.baseAssetReserve;
|
|
27
27
|
const y = amm.quoteAssetReserve;
|
|
28
28
|
|
|
29
|
-
const d = amm.
|
|
29
|
+
const d = amm.baseAssetAmountWithAmm;
|
|
30
30
|
const Q = amm.pegMultiplier;
|
|
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
|
|
|
@@ -125,7 +135,7 @@ export function calculateBudgetedK(amm: AMM, cost: BN): [BN, BN] {
|
|
|
125
135
|
const x = amm.baseAssetReserve;
|
|
126
136
|
const y = amm.quoteAssetReserve;
|
|
127
137
|
|
|
128
|
-
const d = amm.
|
|
138
|
+
const d = amm.baseAssetAmountWithAmm;
|
|
129
139
|
const Q = amm.pegMultiplier;
|
|
130
140
|
|
|
131
141
|
const [numerator, denominator] = calculateBudgetedKBN(x, y, cost, Q, d);
|
|
@@ -149,7 +159,7 @@ export function calculateBudgetedPeg(amm: AMM, cost: BN, targetPrice: BN): BN {
|
|
|
149
159
|
const x = amm.baseAssetReserve;
|
|
150
160
|
const y = amm.quoteAssetReserve;
|
|
151
161
|
|
|
152
|
-
const d = amm.
|
|
162
|
+
const d = amm.baseAssetAmountWithAmm;
|
|
153
163
|
const Q = amm.pegMultiplier;
|
|
154
164
|
|
|
155
165
|
const C = cost.mul(new BN(-1));
|
|
@@ -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;
|