@drift-labs/sdk 0.2.0-master.2 → 0.2.0-master.22

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.
Files changed (149) hide show
  1. package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
  2. package/lib/accounts/bulkUserStatsSubscription.js +21 -0
  3. package/lib/accounts/bulkUserSubscription.js +0 -1
  4. package/lib/accounts/fetch.d.ts +2 -1
  5. package/lib/accounts/fetch.js +9 -1
  6. package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
  7. package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
  8. package/lib/accounts/types.d.ts +14 -1
  9. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
  10. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
  11. package/lib/addresses/pda.d.ts +1 -0
  12. package/lib/addresses/pda.js +8 -1
  13. package/lib/admin.d.ts +9 -5
  14. package/lib/admin.js +52 -11
  15. package/lib/clearingHouse.d.ts +52 -23
  16. package/lib/clearingHouse.js +736 -200
  17. package/lib/clearingHouseConfig.d.ts +1 -0
  18. package/lib/clearingHouseUser.d.ts +24 -16
  19. package/lib/clearingHouseUser.js +223 -101
  20. package/lib/clearingHouseUserStats.d.ts +18 -0
  21. package/lib/clearingHouseUserStats.js +49 -0
  22. package/lib/clearingHouseUserStatsConfig.d.ts +14 -0
  23. package/lib/clearingHouseUserStatsConfig.js +2 -0
  24. package/lib/config.js +1 -1
  25. package/lib/constants/banks.d.ts +2 -2
  26. package/lib/constants/banks.js +12 -4
  27. package/lib/constants/numericConstants.d.ts +5 -0
  28. package/lib/constants/numericConstants.js +8 -3
  29. package/lib/events/eventList.js +3 -0
  30. package/lib/events/types.d.ts +3 -1
  31. package/lib/events/types.js +2 -0
  32. package/lib/factory/bigNum.d.ts +1 -0
  33. package/lib/factory/bigNum.js +34 -10
  34. package/lib/idl/clearing_house.json +1603 -377
  35. package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  36. package/lib/index.d.ts +9 -3
  37. package/lib/index.js +13 -3
  38. package/lib/math/amm.d.ts +1 -0
  39. package/lib/math/amm.js +22 -38
  40. package/lib/math/auction.js +4 -1
  41. package/lib/math/bankBalance.d.ts +7 -1
  42. package/lib/math/bankBalance.js +77 -2
  43. package/lib/math/margin.d.ts +11 -0
  44. package/lib/math/margin.js +72 -0
  45. package/lib/math/market.d.ts +4 -1
  46. package/lib/math/market.js +35 -1
  47. package/lib/math/oracles.d.ts +3 -0
  48. package/lib/math/oracles.js +25 -5
  49. package/lib/math/orders.d.ts +6 -2
  50. package/lib/math/orders.js +62 -12
  51. package/lib/math/position.d.ts +8 -0
  52. package/lib/math/position.js +45 -12
  53. package/lib/math/trade.d.ts +1 -1
  54. package/lib/math/trade.js +7 -10
  55. package/lib/orderParams.d.ts +14 -5
  56. package/lib/orderParams.js +8 -96
  57. package/lib/slot/SlotSubscriber.d.ts +7 -0
  58. package/lib/slot/SlotSubscriber.js +3 -0
  59. package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
  60. package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
  61. package/lib/tx/retryTxSender.js +9 -2
  62. package/lib/tx/utils.js +1 -1
  63. package/lib/types.d.ts +236 -26
  64. package/lib/types.js +64 -1
  65. package/lib/util/computeUnits.js +1 -1
  66. package/lib/util/getTokenAddress.d.ts +2 -0
  67. package/lib/util/getTokenAddress.js +9 -0
  68. package/package.json +3 -3
  69. package/src/accounts/bulkUserStatsSubscription.ts +33 -0
  70. package/src/accounts/bulkUserSubscription.ts +0 -1
  71. package/src/accounts/fetch.ts +27 -2
  72. package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
  73. package/src/accounts/types.ts +18 -0
  74. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
  75. package/src/addresses/marketAddresses.js +26 -0
  76. package/src/addresses/pda.ts +13 -0
  77. package/src/admin.ts +82 -15
  78. package/src/assert/assert.js +9 -0
  79. package/src/clearingHouse.ts +1232 -323
  80. package/src/clearingHouseConfig.ts +1 -0
  81. package/src/clearingHouseUser.ts +343 -155
  82. package/src/clearingHouseUserStats.ts +75 -0
  83. package/src/clearingHouseUserStatsConfig.ts +18 -0
  84. package/src/config.ts +1 -1
  85. package/src/constants/banks.js +42 -0
  86. package/src/constants/banks.ts +14 -4
  87. package/src/constants/markets.js +42 -0
  88. package/src/constants/numericConstants.js +41 -0
  89. package/src/constants/numericConstants.ts +14 -2
  90. package/src/events/eventList.js +77 -0
  91. package/src/events/eventList.ts +3 -0
  92. package/src/events/eventSubscriber.js +139 -0
  93. package/src/events/sort.js +44 -0
  94. package/src/events/txEventCache.js +71 -0
  95. package/src/events/types.ts +6 -0
  96. package/src/examples/makeTradeExample.js +80 -0
  97. package/src/factory/bigNum.js +390 -0
  98. package/src/factory/bigNum.ts +42 -13
  99. package/src/factory/oracleClient.js +20 -0
  100. package/src/idl/clearing_house.json +1603 -377
  101. package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  102. package/src/index.ts +9 -3
  103. package/src/math/amm.ts +54 -55
  104. package/src/math/auction.js +42 -0
  105. package/src/math/auction.ts +5 -1
  106. package/src/math/bankBalance.ts +148 -2
  107. package/src/math/conversion.js +11 -0
  108. package/src/math/funding.js +248 -0
  109. package/src/math/margin.ts +124 -0
  110. package/src/math/market.ts +66 -1
  111. package/src/math/oracles.js +26 -0
  112. package/src/math/oracles.ts +42 -5
  113. package/src/math/orders.ts +129 -13
  114. package/src/math/position.ts +64 -9
  115. package/src/math/repeg.js +128 -0
  116. package/src/math/state.js +15 -0
  117. package/src/math/trade.js +253 -0
  118. package/src/math/trade.ts +23 -25
  119. package/src/math/utils.js +0 -1
  120. package/src/oracles/oracleClientCache.js +19 -0
  121. package/src/oracles/pythClient.js +46 -0
  122. package/src/oracles/quoteAssetOracleClient.js +32 -0
  123. package/src/oracles/switchboardClient.js +69 -0
  124. package/src/oracles/types.js +2 -0
  125. package/src/orderParams.js +20 -0
  126. package/src/orderParams.ts +20 -141
  127. package/src/slot/SlotSubscriber.js +39 -0
  128. package/src/slot/SlotSubscriber.ts +11 -1
  129. package/src/token/index.js +38 -0
  130. package/src/tokenFaucet.js +189 -0
  131. package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
  132. package/src/tx/retryTxSender.ts +11 -3
  133. package/src/tx/types.js +2 -0
  134. package/src/tx/utils.js +17 -0
  135. package/src/tx/utils.ts +1 -1
  136. package/src/types.ts +239 -27
  137. package/src/userName.js +20 -0
  138. package/src/util/computeUnits.js +21 -11
  139. package/src/util/computeUnits.ts +1 -1
  140. package/src/util/getTokenAddress.js +9 -0
  141. package/src/util/getTokenAddress.ts +18 -0
  142. package/src/util/promiseTimeout.js +14 -0
  143. package/src/util/tps.js +27 -0
  144. package/src/wallet.js +35 -0
  145. package/tests/bn/test.ts +10 -0
  146. package/lib/orders.d.ts +0 -8
  147. package/lib/orders.js +0 -142
  148. package/src/orders.ts +0 -251
  149. package/src/util/computeUnits.js.map +0 -1
