@drift-labs/sdk 0.2.0-master.25 → 0.2.0-master.26
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/pollingClearingHouseAccountSubscriber.d.ts +13 -13
- package/lib/accounts/pollingClearingHouseAccountSubscriber.js +27 -27
- package/lib/accounts/types.d.ts +8 -9
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +14 -14
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +35 -34
- package/lib/addresses/pda.d.ts +7 -6
- package/lib/addresses/pda.js +31 -27
- package/lib/admin.d.ts +9 -6
- package/lib/admin.js +83 -42
- package/lib/clearingHouse.d.ts +69 -42
- package/lib/clearingHouse.js +753 -277
- package/lib/clearingHouseConfig.d.ts +2 -2
- package/lib/clearingHouseUser.d.ts +16 -16
- package/lib/clearingHouseUser.js +139 -119
- package/lib/config.d.ts +7 -7
- package/lib/config.js +20 -20
- package/lib/constants/numericConstants.d.ts +12 -12
- package/lib/constants/numericConstants.js +13 -13
- package/lib/constants/{markets.d.ts → perpMarkets.d.ts} +5 -5
- package/{src/constants/markets.js → lib/constants/perpMarkets.js} +4 -4
- package/lib/constants/{banks.d.ts → spotMarkets.d.ts} +6 -6
- package/lib/constants/{banks.js → spotMarkets.js} +16 -16
- package/lib/events/types.d.ts +2 -1
- package/lib/events/types.js +1 -0
- package/lib/examples/makeTradeExample.js +7 -7
- package/lib/idl/clearing_house.json +1008 -279
- package/lib/index.d.ts +5 -3
- package/lib/index.js +5 -3
- package/lib/math/amm.d.ts +2 -2
- package/lib/math/amm.js +1 -1
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +2 -1
- package/lib/math/margin.d.ts +4 -4
- package/lib/math/margin.js +18 -11
- package/lib/math/market.d.ts +10 -9
- package/lib/math/market.js +29 -6
- package/lib/math/oracles.d.ts +2 -1
- package/lib/math/oracles.js +11 -1
- package/lib/math/orders.d.ts +5 -5
- package/lib/math/position.d.ts +13 -13
- package/lib/math/position.js +19 -19
- package/lib/math/spotBalance.d.ts +19 -0
- package/lib/math/spotBalance.js +176 -0
- package/lib/math/spotMarket.d.ts +4 -0
- package/lib/math/spotMarket.js +8 -0
- package/lib/math/spotPosition.d.ts +2 -0
- package/lib/math/spotPosition.js +8 -0
- package/lib/math/state.js +2 -2
- package/lib/math/trade.d.ts +4 -4
- package/lib/orderParams.d.ts +4 -4
- package/lib/orderParams.js +12 -4
- package/lib/serum/serumSubscriber.d.ts +23 -0
- package/lib/serum/serumSubscriber.js +41 -0
- package/lib/serum/types.d.ts +11 -0
- package/lib/serum/types.js +2 -0
- package/lib/tx/retryTxSender.d.ts +1 -1
- package/lib/tx/retryTxSender.js +4 -2
- package/lib/tx/types.d.ts +1 -1
- package/lib/types.d.ts +123 -33
- package/lib/types.js +31 -9
- package/my-script/.env +7 -0
- package/my-script/getUserStats.ts +106 -0
- package/my-script/multiConnections.ts +119 -0
- package/my-script/test-regex.ts +11 -0
- package/my-script/utils.ts +52 -0
- package/package.json +1 -1
- package/src/accounts/bulkAccountLoader.js +249 -0
- package/src/accounts/bulkUserStatsSubscription.js +75 -0
- package/src/accounts/bulkUserSubscription.js +75 -0
- package/src/accounts/fetch.js +92 -0
- package/src/accounts/pollingClearingHouseAccountSubscriber.js +465 -0
- package/src/accounts/pollingClearingHouseAccountSubscriber.ts +38 -38
- package/src/accounts/pollingOracleSubscriber.js +156 -0
- package/src/accounts/pollingTokenAccountSubscriber.js +141 -0
- package/src/accounts/pollingUserAccountSubscriber.js +208 -0
- package/src/accounts/pollingUserStatsAccountSubscriber.js +208 -0
- package/src/accounts/types.js +28 -0
- package/src/accounts/types.ts +11 -9
- package/src/accounts/utils.js +7 -0
- package/src/accounts/webSocketAccountSubscriber.js +138 -0
- package/src/accounts/webSocketClearingHouseAccountSubscriber.js +433 -0
- package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +59 -52
- package/src/accounts/webSocketUserAccountSubscriber.js +113 -0
- package/src/accounts/webSocketUserStatsAccountSubsriber.js +113 -0
- package/src/addresses/pda.js +186 -0
- package/src/addresses/pda.ts +49 -44
- package/src/admin.js +1284 -0
- package/src/admin.ts +140 -47
- package/src/assert/assert.js +1 -1
- package/src/clearingHouse.js +3433 -0
- package/src/clearingHouse.ts +1083 -378
- package/src/clearingHouseConfig.js +2 -0
- package/src/clearingHouseConfig.ts +2 -2
- package/src/clearingHouseUser.js +874 -0
- package/src/clearingHouseUser.ts +232 -168
- package/src/clearingHouseUserConfig.js +2 -0
- package/src/clearingHouseUserStats.js +115 -0
- package/src/clearingHouseUserStatsConfig.js +2 -0
- package/src/config.js +80 -0
- package/src/config.ts +29 -29
- package/src/constants/numericConstants.js +18 -11
- package/src/constants/numericConstants.ts +17 -15
- package/{lib/constants/markets.js → src/constants/perpMarkets.js} +11 -11
- package/src/constants/{markets.ts → perpMarkets.ts} +5 -5
- package/src/constants/spotMarkets.js +51 -0
- package/src/constants/{banks.ts → spotMarkets.ts} +19 -19
- package/src/events/eventList.js +66 -23
- package/src/events/eventSubscriber.js +202 -0
- package/src/events/fetchLogs.js +117 -0
- package/src/events/pollingLogProvider.js +113 -0
- package/src/events/sort.js +41 -0
- package/src/events/txEventCache.js +22 -19
- package/src/events/types.js +25 -0
- package/src/events/types.ts +3 -0
- package/src/events/webSocketLogProvider.js +76 -0
- package/src/examples/makeTradeExample.ts +10 -8
- package/src/factory/bigNum.js +183 -180
- package/src/factory/oracleClient.js +9 -9
- package/src/idl/clearing_house.json +1008 -279
- package/src/index.js +75 -0
- package/src/index.ts +5 -3
- package/src/math/amm.js +422 -0
- package/src/math/amm.ts +6 -3
- package/src/math/auction.js +10 -10
- package/src/math/conversion.js +4 -3
- package/src/math/funding.js +223 -175
- package/src/math/funding.ts +7 -7
- package/src/math/insurance.js +27 -0
- package/src/math/margin.js +77 -0
- package/src/math/margin.ts +34 -23
- package/src/math/market.js +105 -0
- package/src/math/market.ts +71 -19
- package/src/math/oracles.js +40 -10
- package/src/math/oracles.ts +18 -1
- package/src/math/orders.js +153 -0
- package/src/math/orders.ts +5 -5
- package/src/math/position.js +172 -0
- package/src/math/position.ts +31 -31
- package/src/math/repeg.js +40 -40
- package/src/math/spotBalance.js +176 -0
- package/src/math/spotBalance.ts +290 -0
- package/src/math/spotMarket.js +8 -0
- package/src/math/spotMarket.ts +9 -0
- package/src/math/spotPosition.js +8 -0
- package/src/math/spotPosition.ts +6 -0
- package/src/math/state.ts +2 -2
- package/src/math/trade.js +81 -74
- package/src/math/trade.ts +4 -4
- package/src/math/utils.js +8 -7
- package/src/oracles/oracleClientCache.js +10 -9
- package/src/oracles/pythClient.js +52 -17
- package/src/oracles/quoteAssetOracleClient.js +44 -13
- package/src/oracles/switchboardClient.js +69 -37
- package/src/oracles/types.js +1 -1
- package/src/orderParams.js +14 -6
- package/src/orderParams.ts +16 -8
- package/src/serum/serumSubscriber.js +102 -0
- package/src/serum/serumSubscriber.ts +80 -0
- package/src/serum/types.js +2 -0
- package/src/serum/types.ts +13 -0
- package/src/slot/SlotSubscriber.js +67 -20
- package/src/token/index.js +4 -4
- package/src/tokenFaucet.js +288 -154
- package/src/tx/retryTxSender.js +280 -0
- package/src/tx/retryTxSender.ts +5 -2
- package/src/tx/types.js +1 -1
- package/src/tx/types.ts +2 -1
- package/src/tx/utils.js +7 -6
- package/src/types.js +216 -0
- package/src/types.ts +110 -33
- package/src/userName.js +5 -5
- package/src/util/computeUnits.js +46 -11
- package/src/util/promiseTimeout.js +5 -5
- package/src/util/tps.js +46 -12
- package/src/wallet.js +55 -18
- package/lib/math/bankBalance.d.ts +0 -15
- package/lib/math/bankBalance.js +0 -150
- package/src/addresses/marketAddresses.js +0 -26
- package/src/constants/banks.js +0 -42
- package/src/examples/makeTradeExample.js +0 -80
- package/src/math/bankBalance.ts +0 -258
- package/src/math/state.js +0 -15
- package/src/math/utils.js.map +0 -1
- package/src/util/getTokenAddress.js +0 -9
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.__esModule = true;
|
|
3
|
+
exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateCostBasis = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculateUnsettledPnl = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
|
|
4
|
+
var __1 = require("../");
|
|
5
|
+
var numericConstants_1 = require("../constants/numericConstants");
|
|
6
|
+
var types_1 = require("../types");
|
|
7
|
+
var amm_1 = require("./amm");
|
|
8
|
+
var margin_1 = require("./margin");
|
|
9
|
+
/**
|
|
10
|
+
* calculateBaseAssetValue
|
|
11
|
+
* = market value of closing entire position
|
|
12
|
+
* @param market
|
|
13
|
+
* @param userPosition
|
|
14
|
+
* @param oraclePriceData
|
|
15
|
+
* @returns Base Asset Value. : Precision QUOTE_PRECISION
|
|
16
|
+
*/
|
|
17
|
+
function calculateBaseAssetValue(market, userPosition, oraclePriceData) {
|
|
18
|
+
if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
19
|
+
return numericConstants_1.ZERO;
|
|
20
|
+
}
|
|
21
|
+
var directionToClose = findDirectionToClose(userPosition);
|
|
22
|
+
var prepegAmm;
|
|
23
|
+
if (market.amm.baseSpread > 0) {
|
|
24
|
+
var _a = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, directionToClose, oraclePriceData), baseAssetReserve = _a.baseAssetReserve, quoteAssetReserve = _a.quoteAssetReserve, sqrtK = _a.sqrtK, newPeg = _a.newPeg;
|
|
25
|
+
prepegAmm = {
|
|
26
|
+
baseAssetReserve: baseAssetReserve,
|
|
27
|
+
quoteAssetReserve: quoteAssetReserve,
|
|
28
|
+
sqrtK: sqrtK,
|
|
29
|
+
pegMultiplier: newPeg
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
prepegAmm = (0, amm_1.calculateUpdatedAMM)(market.amm, oraclePriceData);
|
|
34
|
+
}
|
|
35
|
+
var _b = (0, amm_1.calculateAmmReservesAfterSwap)(prepegAmm, 'base', userPosition.baseAssetAmount.abs(), (0, amm_1.getSwapDirection)('base', directionToClose)), newQuoteAssetReserve = _b[0], _ = _b[1];
|
|
36
|
+
switch (directionToClose) {
|
|
37
|
+
case types_1.PositionDirection.SHORT:
|
|
38
|
+
return prepegAmm.quoteAssetReserve
|
|
39
|
+
.sub(newQuoteAssetReserve)
|
|
40
|
+
.mul(prepegAmm.pegMultiplier)
|
|
41
|
+
.div(numericConstants_1.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
|
|
42
|
+
case types_1.PositionDirection.LONG:
|
|
43
|
+
return newQuoteAssetReserve
|
|
44
|
+
.sub(prepegAmm.quoteAssetReserve)
|
|
45
|
+
.mul(prepegAmm.pegMultiplier)
|
|
46
|
+
.div(numericConstants_1.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO)
|
|
47
|
+
.add(numericConstants_1.ONE);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.calculateBaseAssetValue = calculateBaseAssetValue;
|
|
51
|
+
/**
|
|
52
|
+
* calculatePositionPNL
|
|
53
|
+
* = BaseAssetAmount * (Avg Exit Price - Avg Entry Price)
|
|
54
|
+
* @param market
|
|
55
|
+
* @param PerpPosition
|
|
56
|
+
* @param withFunding (adds unrealized funding payment pnl to result)
|
|
57
|
+
* @param oraclePriceData
|
|
58
|
+
* @returns BaseAssetAmount : Precision QUOTE_PRECISION
|
|
59
|
+
*/
|
|
60
|
+
function calculatePositionPNL(market, perpPosition, withFunding, oraclePriceData) {
|
|
61
|
+
if (withFunding === void 0) { withFunding = false; }
|
|
62
|
+
if (perpPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
63
|
+
return perpPosition.quoteAssetAmount;
|
|
64
|
+
}
|
|
65
|
+
var baseAssetValue = (0, margin_1.calculateBaseAssetValueWithOracle)(market, perpPosition, oraclePriceData);
|
|
66
|
+
var baseAssetValueSign = perpPosition.baseAssetAmount.isNeg()
|
|
67
|
+
? new __1.BN(-1)
|
|
68
|
+
: new __1.BN(1);
|
|
69
|
+
var pnl = baseAssetValue
|
|
70
|
+
.mul(baseAssetValueSign)
|
|
71
|
+
.add(perpPosition.quoteAssetAmount);
|
|
72
|
+
if (withFunding) {
|
|
73
|
+
var fundingRatePnL = calculatePositionFundingPNL(market, perpPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
|
|
74
|
+
pnl = pnl.add(fundingRatePnL);
|
|
75
|
+
}
|
|
76
|
+
return pnl;
|
|
77
|
+
}
|
|
78
|
+
exports.calculatePositionPNL = calculatePositionPNL;
|
|
79
|
+
function calculateUnsettledPnl(market, perpPosition, oraclePriceData) {
|
|
80
|
+
var unrealizedPnl = calculatePositionPNL(market, perpPosition, true, oraclePriceData);
|
|
81
|
+
var unsettledPnl = unrealizedPnl;
|
|
82
|
+
if (unrealizedPnl.gt(numericConstants_1.ZERO)) {
|
|
83
|
+
var fundingPnL = calculatePositionFundingPNL(market, perpPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
|
|
84
|
+
var maxPositivePnl = __1.BN.max(perpPosition.quoteAssetAmount
|
|
85
|
+
.sub(perpPosition.quoteEntryAmount)
|
|
86
|
+
.add(fundingPnL), numericConstants_1.ZERO);
|
|
87
|
+
unsettledPnl = __1.BN.min(maxPositivePnl, unrealizedPnl);
|
|
88
|
+
}
|
|
89
|
+
return unsettledPnl;
|
|
90
|
+
}
|
|
91
|
+
exports.calculateUnsettledPnl = calculateUnsettledPnl;
|
|
92
|
+
/**
|
|
93
|
+
*
|
|
94
|
+
* @param market
|
|
95
|
+
* @param PerpPosition
|
|
96
|
+
* @returns // TODO-PRECISION
|
|
97
|
+
*/
|
|
98
|
+
function calculatePositionFundingPNL(market, perpPosition) {
|
|
99
|
+
if (perpPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
100
|
+
return numericConstants_1.ZERO;
|
|
101
|
+
}
|
|
102
|
+
var ammCumulativeFundingRate;
|
|
103
|
+
if (perpPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
|
|
104
|
+
ammCumulativeFundingRate = market.amm.cumulativeFundingRateLong;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
ammCumulativeFundingRate = market.amm.cumulativeFundingRateShort;
|
|
108
|
+
}
|
|
109
|
+
var perPositionFundingRate = ammCumulativeFundingRate
|
|
110
|
+
.sub(perpPosition.lastCumulativeFundingRate)
|
|
111
|
+
.mul(perpPosition.baseAssetAmount)
|
|
112
|
+
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
113
|
+
.div(numericConstants_1.FUNDING_PAYMENT_PRECISION)
|
|
114
|
+
.mul(new __1.BN(-1));
|
|
115
|
+
return perPositionFundingRate;
|
|
116
|
+
}
|
|
117
|
+
exports.calculatePositionFundingPNL = calculatePositionFundingPNL;
|
|
118
|
+
function positionIsAvailable(position) {
|
|
119
|
+
return (position.baseAssetAmount.eq(numericConstants_1.ZERO) &&
|
|
120
|
+
position.openOrders.eq(numericConstants_1.ZERO) &&
|
|
121
|
+
position.quoteAssetAmount.eq(numericConstants_1.ZERO) &&
|
|
122
|
+
position.lpShares.eq(numericConstants_1.ZERO));
|
|
123
|
+
}
|
|
124
|
+
exports.positionIsAvailable = positionIsAvailable;
|
|
125
|
+
/**
|
|
126
|
+
*
|
|
127
|
+
* @param userPosition
|
|
128
|
+
* @returns Precision: MARK_PRICE_PRECISION (10^10)
|
|
129
|
+
*/
|
|
130
|
+
function calculateEntryPrice(userPosition) {
|
|
131
|
+
if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
132
|
+
return numericConstants_1.ZERO;
|
|
133
|
+
}
|
|
134
|
+
return userPosition.quoteEntryAmount
|
|
135
|
+
.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
136
|
+
.mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
|
|
137
|
+
.div(userPosition.baseAssetAmount)
|
|
138
|
+
.abs();
|
|
139
|
+
}
|
|
140
|
+
exports.calculateEntryPrice = calculateEntryPrice;
|
|
141
|
+
/**
|
|
142
|
+
*
|
|
143
|
+
* @param userPosition
|
|
144
|
+
* @returns Precision: MARK_PRICE_PRECISION (10^10)
|
|
145
|
+
*/
|
|
146
|
+
function calculateCostBasis(userPosition) {
|
|
147
|
+
if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
148
|
+
return numericConstants_1.ZERO;
|
|
149
|
+
}
|
|
150
|
+
return userPosition.quoteAssetAmount
|
|
151
|
+
.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
152
|
+
.mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
|
|
153
|
+
.div(userPosition.baseAssetAmount)
|
|
154
|
+
.abs();
|
|
155
|
+
}
|
|
156
|
+
exports.calculateCostBasis = calculateCostBasis;
|
|
157
|
+
function findDirectionToClose(userPosition) {
|
|
158
|
+
return userPosition.baseAssetAmount.gt(numericConstants_1.ZERO)
|
|
159
|
+
? types_1.PositionDirection.SHORT
|
|
160
|
+
: types_1.PositionDirection.LONG;
|
|
161
|
+
}
|
|
162
|
+
exports.findDirectionToClose = findDirectionToClose;
|
|
163
|
+
function positionCurrentDirection(userPosition) {
|
|
164
|
+
return userPosition.baseAssetAmount.gte(numericConstants_1.ZERO)
|
|
165
|
+
? types_1.PositionDirection.LONG
|
|
166
|
+
: types_1.PositionDirection.SHORT;
|
|
167
|
+
}
|
|
168
|
+
exports.positionCurrentDirection = positionCurrentDirection;
|
|
169
|
+
function isEmptyPosition(userPosition) {
|
|
170
|
+
return (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO) && userPosition.openOrders.eq(numericConstants_1.ZERO));
|
|
171
|
+
}
|
|
172
|
+
exports.isEmptyPosition = isEmptyPosition;
|
package/src/math/position.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
ZERO,
|
|
11
11
|
} from '../constants/numericConstants';
|
|
12
12
|
import { OraclePriceData } from '../oracles/types';
|
|
13
|
-
import {
|
|
13
|
+
import { PerpMarketAccount, PositionDirection, PerpPosition } from '../types';
|
|
14
14
|
import {
|
|
15
15
|
calculateUpdatedAMM,
|
|
16
16
|
calculateUpdatedAMMSpreadReserves,
|
|
@@ -29,8 +29,8 @@ import { calculateBaseAssetValueWithOracle } from './margin';
|
|
|
29
29
|
* @returns Base Asset Value. : Precision QUOTE_PRECISION
|
|
30
30
|
*/
|
|
31
31
|
export function calculateBaseAssetValue(
|
|
32
|
-
market:
|
|
33
|
-
userPosition:
|
|
32
|
+
market: PerpMarketAccount,
|
|
33
|
+
userPosition: PerpPosition,
|
|
34
34
|
oraclePriceData: OraclePriceData
|
|
35
35
|
): BN {
|
|
36
36
|
if (userPosition.baseAssetAmount.eq(ZERO)) {
|
|
@@ -84,38 +84,38 @@ export function calculateBaseAssetValue(
|
|
|
84
84
|
* calculatePositionPNL
|
|
85
85
|
* = BaseAssetAmount * (Avg Exit Price - Avg Entry Price)
|
|
86
86
|
* @param market
|
|
87
|
-
* @param
|
|
87
|
+
* @param PerpPosition
|
|
88
88
|
* @param withFunding (adds unrealized funding payment pnl to result)
|
|
89
89
|
* @param oraclePriceData
|
|
90
90
|
* @returns BaseAssetAmount : Precision QUOTE_PRECISION
|
|
91
91
|
*/
|
|
92
92
|
export function calculatePositionPNL(
|
|
93
|
-
market:
|
|
94
|
-
|
|
93
|
+
market: PerpMarketAccount,
|
|
94
|
+
perpPosition: PerpPosition,
|
|
95
95
|
withFunding = false,
|
|
96
96
|
oraclePriceData: OraclePriceData
|
|
97
97
|
): BN {
|
|
98
|
-
if (
|
|
99
|
-
return
|
|
98
|
+
if (perpPosition.baseAssetAmount.eq(ZERO)) {
|
|
99
|
+
return perpPosition.quoteAssetAmount;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
const baseAssetValue = calculateBaseAssetValueWithOracle(
|
|
103
103
|
market,
|
|
104
|
-
|
|
104
|
+
perpPosition,
|
|
105
105
|
oraclePriceData
|
|
106
106
|
);
|
|
107
107
|
|
|
108
|
-
const baseAssetValueSign =
|
|
108
|
+
const baseAssetValueSign = perpPosition.baseAssetAmount.isNeg()
|
|
109
109
|
? new BN(-1)
|
|
110
110
|
: new BN(1);
|
|
111
111
|
let pnl = baseAssetValue
|
|
112
112
|
.mul(baseAssetValueSign)
|
|
113
|
-
.add(
|
|
113
|
+
.add(perpPosition.quoteAssetAmount);
|
|
114
114
|
|
|
115
115
|
if (withFunding) {
|
|
116
116
|
const fundingRatePnL = calculatePositionFundingPNL(
|
|
117
117
|
market,
|
|
118
|
-
|
|
118
|
+
perpPosition
|
|
119
119
|
).div(PRICE_TO_QUOTE_PRECISION);
|
|
120
120
|
|
|
121
121
|
pnl = pnl.add(fundingRatePnL);
|
|
@@ -125,26 +125,26 @@ export function calculatePositionPNL(
|
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
export function calculateUnsettledPnl(
|
|
128
|
-
market:
|
|
129
|
-
|
|
128
|
+
market: PerpMarketAccount,
|
|
129
|
+
perpPosition: PerpPosition,
|
|
130
130
|
oraclePriceData: OraclePriceData
|
|
131
131
|
): BN {
|
|
132
132
|
const unrealizedPnl = calculatePositionPNL(
|
|
133
133
|
market,
|
|
134
|
-
|
|
134
|
+
perpPosition,
|
|
135
135
|
true,
|
|
136
136
|
oraclePriceData
|
|
137
137
|
);
|
|
138
138
|
|
|
139
139
|
let unsettledPnl = unrealizedPnl;
|
|
140
140
|
if (unrealizedPnl.gt(ZERO)) {
|
|
141
|
-
const fundingPnL = calculatePositionFundingPNL(market,
|
|
141
|
+
const fundingPnL = calculatePositionFundingPNL(market, perpPosition).div(
|
|
142
142
|
PRICE_TO_QUOTE_PRECISION
|
|
143
143
|
);
|
|
144
144
|
|
|
145
145
|
const maxPositivePnl = BN.max(
|
|
146
|
-
|
|
147
|
-
.sub(
|
|
146
|
+
perpPosition.quoteAssetAmount
|
|
147
|
+
.sub(perpPosition.quoteEntryAmount)
|
|
148
148
|
.add(fundingPnL),
|
|
149
149
|
ZERO
|
|
150
150
|
);
|
|
@@ -157,27 +157,27 @@ export function calculateUnsettledPnl(
|
|
|
157
157
|
/**
|
|
158
158
|
*
|
|
159
159
|
* @param market
|
|
160
|
-
* @param
|
|
160
|
+
* @param PerpPosition
|
|
161
161
|
* @returns // TODO-PRECISION
|
|
162
162
|
*/
|
|
163
163
|
export function calculatePositionFundingPNL(
|
|
164
|
-
market:
|
|
165
|
-
|
|
164
|
+
market: PerpMarketAccount,
|
|
165
|
+
perpPosition: PerpPosition
|
|
166
166
|
): BN {
|
|
167
|
-
if (
|
|
167
|
+
if (perpPosition.baseAssetAmount.eq(ZERO)) {
|
|
168
168
|
return ZERO;
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
let ammCumulativeFundingRate: BN;
|
|
172
|
-
if (
|
|
172
|
+
if (perpPosition.baseAssetAmount.gt(ZERO)) {
|
|
173
173
|
ammCumulativeFundingRate = market.amm.cumulativeFundingRateLong;
|
|
174
174
|
} else {
|
|
175
175
|
ammCumulativeFundingRate = market.amm.cumulativeFundingRateShort;
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
const perPositionFundingRate = ammCumulativeFundingRate
|
|
179
|
-
.sub(
|
|
180
|
-
.mul(
|
|
179
|
+
.sub(perpPosition.lastCumulativeFundingRate)
|
|
180
|
+
.mul(perpPosition.baseAssetAmount)
|
|
181
181
|
.div(AMM_RESERVE_PRECISION)
|
|
182
182
|
.div(FUNDING_PAYMENT_PRECISION)
|
|
183
183
|
.mul(new BN(-1));
|
|
@@ -185,7 +185,7 @@ export function calculatePositionFundingPNL(
|
|
|
185
185
|
return perPositionFundingRate;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
export function positionIsAvailable(position:
|
|
188
|
+
export function positionIsAvailable(position: PerpPosition): boolean {
|
|
189
189
|
return (
|
|
190
190
|
position.baseAssetAmount.eq(ZERO) &&
|
|
191
191
|
position.openOrders.eq(ZERO) &&
|
|
@@ -199,7 +199,7 @@ export function positionIsAvailable(position: UserPosition): boolean {
|
|
|
199
199
|
* @param userPosition
|
|
200
200
|
* @returns Precision: MARK_PRICE_PRECISION (10^10)
|
|
201
201
|
*/
|
|
202
|
-
export function calculateEntryPrice(userPosition:
|
|
202
|
+
export function calculateEntryPrice(userPosition: PerpPosition): BN {
|
|
203
203
|
if (userPosition.baseAssetAmount.eq(ZERO)) {
|
|
204
204
|
return ZERO;
|
|
205
205
|
}
|
|
@@ -216,7 +216,7 @@ export function calculateEntryPrice(userPosition: UserPosition): BN {
|
|
|
216
216
|
* @param userPosition
|
|
217
217
|
* @returns Precision: MARK_PRICE_PRECISION (10^10)
|
|
218
218
|
*/
|
|
219
|
-
export function calculateCostBasis(userPosition:
|
|
219
|
+
export function calculateCostBasis(userPosition: PerpPosition): BN {
|
|
220
220
|
if (userPosition.baseAssetAmount.eq(ZERO)) {
|
|
221
221
|
return ZERO;
|
|
222
222
|
}
|
|
@@ -229,7 +229,7 @@ export function calculateCostBasis(userPosition: UserPosition): BN {
|
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
export function findDirectionToClose(
|
|
232
|
-
userPosition:
|
|
232
|
+
userPosition: PerpPosition
|
|
233
233
|
): PositionDirection {
|
|
234
234
|
return userPosition.baseAssetAmount.gt(ZERO)
|
|
235
235
|
? PositionDirection.SHORT
|
|
@@ -237,14 +237,14 @@ export function findDirectionToClose(
|
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
export function positionCurrentDirection(
|
|
240
|
-
userPosition:
|
|
240
|
+
userPosition: PerpPosition
|
|
241
241
|
): PositionDirection {
|
|
242
242
|
return userPosition.baseAssetAmount.gte(ZERO)
|
|
243
243
|
? PositionDirection.LONG
|
|
244
244
|
: PositionDirection.SHORT;
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
export function isEmptyPosition(userPosition:
|
|
247
|
+
export function isEmptyPosition(userPosition: PerpPosition): boolean {
|
|
248
248
|
return (
|
|
249
249
|
userPosition.baseAssetAmount.eq(ZERO) && userPosition.openOrders.eq(ZERO)
|
|
250
250
|
);
|
package/src/math/repeg.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
2
|
+
exports.__esModule = true;
|
|
3
3
|
exports.calculateBudgetedPeg = exports.calculateBudgetedK = exports.calculateBudgetedKBN = exports.calculateRepegCost = exports.calculateAdjustKCost = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
var anchor_1 = require("@project-serum/anchor");
|
|
5
|
+
var assert_1 = require("../assert/assert");
|
|
6
|
+
var numericConstants_1 = require("../constants/numericConstants");
|
|
7
7
|
/**
|
|
8
8
|
* Helper function calculating adjust k cost
|
|
9
9
|
* @param amm
|
|
@@ -13,13 +13,13 @@ const numericConstants_1 = require("../constants/numericConstants");
|
|
|
13
13
|
*/
|
|
14
14
|
function calculateAdjustKCost(amm, numerator, denomenator) {
|
|
15
15
|
// const k = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
var x = amm.baseAssetReserve;
|
|
17
|
+
var y = amm.quoteAssetReserve;
|
|
18
|
+
var d = amm.netBaseAssetAmount;
|
|
19
|
+
var Q = amm.pegMultiplier;
|
|
20
|
+
var quoteScale = y.mul(d).mul(Q); //.div(AMM_RESERVE_PRECISION);
|
|
21
|
+
var p = numerator.mul(numericConstants_1.MARK_PRICE_PRECISION).div(denomenator);
|
|
22
|
+
var cost = quoteScale
|
|
23
23
|
.div(x.add(d))
|
|
24
24
|
.sub(quoteScale
|
|
25
25
|
.mul(p)
|
|
@@ -38,8 +38,8 @@ exports.calculateAdjustKCost = calculateAdjustKCost;
|
|
|
38
38
|
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
39
39
|
*/
|
|
40
40
|
function calculateRepegCost(amm, newPeg) {
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
var dqar = amm.quoteAssetReserve.sub(amm.terminalQuoteAssetReserve);
|
|
42
|
+
var cost = dqar
|
|
43
43
|
.mul(newPeg.sub(amm.pegMultiplier))
|
|
44
44
|
.div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
|
|
45
45
|
.div(numericConstants_1.PEG_PRECISION);
|
|
@@ -47,32 +47,32 @@ function calculateRepegCost(amm, newPeg) {
|
|
|
47
47
|
}
|
|
48
48
|
exports.calculateRepegCost = calculateRepegCost;
|
|
49
49
|
function calculateBudgetedKBN(x, y, budget, Q, d) {
|
|
50
|
-
assert_1.assert(Q.gt(new anchor_1.BN(0)));
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
(0, assert_1.assert)(Q.gt(new anchor_1.BN(0)));
|
|
51
|
+
var C = budget.mul(new anchor_1.BN(-1));
|
|
52
|
+
var dSign = new anchor_1.BN(1);
|
|
53
53
|
if (d.lt(new anchor_1.BN(0))) {
|
|
54
54
|
dSign = new anchor_1.BN(-1);
|
|
55
55
|
}
|
|
56
|
-
|
|
56
|
+
var pegged_y_d_d = y
|
|
57
57
|
.mul(d)
|
|
58
58
|
.mul(d)
|
|
59
59
|
.mul(Q)
|
|
60
60
|
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
61
61
|
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
62
62
|
.div(numericConstants_1.PEG_PRECISION);
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
var numer1 = pegged_y_d_d;
|
|
64
|
+
var numer2 = C.mul(d)
|
|
65
65
|
.div(numericConstants_1.QUOTE_PRECISION)
|
|
66
66
|
.mul(x.add(d))
|
|
67
67
|
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
68
68
|
.mul(dSign);
|
|
69
|
-
|
|
69
|
+
var denom1 = C.mul(x)
|
|
70
70
|
.mul(x.add(d))
|
|
71
71
|
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
72
72
|
.div(numericConstants_1.QUOTE_PRECISION);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
var denom2 = pegged_y_d_d;
|
|
74
|
+
var numerator = numer1.sub(numer2).div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO);
|
|
75
|
+
var denominator = denom1.add(denom2).div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO);
|
|
76
76
|
return [numerator, denominator];
|
|
77
77
|
}
|
|
78
78
|
exports.calculateBudgetedKBN = calculateBudgetedKBN;
|
|
@@ -90,11 +90,11 @@ function calculateBudgetedK(amm, cost) {
|
|
|
90
90
|
// = x/d**2 + 1 / d + mark/C
|
|
91
91
|
// todo: assumes k = x * y
|
|
92
92
|
// otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
var x = amm.baseAssetReserve;
|
|
94
|
+
var y = amm.quoteAssetReserve;
|
|
95
|
+
var d = amm.netBaseAssetAmount;
|
|
96
|
+
var Q = amm.pegMultiplier;
|
|
97
|
+
var _a = calculateBudgetedKBN(x, y, cost, Q, d), numerator = _a[0], denominator = _a[1];
|
|
98
98
|
return [numerator, denominator];
|
|
99
99
|
}
|
|
100
100
|
exports.calculateBudgetedK = calculateBudgetedK;
|
|
@@ -104,25 +104,25 @@ function calculateBudgetedPeg(amm, cost, targetPrice) {
|
|
|
104
104
|
// p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*y*d*Q)
|
|
105
105
|
// todo: assumes k = x * y
|
|
106
106
|
// otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
|
|
107
|
-
|
|
107
|
+
var targetPeg = targetPrice
|
|
108
108
|
.mul(amm.baseAssetReserve)
|
|
109
109
|
.div(amm.quoteAssetReserve)
|
|
110
110
|
.div(numericConstants_1.PRICE_DIV_PEG);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
111
|
+
var k = amm.sqrtK.mul(amm.sqrtK);
|
|
112
|
+
var x = amm.baseAssetReserve;
|
|
113
|
+
var y = amm.quoteAssetReserve;
|
|
114
|
+
var d = amm.netBaseAssetAmount;
|
|
115
|
+
var Q = amm.pegMultiplier;
|
|
116
|
+
var C = cost.mul(new anchor_1.BN(-1));
|
|
117
|
+
var deltaQuoteAssetReserves = y.sub(k.div(x.add(d)));
|
|
118
|
+
var pegChangeDirection = targetPeg.sub(Q);
|
|
119
|
+
var useTargetPeg = (deltaQuoteAssetReserves.lt(numericConstants_1.ZERO) && pegChangeDirection.gt(numericConstants_1.ZERO)) ||
|
|
120
120
|
(deltaQuoteAssetReserves.gt(numericConstants_1.ZERO) && pegChangeDirection.lt(numericConstants_1.ZERO));
|
|
121
121
|
if (deltaQuoteAssetReserves.eq(numericConstants_1.ZERO) || useTargetPeg) {
|
|
122
122
|
return targetPeg;
|
|
123
123
|
}
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
var deltaPegMultiplier = C.mul(numericConstants_1.MARK_PRICE_PRECISION).div(deltaQuoteAssetReserves.div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO));
|
|
125
|
+
var newPeg = Q.sub(deltaPegMultiplier.mul(numericConstants_1.PEG_PRECISION).div(numericConstants_1.MARK_PRICE_PRECISION));
|
|
126
126
|
return newPeg;
|
|
127
127
|
}
|
|
128
128
|
exports.calculateBudgetedPeg = calculateBudgetedPeg;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.__esModule = true;
|
|
3
|
+
exports.calculateWithdrawLimit = exports.calculateInterestAccumulated = exports.calculateBorrowRate = exports.calculateDepositRate = exports.calculateInterestRate = exports.calculateUtilization = exports.calculateLiabilityWeight = exports.calculateAssetWeight = exports.getTokenAmount = exports.getBalance = void 0;
|
|
4
|
+
var types_1 = require("../types");
|
|
5
|
+
var anchor_1 = require("@project-serum/anchor");
|
|
6
|
+
var numericConstants_1 = require("../constants/numericConstants");
|
|
7
|
+
var margin_1 = require("./margin");
|
|
8
|
+
function getBalance(tokenAmount, spotMarket, balanceType) {
|
|
9
|
+
var precisionIncrease = numericConstants_1.TEN.pow(new anchor_1.BN(16 - spotMarket.decimals));
|
|
10
|
+
var cumulativeInterest = (0, types_1.isVariant)(balanceType, 'deposit')
|
|
11
|
+
? spotMarket.cumulativeDepositInterest
|
|
12
|
+
: spotMarket.cumulativeBorrowInterest;
|
|
13
|
+
var balance = tokenAmount.mul(precisionIncrease).div(cumulativeInterest);
|
|
14
|
+
if (!balance.eq(numericConstants_1.ZERO) && (0, types_1.isVariant)(balanceType, 'borrow')) {
|
|
15
|
+
balance = balance.add(numericConstants_1.ONE);
|
|
16
|
+
}
|
|
17
|
+
return balance;
|
|
18
|
+
}
|
|
19
|
+
exports.getBalance = getBalance;
|
|
20
|
+
function getTokenAmount(balanceAmount, spotMarket, balanceType) {
|
|
21
|
+
var precisionDecrease = numericConstants_1.TEN.pow(new anchor_1.BN(16 - spotMarket.decimals));
|
|
22
|
+
var cumulativeInterest = (0, types_1.isVariant)(balanceType, 'deposit')
|
|
23
|
+
? spotMarket.cumulativeDepositInterest
|
|
24
|
+
: spotMarket.cumulativeBorrowInterest;
|
|
25
|
+
return balanceAmount.mul(cumulativeInterest).div(precisionDecrease);
|
|
26
|
+
}
|
|
27
|
+
exports.getTokenAmount = getTokenAmount;
|
|
28
|
+
function calculateAssetWeight(balanceAmount, spotMarket, marginCategory) {
|
|
29
|
+
var sizePrecision = numericConstants_1.TEN.pow(new anchor_1.BN(spotMarket.decimals));
|
|
30
|
+
var sizeInAmmReservePrecision;
|
|
31
|
+
if (sizePrecision.gt(numericConstants_1.AMM_RESERVE_PRECISION)) {
|
|
32
|
+
sizeInAmmReservePrecision = balanceAmount.div(sizePrecision.div(numericConstants_1.AMM_RESERVE_PRECISION));
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
sizeInAmmReservePrecision = balanceAmount
|
|
36
|
+
.mul(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
37
|
+
.div(sizePrecision);
|
|
38
|
+
}
|
|
39
|
+
var assetWeight;
|
|
40
|
+
switch (marginCategory) {
|
|
41
|
+
case 'Initial':
|
|
42
|
+
assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(sizeInAmmReservePrecision, spotMarket.imfFactor, spotMarket.initialAssetWeight);
|
|
43
|
+
break;
|
|
44
|
+
case 'Maintenance':
|
|
45
|
+
assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(sizeInAmmReservePrecision, spotMarket.imfFactor, spotMarket.maintenanceAssetWeight);
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
assetWeight = spotMarket.initialAssetWeight;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
return assetWeight;
|
|
52
|
+
}
|
|
53
|
+
exports.calculateAssetWeight = calculateAssetWeight;
|
|
54
|
+
function calculateLiabilityWeight(balanceAmount, spotMarket, marginCategory) {
|
|
55
|
+
var sizePrecision = numericConstants_1.TEN.pow(new anchor_1.BN(spotMarket.decimals));
|
|
56
|
+
var sizeInAmmReservePrecision;
|
|
57
|
+
if (sizePrecision.gt(numericConstants_1.AMM_RESERVE_PRECISION)) {
|
|
58
|
+
sizeInAmmReservePrecision = balanceAmount.div(sizePrecision.div(numericConstants_1.AMM_RESERVE_PRECISION));
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
sizeInAmmReservePrecision = balanceAmount
|
|
62
|
+
.mul(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
63
|
+
.div(sizePrecision);
|
|
64
|
+
}
|
|
65
|
+
var assetWeight;
|
|
66
|
+
switch (marginCategory) {
|
|
67
|
+
case 'Initial':
|
|
68
|
+
assetWeight = (0, margin_1.calculateSizePremiumLiabilityWeight)(sizeInAmmReservePrecision, spotMarket.imfFactor, spotMarket.initialLiabilityWeight, numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
69
|
+
break;
|
|
70
|
+
case 'Maintenance':
|
|
71
|
+
assetWeight = (0, margin_1.calculateSizePremiumLiabilityWeight)(sizeInAmmReservePrecision, spotMarket.imfFactor, spotMarket.maintenanceLiabilityWeight, numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
72
|
+
break;
|
|
73
|
+
default:
|
|
74
|
+
assetWeight = spotMarket.initialLiabilityWeight;
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
return assetWeight;
|
|
78
|
+
}
|
|
79
|
+
exports.calculateLiabilityWeight = calculateLiabilityWeight;
|
|
80
|
+
function calculateUtilization(bank) {
|
|
81
|
+
var tokenDepositAmount = getTokenAmount(bank.depositBalance, bank, types_1.SpotBalanceType.DEPOSIT);
|
|
82
|
+
var tokenBorrowAmount = getTokenAmount(bank.borrowBalance, bank, types_1.SpotBalanceType.BORROW);
|
|
83
|
+
var utilization;
|
|
84
|
+
if (tokenBorrowAmount.eq(numericConstants_1.ZERO) && tokenDepositAmount.eq(numericConstants_1.ZERO)) {
|
|
85
|
+
utilization = numericConstants_1.ZERO;
|
|
86
|
+
}
|
|
87
|
+
else if (tokenDepositAmount.eq(numericConstants_1.ZERO)) {
|
|
88
|
+
utilization = numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
utilization = tokenBorrowAmount
|
|
92
|
+
.mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
|
|
93
|
+
.div(tokenDepositAmount);
|
|
94
|
+
}
|
|
95
|
+
return utilization;
|
|
96
|
+
}
|
|
97
|
+
exports.calculateUtilization = calculateUtilization;
|
|
98
|
+
function calculateInterestRate(bank) {
|
|
99
|
+
var utilization = calculateUtilization(bank);
|
|
100
|
+
var interestRate;
|
|
101
|
+
if (utilization.gt(bank.optimalUtilization)) {
|
|
102
|
+
var surplusUtilization = utilization.sub(bank.optimalUtilization);
|
|
103
|
+
var borrowRateSlope = bank.maxBorrowRate
|
|
104
|
+
.sub(bank.optimalBorrowRate)
|
|
105
|
+
.mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
|
|
106
|
+
.div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION.sub(bank.optimalUtilization));
|
|
107
|
+
interestRate = bank.optimalBorrowRate.add(surplusUtilization
|
|
108
|
+
.mul(borrowRateSlope)
|
|
109
|
+
.div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION));
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
var borrowRateSlope = bank.optimalBorrowRate
|
|
113
|
+
.mul(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION)
|
|
114
|
+
.div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION.sub(bank.optimalUtilization));
|
|
115
|
+
interestRate = utilization
|
|
116
|
+
.mul(borrowRateSlope)
|
|
117
|
+
.div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION);
|
|
118
|
+
}
|
|
119
|
+
return interestRate;
|
|
120
|
+
}
|
|
121
|
+
exports.calculateInterestRate = calculateInterestRate;
|
|
122
|
+
function calculateDepositRate(bank) {
|
|
123
|
+
var utilization = calculateUtilization(bank);
|
|
124
|
+
var borrowRate = calculateBorrowRate(bank);
|
|
125
|
+
var depositRate = borrowRate
|
|
126
|
+
.mul(utilization)
|
|
127
|
+
.div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION);
|
|
128
|
+
return depositRate;
|
|
129
|
+
}
|
|
130
|
+
exports.calculateDepositRate = calculateDepositRate;
|
|
131
|
+
function calculateBorrowRate(bank) {
|
|
132
|
+
return calculateInterestRate(bank);
|
|
133
|
+
}
|
|
134
|
+
exports.calculateBorrowRate = calculateBorrowRate;
|
|
135
|
+
function calculateInterestAccumulated(bank, now) {
|
|
136
|
+
var interestRate = calculateInterestRate(bank);
|
|
137
|
+
var timeSinceLastUpdate = now.sub(bank.lastInterestTs);
|
|
138
|
+
var modifiedBorrowRate = interestRate.mul(timeSinceLastUpdate);
|
|
139
|
+
var utilization = calculateUtilization(bank);
|
|
140
|
+
var modifiedDepositRate = modifiedBorrowRate
|
|
141
|
+
.mul(utilization)
|
|
142
|
+
.div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION);
|
|
143
|
+
var borrowInterest = bank.cumulativeBorrowInterest
|
|
144
|
+
.mul(modifiedBorrowRate)
|
|
145
|
+
.div(numericConstants_1.ONE_YEAR)
|
|
146
|
+
.div(numericConstants_1.SPOT_MARKET_INTEREST_PRECISION)
|
|
147
|
+
.add(numericConstants_1.ONE);
|
|
148
|
+
var depositInterest = bank.cumulativeDepositInterest
|
|
149
|
+
.mul(modifiedDepositRate)
|
|
150
|
+
.div(numericConstants_1.ONE_YEAR)
|
|
151
|
+
.div(numericConstants_1.SPOT_MARKET_INTEREST_PRECISION);
|
|
152
|
+
return { borrowInterest: borrowInterest, depositInterest: depositInterest };
|
|
153
|
+
}
|
|
154
|
+
exports.calculateInterestAccumulated = calculateInterestAccumulated;
|
|
155
|
+
function calculateWithdrawLimit(spotMarket, now) {
|
|
156
|
+
var marketDepositTokenAmount = getTokenAmount(spotMarket.depositBalance, spotMarket, types_1.SpotBalanceType.DEPOSIT);
|
|
157
|
+
var marketBorrowTokenAmount = getTokenAmount(spotMarket.borrowBalance, spotMarket, types_1.SpotBalanceType.BORROW);
|
|
158
|
+
var twentyFourHours = new anchor_1.BN(60 * 60 * 24);
|
|
159
|
+
var sinceLast = now.sub(spotMarket.lastTwapTs);
|
|
160
|
+
var sinceStart = anchor_1.BN.max(numericConstants_1.ZERO, twentyFourHours.sub(sinceLast));
|
|
161
|
+
var borrowTokenTwapLive = spotMarket.borrowTokenTwap
|
|
162
|
+
.mul(sinceStart)
|
|
163
|
+
.add(marketBorrowTokenAmount.mul(sinceLast))
|
|
164
|
+
.div(sinceLast.add(sinceLast));
|
|
165
|
+
var depositTokenTwapLive = spotMarket.depositTokenTwap
|
|
166
|
+
.mul(sinceStart)
|
|
167
|
+
.add(marketDepositTokenAmount.mul(sinceLast))
|
|
168
|
+
.div(sinceLast.add(sinceLast));
|
|
169
|
+
var maxBorrowTokens = anchor_1.BN.min(anchor_1.BN.max(marketDepositTokenAmount.div(new anchor_1.BN(6)), borrowTokenTwapLive.add(borrowTokenTwapLive.div(new anchor_1.BN(5)))), marketDepositTokenAmount.sub(marketDepositTokenAmount.div(new anchor_1.BN(10)))); // between ~15-90% utilization with friction on twap
|
|
170
|
+
var minDepositTokens = depositTokenTwapLive.sub(anchor_1.BN.min(anchor_1.BN.max(depositTokenTwapLive.div(new anchor_1.BN(5)), spotMarket.withdrawGuardThreshold), depositTokenTwapLive));
|
|
171
|
+
return {
|
|
172
|
+
borrowLimit: maxBorrowTokens.sub(marketBorrowTokenAmount),
|
|
173
|
+
withdrawLimit: marketDepositTokenAmount.sub(minDepositTokens)
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
exports.calculateWithdrawLimit = calculateWithdrawLimit;
|