@drift-labs/sdk 0.2.0-master.0 → 0.2.0-master.11
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/admin.d.ts +8 -5
- package/lib/admin.js +43 -11
- package/lib/clearingHouse.d.ts +28 -18
- package/lib/clearingHouse.js +366 -143
- package/lib/clearingHouseUser.d.ts +2 -2
- package/lib/clearingHouseUser.js +8 -17
- package/lib/config.js +1 -1
- package/lib/constants/banks.js +9 -2
- package/lib/constants/numericConstants.d.ts +2 -0
- package/lib/constants/numericConstants.js +3 -1
- package/lib/factory/bigNum.d.ts +8 -2
- package/lib/factory/bigNum.js +14 -6
- package/lib/idl/clearing_house.json +805 -202
- package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/lib/index.d.ts +3 -2
- package/lib/index.js +7 -2
- package/lib/math/amm.d.ts +6 -1
- package/lib/math/amm.js +124 -41
- package/lib/math/auction.js +4 -1
- package/lib/math/orders.d.ts +2 -2
- package/lib/math/orders.js +18 -11
- package/lib/math/position.js +3 -1
- package/lib/math/repeg.js +1 -1
- package/lib/math/trade.d.ts +1 -1
- package/lib/math/trade.js +7 -10
- package/lib/orderParams.d.ts +14 -5
- package/lib/orderParams.js +8 -96
- package/lib/orders.d.ts +1 -2
- package/lib/orders.js +6 -85
- package/lib/slot/SlotSubscriber.d.ts +7 -0
- package/lib/slot/SlotSubscriber.js +3 -0
- package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +7 -5
- package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +41 -40
- package/lib/tx/utils.js +1 -1
- package/lib/types.d.ts +137 -14
- package/lib/types.js +53 -1
- package/lib/util/computeUnits.js +1 -1
- package/package.json +3 -3
- package/src/accounts/bulkAccountLoader.js +197 -0
- package/src/accounts/bulkUserSubscription.js +33 -0
- package/src/accounts/fetch.js +29 -0
- package/src/accounts/pollingClearingHouseAccountSubscriber.js +311 -0
- package/src/accounts/pollingOracleSubscriber.js +93 -0
- package/src/accounts/pollingTokenAccountSubscriber.js +90 -0
- package/src/accounts/pollingUserAccountSubscriber.js +132 -0
- package/src/accounts/types.js +10 -0
- package/src/accounts/utils.js +7 -0
- package/src/accounts/webSocketAccountSubscriber.js +93 -0
- package/src/accounts/webSocketClearingHouseAccountSubscriber.js +233 -0
- package/src/accounts/webSocketUserAccountSubscriber.js +62 -0
- package/src/addresses/marketAddresses.js +26 -0
- package/src/addresses/pda.js +104 -0
- package/src/admin.ts +66 -14
- package/src/assert/assert.js +9 -0
- package/src/clearingHouse.ts +558 -230
- package/src/clearingHouseUser.ts +12 -23
- package/src/config.ts +1 -1
- package/src/constants/banks.ts +9 -2
- package/src/constants/numericConstants.ts +2 -0
- package/src/events/eventList.js +77 -0
- package/src/events/eventSubscriber.js +139 -0
- package/src/events/fetchLogs.js +50 -0
- package/src/events/pollingLogProvider.js +64 -0
- package/src/events/sort.js +44 -0
- package/src/events/txEventCache.js +71 -0
- package/src/events/types.js +20 -0
- package/src/events/webSocketLogProvider.js +41 -0
- package/src/examples/makeTradeExample.js +80 -0
- package/src/factory/bigNum.js +364 -0
- package/src/factory/bigNum.ts +26 -9
- package/src/factory/oracleClient.js +20 -0
- package/src/idl/clearing_house.json +805 -202
- package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/src/index.js +100 -0
- package/src/index.ts +3 -2
- package/src/math/amm.js +369 -0
- package/src/math/amm.ts +207 -52
- package/src/math/auction.js +42 -0
- package/src/math/auction.ts +5 -1
- package/src/math/bankBalance.js +75 -0
- package/src/math/conversion.js +11 -0
- package/src/math/funding.js +248 -0
- package/src/math/market.js +57 -0
- package/src/math/oracles.js +26 -0
- package/src/math/orders.js +110 -0
- package/src/math/orders.ts +17 -13
- package/src/math/position.js +140 -0
- package/src/math/position.ts +5 -1
- package/src/math/repeg.js +128 -0
- package/src/math/repeg.ts +2 -1
- package/src/math/state.js +15 -0
- package/src/math/trade.js +253 -0
- package/src/math/trade.ts +23 -25
- package/src/math/utils.js +0 -1
- package/src/mockUSDCFaucet.js +280 -0
- package/src/oracles/oracleClientCache.js +19 -0
- package/src/oracles/pythClient.js +46 -0
- package/src/oracles/quoteAssetOracleClient.js +32 -0
- package/src/oracles/switchboardClient.js +69 -0
- package/src/oracles/types.js +2 -0
- package/src/orderParams.js +20 -0
- package/src/orderParams.ts +20 -141
- package/src/orders.js +134 -0
- package/src/orders.ts +7 -131
- package/src/slot/SlotSubscriber.js +39 -0
- package/src/slot/SlotSubscriber.ts +11 -1
- package/src/token/index.js +38 -0
- package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +48 -59
- package/src/tx/retryTxSender.js +188 -0
- package/src/tx/types.js +2 -0
- package/src/tx/utils.js +17 -0
- package/src/tx/utils.ts +1 -1
- package/src/types.js +114 -0
- package/src/types.ts +132 -16
- package/src/userName.js +20 -0
- package/src/util/computeUnits.ts +1 -1
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
- package/src/wallet.js +35 -0
- package/src/util/computeUnits.js +0 -17
- package/src/util/computeUnits.js.map +0 -1
package/src/math/amm.ts
CHANGED
|
@@ -6,8 +6,10 @@ import {
|
|
|
6
6
|
ZERO,
|
|
7
7
|
BID_ASK_SPREAD_PRECISION,
|
|
8
8
|
ONE,
|
|
9
|
-
// QUOTE_PRECISION,
|
|
10
9
|
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
10
|
+
QUOTE_PRECISION,
|
|
11
|
+
MARGIN_PRECISION,
|
|
12
|
+
PRICE_DIV_PEG,
|
|
11
13
|
} from '../constants/numericConstants';
|
|
12
14
|
import {
|
|
13
15
|
AMM,
|
|
@@ -25,6 +27,71 @@ import {
|
|
|
25
27
|
calculateAdjustKCost,
|
|
26
28
|
calculateBudgetedPeg,
|
|
27
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
|
+
|
|
72
|
+
if (targetPriceGap.abs().gt(maxPriceSpread)) {
|
|
73
|
+
const markAdj = targetPriceGap.abs().sub(maxPriceSpread);
|
|
74
|
+
|
|
75
|
+
if (targetPriceGap.lt(new BN(0))) {
|
|
76
|
+
newTargetPrice = markPriceBefore.add(markAdj);
|
|
77
|
+
} else {
|
|
78
|
+
newTargetPrice = markPriceBefore.sub(markAdj);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
newOptimalPeg = calculatePegFromTargetPrice(
|
|
82
|
+
newTargetPrice,
|
|
83
|
+
amm.baseAssetReserve,
|
|
84
|
+
amm.quoteAssetReserve
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
newBudget = calculateRepegCost(amm, newOptimalPeg);
|
|
88
|
+
return [newTargetPrice, newOptimalPeg, newBudget, false];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return [targetPrice, newPeg, budget, true];
|
|
93
|
+
}
|
|
94
|
+
|
|
28
95
|
export function calculateNewAmm(
|
|
29
96
|
amm: AMM,
|
|
30
97
|
oraclePriceData: OraclePriceData
|
|
@@ -32,18 +99,12 @@ export function calculateNewAmm(
|
|
|
32
99
|
let pKNumer = new BN(1);
|
|
33
100
|
let pKDenom = new BN(1);
|
|
34
101
|
|
|
35
|
-
const targetPrice =
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
.add(MARK_PRICE_PRECISION.div(PEG_PRECISION).div(new BN(2)))
|
|
40
|
-
.div(MARK_PRICE_PRECISION.div(PEG_PRECISION));
|
|
41
|
-
let prePegCost = calculateRepegCost(amm, newPeg);
|
|
42
|
-
|
|
43
|
-
const totalFeeLB = amm.totalExchangeFee.div(new BN(2));
|
|
44
|
-
const budget = BN.max(ZERO, amm.totalFeeMinusDistributions.sub(totalFeeLB));
|
|
102
|
+
const [targetPrice, _newPeg, budget, checkLowerBound] =
|
|
103
|
+
calculateOptimalPegAndBudget(amm, oraclePriceData);
|
|
104
|
+
let prePegCost = calculateRepegCost(amm, _newPeg);
|
|
105
|
+
let newPeg = _newPeg;
|
|
45
106
|
|
|
46
|
-
if (prePegCost.gt(budget)) {
|
|
107
|
+
if (prePegCost.gt(budget) && checkLowerBound) {
|
|
47
108
|
[pKNumer, pKDenom] = [new BN(999), new BN(1000)];
|
|
48
109
|
const deficitMadeup = calculateAdjustKCost(amm, pKNumer, pKDenom);
|
|
49
110
|
assert(deficitMadeup.lte(new BN(0)));
|
|
@@ -136,9 +197,16 @@ export function calculateUpdatedAMMSpreadReserves(
|
|
|
136
197
|
|
|
137
198
|
export function calculateBidAskPrice(
|
|
138
199
|
amm: AMM,
|
|
139
|
-
oraclePriceData: OraclePriceData
|
|
200
|
+
oraclePriceData: OraclePriceData,
|
|
201
|
+
withUpdate = true
|
|
140
202
|
): [BN, BN] {
|
|
141
|
-
|
|
203
|
+
let newAmm: AMM;
|
|
204
|
+
if (withUpdate) {
|
|
205
|
+
newAmm = calculateUpdatedAMM(amm, oraclePriceData);
|
|
206
|
+
} else {
|
|
207
|
+
newAmm = amm;
|
|
208
|
+
}
|
|
209
|
+
|
|
142
210
|
const askReserves = calculateSpreadReserves(
|
|
143
211
|
newAmm,
|
|
144
212
|
PositionDirection.LONG,
|
|
@@ -237,15 +305,115 @@ export function calculateAmmReservesAfterSwap(
|
|
|
237
305
|
return [newQuoteAssetReserve, newBaseAssetReserve];
|
|
238
306
|
}
|
|
239
307
|
|
|
308
|
+
export function calculateEffectiveLeverage(
|
|
309
|
+
baseSpread: number,
|
|
310
|
+
quoteAssetReserve: BN,
|
|
311
|
+
terminalQuoteAssetReserve: BN,
|
|
312
|
+
pegMultiplier: BN,
|
|
313
|
+
netBaseAssetAmount: BN,
|
|
314
|
+
markPrice: BN,
|
|
315
|
+
totalFeeMinusDistributions: BN
|
|
316
|
+
): number {
|
|
317
|
+
// inventory skew
|
|
318
|
+
const netBaseAssetValue = quoteAssetReserve
|
|
319
|
+
.sub(terminalQuoteAssetReserve)
|
|
320
|
+
.mul(pegMultiplier)
|
|
321
|
+
.div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
|
|
322
|
+
|
|
323
|
+
const localBaseAssetValue = netBaseAssetAmount
|
|
324
|
+
.mul(markPrice)
|
|
325
|
+
.div(AMM_TO_QUOTE_PRECISION_RATIO.mul(MARK_PRICE_PRECISION));
|
|
326
|
+
|
|
327
|
+
const effectiveLeverage =
|
|
328
|
+
localBaseAssetValue.sub(netBaseAssetValue).toNumber() /
|
|
329
|
+
(Math.max(0, totalFeeMinusDistributions.toNumber()) + 1) +
|
|
330
|
+
1 / QUOTE_PRECISION.toNumber();
|
|
331
|
+
|
|
332
|
+
return effectiveLeverage;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export function calculateMaxSpread(marginRatioInitial: number): number {
|
|
336
|
+
const maxTargetSpread: number = new BN(marginRatioInitial)
|
|
337
|
+
.mul(BID_ASK_SPREAD_PRECISION.div(MARGIN_PRECISION))
|
|
338
|
+
.toNumber();
|
|
339
|
+
|
|
340
|
+
return maxTargetSpread;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export function calculateSpreadBN(
|
|
344
|
+
baseSpread: number,
|
|
345
|
+
lastOracleMarkSpreadPct: BN,
|
|
346
|
+
lastOracleConfPct: BN,
|
|
347
|
+
maxSpread: number,
|
|
348
|
+
quoteAssetReserve: BN,
|
|
349
|
+
terminalQuoteAssetReserve: BN,
|
|
350
|
+
pegMultiplier: BN,
|
|
351
|
+
netBaseAssetAmount: BN,
|
|
352
|
+
markPrice: BN,
|
|
353
|
+
totalFeeMinusDistributions: BN
|
|
354
|
+
): [number, number] {
|
|
355
|
+
let longSpread = baseSpread / 2;
|
|
356
|
+
let shortSpread = baseSpread / 2;
|
|
357
|
+
|
|
358
|
+
if (lastOracleMarkSpreadPct.gt(ZERO)) {
|
|
359
|
+
shortSpread = Math.max(
|
|
360
|
+
shortSpread,
|
|
361
|
+
lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber()
|
|
362
|
+
);
|
|
363
|
+
} else if (lastOracleMarkSpreadPct.lt(ZERO)) {
|
|
364
|
+
longSpread = Math.max(
|
|
365
|
+
longSpread,
|
|
366
|
+
lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber()
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const maxTargetSpread: number = maxSpread;
|
|
371
|
+
|
|
372
|
+
const MAX_INVENTORY_SKEW = 5;
|
|
373
|
+
|
|
374
|
+
const effectiveLeverage = calculateEffectiveLeverage(
|
|
375
|
+
baseSpread,
|
|
376
|
+
quoteAssetReserve,
|
|
377
|
+
terminalQuoteAssetReserve,
|
|
378
|
+
pegMultiplier,
|
|
379
|
+
netBaseAssetAmount,
|
|
380
|
+
markPrice,
|
|
381
|
+
totalFeeMinusDistributions
|
|
382
|
+
);
|
|
383
|
+
|
|
384
|
+
if (totalFeeMinusDistributions.gt(ZERO)) {
|
|
385
|
+
const spreadScale = Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
|
|
386
|
+
if (netBaseAssetAmount.gt(ZERO)) {
|
|
387
|
+
longSpread *= spreadScale;
|
|
388
|
+
} else {
|
|
389
|
+
shortSpread *= spreadScale;
|
|
390
|
+
}
|
|
391
|
+
} else {
|
|
392
|
+
longSpread *= MAX_INVENTORY_SKEW;
|
|
393
|
+
shortSpread *= MAX_INVENTORY_SKEW;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const totalSpread = longSpread + shortSpread;
|
|
397
|
+
if (totalSpread > maxTargetSpread) {
|
|
398
|
+
if (longSpread > shortSpread) {
|
|
399
|
+
longSpread = Math.min(longSpread, maxTargetSpread);
|
|
400
|
+
shortSpread = maxTargetSpread - longSpread;
|
|
401
|
+
} else {
|
|
402
|
+
shortSpread = Math.min(shortSpread, maxTargetSpread);
|
|
403
|
+
longSpread = maxTargetSpread - shortSpread;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return [longSpread, shortSpread];
|
|
408
|
+
}
|
|
409
|
+
|
|
240
410
|
export function calculateSpread(
|
|
241
411
|
amm: AMM,
|
|
242
412
|
direction: PositionDirection,
|
|
243
413
|
oraclePriceData: OraclePriceData
|
|
244
414
|
): number {
|
|
245
|
-
let spread = amm.baseSpread / 2;
|
|
246
|
-
|
|
247
415
|
if (amm.baseSpread == 0 || amm.curveUpdateIntensity == 0) {
|
|
248
|
-
return
|
|
416
|
+
return amm.baseSpread / 2;
|
|
249
417
|
}
|
|
250
418
|
|
|
251
419
|
const markPrice = calculatePrice(
|
|
@@ -255,49 +423,36 @@ export function calculateSpread(
|
|
|
255
423
|
);
|
|
256
424
|
|
|
257
425
|
const targetPrice = oraclePriceData?.price || markPrice;
|
|
426
|
+
const confInterval = oraclePriceData.confidence || ZERO;
|
|
258
427
|
|
|
259
428
|
const targetMarkSpreadPct = markPrice
|
|
260
429
|
.sub(targetPrice)
|
|
261
430
|
.mul(BID_ASK_SPREAD_PRECISION)
|
|
262
431
|
.div(markPrice);
|
|
263
432
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
(isVariant(direction, 'short') && targetMarkSpreadPct.gt(ZERO))
|
|
268
|
-
) {
|
|
269
|
-
spread = Math.max(spread, targetMarkSpreadPct.abs().toNumber());
|
|
270
|
-
}
|
|
433
|
+
const confIntervalPct = confInterval
|
|
434
|
+
.mul(BID_ASK_SPREAD_PRECISION)
|
|
435
|
+
.div(markPrice);
|
|
271
436
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
amm.
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
const localBaseAssetValue = amm.netBaseAssetAmount
|
|
288
|
-
.mul(markPrice)
|
|
289
|
-
.div(AMM_TO_QUOTE_PRECISION_RATIO.mul(MARK_PRICE_PRECISION));
|
|
290
|
-
const netPnl = netBaseAssetValue.sub(netCostBasis);
|
|
291
|
-
const localPnl = localBaseAssetValue.sub(netCostBasis);
|
|
292
|
-
|
|
293
|
-
let effectiveLeverage = MAX_INVENTORY_SKEW;
|
|
294
|
-
if (amm.totalFeeMinusDistributions.gt(ZERO)) {
|
|
295
|
-
effectiveLeverage =
|
|
296
|
-
localPnl.sub(netPnl).toNumber() /
|
|
297
|
-
amm.totalFeeMinusDistributions.toNumber();
|
|
298
|
-
}
|
|
437
|
+
const [longSpread, shortSpread] = calculateSpreadBN(
|
|
438
|
+
amm.baseSpread,
|
|
439
|
+
targetMarkSpreadPct,
|
|
440
|
+
confIntervalPct,
|
|
441
|
+
amm.maxSpread,
|
|
442
|
+
amm.quoteAssetReserve,
|
|
443
|
+
amm.terminalQuoteAssetReserve,
|
|
444
|
+
amm.pegMultiplier,
|
|
445
|
+
amm.netBaseAssetAmount,
|
|
446
|
+
markPrice,
|
|
447
|
+
amm.totalFeeMinusDistributions
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
let spread: number;
|
|
299
451
|
|
|
300
|
-
|
|
452
|
+
if (isVariant(direction, 'long')) {
|
|
453
|
+
spread = longSpread;
|
|
454
|
+
} else {
|
|
455
|
+
spread = shortSpread;
|
|
301
456
|
}
|
|
302
457
|
|
|
303
458
|
return spread;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAuctionPrice = exports.isAuctionComplete = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
const _1 = require("../.");
|
|
6
|
+
function isAuctionComplete(order, slot) {
|
|
7
|
+
if (order.auctionDuration === 0) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
return new _1.BN(slot).sub(order.slot).gt(new _1.BN(order.auctionDuration));
|
|
11
|
+
}
|
|
12
|
+
exports.isAuctionComplete = isAuctionComplete;
|
|
13
|
+
function getAuctionPrice(order, slot) {
|
|
14
|
+
const slotsElapsed = new _1.BN(slot).sub(order.slot);
|
|
15
|
+
const deltaDenominator = new _1.BN(order.auctionDuration);
|
|
16
|
+
const deltaNumerator = _1.BN.min(slotsElapsed, deltaDenominator);
|
|
17
|
+
if (deltaDenominator.eq(_1.ZERO)) {
|
|
18
|
+
return order.auctionEndPrice;
|
|
19
|
+
}
|
|
20
|
+
let priceDelta;
|
|
21
|
+
if (types_1.isVariant(order.direction, 'long')) {
|
|
22
|
+
priceDelta = order.auctionEndPrice
|
|
23
|
+
.sub(order.auctionStartPrice)
|
|
24
|
+
.mul(deltaNumerator)
|
|
25
|
+
.div(deltaDenominator);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
priceDelta = order.auctionStartPrice
|
|
29
|
+
.sub(order.auctionEndPrice)
|
|
30
|
+
.mul(deltaNumerator)
|
|
31
|
+
.div(deltaDenominator);
|
|
32
|
+
}
|
|
33
|
+
let price;
|
|
34
|
+
if (types_1.isVariant(order.direction, 'long')) {
|
|
35
|
+
price = order.auctionStartPrice.add(priceDelta);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
price = order.auctionStartPrice.sub(priceDelta);
|
|
39
|
+
}
|
|
40
|
+
return price;
|
|
41
|
+
}
|
|
42
|
+
exports.getAuctionPrice = getAuctionPrice;
|
package/src/math/auction.ts
CHANGED
|
@@ -2,7 +2,11 @@ import { isVariant, Order } from '../types';
|
|
|
2
2
|
import { BN, ZERO } from '../.';
|
|
3
3
|
|
|
4
4
|
export function isAuctionComplete(order: Order, slot: number): boolean {
|
|
5
|
-
|
|
5
|
+
if (order.auctionDuration === 0) {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
return new BN(slot).sub(order.slot).gt(new BN(order.auctionDuration));
|
|
6
10
|
}
|
|
7
11
|
|
|
8
12
|
export function getAuctionPrice(order: Order, slot: number): BN {
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateInterestAccumulated = exports.getTokenAmount = exports.getBalance = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
const anchor_1 = require("@project-serum/anchor");
|
|
6
|
+
const numericConstants_1 = require("../constants/numericConstants");
|
|
7
|
+
function getBalance(tokenAmount, bank, balanceType) {
|
|
8
|
+
const precisionIncrease = numericConstants_1.TEN.pow(new anchor_1.BN(16 - bank.decimals));
|
|
9
|
+
const cumulativeInterest = types_1.isVariant(balanceType, 'deposit')
|
|
10
|
+
? bank.cumulativeDepositInterest
|
|
11
|
+
: bank.cumulativeBorrowInterest;
|
|
12
|
+
let balance = tokenAmount.mul(precisionIncrease).div(cumulativeInterest);
|
|
13
|
+
if (!balance.eq(numericConstants_1.ZERO) && types_1.isVariant(balanceType, 'borrow')) {
|
|
14
|
+
balance = balance.add(numericConstants_1.ONE);
|
|
15
|
+
}
|
|
16
|
+
return balance;
|
|
17
|
+
}
|
|
18
|
+
exports.getBalance = getBalance;
|
|
19
|
+
function getTokenAmount(balanceAmount, bank, balanceType) {
|
|
20
|
+
const precisionDecrease = numericConstants_1.TEN.pow(new anchor_1.BN(16 - bank.decimals));
|
|
21
|
+
const cumulativeInterest = types_1.isVariant(balanceType, 'deposit')
|
|
22
|
+
? bank.cumulativeDepositInterest
|
|
23
|
+
: bank.cumulativeBorrowInterest;
|
|
24
|
+
return balanceAmount.mul(cumulativeInterest).div(precisionDecrease);
|
|
25
|
+
}
|
|
26
|
+
exports.getTokenAmount = getTokenAmount;
|
|
27
|
+
function calculateInterestAccumulated(bank, now) {
|
|
28
|
+
const token_deposit_amount = getTokenAmount(bank.depositBalance, bank, types_1.BankBalanceType.DEPOSIT);
|
|
29
|
+
const token_borrow_amount = getTokenAmount(bank.borrowBalance, bank, types_1.BankBalanceType.BORROW);
|
|
30
|
+
let utilization;
|
|
31
|
+
if (token_borrow_amount.eq(numericConstants_1.ZERO) && token_deposit_amount.eq(numericConstants_1.ZERO)) {
|
|
32
|
+
utilization = numericConstants_1.ZERO;
|
|
33
|
+
}
|
|
34
|
+
else if (token_deposit_amount.eq(numericConstants_1.ZERO)) {
|
|
35
|
+
utilization = numericConstants_1.BANK_UTILIZATION_PRECISION;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
utilization = token_borrow_amount
|
|
39
|
+
.mul(numericConstants_1.BANK_UTILIZATION_PRECISION)
|
|
40
|
+
.div(token_deposit_amount);
|
|
41
|
+
}
|
|
42
|
+
let interest_rate;
|
|
43
|
+
if (utilization.gt(bank.optimalUtilization)) {
|
|
44
|
+
const surplusUtilization = utilization.sub(bank.optimalUtilization);
|
|
45
|
+
const borrowRateSlope = bank.maxBorrowRate
|
|
46
|
+
.sub(bank.optimalBorrowRate)
|
|
47
|
+
.mul(numericConstants_1.BANK_UTILIZATION_PRECISION)
|
|
48
|
+
.div(numericConstants_1.BANK_UTILIZATION_PRECISION.sub(bank.optimalUtilization));
|
|
49
|
+
interest_rate = bank.optimalBorrowRate.add(surplusUtilization.mul(borrowRateSlope).div(numericConstants_1.BANK_UTILIZATION_PRECISION));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const borrowRateSlope = bank.optimalBorrowRate
|
|
53
|
+
.mul(numericConstants_1.BANK_UTILIZATION_PRECISION)
|
|
54
|
+
.div(numericConstants_1.BANK_UTILIZATION_PRECISION.sub(bank.optimalUtilization));
|
|
55
|
+
interest_rate = utilization
|
|
56
|
+
.mul(borrowRateSlope)
|
|
57
|
+
.div(numericConstants_1.BANK_UTILIZATION_PRECISION);
|
|
58
|
+
}
|
|
59
|
+
const timeSinceLastUpdate = now.sub(bank.lastUpdated);
|
|
60
|
+
const modifiedBorrowRate = interest_rate.mul(timeSinceLastUpdate);
|
|
61
|
+
const modifiedDepositRate = modifiedBorrowRate
|
|
62
|
+
.mul(utilization)
|
|
63
|
+
.div(numericConstants_1.BANK_UTILIZATION_PRECISION);
|
|
64
|
+
const borrowInterest = bank.cumulativeBorrowInterest
|
|
65
|
+
.mul(modifiedBorrowRate)
|
|
66
|
+
.div(numericConstants_1.ONE_YEAR)
|
|
67
|
+
.div(numericConstants_1.BANK_INTEREST_PRECISION)
|
|
68
|
+
.add(numericConstants_1.ONE);
|
|
69
|
+
const depositInterest = bank.cumulativeDepositInterest
|
|
70
|
+
.mul(modifiedDepositRate)
|
|
71
|
+
.div(numericConstants_1.ONE_YEAR)
|
|
72
|
+
.div(numericConstants_1.BANK_INTEREST_PRECISION);
|
|
73
|
+
return { borrowInterest, depositInterest };
|
|
74
|
+
}
|
|
75
|
+
exports.calculateInterestAccumulated = calculateInterestAccumulated;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertToNumber = void 0;
|
|
4
|
+
const numericConstants_1 = require("../constants/numericConstants");
|
|
5
|
+
const convertToNumber = (bigNumber, precision = numericConstants_1.MARK_PRICE_PRECISION) => {
|
|
6
|
+
if (!bigNumber)
|
|
7
|
+
return 0;
|
|
8
|
+
return (bigNumber.div(precision).toNumber() +
|
|
9
|
+
bigNumber.mod(precision).toNumber() / precision.toNumber());
|
|
10
|
+
};
|
|
11
|
+
exports.convertToNumber = convertToNumber;
|