@@ -1,23 +1,23 @@
1
1
  {
2
- "version": "0.0.0",
3
- "name": "mock_usdc_faucet",
2
+ "version": "0.1.0",
3
+ "name": "token_faucet",
4
4
  "instructions": [
5
5
  {
6
6
  "name": "initialize",
7
7
  "accounts": [
8
8
  {
9
- "name": "mockUsdcFaucetState",
9
+ "name": "faucetConfig",
10
10
  "isMut": true,
11
11
  "isSigner": false
12
12
  },
13
13
  {
14
14
  "name": "admin",
15
- "isMut": false,
15
+ "isMut": true,
16
16
  "isSigner": true
17
17
  },
18
18
  {
19
19
  "name": "mintAccount",
20
- "isMut": false,
20
+ "isMut": true,
21
21
  "isSigner": false
22
22
  },
23
23
  {
@@ -29,20 +29,20 @@
29
29
  "name": "systemProgram",
30
30
  "isMut": false,
31
31
  "isSigner": false
32
- }
33
- ],
34
- "args": [
32
+ },
35
33
  {
36
- "name": "mockUsdcFaucetNonce",
37
- "type": "u8"
34
+ "name": "tokenProgram",
35
+ "isMut": false,
36
+ "isSigner": false
38
37
  }
39
- ]
38
+ ],
39
+ "args": []
40
40
  },
