@drift-labs/sdk 0.2.0-master.3 → 0.2.0-master.31

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 (208) hide show
  1. package/README.md +13 -13
  2. package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
  3. package/lib/accounts/bulkUserStatsSubscription.js +21 -0
  4. package/lib/accounts/bulkUserSubscription.js +0 -1
  5. package/lib/accounts/fetch.d.ts +2 -1
  6. package/lib/accounts/fetch.js +9 -1
  7. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +16 -16
  8. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +31 -28
  9. package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
  10. package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
  11. package/lib/accounts/types.d.ts +22 -11
  12. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +17 -17
  13. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +37 -35
  14. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
  15. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
  16. package/lib/addresses/marketAddresses.d.ts +1 -3
  17. package/lib/addresses/pda.d.ts +10 -4
  18. package/lib/addresses/pda.js +51 -14
  19. package/lib/admin.d.ts +42 -26
  20. package/lib/admin.js +228 -81
  21. package/lib/clearingHouse.d.ts +130 -49
  22. package/lib/clearingHouse.js +1256 -367
  23. package/lib/clearingHouseConfig.d.ts +4 -4
  24. package/lib/clearingHouseUser.d.ts +51 -39
  25. package/lib/clearingHouseUser.js +408 -191
  26. package/lib/clearingHouseUserStats.d.ts +18 -0
  27. package/lib/clearingHouseUserStats.js +49 -0
  28. package/lib/clearingHouseUserStatsConfig.d.ts +14 -0
  29. package/lib/clearingHouseUserStatsConfig.js +2 -0
  30. package/lib/config.d.ts +7 -9
  31. package/lib/config.js +21 -21
  32. package/lib/constants/numericConstants.d.ts +25 -12
  33. package/lib/constants/numericConstants.js +35 -21
  34. package/lib/constants/perpMarkets.d.ts +18 -0
  35. package/lib/constants/{markets.js → perpMarkets.js} +7 -7
  36. package/lib/constants/spotMarkets.d.ts +19 -0
  37. package/lib/constants/spotMarkets.js +53 -0
  38. package/lib/dlob/DLOB.d.ts +74 -0
  39. package/lib/dlob/DLOB.js +595 -0
  40. package/lib/dlob/DLOBNode.d.ts +54 -0
  41. package/lib/dlob/DLOBNode.js +85 -0
  42. package/lib/dlob/NodeList.d.ts +26 -0
  43. package/lib/dlob/NodeList.js +139 -0
  44. package/lib/events/eventList.js +3 -0
  45. package/lib/events/eventSubscriber.d.ts +4 -2
  46. package/lib/events/eventSubscriber.js +16 -9
  47. package/lib/events/fetchLogs.d.ts +10 -1
  48. package/lib/events/fetchLogs.js +27 -7
  49. package/lib/events/pollingLogProvider.d.ts +2 -1
  50. package/lib/events/pollingLogProvider.js +6 -2
  51. package/lib/events/sort.js +8 -11
  52. package/lib/events/types.d.ts +8 -2
  53. package/lib/events/types.js +6 -0
  54. package/lib/examples/makeTradeExample.js +20 -8
  55. package/lib/factory/bigNum.d.ts +2 -0
  56. package/lib/factory/bigNum.js +48 -10
  57. package/lib/idl/clearing_house.json +4889 -1529
  58. package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  59. package/lib/index.d.ts +21 -6
  60. package/lib/index.js +25 -6
  61. package/lib/math/amm.d.ts +9 -6
  62. package/lib/math/amm.js +91 -66
  63. package/lib/math/auction.js +4 -1
  64. package/lib/math/conversion.js +1 -1
  65. package/lib/math/funding.d.ts +6 -6
  66. package/lib/math/funding.js +11 -10
  67. package/lib/math/insurance.d.ts +4 -0
  68. package/lib/math/insurance.js +27 -0
  69. package/lib/math/margin.d.ts +11 -0
  70. package/lib/math/margin.js +77 -0
  71. package/lib/math/market.d.ts +14 -9
  72. package/lib/math/market.js +72 -10
  73. package/lib/math/oracles.d.ts +4 -0
  74. package/lib/math/oracles.js +36 -8
  75. package/lib/math/orders.d.ts +6 -2
  76. package/lib/math/orders.js +78 -3
  77. package/lib/math/position.d.ts +21 -13
  78. package/lib/math/position.js +76 -36
  79. package/lib/math/repeg.js +14 -5
  80. package/lib/math/spotBalance.d.ts +22 -0
  81. package/lib/math/spotBalance.js +192 -0
  82. package/lib/math/spotMarket.d.ts +4 -0
  83. package/lib/math/spotMarket.js +8 -0
  84. package/lib/math/spotPosition.d.ts +6 -0
  85. package/lib/math/spotPosition.js +23 -0
  86. package/lib/math/trade.d.ts +10 -10
  87. package/lib/math/trade.js +32 -39
  88. package/lib/oracles/pythClient.js +1 -1
  89. package/lib/oracles/quoteAssetOracleClient.js +1 -1
  90. package/lib/oracles/switchboardClient.js +1 -1
  91. package/lib/orderParams.d.ts +14 -5
  92. package/lib/orderParams.js +12 -92
  93. package/lib/serum/serumSubscriber.d.ts +23 -0
  94. package/lib/serum/serumSubscriber.js +41 -0
  95. package/lib/serum/types.d.ts +11 -0
  96. package/lib/serum/types.js +2 -0
  97. package/lib/slot/SlotSubscriber.d.ts +7 -0
  98. package/lib/slot/SlotSubscriber.js +3 -0
  99. package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
  100. package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
  101. package/lib/tx/retryTxSender.d.ts +1 -1
  102. package/lib/tx/retryTxSender.js +13 -4
  103. package/lib/tx/types.d.ts +1 -1
  104. package/lib/tx/utils.js +1 -1
  105. package/lib/types.d.ts +566 -138
  106. package/lib/types.js +129 -5
  107. package/lib/userMap/userMap.d.ts +25 -0
  108. package/lib/userMap/userMap.js +73 -0
  109. package/lib/userMap/userStatsMap.d.ts +19 -0
  110. package/lib/userMap/userStatsMap.js +68 -0
  111. package/lib/util/computeUnits.js +1 -1
  112. package/lib/util/getTokenAddress.d.ts +2 -0
  113. package/lib/util/getTokenAddress.js +9 -0
  114. package/package.json +12 -6
  115. package/src/accounts/bulkUserStatsSubscription.ts +33 -0
  116. package/src/accounts/bulkUserSubscription.ts +0 -1
  117. package/src/accounts/fetch.ts +27 -2
  118. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +46 -42
  119. package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
  120. package/src/accounts/types.ts +31 -11
  121. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +64 -59
  122. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
  123. package/src/addresses/marketAddresses.ts +1 -2
  124. package/src/addresses/pda.ts +88 -14
  125. package/src/admin.ts +452 -147
  126. package/src/assert/assert.js +9 -0
  127. package/src/clearingHouse.ts +2066 -467
  128. package/src/clearingHouseConfig.ts +4 -3
  129. package/src/clearingHouseUser.ts +747 -294
  130. package/src/clearingHouseUserStats.ts +75 -0
  131. package/src/clearingHouseUserStatsConfig.ts +18 -0
  132. package/src/config.ts +30 -31
  133. package/src/constants/numericConstants.ts +48 -25
  134. package/src/constants/{markets.ts → perpMarkets.ts} +10 -10
  135. package/src/constants/spotMarkets.ts +73 -0
  136. package/src/dlob/DLOB.ts +953 -0
  137. package/src/dlob/DLOBNode.ts +167 -0
  138. package/src/dlob/NodeList.ts +189 -0
  139. package/src/events/eventList.js +77 -0
  140. package/src/events/eventList.ts +3 -0
  141. package/src/events/eventSubscriber.ts +20 -12
  142. package/src/events/fetchLogs.ts +35 -8
  143. package/src/events/pollingLogProvider.ts +10 -2
  144. package/src/events/sort.ts +11 -15
  145. package/src/events/types.ts +19 -1
  146. package/src/examples/makeTradeExample.js +157 -0
  147. package/src/examples/makeTradeExample.ts +32 -14
  148. package/src/factory/bigNum.ts +65 -13
  149. package/src/idl/clearing_house.json +4889 -1529
  150. package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  151. package/src/index.ts +21 -6
  152. package/src/math/amm.ts +171 -88
  153. package/src/math/auction.ts +5 -1
  154. package/src/math/conversion.ts +2 -2
  155. package/src/math/funding.ts +20 -18
  156. package/src/math/insurance.ts +35 -0
  157. package/src/math/margin.ts +127 -0
  158. package/src/math/market.ts +145 -14
  159. package/src/math/oracles.ts +63 -9
  160. package/src/math/orders.ts +138 -4
  161. package/src/math/position.ts +119 -58
  162. package/src/math/repeg.ts +16 -6
  163. package/src/math/spotBalance.ts +319 -0
  164. package/src/math/spotMarket.ts +9 -0
  165. package/src/math/spotPosition.ts +47 -0
  166. package/src/math/trade.ts +53 -59
  167. package/src/oracles/pythClient.ts +2 -2
  168. package/src/oracles/quoteAssetOracleClient.ts +2 -2
  169. package/src/oracles/switchboardClient.ts +2 -2
  170. package/src/orderParams.ts +24 -137
  171. package/src/serum/serumSubscriber.ts +80 -0
  172. package/src/serum/types.ts +13 -0
  173. package/src/slot/SlotSubscriber.ts +11 -1
  174. package/src/token/index.js +38 -0
  175. package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
  176. package/src/tx/retryTxSender.ts +16 -5
  177. package/src/tx/types.js +2 -0
  178. package/src/tx/types.ts +2 -1
  179. package/src/tx/utils.js +17 -0
  180. package/src/tx/utils.ts +1 -1
  181. package/src/types.ts +533 -140
  182. package/src/userMap/userMap.ts +100 -0
  183. package/src/userMap/userStatsMap.ts +110 -0
  184. package/src/util/computeUnits.js +21 -11
  185. package/src/util/computeUnits.ts +1 -1
  186. package/src/util/getTokenAddress.js +9 -0
  187. package/src/util/getTokenAddress.ts +18 -0
  188. package/src/util/promiseTimeout.js +14 -0
  189. package/src/util/tps.js +27 -0
  190. package/tests/bn/test.ts +24 -10
  191. package/tests/dlob/helpers.ts +397 -0
  192. package/tests/dlob/test.ts +3688 -0
  193. package/lib/constants/banks.d.ts +0 -16
  194. package/lib/constants/banks.js +0 -34
  195. package/lib/constants/markets.d.ts +0 -19
  196. package/lib/math/bankBalance.d.ts +0 -9
  197. package/lib/math/bankBalance.js +0 -75
  198. package/lib/math/state.d.ts +0 -8
  199. package/lib/math/state.js +0 -15
  200. package/lib/orders.d.ts +0 -8
  201. package/lib/orders.js +0 -134
  202. package/src/constants/banks.ts +0 -43
  203. package/src/math/bankBalance.ts +0 -112
  204. package/src/math/state.ts +0 -14
  205. package/src/math/utils.js +0 -27
  206. package/src/math/utils.js.map +0 -1
  207. package/src/orders.ts +0 -244
  208. 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,30 +1,38 @@
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';
8
9
  export * from './types';
