@drift-labs/sdk 0.1.36-master.7 → 0.2.0-master.2
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/bulkAccountLoader.d.ts +6 -6
- package/lib/accounts/bulkAccountLoader.js +81 -95
- package/lib/accounts/bulkUserSubscription.js +13 -57
- package/lib/accounts/fetch.d.ts +4 -0
- package/lib/accounts/fetch.js +18 -0
- package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +34 -38
- package/lib/accounts/pollingClearingHouseAccountSubscriber.js +224 -224
- package/lib/accounts/pollingOracleSubscriber.d.ts +3 -3
- package/lib/accounts/pollingOracleSubscriber.js +37 -49
- package/lib/accounts/pollingTokenAccountSubscriber.d.ts +3 -3
- package/lib/accounts/pollingTokenAccountSubscriber.js +35 -50
- package/lib/accounts/pollingUserAccountSubscriber.d.ts +7 -13
- package/lib/accounts/pollingUserAccountSubscriber.js +71 -134
- package/lib/accounts/types.d.ts +34 -41
- package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -4
- package/lib/accounts/webSocketAccountSubscriber.js +39 -35
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +33 -28
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +153 -185
- package/lib/accounts/webSocketUserAccountSubscriber.d.ts +5 -11
- package/lib/accounts/webSocketUserAccountSubscriber.js +22 -67
- package/lib/addresses/marketAddresses.d.ts +4 -0
- package/lib/addresses/marketAddresses.js +15 -0
- package/lib/addresses/pda.d.ts +12 -0
- package/lib/addresses/pda.js +83 -0
- package/lib/admin.d.ts +9 -17
- package/lib/admin.js +375 -558
- package/lib/clearingHouse.d.ts +86 -109
- package/lib/clearingHouse.js +828 -895
- package/lib/clearingHouseConfig.d.ts +34 -0
- package/lib/clearingHouseConfig.js +2 -0
- package/lib/clearingHouseUser.d.ts +19 -22
- package/lib/clearingHouseUser.js +155 -141
- package/lib/clearingHouseUserConfig.d.ts +14 -0
- package/lib/clearingHouseUserConfig.js +2 -0
- package/lib/config.d.ts +12 -0
- package/lib/config.js +35 -4
- package/lib/constants/banks.d.ts +16 -0
- package/lib/constants/banks.js +34 -0
- package/lib/constants/markets.d.ts +8 -3
- package/lib/constants/markets.js +13 -206
- package/lib/constants/numericConstants.d.ts +17 -0
- package/lib/constants/numericConstants.js +23 -6
- package/lib/events/eventList.d.ts +22 -0
- package/lib/events/eventList.js +77 -0
- package/lib/events/eventSubscriber.d.ts +34 -0
- package/lib/events/eventSubscriber.js +126 -0
- package/lib/events/fetchLogs.d.ts +13 -0
- package/lib/events/fetchLogs.js +39 -0
- package/lib/events/pollingLogProvider.d.ts +15 -0
- package/lib/events/pollingLogProvider.js +53 -0
- package/lib/events/sort.d.ts +2 -0
- package/lib/events/sort.js +44 -0
- package/lib/events/txEventCache.d.ts +24 -0
- package/lib/events/txEventCache.js +71 -0
- package/lib/events/types.d.ts +49 -0
- package/lib/events/types.js +20 -0
- package/lib/events/webSocketLogProvider.d.ts +12 -0
- package/lib/events/webSocketLogProvider.js +30 -0
- package/lib/examples/makeTradeExample.js +26 -27
- package/lib/factory/bigNum.d.ts +118 -0
- package/lib/factory/bigNum.js +364 -0
- package/lib/factory/oracleClient.d.ts +1 -2
- package/lib/factory/oracleClient.js +6 -2
- package/lib/idl/clearing_house.json +2287 -2938
- package/lib/index.d.ts +12 -4
- package/lib/index.js +12 -4
- package/lib/math/amm.d.ts +24 -29
- package/lib/math/amm.js +239 -178
- package/lib/math/auction.d.ts +5 -0
- package/lib/math/auction.js +39 -0
- package/lib/math/bankBalance.d.ts +9 -0
- package/lib/math/bankBalance.js +75 -0
- package/lib/math/conversion.d.ts +0 -1
- package/lib/math/conversion.js +1 -5
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +158 -175
- package/lib/math/market.d.ts +6 -6
- package/lib/math/market.js +10 -9
- package/lib/math/orders.d.ts +5 -0
- package/lib/math/orders.js +31 -1
- package/lib/math/position.d.ts +7 -5
- package/lib/math/position.js +27 -27
- package/lib/math/repeg.d.ts +22 -0
- package/lib/math/repeg.js +128 -0
- package/lib/math/trade.d.ts +5 -4
- package/lib/math/trade.js +29 -21
- package/lib/mockUSDCFaucet.js +87 -116
- package/lib/oracles/oracleClientCache.d.ts +8 -0
- package/lib/oracles/oracleClientCache.js +19 -0
- package/lib/oracles/pythClient.d.ts +3 -5
- package/lib/oracles/pythClient.js +12 -31
- package/lib/oracles/quoteAssetOracleClient.d.ts +9 -0
- package/lib/oracles/quoteAssetOracleClient.js +21 -0
- package/lib/oracles/switchboardClient.d.ts +3 -5
- package/lib/oracles/switchboardClient.js +29 -50
- package/lib/oracles/types.d.ts +6 -1
- package/lib/orders.d.ts +6 -7
- package/lib/orders.js +10 -80
- package/lib/slot/SlotSubscriber.d.ts +12 -0
- package/lib/slot/SlotSubscriber.js +23 -0
- package/lib/tx/retryTxSender.d.ts +2 -2
- package/lib/tx/retryTxSender.js +108 -123
- package/lib/tx/types.d.ts +5 -1
- package/lib/tx/utils.d.ts +1 -1
- package/lib/tx/utils.js +11 -2
- package/lib/types.d.ts +110 -109
- package/lib/types.js +14 -1
- package/lib/userName.d.ts +4 -0
- package/lib/userName.js +20 -0
- package/lib/util/computeUnits.js +10 -21
- package/lib/util/tps.js +11 -22
- package/lib/wallet.js +7 -20
- package/package.json +11 -4
- package/src/accounts/bulkAccountLoader.ts +21 -15
- package/src/accounts/bulkUserSubscription.ts +1 -45
- package/src/accounts/fetch.ts +33 -0
- package/src/accounts/pollingClearingHouseAccountSubscriber.ts +249 -214
- package/src/accounts/pollingOracleSubscriber.ts +16 -8
- package/src/accounts/pollingTokenAccountSubscriber.ts +11 -8
- package/src/accounts/pollingUserAccountSubscriber.ts +21 -86
- package/src/accounts/types.ts +41 -70
- package/src/accounts/webSocketAccountSubscriber.ts +33 -16
- package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +190 -240
- package/src/accounts/webSocketUserAccountSubscriber.ts +11 -71
- package/src/addresses/marketAddresses.ts +18 -0
- package/src/addresses/pda.ts +118 -0
- package/src/admin.ts +218 -346
- package/src/clearingHouse.ts +983 -952
- package/src/clearingHouseConfig.ts +37 -0
- package/src/clearingHouseUser.ts +275 -185
- package/src/clearingHouseUserConfig.ts +18 -0
- package/src/config.ts +54 -1
- package/src/constants/banks.ts +43 -0
- package/src/constants/markets.ts +16 -207
- package/src/constants/numericConstants.ts +34 -5
- package/src/events/eventList.ts +94 -0
- package/src/events/eventSubscriber.ts +194 -0
- package/src/events/fetchLogs.ts +80 -0
- package/src/events/pollingLogProvider.ts +79 -0
- package/src/events/sort.ts +65 -0
- package/src/events/txEventCache.ts +74 -0
- package/src/events/types.ts +98 -0
- package/src/events/webSocketLogProvider.ts +38 -0
- package/src/examples/makeTradeExample.ts +20 -11
- package/src/factory/bigNum.ts +524 -0
- package/src/factory/oracleClient.ts +7 -4
- package/src/idl/clearing_house.json +2287 -2938
- package/src/index.ts +12 -4
- package/src/math/amm.ts +414 -245
- package/src/math/auction.ts +39 -0
- package/src/math/bankBalance.ts +112 -0
- package/src/math/conversion.ts +1 -11
- package/src/math/funding.ts +12 -9
- package/src/math/market.ts +37 -30
- package/src/math/orders.ts +38 -0
- package/src/math/position.ts +48 -35
- package/src/math/repeg.ts +176 -0
- package/src/math/trade.ts +45 -35
- package/src/math/utils.js +27 -0
- package/src/math/utils.js.map +1 -0
- package/src/oracles/oracleClientCache.ts +20 -0
- package/src/oracles/pythClient.ts +4 -11
- package/src/oracles/quoteAssetOracleClient.ts +25 -0
- package/src/oracles/switchboardClient.ts +11 -24
- package/src/oracles/types.ts +7 -1
- package/src/orders.ts +24 -126
- package/src/slot/SlotSubscriber.ts +32 -0
- package/src/tx/retryTxSender.ts +6 -4
- package/src/tx/types.ts +6 -1
- package/src/tx/utils.ts +22 -3
- package/src/types.ts +111 -122
- package/src/userName.ts +20 -0
- package/src/util/computeUnits.js +17 -0
- package/src/util/computeUnits.js.map +1 -0
- package/tests/bn/test.ts +255 -0
- package/tsconfig.json +12 -12
- package/lib/addresses.d.ts +0 -10
- package/lib/addresses.js +0 -93
- package/lib/constants/accounts.d.ts +0 -15
- package/lib/constants/accounts.js +0 -18
- package/lib/factory/clearingHouse.d.ts +0 -35
- package/lib/factory/clearingHouse.js +0 -81
- package/lib/factory/clearingHouseUser.d.ts +0 -19
- package/lib/factory/clearingHouseUser.js +0 -34
- package/lib/math/insuranceFund.d.ts +0 -15
- package/lib/math/insuranceFund.js +0 -33
- package/lib/settlement.d.ts +0 -4
- package/lib/settlement.js +0 -10
- package/lib/tx/defaultTxSender.d.ts +0 -8
- package/lib/tx/defaultTxSender.js +0 -12
- package/src/addresses.ts +0 -82
- package/src/constants/accounts.ts +0 -26
- package/src/factory/clearingHouse.ts +0 -173
- package/src/factory/clearingHouseUser.ts +0 -73
- package/src/math/insuranceFund.ts +0 -29
- package/src/settlement.ts +0 -9
- package/src/tx/defaultTxSender.ts +0 -24
package/src/math/amm.ts
CHANGED
|
@@ -4,50 +4,256 @@ import {
|
|
|
4
4
|
MARK_PRICE_PRECISION,
|
|
5
5
|
PEG_PRECISION,
|
|
6
6
|
ZERO,
|
|
7
|
-
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
8
|
-
QUOTE_PRECISION,
|
|
9
|
-
AMM_RESERVE_PRECISION,
|
|
10
7
|
BID_ASK_SPREAD_PRECISION,
|
|
11
8
|
ONE,
|
|
9
|
+
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
10
|
+
QUOTE_PRECISION,
|
|
11
|
+
MARGIN_PRECISION,
|
|
12
|
+
PRICE_DIV_PEG,
|
|
12
13
|
} from '../constants/numericConstants';
|
|
13
|
-
import { calculateBaseAssetValue } from './position';
|
|
14
14
|
import {
|
|
15
15
|
AMM,
|
|
16
16
|
PositionDirection,
|
|
17
17
|
SwapDirection,
|
|
18
|
-
|
|
18
|
+
MarketAccount,
|
|
19
19
|
isVariant,
|
|
20
20
|
} from '../types';
|
|
21
21
|
import { assert } from '../assert/assert';
|
|
22
|
+
import { squareRootBN } from '..';
|
|
23
|
+
|
|
24
|
+
import { OraclePriceData } from '../oracles/types';
|
|
22
25
|
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
calculateRepegCost,
|
|
27
|
+
calculateAdjustKCost,
|
|
28
|
+
calculateBudgetedPeg,
|
|
29
|
+
} from './repeg';
|
|
30
|
+
|
|
31
|
+
export function calculatePegFromTargetPrice(
|
|
32
|
+
targetPrice: BN,
|
|
33
|
+
baseAssetReserve: BN,
|
|
34
|
+
quoteAssetReserve: BN
|
|
35
|
+
): BN {
|
|
36
|
+
return targetPrice
|
|
37
|
+
.mul(baseAssetReserve)
|
|
38
|
+
.div(quoteAssetReserve)
|
|
39
|
+
.add(PRICE_DIV_PEG.div(new BN(2)))
|
|
40
|
+
.div(PRICE_DIV_PEG);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function calculateOptimalPegAndBudget(
|
|
44
|
+
amm: AMM,
|
|
45
|
+
oraclePriceData: OraclePriceData
|
|
46
|
+
): [BN, BN, BN, boolean] {
|
|
47
|
+
const markPriceBefore = calculatePrice(
|
|
48
|
+
amm.baseAssetReserve,
|
|
49
|
+
amm.quoteAssetReserve,
|
|
50
|
+
amm.pegMultiplier
|
|
51
|
+
);
|
|
52
|
+
const targetPrice = oraclePriceData.price;
|
|
53
|
+
const newPeg = calculatePegFromTargetPrice(
|
|
54
|
+
targetPrice,
|
|
55
|
+
amm.baseAssetReserve,
|
|
56
|
+
amm.quoteAssetReserve
|
|
57
|
+
);
|
|
58
|
+
const prePegCost = calculateRepegCost(amm, newPeg);
|
|
59
|
+
|
|
60
|
+
const totalFeeLB = amm.totalExchangeFee.div(new BN(2));
|
|
61
|
+
const budget = BN.max(ZERO, amm.totalFeeMinusDistributions.sub(totalFeeLB));
|
|
62
|
+
if (budget.lt(prePegCost)) {
|
|
63
|
+
const maxPriceSpread = new BN(amm.maxSpread)
|
|
64
|
+
.mul(targetPrice)
|
|
65
|
+
.div(BID_ASK_SPREAD_PRECISION);
|
|
66
|
+
|
|
67
|
+
let newTargetPrice: BN;
|
|
68
|
+
let newOptimalPeg: BN;
|
|
69
|
+
let newBudget: BN;
|
|
70
|
+
const targetPriceGap = markPriceBefore.sub(targetPrice);
|
|
71
|
+
if (targetPriceGap.abs().gt(maxPriceSpread)) {
|
|
72
|
+
const markAdj = targetPriceGap.abs().sub(maxPriceSpread);
|
|
73
|
+
|
|
74
|
+
if (targetPriceGap.lt(new BN(0))) {
|
|
75
|
+
newTargetPrice = markPriceBefore.add(markAdj);
|
|
76
|
+
} else {
|
|
77
|
+
newTargetPrice = markPriceBefore.sub(markAdj);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
newOptimalPeg = calculatePegFromTargetPrice(
|
|
81
|
+
newTargetPrice,
|
|
82
|
+
amm.baseAssetReserve,
|
|
83
|
+
amm.quoteAssetReserve
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
newBudget = calculateRepegCost(amm, newOptimalPeg);
|
|
87
|
+
return [newTargetPrice, newOptimalPeg, newBudget, false];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return [targetPrice, newPeg, budget, true];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function calculateNewAmm(
|
|
95
|
+
amm: AMM,
|
|
96
|
+
oraclePriceData: OraclePriceData
|
|
97
|
+
): [BN, BN, BN, BN] {
|
|
98
|
+
let pKNumer = new BN(1);
|
|
99
|
+
let pKDenom = new BN(1);
|
|
100
|
+
|
|
101
|
+
const [targetPrice, _newPeg, budget, checkLowerBound] =
|
|
102
|
+
calculateOptimalPegAndBudget(amm, oraclePriceData);
|
|
103
|
+
let prePegCost = calculateRepegCost(amm, _newPeg);
|
|
104
|
+
let newPeg = _newPeg;
|
|
105
|
+
|
|
106
|
+
if (prePegCost.gt(budget) && checkLowerBound) {
|
|
107
|
+
[pKNumer, pKDenom] = [new BN(999), new BN(1000)];
|
|
108
|
+
const deficitMadeup = calculateAdjustKCost(amm, pKNumer, pKDenom);
|
|
109
|
+
assert(deficitMadeup.lte(new BN(0)));
|
|
110
|
+
prePegCost = budget.add(deficitMadeup.abs());
|
|
111
|
+
const newAmm = Object.assign({}, amm);
|
|
112
|
+
newAmm.baseAssetReserve = newAmm.baseAssetReserve.mul(pKNumer).div(pKDenom);
|
|
113
|
+
newAmm.sqrtK = newAmm.sqrtK.mul(pKNumer).div(pKDenom);
|
|
114
|
+
const invariant = newAmm.sqrtK.mul(newAmm.sqrtK);
|
|
115
|
+
newAmm.quoteAssetReserve = invariant.div(newAmm.baseAssetReserve);
|
|
116
|
+
const directionToClose = amm.netBaseAssetAmount.gt(ZERO)
|
|
117
|
+
? PositionDirection.SHORT
|
|
118
|
+
: PositionDirection.LONG;
|
|
119
|
+
|
|
120
|
+
const [newQuoteAssetReserve, _newBaseAssetReserve] =
|
|
121
|
+
calculateAmmReservesAfterSwap(
|
|
122
|
+
newAmm,
|
|
123
|
+
'base',
|
|
124
|
+
amm.netBaseAssetAmount.abs(),
|
|
125
|
+
getSwapDirection('base', directionToClose)
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
newAmm.terminalQuoteAssetReserve = newQuoteAssetReserve;
|
|
129
|
+
|
|
130
|
+
newPeg = calculateBudgetedPeg(newAmm, prePegCost, targetPrice);
|
|
131
|
+
prePegCost = calculateRepegCost(newAmm, newPeg);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return [prePegCost, pKNumer, pKDenom, newPeg];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function calculateUpdatedAMM(
|
|
138
|
+
amm: AMM,
|
|
139
|
+
oraclePriceData: OraclePriceData
|
|
140
|
+
): AMM {
|
|
141
|
+
if (amm.curveUpdateIntensity == 0) {
|
|
142
|
+
return amm;
|
|
143
|
+
}
|
|
144
|
+
const newAmm = Object.assign({}, amm);
|
|
145
|
+
const [prepegCost, pKNumer, pKDenom, newPeg] = calculateNewAmm(
|
|
146
|
+
amm,
|
|
147
|
+
oraclePriceData
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
newAmm.baseAssetReserve = newAmm.baseAssetReserve.mul(pKNumer).div(pKDenom);
|
|
151
|
+
newAmm.sqrtK = newAmm.sqrtK.mul(pKNumer).div(pKDenom);
|
|
152
|
+
const invariant = newAmm.sqrtK.mul(newAmm.sqrtK);
|
|
153
|
+
newAmm.quoteAssetReserve = invariant.div(newAmm.baseAssetReserve);
|
|
154
|
+
newAmm.pegMultiplier = newPeg;
|
|
155
|
+
|
|
156
|
+
const directionToClose = amm.netBaseAssetAmount.gt(ZERO)
|
|
157
|
+
? PositionDirection.SHORT
|
|
158
|
+
: PositionDirection.LONG;
|
|
159
|
+
|
|
160
|
+
const [newQuoteAssetReserve, _newBaseAssetReserve] =
|
|
161
|
+
calculateAmmReservesAfterSwap(
|
|
162
|
+
newAmm,
|
|
163
|
+
'base',
|
|
164
|
+
amm.netBaseAssetAmount.abs(),
|
|
165
|
+
getSwapDirection('base', directionToClose)
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
newAmm.terminalQuoteAssetReserve = newQuoteAssetReserve;
|
|
169
|
+
|
|
170
|
+
newAmm.totalFeeMinusDistributions =
|
|
171
|
+
newAmm.totalFeeMinusDistributions.sub(prepegCost);
|
|
172
|
+
|
|
173
|
+
return newAmm;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export function calculateUpdatedAMMSpreadReserves(
|
|
177
|
+
amm: AMM,
|
|
178
|
+
direction: PositionDirection,
|
|
179
|
+
oraclePriceData: OraclePriceData
|
|
180
|
+
): { baseAssetReserve: BN; quoteAssetReserve: BN; sqrtK: BN; newPeg: BN } {
|
|
181
|
+
const newAmm = calculateUpdatedAMM(amm, oraclePriceData);
|
|
182
|
+
const dirReserves = calculateSpreadReserves(
|
|
183
|
+
newAmm,
|
|
184
|
+
direction,
|
|
185
|
+
oraclePriceData
|
|
186
|
+
);
|
|
187
|
+
const result = {
|
|
188
|
+
baseAssetReserve: dirReserves.baseAssetReserve,
|
|
189
|
+
quoteAssetReserve: dirReserves.quoteAssetReserve,
|
|
190
|
+
sqrtK: newAmm.sqrtK,
|
|
191
|
+
newPeg: newAmm.pegMultiplier,
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
return result;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export function calculateBidAskPrice(
|
|
198
|
+
amm: AMM,
|
|
199
|
+
oraclePriceData: OraclePriceData,
|
|
200
|
+
withUpdate = true
|
|
201
|
+
): [BN, BN] {
|
|
202
|
+
let newAmm: AMM;
|
|
203
|
+
if (withUpdate) {
|
|
204
|
+
newAmm = calculateUpdatedAMM(amm, oraclePriceData);
|
|
205
|
+
} else {
|
|
206
|
+
newAmm = amm;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const askReserves = calculateSpreadReserves(
|
|
210
|
+
newAmm,
|
|
211
|
+
PositionDirection.LONG,
|
|
212
|
+
oraclePriceData
|
|
213
|
+
);
|
|
214
|
+
const bidReserves = calculateSpreadReserves(
|
|
215
|
+
newAmm,
|
|
216
|
+
PositionDirection.SHORT,
|
|
217
|
+
oraclePriceData
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
const askPrice = calculatePrice(
|
|
221
|
+
askReserves.baseAssetReserve,
|
|
222
|
+
askReserves.quoteAssetReserve,
|
|
223
|
+
newAmm.pegMultiplier
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
const bidPrice = calculatePrice(
|
|
227
|
+
bidReserves.baseAssetReserve,
|
|
228
|
+
bidReserves.quoteAssetReserve,
|
|
229
|
+
newAmm.pegMultiplier
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
return [bidPrice, askPrice];
|
|
233
|
+
}
|
|
28
234
|
|
|
29
235
|
/**
|
|
30
236
|
* Calculates a price given an arbitrary base and quote amount (they must have the same precision)
|
|
31
237
|
*
|
|
32
|
-
* @param
|
|
33
|
-
* @param
|
|
34
|
-
* @param
|
|
238
|
+
* @param baseAssetReserves
|
|
239
|
+
* @param quoteAssetReserves
|
|
240
|
+
* @param pegMultiplier
|
|
35
241
|
* @returns price : Precision MARK_PRICE_PRECISION
|
|
36
242
|
*/
|
|
37
243
|
export function calculatePrice(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
244
|
+
baseAssetReserves: BN,
|
|
245
|
+
quoteAssetReserves: BN,
|
|
246
|
+
pegMultiplier: BN
|
|
41
247
|
): BN {
|
|
42
|
-
if (
|
|
248
|
+
if (baseAssetReserves.abs().lte(ZERO)) {
|
|
43
249
|
return new BN(0);
|
|
44
250
|
}
|
|
45
251
|
|
|
46
|
-
return
|
|
252
|
+
return quoteAssetReserves
|
|
47
253
|
.mul(MARK_PRICE_PRECISION)
|
|
48
|
-
.mul(
|
|
254
|
+
.mul(pegMultiplier)
|
|
49
255
|
.div(PEG_PRECISION)
|
|
50
|
-
.div(
|
|
256
|
+
.div(baseAssetReserves);
|
|
51
257
|
}
|
|
52
258
|
|
|
53
259
|
export type AssetType = 'quote' | 'base';
|
|
@@ -98,17 +304,185 @@ export function calculateAmmReservesAfterSwap(
|
|
|
98
304
|
return [newQuoteAssetReserve, newBaseAssetReserve];
|
|
99
305
|
}
|
|
100
306
|
|
|
307
|
+
export function calculateEffectiveLeverage(
|
|
308
|
+
baseSpread: number,
|
|
309
|
+
quoteAssetReserve: BN,
|
|
310
|
+
terminalQuoteAssetReserve: BN,
|
|
311
|
+
pegMultiplier: BN,
|
|
312
|
+
netBaseAssetAmount: BN,
|
|
313
|
+
markPrice: BN,
|
|
314
|
+
totalFeeMinusDistributions: BN
|
|
315
|
+
): number {
|
|
316
|
+
// inventory skew
|
|
317
|
+
const netBaseAssetValue = quoteAssetReserve
|
|
318
|
+
.sub(terminalQuoteAssetReserve)
|
|
319
|
+
.mul(pegMultiplier)
|
|
320
|
+
.div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
|
|
321
|
+
|
|
322
|
+
const localBaseAssetValue = netBaseAssetAmount
|
|
323
|
+
.mul(markPrice)
|
|
324
|
+
.div(AMM_TO_QUOTE_PRECISION_RATIO.mul(MARK_PRICE_PRECISION));
|
|
325
|
+
|
|
326
|
+
const effectiveLeverage =
|
|
327
|
+
localBaseAssetValue.sub(netBaseAssetValue).toNumber() /
|
|
328
|
+
(Math.max(0, totalFeeMinusDistributions.toNumber()) + 1) +
|
|
329
|
+
1 / QUOTE_PRECISION.toNumber();
|
|
330
|
+
|
|
331
|
+
return effectiveLeverage;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export function calculateMaxSpread(marginRatioInitial: number): number {
|
|
335
|
+
const maxTargetSpread: number = new BN(marginRatioInitial)
|
|
336
|
+
.mul(BID_ASK_SPREAD_PRECISION.div(MARGIN_PRECISION))
|
|
337
|
+
.toNumber();
|
|
338
|
+
|
|
339
|
+
return maxTargetSpread;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export function calculateSpreadBN(
|
|
343
|
+
baseSpread: number,
|
|
344
|
+
lastOracleMarkSpreadPct: BN,
|
|
345
|
+
lastOracleConfPct: BN,
|
|
346
|
+
maxSpread: number,
|
|
347
|
+
quoteAssetReserve: BN,
|
|
348
|
+
terminalQuoteAssetReserve: BN,
|
|
349
|
+
pegMultiplier: BN,
|
|
350
|
+
netBaseAssetAmount: BN,
|
|
351
|
+
markPrice: BN,
|
|
352
|
+
totalFeeMinusDistributions: BN
|
|
353
|
+
): [number, number] {
|
|
354
|
+
let longSpread = baseSpread / 2;
|
|
355
|
+
let shortSpread = baseSpread / 2;
|
|
356
|
+
|
|
357
|
+
if (lastOracleMarkSpreadPct.gt(ZERO)) {
|
|
358
|
+
shortSpread = Math.max(
|
|
359
|
+
shortSpread,
|
|
360
|
+
lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber()
|
|
361
|
+
);
|
|
362
|
+
} else if (lastOracleMarkSpreadPct.lt(ZERO)) {
|
|
363
|
+
longSpread = Math.max(
|
|
364
|
+
longSpread,
|
|
365
|
+
lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber()
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const maxTargetSpread: number = maxSpread;
|
|
370
|
+
|
|
371
|
+
const MAX_INVENTORY_SKEW = 5;
|
|
372
|
+
|
|
373
|
+
const effectiveLeverage = calculateEffectiveLeverage(
|
|
374
|
+
baseSpread,
|
|
375
|
+
quoteAssetReserve,
|
|
376
|
+
terminalQuoteAssetReserve,
|
|
377
|
+
pegMultiplier,
|
|
378
|
+
netBaseAssetAmount,
|
|
379
|
+
markPrice,
|
|
380
|
+
totalFeeMinusDistributions
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
if (totalFeeMinusDistributions.gt(ZERO)) {
|
|
384
|
+
const spreadScale = Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
|
|
385
|
+
if (netBaseAssetAmount.gt(ZERO)) {
|
|
386
|
+
longSpread *= spreadScale;
|
|
387
|
+
} else {
|
|
388
|
+
shortSpread *= spreadScale;
|
|
389
|
+
}
|
|
390
|
+
} else {
|
|
391
|
+
longSpread *= MAX_INVENTORY_SKEW;
|
|
392
|
+
shortSpread *= MAX_INVENTORY_SKEW;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const totalSpread = longSpread + shortSpread;
|
|
396
|
+
if (totalSpread > maxTargetSpread) {
|
|
397
|
+
if (longSpread > shortSpread) {
|
|
398
|
+
longSpread = Math.min(longSpread, maxTargetSpread);
|
|
399
|
+
shortSpread = maxTargetSpread - longSpread;
|
|
400
|
+
} else {
|
|
401
|
+
shortSpread = Math.min(shortSpread, maxTargetSpread);
|
|
402
|
+
longSpread = maxTargetSpread - shortSpread;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return [longSpread, shortSpread];
|
|
407
|
+
}
|
|
408
|
+
|
|
101
409
|
export function calculateSpread(
|
|
102
410
|
amm: AMM,
|
|
103
|
-
direction: PositionDirection
|
|
411
|
+
direction: PositionDirection,
|
|
412
|
+
oraclePriceData: OraclePriceData
|
|
104
413
|
): number {
|
|
105
|
-
let spread;
|
|
414
|
+
let spread = amm.baseSpread / 2;
|
|
106
415
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
416
|
+
if (amm.baseSpread == 0 || amm.curveUpdateIntensity == 0) {
|
|
417
|
+
return spread;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const markPrice = calculatePrice(
|
|
421
|
+
amm.baseAssetReserve,
|
|
422
|
+
amm.quoteAssetReserve,
|
|
423
|
+
amm.pegMultiplier
|
|
424
|
+
);
|
|
425
|
+
|
|
426
|
+
const targetPrice = oraclePriceData?.price || markPrice;
|
|
427
|
+
const confInterval = oraclePriceData.confidence || ZERO;
|
|
428
|
+
|
|
429
|
+
const targetMarkSpreadPct = markPrice
|
|
430
|
+
.sub(targetPrice)
|
|
431
|
+
.mul(BID_ASK_SPREAD_PRECISION)
|
|
432
|
+
.div(markPrice);
|
|
433
|
+
|
|
434
|
+
const confIntervalPct = confInterval
|
|
435
|
+
.mul(BID_ASK_SPREAD_PRECISION)
|
|
436
|
+
.div(markPrice);
|
|
437
|
+
|
|
438
|
+
// oracle retreat
|
|
439
|
+
if (
|
|
440
|
+
(isVariant(direction, 'long') && targetMarkSpreadPct.lt(ZERO)) ||
|
|
441
|
+
(isVariant(direction, 'short') && targetMarkSpreadPct.gt(ZERO))
|
|
442
|
+
) {
|
|
443
|
+
spread = Math.max(
|
|
444
|
+
spread,
|
|
445
|
+
targetMarkSpreadPct.abs().toNumber() + confIntervalPct.abs().toNumber()
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// inventory skew
|
|
450
|
+
const MAX_INVENTORY_SKEW = 5;
|
|
451
|
+
if (
|
|
452
|
+
(amm.netBaseAssetAmount.gt(ZERO) && isVariant(direction, 'long')) ||
|
|
453
|
+
(amm.netBaseAssetAmount.lt(ZERO) && isVariant(direction, 'short')) ||
|
|
454
|
+
amm.totalFeeMinusDistributions.eq(ZERO)
|
|
455
|
+
) {
|
|
456
|
+
const netCostBasis = amm.quoteAssetAmountLong.sub(
|
|
457
|
+
amm.quoteAssetAmountShort
|
|
458
|
+
);
|
|
459
|
+
const netBaseAssetValue = amm.quoteAssetReserve
|
|
460
|
+
.sub(amm.terminalQuoteAssetReserve)
|
|
461
|
+
.mul(amm.pegMultiplier)
|
|
462
|
+
.div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
|
|
463
|
+
|
|
464
|
+
const localBaseAssetValue = amm.netBaseAssetAmount
|
|
465
|
+
.mul(markPrice)
|
|
466
|
+
.div(AMM_TO_QUOTE_PRECISION_RATIO.mul(MARK_PRICE_PRECISION));
|
|
467
|
+
const netPnl = netBaseAssetValue.sub(netCostBasis);
|
|
468
|
+
const localPnl = localBaseAssetValue.sub(netCostBasis);
|
|
469
|
+
|
|
470
|
+
let effectiveLeverage = MAX_INVENTORY_SKEW;
|
|
471
|
+
if (amm.totalFeeMinusDistributions.gt(ZERO)) {
|
|
472
|
+
effectiveLeverage =
|
|
473
|
+
localPnl.sub(netPnl).toNumber() /
|
|
474
|
+
(amm.totalFeeMinusDistributions.toNumber() + 1);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
let spreadScale = Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
|
|
478
|
+
const maxTargetSpread = BID_ASK_SPREAD_PRECISION.toNumber() / 50; // 2%
|
|
479
|
+
// cap the scale to attempt to only scale up to maxTargetSpread
|
|
480
|
+
// always let the oracle retreat methods go through 100%
|
|
481
|
+
if (spreadScale * spread > maxTargetSpread) {
|
|
482
|
+
spreadScale = Math.max(1.05, maxTargetSpread / spread);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
spread *= spreadScale;
|
|
112
486
|
}
|
|
113
487
|
|
|
114
488
|
return spread;
|
|
@@ -116,12 +490,13 @@ export function calculateSpread(
|
|
|
116
490
|
|
|
117
491
|
export function calculateSpreadReserves(
|
|
118
492
|
amm: AMM,
|
|
119
|
-
direction: PositionDirection
|
|
493
|
+
direction: PositionDirection,
|
|
494
|
+
oraclePriceData: OraclePriceData
|
|
120
495
|
): {
|
|
121
496
|
baseAssetReserve: BN;
|
|
122
497
|
quoteAssetReserve: BN;
|
|
123
498
|
} {
|
|
124
|
-
const spread = calculateSpread(amm, direction);
|
|
499
|
+
const spread = calculateSpread(amm, direction, oraclePriceData);
|
|
125
500
|
|
|
126
501
|
if (spread === 0) {
|
|
127
502
|
return {
|
|
@@ -131,7 +506,7 @@ export function calculateSpreadReserves(
|
|
|
131
506
|
}
|
|
132
507
|
|
|
133
508
|
const quoteAsserReserveDelta = amm.quoteAssetReserve.div(
|
|
134
|
-
BID_ASK_SPREAD_PRECISION.div(new BN(spread /
|
|
509
|
+
BID_ASK_SPREAD_PRECISION.div(new BN(spread / 2))
|
|
135
510
|
);
|
|
136
511
|
|
|
137
512
|
let quoteAssetReserve;
|
|
@@ -194,133 +569,14 @@ export function getSwapDirection(
|
|
|
194
569
|
return SwapDirection.ADD;
|
|
195
570
|
}
|
|
196
571
|
|
|
197
|
-
/**
|
|
198
|
-
* Helper function calculating adjust k cost
|
|
199
|
-
* @param market
|
|
200
|
-
* @param marketIndex
|
|
201
|
-
* @param numerator
|
|
202
|
-
* @param denomenator
|
|
203
|
-
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
204
|
-
*/
|
|
205
|
-
export function calculateAdjustKCost(
|
|
206
|
-
market: Market,
|
|
207
|
-
marketIndex: BN,
|
|
208
|
-
numerator: BN,
|
|
209
|
-
denomenator: BN
|
|
210
|
-
): BN {
|
|
211
|
-
const netUserPosition = {
|
|
212
|
-
baseAssetAmount: market.baseAssetAmount,
|
|
213
|
-
lastCumulativeFundingRate: market.amm.cumulativeFundingRate,
|
|
214
|
-
marketIndex: new BN(marketIndex),
|
|
215
|
-
quoteAssetAmount: new BN(0),
|
|
216
|
-
openOrders: new BN(0),
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
const currentValue = calculateBaseAssetValue(market, netUserPosition);
|
|
220
|
-
|
|
221
|
-
const marketNewK = Object.assign({}, market);
|
|
222
|
-
marketNewK.amm = Object.assign({}, market.amm);
|
|
223
|
-
|
|
224
|
-
marketNewK.amm.baseAssetReserve = market.amm.baseAssetReserve
|
|
225
|
-
.mul(numerator)
|
|
226
|
-
.div(denomenator);
|
|
227
|
-
marketNewK.amm.quoteAssetReserve = market.amm.quoteAssetReserve
|
|
228
|
-
.mul(numerator)
|
|
229
|
-
.div(denomenator);
|
|
230
|
-
marketNewK.amm.sqrtK = market.amm.sqrtK.mul(numerator).div(denomenator);
|
|
231
|
-
|
|
232
|
-
netUserPosition.quoteAssetAmount = currentValue;
|
|
233
|
-
|
|
234
|
-
const cost = calculatePositionPNL(marketNewK, netUserPosition);
|
|
235
|
-
|
|
236
|
-
const p = PEG_PRECISION.mul(numerator).div(denomenator);
|
|
237
|
-
const x = market.amm.baseAssetReserve;
|
|
238
|
-
const y = market.amm.quoteAssetReserve;
|
|
239
|
-
const delta = market.baseAssetAmount;
|
|
240
|
-
const k = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
241
|
-
|
|
242
|
-
const numer1 = PEG_PRECISION.sub(p).mul(y).div(PEG_PRECISION);
|
|
243
|
-
const numer20 = k
|
|
244
|
-
.mul(p)
|
|
245
|
-
.mul(p)
|
|
246
|
-
.div(PEG_PRECISION)
|
|
247
|
-
.div(PEG_PRECISION)
|
|
248
|
-
.div(x.mul(p).div(PEG_PRECISION).add(delta));
|
|
249
|
-
const numer21 = k.div(x.add(delta));
|
|
250
|
-
|
|
251
|
-
const formulaCost = numer21
|
|
252
|
-
.sub(numer20)
|
|
253
|
-
.sub(numer1)
|
|
254
|
-
.mul(market.amm.pegMultiplier)
|
|
255
|
-
.div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
|
|
256
|
-
console.log(convertToNumber(formulaCost, QUOTE_PRECISION));
|
|
257
|
-
|
|
258
|
-
// p.div(p.mul(x).add(delta)).sub()
|
|
259
|
-
|
|
260
|
-
return cost;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Helper function calculating adjust pegMultiplier (repeg) cost
|
|
265
|
-
*
|
|
266
|
-
* @param market
|
|
267
|
-
* @param marketIndex
|
|
268
|
-
* @param newPeg
|
|
269
|
-
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
270
|
-
*/
|
|
271
|
-
export function calculateRepegCost(
|
|
272
|
-
market: Market,
|
|
273
|
-
marketIndex: BN,
|
|
274
|
-
newPeg: BN
|
|
275
|
-
): BN {
|
|
276
|
-
const netUserPosition = {
|
|
277
|
-
baseAssetAmount: market.baseAssetAmount,
|
|
278
|
-
lastCumulativeFundingRate: market.amm.cumulativeFundingRate,
|
|
279
|
-
marketIndex: new BN(marketIndex),
|
|
280
|
-
quoteAssetAmount: new BN(0),
|
|
281
|
-
openOrders: new BN(0),
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
const currentValue = calculateBaseAssetValue(market, netUserPosition);
|
|
285
|
-
netUserPosition.quoteAssetAmount = currentValue;
|
|
286
|
-
const prevMarketPrice = calculateMarkPrice(market);
|
|
287
|
-
const marketNewPeg = Object.assign({}, market);
|
|
288
|
-
marketNewPeg.amm = Object.assign({}, market.amm);
|
|
289
|
-
|
|
290
|
-
// const marketNewPeg = JSON.parse(JSON.stringify(market));
|
|
291
|
-
marketNewPeg.amm.pegMultiplier = newPeg;
|
|
292
|
-
|
|
293
|
-
console.log(
|
|
294
|
-
'Price moves from',
|
|
295
|
-
convertToNumber(prevMarketPrice),
|
|
296
|
-
'to',
|
|
297
|
-
convertToNumber(calculateMarkPrice(marketNewPeg))
|
|
298
|
-
);
|
|
299
|
-
|
|
300
|
-
const cost = calculatePositionPNL(marketNewPeg, netUserPosition);
|
|
301
|
-
|
|
302
|
-
const k = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
303
|
-
const newQuoteAssetReserve = k.div(
|
|
304
|
-
market.amm.baseAssetReserve.add(netUserPosition.baseAssetAmount)
|
|
305
|
-
);
|
|
306
|
-
const deltaQuoteAssetReserves = newQuoteAssetReserve.sub(
|
|
307
|
-
market.amm.quoteAssetReserve
|
|
308
|
-
);
|
|
309
|
-
const cost2 = deltaQuoteAssetReserves
|
|
310
|
-
.mul(market.amm.pegMultiplier.sub(newPeg))
|
|
311
|
-
.div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
|
|
312
|
-
console.log(convertToNumber(cost2, QUOTE_PRECISION));
|
|
313
|
-
return cost;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
572
|
/**
|
|
317
573
|
* Helper function calculating terminal price of amm
|
|
318
574
|
*
|
|
319
575
|
* @param market
|
|
320
576
|
* @returns cost : Precision MARK_PRICE_PRECISION
|
|
321
577
|
*/
|
|
322
|
-
export function calculateTerminalPrice(market:
|
|
323
|
-
const directionToClose = market.
|
|
578
|
+
export function calculateTerminalPrice(market: MarketAccount) {
|
|
579
|
+
const directionToClose = market.amm.netBaseAssetAmount.gt(ZERO)
|
|
324
580
|
? PositionDirection.SHORT
|
|
325
581
|
: PositionDirection.LONG;
|
|
326
582
|
|
|
@@ -328,7 +584,7 @@ export function calculateTerminalPrice(market: Market) {
|
|
|
328
584
|
calculateAmmReservesAfterSwap(
|
|
329
585
|
market.amm,
|
|
330
586
|
'base',
|
|
331
|
-
market.
|
|
587
|
+
market.amm.netBaseAssetAmount.abs(),
|
|
332
588
|
getSwapDirection('base', directionToClose)
|
|
333
589
|
);
|
|
334
590
|
|
|
@@ -345,7 +601,7 @@ export function calculateMaxBaseAssetAmountToTrade(
|
|
|
345
601
|
amm: AMM,
|
|
346
602
|
limit_price: BN,
|
|
347
603
|
direction: PositionDirection,
|
|
348
|
-
|
|
604
|
+
oraclePriceData?: OraclePriceData
|
|
349
605
|
): [BN, PositionDirection] {
|
|
350
606
|
const invariant = amm.sqrtK.mul(amm.sqrtK);
|
|
351
607
|
|
|
@@ -357,15 +613,11 @@ export function calculateMaxBaseAssetAmountToTrade(
|
|
|
357
613
|
|
|
358
614
|
const newBaseAssetReserve = squareRootBN(newBaseAssetReserveSquared);
|
|
359
615
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
).baseAssetReserve;
|
|
366
|
-
} else {
|
|
367
|
-
baseAssetReserveBefore = amm.baseAssetReserve;
|
|
368
|
-
}
|
|
616
|
+
const baseAssetReserveBefore = calculateSpreadReserves(
|
|
617
|
+
amm,
|
|
618
|
+
direction,
|
|
619
|
+
oraclePriceData
|
|
620
|
+
).baseAssetReserve;
|
|
369
621
|
|
|
370
622
|
if (newBaseAssetReserve.gt(baseAssetReserveBefore)) {
|
|
371
623
|
return [
|
|
@@ -383,89 +635,6 @@ export function calculateMaxBaseAssetAmountToTrade(
|
|
|
383
635
|
}
|
|
384
636
|
}
|
|
385
637
|
|
|
386
|
-
export function calculateBudgetedK(market: Market, cost: BN): [BN, BN] {
|
|
387
|
-
// wolframalpha.com
|
|
388
|
-
// (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
|
|
389
|
-
// p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*y*d*Q)
|
|
390
|
-
|
|
391
|
-
// todo: assumes k = x * y
|
|
392
|
-
// otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
|
|
393
|
-
|
|
394
|
-
// const k = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
395
|
-
const x = market.amm.baseAssetReserve;
|
|
396
|
-
const y = market.amm.quoteAssetReserve;
|
|
397
|
-
|
|
398
|
-
const d = market.baseAssetAmount;
|
|
399
|
-
const Q = market.amm.pegMultiplier;
|
|
400
|
-
|
|
401
|
-
const C = cost.mul(new BN(-1));
|
|
402
|
-
|
|
403
|
-
const numer1 = y.mul(d).mul(Q).div(AMM_RESERVE_PRECISION).div(PEG_PRECISION);
|
|
404
|
-
const numer2 = C.mul(x.add(d)).div(QUOTE_PRECISION);
|
|
405
|
-
const denom1 = C.mul(x)
|
|
406
|
-
.mul(x.add(d))
|
|
407
|
-
.div(AMM_RESERVE_PRECISION)
|
|
408
|
-
.div(QUOTE_PRECISION);
|
|
409
|
-
const denom2 = y
|
|
410
|
-
.mul(d)
|
|
411
|
-
.mul(d)
|
|
412
|
-
.mul(Q)
|
|
413
|
-
.div(AMM_RESERVE_PRECISION)
|
|
414
|
-
.div(AMM_RESERVE_PRECISION)
|
|
415
|
-
.div(PEG_PRECISION);
|
|
416
|
-
|
|
417
|
-
const numerator = d
|
|
418
|
-
.mul(numer1.add(numer2))
|
|
419
|
-
.div(AMM_RESERVE_PRECISION)
|
|
420
|
-
.div(AMM_RESERVE_PRECISION)
|
|
421
|
-
.div(AMM_TO_QUOTE_PRECISION_RATIO);
|
|
422
|
-
const denominator = denom1
|
|
423
|
-
.add(denom2)
|
|
424
|
-
.div(AMM_RESERVE_PRECISION)
|
|
425
|
-
.div(AMM_TO_QUOTE_PRECISION_RATIO);
|
|
426
|
-
console.log(numerator, denominator);
|
|
427
|
-
// const p = (numerator).div(denominator);
|
|
428
|
-
|
|
429
|
-
// const formulaCost = (numer21.sub(numer20).sub(numer1)).mul(market.amm.pegMultiplier).div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO)
|
|
430
|
-
// console.log(convertToNumber(formulaCost, QUOTE_PRECISION))
|
|
431
|
-
|
|
432
|
-
return [numerator, denominator];
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
export function calculateBudgetedPeg(market: Market, cost: BN): BN {
|
|
436
|
-
// wolframalpha.com
|
|
437
|
-
// (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p
|
|
438
|
-
// p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*y*d*Q)
|
|
439
|
-
|
|
440
|
-
// todo: assumes k = x * y
|
|
441
|
-
// otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
|
|
442
|
-
|
|
443
|
-
const k = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
444
|
-
const x = market.amm.baseAssetReserve;
|
|
445
|
-
const y = market.amm.quoteAssetReserve;
|
|
446
|
-
|
|
447
|
-
const d = market.baseAssetAmount;
|
|
448
|
-
const Q = market.amm.pegMultiplier;
|
|
449
|
-
|
|
450
|
-
const C = cost.mul(new BN(-1));
|
|
451
|
-
|
|
452
|
-
const deltaQuoteAssetReserves = y.sub(k.div(x.add(d)));
|
|
453
|
-
const deltaPegMultiplier = C.mul(MARK_PRICE_PRECISION)
|
|
454
|
-
.div(deltaQuoteAssetReserves.div(AMM_TO_QUOTE_PRECISION_RATIO))
|
|
455
|
-
.mul(PEG_PRECISION)
|
|
456
|
-
.div(QUOTE_PRECISION);
|
|
457
|
-
console.log(
|
|
458
|
-
Q.toNumber(),
|
|
459
|
-
'change by',
|
|
460
|
-
deltaPegMultiplier.toNumber() / MARK_PRICE_PRECISION.toNumber()
|
|
461
|
-
);
|
|
462
|
-
const newPeg = Q.sub(
|
|
463
|
-
deltaPegMultiplier.mul(PEG_PRECISION).div(MARK_PRICE_PRECISION)
|
|
464
|
-
);
|
|
465
|
-
|
|
466
|
-
return newPeg;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
638
|
export function calculateQuoteAssetAmountSwapped(
|
|
470
639
|
quoteAssetReserves: BN,
|
|
471
640
|
pegMultiplier: BN,
|