41
41
  {
42
42
  "name": "mintToUser",
43
43
  "accounts": [
44
44
  {
45
- "name": "mockUsdcFaucetState",
45
+ "name": "faucetConfig",
46
46
  "isMut": false,
47
47
  "isSigner": false
48
48
  },
@@ -73,11 +73,42 @@
73
73
  "type": "u64"
74
74
  }
75
75
  ]
76
+ },
77
+ {
78
+ "name": "transferMintAuthority",
79
+ "accounts": [
80
+ {
81
+ "name": "faucetConfig",
82
+ "isMut": false,
83
+ "isSigner": false
84
+ },
85
+ {
86
+ "name": "admin",
87
+ "isMut": true,
88
+ "isSigner": true
89
+ },
90
+ {
91
+ "name": "mintAccount",
92
+ "isMut": true,
93
+ "isSigner": false
94
+ },
95
+ {
96
+ "name": "mintAuthority",
97
+ "isMut": false,
98
+ "isSigner": false
99
+ },
100
+ {
101
+ "name": "tokenProgram",
102
+ "isMut": false,
103
+ "isSigner": false
104
+ }
105
+ ],
106
+ "args": []
76
107
  }
77
108
  ],
78
109
  "accounts": [
79
110
  {
80
- "name": "MockUSDCFaucetState",
111
+ "name": "FaucetConfig",
81
112
  "type": {
82
113
  "kind": "struct",
83
114
  "fields": [
@@ -103,17 +134,9 @@
103
134
  ],
104
135
  "errors": [
105
136
  {
106
- "code": 300,
137
+ "code": 6000,
107
138
  "name": "InvalidMintAccountAuthority",
108
139
  "msg": "Program not mint authority"
109
- },
110
- {
111
- "code": 301,
112
- "name": "Unauthorized",
113
- "msg": "Signer must be MockUSDCFaucet admin"
114
140
  }
115
- ],
116
- "metadata": {
117
- "address": "2z2DLVD3tBWc86pbvvy5qN31v1NXprM6zA5MDr2FMx64"
118
- }
141
+ ]
119
142
  }
package/src/index.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { BN } from '@project-serum/anchor';
2
2
  import { PublicKey } from '@solana/web3.js';
3
+ import pyth from '@pythnetwork/client';
3
4
 
4
- export * from './mockUSDCFaucet';
5
+ export * from './tokenFaucet';
5
6
  export * from './oracles/types';
6
7
  export * from './oracles/pythClient';
7
8
  export * from './oracles/switchboardClient';
@@ -11,14 +12,19 @@ export * from './accounts/fetch';
11
12
  export * from './accounts/webSocketClearingHouseAccountSubscriber';
12
13
  export * from './accounts/bulkAccountLoader';
13
14
  export * from './accounts/bulkUserSubscription';
15
+ export * from './accounts/bulkUserStatsSubscription';
14
16
  export * from './accounts/pollingClearingHouseAccountSubscriber';
15
17
  export * from './accounts/pollingOracleSubscriber';
16
18
  export * from './accounts/pollingTokenAccountSubscriber';
19
+ export * from './accounts/pollingUserAccountSubscriber';
20
+ export * from './accounts/pollingUserStatsAccountSubscriber';
17
21
  export * from './accounts/types';
18
22
  export * from './addresses/pda';
19
23
  export * from './admin';
20
24
  export * from './clearingHouseUser';
21
25
  export * from './clearingHouseUserConfig';
26
+ export * from './clearingHouseUserStats';
27
+ export * from './clearingHouseUserStatsConfig';
22
28
  export * from './clearingHouse';
23
29
  export * from './factory/oracleClient';
24
30
  export * from './factory/bigNum';
@@ -34,7 +40,7 @@ export * from './math/amm';
34
40
  export * from './math/trade';
35
41
  export * from './math/orders';
36
42
  export * from './math/repeg';
37
- export * from './orders';
43
+ export * from './math/margin';
38
44
  export * from './orderParams';
39
45
  export * from './slot/SlotSubscriber';
40
46
  export * from './wallet';
@@ -49,4 +55,4 @@ export * from './math/bankBalance';
49
55
  export * from './constants/banks';
50
56
  export * from './clearingHouseConfig';
51
57
 
52
- export { BN, PublicKey };
58
+ export { BN, PublicKey, pyth };
package/src/math/amm.ts CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  isVariant,
20
20
  } from '../types';