9
- export * from './constants/markets';
10
+ export * from './constants/perpMarkets';
10
11
  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';
25
31
  export * from './events/types';
26
32
  export * from './events/eventSubscriber';
33
+ export * from './events/fetchLogs';
27
34
  export * from './math/auction';
35
+ export * from './math/spotMarket';
28
36
  export * from './math/conversion';
29
37
  export * from './math/funding';
30
38
  export * from './math/market';
@@ -34,7 +42,8 @@ export * from './math/amm';
34
42
  export * from './math/trade';
35
43
  export * from './math/orders';
36
44
  export * from './math/repeg';
37
- export * from './orders';
45
+ export * from './math/margin';
46
+ export * from './math/insurance';
38
47
  export * from './orderParams';
39
48
  export * from './slot/SlotSubscriber';
40
49
  export * from './wallet';
@@ -42,11 +51,17 @@ export * from './types';
42
51
  export * from './math/utils';
43
52
  export * from './config';
44
53
  export * from './constants/numericConstants';
54
+ export * from './serum/serumSubscriber';
45
55
  export * from './tx/retryTxSender';
46
56
  export * from './util/computeUnits';
47
57
  export * from './util/tps';
48
- export * from './math/bankBalance';
49
- export * from './constants/banks';
58
+ export * from './math/spotBalance';
59
+ export * from './constants/spotMarkets';
50
60
  export * from './clearingHouseConfig';
61
+ export * from './dlob/DLOB';
62
+ export * from './dlob/DLOBNode';
63
+ export * from './dlob/NodeList';
64
+ export * from './userMap/userMap';
65
+ export * from './userMap/userStatsMap';
51
66
 
52
- export { BN, PublicKey };
67
+ export { BN, PublicKey, pyth };
package/src/math/amm.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { BN } from '@project-serum/anchor';
2
2
  import {
3
3
  AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO,
4
- MARK_PRICE_PRECISION,
4
+ PRICE_PRECISION,
5
5
  PEG_PRECISION,
6
6
  ZERO,
7
7
  BID_ASK_SPREAD_PRECISION,
@@ -15,11 +15,11 @@ import {
15
15
  AMM,
16
16
  PositionDirection,
17
17
  SwapDirection,
18
- MarketAccount,
18
+ PerpMarketAccount,
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,18 +33,21 @@ 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(
44
47
  amm: AMM,
45
48
  oraclePriceData: OraclePriceData
46
49
  ): [BN, BN, BN, boolean] {
47
- const markPriceBefore = calculatePrice(
50
+ const reservePriceBefore = calculatePrice(
48
51
  amm.baseAssetReserve,
49
52
  amm.quoteAssetReserve,
50
53
  amm.pegMultiplier
@@ -67,14 +70,15 @@ export function calculateOptimalPegAndBudget(
67
70
  let newTargetPrice: BN;
68
71
  let newOptimalPeg: BN;
69
72
  let newBudget: BN;
70
- const targetPriceGap = markPriceBefore.sub(targetPrice);
73
+ const targetPriceGap = reservePriceBefore.sub(targetPrice);
74
+
71
75
  if (targetPriceGap.abs().gt(maxPriceSpread)) {
72
76
  const markAdj = targetPriceGap.abs().sub(maxPriceSpread);
73
77
 
74
78
  if (targetPriceGap.lt(new BN(0))) {
75
- newTargetPrice = markPriceBefore.add(markAdj);
79
+ newTargetPrice = reservePriceBefore.add(markAdj);
76
80
  } else {
77
- newTargetPrice = markPriceBefore.sub(markAdj);
81
+ newTargetPrice = reservePriceBefore.sub(markAdj);
78
82
  }
79
83
 
80
84
  newOptimalPeg = calculatePegFromTargetPrice(
@@ -238,7 +242,7 @@ export function calculateBidAskPrice(
238
242
  * @param baseAssetReserves
239
243
  * @param quoteAssetReserves
240
244
  * @param pegMultiplier
241
- * @returns price : Precision MARK_PRICE_PRECISION
245
+ * @returns price : Precision PRICE_PRECISION
242
246
  */
243
247
  export function calculatePrice(
244
248
  baseAssetReserves: BN,
@@ -250,7 +254,7 @@ export function calculatePrice(
250
254
  }
251
255
 
252
256
  return quoteAssetReserves
253
- .mul(MARK_PRICE_PRECISION)
257
+ .mul(PRICE_PRECISION)
254
258
  .mul(pegMultiplier)
255
259
  .div(PEG_PRECISION)
256
260
  .div(baseAssetReserves);
@@ -304,13 +308,62 @@ export function calculateAmmReservesAfterSwap(
304
308
  return [newQuoteAssetReserve, newBaseAssetReserve];
305
309
  }
306
310
 
311
+ export function calculateMarketOpenBidAsk(
312
+ baseAssetReserve: BN,
313
+ minBaseAssetReserve: BN,
314
+ maxBaseAssetReserve: BN
315
+ ): [BN, BN] {
316
+ // open orders
317
+ let openAsks;
318
+ if (maxBaseAssetReserve > baseAssetReserve) {
319
+ openAsks = maxBaseAssetReserve.sub(baseAssetReserve).mul(new BN(-1));
320
+ } else {
321
+ openAsks = ZERO;
322
+ }
323
+
324
+ let openBids;
325
+ if (minBaseAssetReserve < baseAssetReserve) {
326
+ openBids = baseAssetReserve.sub(minBaseAssetReserve);
327
+ } else {
328
+ openBids = ZERO;
329
+ }
330
+ return [openBids, openAsks];
331
+ }
332
+
333
+ export function calculateInventoryScale(
334
+ netBaseAssetAmount: BN,
335
+ baseAssetReserve: BN,
336
+ minBaseAssetReserve: BN,
337
+ maxBaseAssetReserve: BN
338
+ ): number {
339
+ const maxScale = BID_ASK_SPREAD_PRECISION.mul(new BN(10));
340
+ // inventory skew
341
+ const [openBids, openAsks] = calculateMarketOpenBidAsk(
342
+ baseAssetReserve,
343
+ minBaseAssetReserve,
344
+ maxBaseAssetReserve
345
+ );
346
+
347
+ const minSideLiquidity = BN.max(
348
+ new BN(1),
349
+ BN.min(openBids.abs(), openAsks.abs())
350
+ );
351
+ const inventoryScale =
352
+ BN.min(
353
+ maxScale,
354
+ netBaseAssetAmount.mul(maxScale).div(minSideLiquidity).abs()
355
+ ).toNumber() / BID_ASK_SPREAD_PRECISION.toNumber();
356
+
357
+ return inventoryScale;
358
+ }
359
+
307
360
  export function calculateEffectiveLeverage(
308
361
  baseSpread: number,
309
362
  quoteAssetReserve: BN,
310
363
  terminalQuoteAssetReserve: BN,
311
364
  pegMultiplier: BN,
312
365
  netBaseAssetAmount: BN,
313
- markPrice: BN,
366
+ reservePrice: BN,
314
367
  totalFeeMinusDistributions: BN
315
368
  ): number {
316
369
  // inventory skew
@@ -320,8 +373,8 @@ export function calculateEffectiveLeverage(
320
373
  .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
321
374
 
322
375
  const localBaseAssetValue = netBaseAssetAmount
323
- .mul(markPrice)
324
- .div(AMM_TO_QUOTE_PRECISION_RATIO.mul(MARK_PRICE_PRECISION));
376
+ .mul(reservePrice)
377
+ .div(AMM_TO_QUOTE_PRECISION_RATIO.mul(PRICE_PRECISION));
325
378
 
326
379
  const effectiveLeverage =
327
380
  localBaseAssetValue.sub(netBaseAssetValue).toNumber() /
@@ -341,34 +394,59 @@ export function calculateMaxSpread(marginRatioInitial: number): number {
341
394
 
342
395
  export function calculateSpreadBN(
343
396
  baseSpread: number,
344
- lastOracleMarkSpreadPct: BN,
397
+ lastOracleReservePriceSpreadPct: BN,
345
398
  lastOracleConfPct: BN,
346
399
  maxSpread: number,
347
400
  quoteAssetReserve: BN,
348
401
  terminalQuoteAssetReserve: BN,
349
402
  pegMultiplier: BN,
350
403
  netBaseAssetAmount: BN,
351
- markPrice: BN,
352
- totalFeeMinusDistributions: BN
404
+ reservePrice: BN,
405
+ totalFeeMinusDistributions: BN,
406
+ baseAssetReserve: BN,
407
+ minBaseAssetReserve: BN,
408
+ maxBaseAssetReserve: BN
353
409
  ): [number, number] {
354
410
  let longSpread = baseSpread / 2;
355
411
  let shortSpread = baseSpread / 2;
356
412
 
357
- if (lastOracleMarkSpreadPct.gt(ZERO)) {
413
+ if (lastOracleReservePriceSpreadPct.gt(ZERO)) {
358
414
  shortSpread = Math.max(
359
415
  shortSpread,
360
- lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber()
416
+ lastOracleReservePriceSpreadPct.abs().toNumber() +
417
+ lastOracleConfPct.toNumber()
361
418
  );
362
- } else if (lastOracleMarkSpreadPct.lt(ZERO)) {
419
+ } else if (lastOracleReservePriceSpreadPct.lt(ZERO)) {
363
420
  longSpread = Math.max(
364
421
  longSpread,
365
- lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber()
422
+ lastOracleReservePriceSpreadPct.abs().toNumber() +
423
+ lastOracleConfPct.toNumber()
366
424
  );
367
425
  }
368
426
 
369
- const maxTargetSpread: number = maxSpread;
427
+ const maxTargetSpread: number = Math.max(
428
+ maxSpread,
429
+ lastOracleReservePriceSpreadPct.abs().toNumber()
430
+ );
431
+
432
+ const MAX_BID_ASK_INVENTORY_SKEW_FACTOR = 10;
370
433
 
371
- const MAX_INVENTORY_SKEW = 5;
434
+ const inventoryScale = calculateInventoryScale(
435
+ netBaseAssetAmount,
436
+ baseAssetReserve,
437
+ minBaseAssetReserve,
438
+ maxBaseAssetReserve
439
+ );
440
+ const inventorySpreadScale = Math.min(
441
+ MAX_BID_ASK_INVENTORY_SKEW_FACTOR,
442
+ 1 + inventoryScale
443
+ );
444
+
445
+ if (netBaseAssetAmount.gt(ZERO)) {
446
+ longSpread *= inventorySpreadScale;
447
+ } else if (netBaseAssetAmount.lt(ZERO)) {
448
+ shortSpread *= inventorySpreadScale;
449
+ }
372
450
 
373
451
  const effectiveLeverage = calculateEffectiveLeverage(
374
452
  baseSpread,
@@ -376,20 +454,23 @@ export function calculateSpreadBN(
376
454
  terminalQuoteAssetReserve,
377
455
  pegMultiplier,
378
456
  netBaseAssetAmount,
379
- markPrice,
457
+ reservePrice,
380
458
  totalFeeMinusDistributions
381
459
  );
382
460
 
383
461
  if (totalFeeMinusDistributions.gt(ZERO)) {
384
- const spreadScale = Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
462
+ const spreadScale = Math.min(
463
+ MAX_BID_ASK_INVENTORY_SKEW_FACTOR,
464
+ 1 + effectiveLeverage
465
+ );
385
466
  if (netBaseAssetAmount.gt(ZERO)) {
386
467
  longSpread *= spreadScale;
387
468
  } else {
388
469
  shortSpread *= spreadScale;
389
470
  }
390
471
  } else {
391
- longSpread *= MAX_INVENTORY_SKEW;
392
- shortSpread *= MAX_INVENTORY_SKEW;
472
+ longSpread *= MAX_BID_ASK_INVENTORY_SKEW_FACTOR;
473
+ shortSpread *= MAX_BID_ASK_INVENTORY_SKEW_FACTOR;
393
474
  }
394
475
 
395
476
  const totalSpread = longSpread + shortSpread;
@@ -411,78 +492,50 @@ export function calculateSpread(
411
492
  direction: PositionDirection,
412
493
  oraclePriceData: OraclePriceData
413
494
  ): number {
414
- let spread = amm.baseSpread / 2;
415
-
416
495
  if (amm.baseSpread == 0 || amm.curveUpdateIntensity == 0) {
417
- return spread;
496
+ return amm.baseSpread / 2;
418
497
  }
419
498
 
420
- const markPrice = calculatePrice(
499
+ const reservePrice = calculatePrice(
421
500
  amm.baseAssetReserve,
422
501
  amm.quoteAssetReserve,
423
502
  amm.pegMultiplier
424
503
  );
425
504
 
426
- const targetPrice = oraclePriceData?.price || markPrice;
505
+ const targetPrice = oraclePriceData?.price || reservePrice;
427
506
  const confInterval = oraclePriceData.confidence || ZERO;
428
507
 
429
- const targetMarkSpreadPct = markPrice
508
+ const targetMarkSpreadPct = reservePrice
430
509
  .sub(targetPrice)
431
510
  .mul(BID_ASK_SPREAD_PRECISION)
432
- .div(markPrice);
511
+ .div(reservePrice);
433
512
 
434
513
  const confIntervalPct = confInterval
435
514
  .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
- }
515
+ .div(reservePrice);
448
516
 
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
- }
517
+ const [longSpread, shortSpread] = calculateSpreadBN(
518
+ amm.baseSpread,
519
+ targetMarkSpreadPct,
520
+ confIntervalPct,
521
+ amm.maxSpread,
522
+ amm.quoteAssetReserve,
523
+ amm.terminalQuoteAssetReserve,
524
+ amm.pegMultiplier,
525
+ amm.netBaseAssetAmount,
526
+ reservePrice,
527
+ amm.totalFeeMinusDistributions,
528
+ amm.baseAssetReserve,
529
+ amm.minBaseAssetReserve,
530
+ amm.maxBaseAssetReserve
531
+ );
476
532
 
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
- }
533
+ let spread: number;
484
534
 
485
- spread *= spreadScale;
535
+ if (isVariant(direction, 'long')) {
536
+ spread = longSpread;
537
+ } else {
538
+ spread = shortSpread;
486
539
  }
487
540
 
488
541
  return spread;
@@ -573,9 +626,9 @@ export function getSwapDirection(
573
626
  * Helper function calculating terminal price of amm
574
627
  *
575
628
  * @param market
576
- * @returns cost : Precision MARK_PRICE_PRECISION
629
+ * @returns cost : Precision PRICE_PRECISION
577
630
  */
578
- export function calculateTerminalPrice(market: MarketAccount) {
631
+ export function calculateTerminalPrice(market: PerpMarketAccount) {
579
632
  const directionToClose = market.amm.netBaseAssetAmount.gt(ZERO)
580
633
  ? PositionDirection.SHORT
581
634
  : PositionDirection.LONG;
@@ -589,7 +642,7 @@ export function calculateTerminalPrice(market: MarketAccount) {
589
642
  );
590
643
 
591
644
  const terminalPrice = newQuoteAssetReserve
592
- .mul(MARK_PRICE_PRECISION)
645
+ .mul(PRICE_PRECISION)
593
646
  .mul(market.amm.pegMultiplier)
594
647
  .div(PEG_PRECISION)
595
648
  .div(newBaseAssetReserve);
@@ -606,7 +659,7 @@ export function calculateMaxBaseAssetAmountToTrade(
606
659
  const invariant = amm.sqrtK.mul(amm.sqrtK);
607
660
 
608
661
  const newBaseAssetReserveSquared = invariant
609
- .mul(MARK_PRICE_PRECISION)
662
+ .mul(PRICE_PRECISION)
610
663
  .mul(amm.pegMultiplier)
611
664
  .div(limit_price)
612
665
  .div(PEG_PRECISION);
@@ -640,6 +693,10 @@ export function calculateQuoteAssetAmountSwapped(
640
693
  pegMultiplier: BN,
641
694
  swapDirection: SwapDirection
642
695
  ): BN {
696
+ if (isVariant(swapDirection, 'remove')) {
697
+ quoteAssetReserves = quoteAssetReserves.add(ONE);
698
+ }
699
+
643
700
  let quoteAssetAmount = quoteAssetReserves
644
701
  .mul(pegMultiplier)
645
702
  .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
@@ -650,3 +707,29 @@ export function calculateQuoteAssetAmountSwapped(
650
707
 
651
708
  return quoteAssetAmount;
652
709
  }
710
+
711
+ export function calculateMaxBaseAssetAmountFillable(
712
+ amm: AMM,
713
+ orderDirection: PositionDirection
714
+ ): BN {
715
+ const maxFillSize = amm.baseAssetReserve.div(
716
+ new BN(amm.maxBaseAssetAmountRatio)
717
+ );
718
+ let maxBaseAssetAmountOnSide: BN;
719
+ if (isVariant(orderDirection, 'long')) {
720
+ maxBaseAssetAmountOnSide = BN.max(
721
+ ZERO,
722
+ amm.baseAssetReserve.sub(amm.minBaseAssetReserve)
723
+ );
724
+ } else {
725
+ maxBaseAssetAmountOnSide = BN.max(
726
+ ZERO,
727
+ amm.maxBaseAssetReserve.sub(amm.baseAssetReserve)
728
+ );
729
+ }
730
+
731
+ return standardizeBaseAssetAmount(
732
+ BN.min(maxFillSize, maxBaseAssetAmountOnSide),
733
+ amm.baseAssetAmountStepSize
734
+ );
735
+ }
@@ -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,9 +1,9 @@
1
1
  import { BN } from '../';
2
- import { MARK_PRICE_PRECISION } from '../constants/numericConstants';
2
+ import { PRICE_PRECISION } from '../constants/numericConstants';
3
3
 
4
4
  export const convertToNumber = (
5
5
  bigNumber: BN,
6
- precision: BN = MARK_PRICE_PRECISION
6
+ precision: BN = PRICE_PRECISION
7
7
  ) => {
8
8
  if (!bigNumber) return 0;
9
9
  return (