21
21
  import { assert } from '../assert/assert';
22
- import { squareRootBN } from '..';
22
+ import { squareRootBN, standardizeBaseAssetAmount } from '..';
23
23
 
24
24
  import { OraclePriceData } from '../oracles/types';
25
25
  import {
@@ -33,11 +33,14 @@ export function calculatePegFromTargetPrice(
33
33
  baseAssetReserve: BN,
34
34
  quoteAssetReserve: BN
35
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);
36
+ return BN.max(
37
+ targetPrice
38
+ .mul(baseAssetReserve)
39
+ .div(quoteAssetReserve)
40
+ .add(PRICE_DIV_PEG.div(new BN(2)))
41
+ .div(PRICE_DIV_PEG),
42
+ ONE
43
+ );
41
44
  }
42
45
 
43
46
  export function calculateOptimalPegAndBudget(
@@ -68,6 +71,7 @@ export function calculateOptimalPegAndBudget(
68
71
  let newOptimalPeg: BN;
69
72
  let newBudget: BN;
70
73
  const targetPriceGap = markPriceBefore.sub(targetPrice);
74
+
71
75
  if (targetPriceGap.abs().gt(maxPriceSpread)) {
72
76
  const markAdj = targetPriceGap.abs().sub(maxPriceSpread);
73
77
 
@@ -411,10 +415,8 @@ export function calculateSpread(
411
415
  direction: PositionDirection,
412
416
  oraclePriceData: OraclePriceData
413
417
  ): number {
414
- let spread = amm.baseSpread / 2;
415
-
416
418
  if (amm.baseSpread == 0 || amm.curveUpdateIntensity == 0) {
417
- return spread;
419
+ return amm.baseSpread / 2;
418
420
  }
419
421
 
420
422
  const markPrice = calculatePrice(
@@ -435,54 +437,25 @@ export function calculateSpread(
435
437
  .mul(BID_ASK_SPREAD_PRECISION)
436
438
  .div(markPrice);
437
439
 
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
- }
440
+ const [longSpread, shortSpread] = calculateSpreadBN(
441
+ amm.baseSpread,
442
+ targetMarkSpreadPct,
443
+ confIntervalPct,
444
+ amm.maxSpread,
445
+ amm.quoteAssetReserve,
446
+ amm.terminalQuoteAssetReserve,
447
+ amm.pegMultiplier,
448
+ amm.netBaseAssetAmount,
449
+ markPrice,
450
+ amm.totalFeeMinusDistributions
451
+ );
476
452
 
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
- }
453
+ let spread: number;
484
454
 
485
- spread *= spreadScale;
455
+ if (isVariant(direction, 'long')) {
456
+ spread = longSpread;
457
+ } else {
458
+ spread = shortSpread;
486
459
  }
487
460
 
488
461
  return spread;
@@ -650,3 +623,29 @@ export function calculateQuoteAssetAmountSwapped(
650
623
 
651
624
  return quoteAssetAmount;
652
625
  }
626
+
627
+ export function calculateMaxBaseAssetAmountFillable(
628
+ amm: AMM,
629
+ orderDirection: PositionDirection
630
+ ): BN {
631
+ const maxFillSize = amm.baseAssetReserve.div(
632
+ new BN(amm.maxBaseAssetAmountRatio)
633
+ );
634
+ let maxBaseAssetAmountOnSide: BN;
635
+ if (isVariant(orderDirection, 'long')) {
636
+ maxBaseAssetAmountOnSide = BN.max(
637
+ ZERO,
638
+ amm.baseAssetReserve.sub(amm.minBaseAssetReserve)
639
+ );
640
+ } else {
641
+ maxBaseAssetAmountOnSide = BN.max(
642
+ ZERO,
643
+ amm.maxBaseAssetReserve.sub(amm.baseAssetReserve)
644
+ );
645
+ }
646
+
647
+ return standardizeBaseAssetAmount(
648
+ BN.min(maxFillSize, maxBaseAssetAmountOnSide),
649
+ amm.baseAssetAmountStepSize
650
+ );
651
+ }
@@ -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;
@@ -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
- return new BN(slot).sub(order.slot).gte(new BN(order.auctionDuration));
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 {
@@ -1,4 +1,9 @@
1
- import { BankAccount, BankBalanceType, isVariant } from '../types';
1
+ import {
2
+ BankAccount,
3
+ BankBalanceType,
4
+ isVariant,
5
+ MarginCategory,
6
+ } from '../types';
2
7
  import { BN } from '@project-serum/anchor';
3
8
  import {
4
9
  BANK_UTILIZATION_PRECISION,
@@ -6,8 +11,14 @@ import {
6
11
  TEN,
7
12
  ZERO,
8
13
  BANK_INTEREST_PRECISION,
14
+ BANK_WEIGHT_PRECISION,
9
15
  ONE_YEAR,
16
+ AMM_RESERVE_PRECISION,
10
17
  } from '../constants/numericConstants';
18
+ import {
19
+ calculateSizeDiscountAssetWeight,
20
+ calculateSizePremiumLiabilityWeight,
21
+ } from './margin';
11
22
 
12
23
  export function getBalance(
13
24
  tokenAmount: BN,
@@ -43,6 +54,92 @@ export function getTokenAmount(
43
54
  return balanceAmount.mul(cumulativeInterest).div(precisionDecrease);
44
55
  }
45
56
 
57
+ export function calculateAssetWeight(
58
+ balanceAmount: BN,
59
+ bank: BankAccount,
60
+ marginCategory: MarginCategory
61
+ ): BN {
62
+ const sizePrecision = TEN.pow(new BN(bank.decimals));
63
+ let sizeInAmmReservePrecision;
64
+ if (sizePrecision.gt(AMM_RESERVE_PRECISION)) {
65
+ sizeInAmmReservePrecision = balanceAmount.div(
66
+ sizePrecision.div(AMM_RESERVE_PRECISION)
67
+ );
68
+ } else {
69
+ sizeInAmmReservePrecision = balanceAmount
70
+ .mul(AMM_RESERVE_PRECISION)
71
+ .div(sizePrecision);
72
+ }
73
+
74
+ let assetWeight;
75
+
76
+ switch (marginCategory) {
77
+ case 'Initial':
78
+ assetWeight = calculateSizeDiscountAssetWeight(
79
+ sizeInAmmReservePrecision,
80
+ bank.imfFactor,
81
+ bank.initialAssetWeight
82
+ );
83
+ break;
84
+ case 'Maintenance':
85
+ assetWeight = calculateSizeDiscountAssetWeight(
86
+ sizeInAmmReservePrecision,
87
+ bank.imfFactor,
88
+ bank.maintenanceAssetWeight
89
+ );
90
+ break;
91
+ default:
92
+ assetWeight = bank.initialAssetWeight;
93
+ break;
94
+ }
95
+
96
+ return assetWeight;
97
+ }
98
+
99
+ export function calculateLiabilityWeight(
100
+ balanceAmount: BN,
101
+ bank: BankAccount,
102
+ marginCategory: MarginCategory
103
+ ): BN {
104
+ const sizePrecision = TEN.pow(new BN(bank.decimals));
105
+ let sizeInAmmReservePrecision;
106
+ if (sizePrecision.gt(AMM_RESERVE_PRECISION)) {
107
+ sizeInAmmReservePrecision = balanceAmount.div(
108
+ sizePrecision.div(AMM_RESERVE_PRECISION)
109
+ );
110
+ } else {
111
+ sizeInAmmReservePrecision = balanceAmount
112
+ .mul(AMM_RESERVE_PRECISION)
113
+ .div(sizePrecision);
114
+ }
115
+
116
+ let assetWeight;
117
+
118
+ switch (marginCategory) {
119
+ case 'Initial':
120
+ assetWeight = calculateSizePremiumLiabilityWeight(
121
+ sizeInAmmReservePrecision,
122
+ bank.imfFactor,
123
+ bank.initialLiabilityWeight,
124
+ BANK_WEIGHT_PRECISION
125
+ );
126
+ break;
127
+ case 'Maintenance':
128
+ assetWeight = calculateSizePremiumLiabilityWeight(
129
+ sizeInAmmReservePrecision,
130
+ bank.imfFactor,
131
+ bank.maintenanceLiabilityWeight,
132
+ BANK_WEIGHT_PRECISION
133
+ );
134
+ break;
135
+ default:
136
+ assetWeight = bank.initialLiabilityWeight;
137
+ break;
138
+ }
139
+
140
+ return assetWeight;
141
+ }
142
+
46
143
  export function calculateInterestAccumulated(
47
144
  bank: BankAccount,
48
145
  now: BN
@@ -90,7 +187,7 @@ export function calculateInterestAccumulated(
90
187
  .div(BANK_UTILIZATION_PRECISION);
91
188
  }
92
189
 
93
- const timeSinceLastUpdate = now.sub(bank.lastUpdated);
190
+ const timeSinceLastUpdate = now.sub(bank.lastInterestTs);
94
191
 
95
192
  const modifiedBorrowRate = interest_rate.mul(timeSinceLastUpdate);
96
193
 
@@ -110,3 +207,52 @@ export function calculateInterestAccumulated(
110
207
 
111
208
  return { borrowInterest, depositInterest };
112
209
  }
210
+
211
+ export function calculateWithdrawLimit(
212
+ bank: BankAccount,
213
+ now: BN
214
+ ): { borrowLimit: BN; withdrawLimit: BN } {
215
+ const bankDepositTokenAmount = getTokenAmount(
216
+ bank.depositBalance,
217
+ bank,
218
+ BankBalanceType.DEPOSIT
219
+ );
220
+ const bankBorrowTokenAmount = getTokenAmount(
221
+ bank.borrowBalance,
222
+ bank,
223
+ BankBalanceType.BORROW
224
+ );
225
+
226
+ const twentyFourHours = new BN(60 * 60 * 24);
227
+ const sinceLast = now.sub(bank.lastTwapTs);
228
+ const sinceStart = BN.max(ZERO, twentyFourHours.sub(sinceLast));
229
+ const borrowTokenTwapLive = bank.borrowTokenTwap
230
+ .mul(sinceStart)
231
+ .add(bankBorrowTokenAmount.mul(sinceLast))
232
+ .div(sinceLast.add(sinceLast));
233
+
234
+ const depositTokenTwapLive = bank.depositTokenTwap
235
+ .mul(sinceStart)
236
+ .add(bankDepositTokenAmount.mul(sinceLast))
237
+ .div(sinceLast.add(sinceLast));
238
+
239
+ const maxBorrowTokens = BN.min(
240
+ BN.max(
241
+ bankDepositTokenAmount.div(new BN(6)),
242
+ borrowTokenTwapLive.add(borrowTokenTwapLive.div(new BN(5)))
243
+ ),
244
+ bankDepositTokenAmount.sub(bankDepositTokenAmount.div(new BN(10)))
245
+ ); // between ~15-90% utilization with friction on twap
246
+
247
+ const minDepositTokens = depositTokenTwapLive.sub(
248
+ BN.min(
249
+ BN.max(depositTokenTwapLive.div(new BN(5)), bank.withdrawGuardThreshold),
250
+ depositTokenTwapLive
251
+ )
252
+ );
253
+
254
+ return {
255
+ borrowLimit: maxBorrowTokens.sub(bankBorrowTokenAmount),
256
+ withdrawLimit: bankDepositTokenAmount.sub(minDepositTokens),
257
+ };
258
+ }
@@ -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;