@velocity-exchange/sdk 0.4.0 → 0.6.1

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 (325) hide show
  1. package/README.md +3 -3
  2. package/lib/browser/adminClient.d.ts +52 -0
  3. package/lib/browser/adminClient.js +97 -0
  4. package/lib/browser/config.js +6 -7
  5. package/lib/browser/constants/numericConstants.d.ts +1 -1
  6. package/lib/browser/constants/numericConstants.js +1 -1
  7. package/lib/browser/decode/user.js +5 -1
  8. package/lib/browser/idl/velocity.d.ts +191 -15
  9. package/lib/browser/idl/velocity.json +192 -16
  10. package/lib/browser/orderSubscriber/OrderSubscriber.d.ts +1 -0
  11. package/lib/browser/orderSubscriber/OrderSubscriber.js +10 -4
  12. package/lib/browser/pyth/pythLazerSubscriber.js +37 -27
  13. package/lib/browser/types.d.ts +6 -0
  14. package/lib/browser/user.d.ts +20 -3
  15. package/lib/browser/user.js +52 -4
  16. package/lib/browser/velocityClient.d.ts +46 -10
  17. package/lib/browser/velocityClient.js +107 -35
  18. package/lib/node/adminClient.d.ts +52 -0
  19. package/lib/node/adminClient.d.ts.map +1 -1
  20. package/lib/node/adminClient.js +97 -0
  21. package/lib/node/config.d.ts.map +1 -1
  22. package/lib/node/config.js +6 -7
  23. package/lib/node/constants/numericConstants.d.ts +1 -1
  24. package/lib/node/constants/numericConstants.d.ts.map +1 -1
  25. package/lib/node/constants/numericConstants.js +1 -1
  26. package/lib/node/decode/user.d.ts.map +1 -1
  27. package/lib/node/decode/user.js +5 -1
  28. package/lib/node/idl/velocity.d.ts +191 -15
  29. package/lib/node/idl/velocity.d.ts.map +1 -1
  30. package/lib/node/idl/velocity.json +192 -16
  31. package/lib/node/orderSubscriber/OrderSubscriber.d.ts +1 -0
  32. package/lib/node/orderSubscriber/OrderSubscriber.d.ts.map +1 -1
  33. package/lib/node/orderSubscriber/OrderSubscriber.js +10 -4
  34. package/lib/node/pyth/pythLazerSubscriber.d.ts.map +1 -1
  35. package/lib/node/pyth/pythLazerSubscriber.js +37 -27
  36. package/lib/node/types.d.ts +6 -0
  37. package/lib/node/types.d.ts.map +1 -1
  38. package/lib/node/user.d.ts +20 -3
  39. package/lib/node/user.d.ts.map +1 -1
  40. package/lib/node/user.js +52 -4
  41. package/lib/node/velocityClient.d.ts +46 -10
  42. package/lib/node/velocityClient.d.ts.map +1 -1
  43. package/lib/node/velocityClient.js +107 -35
  44. package/package.json +7 -3
  45. package/.prettierignore +0 -1
  46. package/CHANGELOG.md +0 -132
  47. package/build-browser.js +0 -58
  48. package/bunfig.toml +0 -3
  49. package/esbuild-shims.js +0 -12
  50. package/scripts/deposit-isolated-positions.ts +0 -110
  51. package/scripts/find-flagged-users.ts +0 -213
  52. package/scripts/grpc-client-test-comparison.ts +0 -372
  53. package/scripts/grpc-multiuser-client-test-comparison.ts +0 -158
  54. package/scripts/postbuild.js +0 -95
  55. package/scripts/single-grpc-client-test.ts +0 -284
  56. package/scripts/withdraw-isolated-positions.ts +0 -174
  57. package/src/accounts/README_WebSocketAccountSubscriberV2.md +0 -95
  58. package/src/accounts/README_WebSocketProgramAccountSubscriberV2.md +0 -135
  59. package/src/accounts/basicUserAccountSubscriber.ts +0 -79
  60. package/src/accounts/basicUserStatsAccountSubscriber.ts +0 -87
  61. package/src/accounts/bulkAccountLoader.ts +0 -358
  62. package/src/accounts/bulkUserStatsSubscription.ts +0 -40
  63. package/src/accounts/bulkUserSubscription.ts +0 -39
  64. package/src/accounts/customizedCadenceBulkAccountLoader.ts +0 -250
  65. package/src/accounts/fetch.ts +0 -200
  66. package/src/accounts/grpcAccountSubscriber.ts +0 -225
  67. package/src/accounts/grpcInsuranceFundStakeAccountSubscriber.ts +0 -73
  68. package/src/accounts/grpcMultiAccountSubscriber.ts +0 -566
  69. package/src/accounts/grpcMultiUserAccountSubscriber.ts +0 -328
  70. package/src/accounts/grpcProgramAccountSubscriber.ts +0 -264
  71. package/src/accounts/grpcUserAccountSubscriber.ts +0 -63
  72. package/src/accounts/grpcUserStatsAccountSubscriber.ts +0 -65
  73. package/src/accounts/grpcVelocityClientAccountSubscriber.ts +0 -257
  74. package/src/accounts/grpcVelocityClientAccountSubscriberV2.ts +0 -941
  75. package/src/accounts/laserProgramAccountSubscriber.ts +0 -266
  76. package/src/accounts/oneShotUserAccountSubscriber.ts +0 -88
  77. package/src/accounts/oneShotUserStatsAccountSubscriber.ts +0 -94
  78. package/src/accounts/pollingInsuranceFundStakeAccountSubscriber.ts +0 -223
  79. package/src/accounts/pollingOracleAccountSubscriber.ts +0 -151
  80. package/src/accounts/pollingTokenAccountSubscriber.ts +0 -147
  81. package/src/accounts/pollingUserAccountSubscriber.ts +0 -198
  82. package/src/accounts/pollingUserStatsAccountSubscriber.ts +0 -180
  83. package/src/accounts/pollingVelocityClientAccountSubscriber.ts +0 -774
  84. package/src/accounts/testBulkAccountLoader.ts +0 -59
  85. package/src/accounts/types.ts +0 -428
  86. package/src/accounts/utils.ts +0 -90
  87. package/src/accounts/webSocketAccountSubscriber.ts +0 -304
  88. package/src/accounts/webSocketAccountSubscriberV2.ts +0 -536
  89. package/src/accounts/webSocketInsuranceFundStakeAccountSubscriber.ts +0 -171
  90. package/src/accounts/webSocketProgramAccountSubscriber.ts +0 -244
  91. package/src/accounts/webSocketProgramAccountSubscriberV2.ts +0 -1048
  92. package/src/accounts/webSocketProgramAccountsSubscriberV2.ts +0 -1042
  93. package/src/accounts/webSocketUserAccountSubscriber.ts +0 -139
  94. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +0 -131
  95. package/src/accounts/webSocketVelocityClientAccountSubscriber.ts +0 -865
  96. package/src/accounts/webSocketVelocityClientAccountSubscriberV2.ts +0 -897
  97. package/src/accounts/websocketProgramUserAccountSubscriber.ts +0 -127
  98. package/src/addresses/marketAddresses.ts +0 -28
  99. package/src/addresses/pda.ts +0 -620
  100. package/src/adminClient.ts +0 -8136
  101. package/src/assert/assert.ts +0 -5
  102. package/src/auctionSubscriber/auctionSubscriber.ts +0 -86
  103. package/src/auctionSubscriber/auctionSubscriberGrpc.ts +0 -99
  104. package/src/auctionSubscriber/index.ts +0 -9
  105. package/src/auctionSubscriber/types.ts +0 -30
  106. package/src/bankrun/bankrunConnection.ts +0 -630
  107. package/src/blockhashSubscriber/BlockhashSubscriber.ts +0 -160
  108. package/src/blockhashSubscriber/index.ts +0 -6
  109. package/src/blockhashSubscriber/types.ts +0 -13
  110. package/src/clock/clockSubscriber.ts +0 -146
  111. package/src/config.ts +0 -312
  112. package/src/constants/index.ts +0 -9
  113. package/src/constants/numericConstants.ts +0 -194
  114. package/src/constants/perpMarkets.ts +0 -127
  115. package/src/constants/spotMarkets.ts +0 -104
  116. package/src/constants/txConstants.ts +0 -2
  117. package/src/constituentMap/constituentMap.ts +0 -305
  118. package/src/constituentMap/pollingConstituentAccountSubscriber.ts +0 -99
  119. package/src/constituentMap/webSocketConstituentAccountSubscriber.ts +0 -121
  120. package/src/core/VelocityCore.ts +0 -606
  121. package/src/core/index.ts +0 -12
  122. package/src/core/instructions/deposit.ts +0 -64
  123. package/src/core/instructions/fill.ts +0 -51
  124. package/src/core/instructions/funding.ts +0 -33
  125. package/src/core/instructions/liquidation.ts +0 -55
  126. package/src/core/instructions/orders.ts +0 -84
  127. package/src/core/instructions/perpOrders.ts +0 -312
  128. package/src/core/instructions/settlement.ts +0 -40
  129. package/src/core/instructions/trigger.ts +0 -41
  130. package/src/core/instructions/withdraw.ts +0 -65
  131. package/src/core/remainingAccounts.ts +0 -320
  132. package/src/core/signedMsg.ts +0 -109
  133. package/src/decode/customCoder.ts +0 -148
  134. package/src/decode/user.ts +0 -401
  135. package/src/dlob/DLOB.ts +0 -2793
  136. package/src/dlob/DLOBNode.ts +0 -305
  137. package/src/dlob/DLOBSubscriber.ts +0 -269
  138. package/src/dlob/NodeList.ts +0 -244
  139. package/src/dlob/orderBookLevels.ts +0 -695
  140. package/src/dlob/types.ts +0 -37
  141. package/src/events/eventList.ts +0 -114
  142. package/src/events/eventSubscriber.ts +0 -521
  143. package/src/events/eventsServerLogProvider.ts +0 -189
  144. package/src/events/fetchLogs.ts +0 -219
  145. package/src/events/parse.ts +0 -271
  146. package/src/events/pollingLogProvider.ts +0 -113
  147. package/src/events/sort.ts +0 -51
  148. package/src/events/txEventCache.ts +0 -92
  149. package/src/events/types.ts +0 -337
  150. package/src/events/webSocketLogProvider.ts +0 -152
  151. package/src/factory/bigNum.ts +0 -709
  152. package/src/factory/oracleClient.ts +0 -73
  153. package/src/idl/pyth.json +0 -142
  154. package/src/idl/pyth.ts +0 -97
  155. package/src/idl/pyth_solana_receiver.json +0 -628
  156. package/src/idl/token_faucet.json +0 -229
  157. package/src/idl/token_faucet.ts +0 -197
  158. package/src/idl/velocity.json +0 -23974
  159. package/src/idl/velocity.ts +0 -23980
  160. package/src/index.ts +0 -150
  161. package/src/indicative-quotes/indicativeQuotesSender.ts +0 -233
  162. package/src/isomorphic/README.md +0 -19
  163. package/src/isomorphic/anchor.browser.ts +0 -44
  164. package/src/isomorphic/anchor.node.ts +0 -1
  165. package/src/isomorphic/anchor.ts +0 -1
  166. package/src/isomorphic/anchor29.browser.ts +0 -24
  167. package/src/isomorphic/anchor29.node.ts +0 -1
  168. package/src/isomorphic/anchor29.ts +0 -1
  169. package/src/isomorphic/grpc.browser.ts +0 -4
  170. package/src/isomorphic/grpc.node.ts +0 -130
  171. package/src/isomorphic/grpc.ts +0 -1
  172. package/src/jupiter/jupiterClient.ts +0 -502
  173. package/src/keypair.ts +0 -32
  174. package/src/margin/README.md +0 -138
  175. package/src/marginCalculation.ts +0 -407
  176. package/src/marinade/idl/idl.json +0 -1962
  177. package/src/marinade/index.ts +0 -73
  178. package/src/marinade/types.ts +0 -3925
  179. package/src/math/amm.ts +0 -1758
  180. package/src/math/auction.ts +0 -480
  181. package/src/math/bankruptcy.ts +0 -138
  182. package/src/math/builder.ts +0 -130
  183. package/src/math/conversion.ts +0 -45
  184. package/src/math/exchangeStatus.ts +0 -261
  185. package/src/math/funding.ts +0 -498
  186. package/src/math/insurance.ts +0 -171
  187. package/src/math/liquidation.ts +0 -433
  188. package/src/math/margin.ts +0 -327
  189. package/src/math/market.ts +0 -487
  190. package/src/math/oracles.ts +0 -477
  191. package/src/math/orders.ts +0 -500
  192. package/src/math/position.ts +0 -381
  193. package/src/math/repeg.ts +0 -223
  194. package/src/math/spotBalance.ts +0 -996
  195. package/src/math/spotMarket.ts +0 -115
  196. package/src/math/spotPosition.ts +0 -263
  197. package/src/math/state.ts +0 -71
  198. package/src/math/superStake.ts +0 -602
  199. package/src/math/tiers.ts +0 -73
  200. package/src/math/trade.ts +0 -879
  201. package/src/math/utils.ts +0 -183
  202. package/src/memcmp.ts +0 -279
  203. package/src/oracles/oracleClientCache.ts +0 -41
  204. package/src/oracles/oracleId.ts +0 -99
  205. package/src/oracles/prelaunchOracleClient.ts +0 -63
  206. package/src/oracles/pythClient.ts +0 -125
  207. package/src/oracles/pythLazerClient.ts +0 -141
  208. package/src/oracles/quoteAssetOracleClient.ts +0 -43
  209. package/src/oracles/strictOraclePrice.ts +0 -40
  210. package/src/oracles/types.ts +0 -82
  211. package/src/oracles/utils.ts +0 -45
  212. package/src/orderParams.ts +0 -117
  213. package/src/orderSubscriber/OrderSubscriber.ts +0 -378
  214. package/src/orderSubscriber/PollingSubscription.ts +0 -50
  215. package/src/orderSubscriber/WebsocketSubscription.ts +0 -137
  216. package/src/orderSubscriber/grpcSubscription.ts +0 -155
  217. package/src/orderSubscriber/index.ts +0 -7
  218. package/src/orderSubscriber/types.ts +0 -64
  219. package/src/priorityFee/averageOverSlotsStrategy.ts +0 -17
  220. package/src/priorityFee/averageStrategy.ts +0 -13
  221. package/src/priorityFee/ewmaStrategy.ts +0 -51
  222. package/src/priorityFee/heliusPriorityFeeMethod.ts +0 -68
  223. package/src/priorityFee/index.ts +0 -16
  224. package/src/priorityFee/maxOverSlotsStrategy.ts +0 -18
  225. package/src/priorityFee/maxStrategy.ts +0 -8
  226. package/src/priorityFee/priorityFeeSubscriber.ts +0 -328
  227. package/src/priorityFee/priorityFeeSubscriberMap.ts +0 -134
  228. package/src/priorityFee/solanaPriorityFeeMethod.ts +0 -46
  229. package/src/priorityFee/types.ts +0 -82
  230. package/src/priorityFee/velocityPriorityFeeMethod.ts +0 -53
  231. package/src/pyth/constants.ts +0 -9
  232. package/src/pyth/index.ts +0 -15
  233. package/src/pyth/pythLazerSubscriber.ts +0 -365
  234. package/src/pyth/types.ts +0 -4451
  235. package/src/pyth/utils.ts +0 -13
  236. package/src/slot/SlotSubscriber.ts +0 -126
  237. package/src/slot/SlothashSubscriber.ts +0 -163
  238. package/src/swap/UnifiedSwapClient.ts +0 -315
  239. package/src/swift/grpcSignedMsgUserAccountSubscriber.ts +0 -81
  240. package/src/swift/index.ts +0 -10
  241. package/src/swift/signedMsgUserAccountSubscriber.ts +0 -251
  242. package/src/swift/swiftOrderSubscriber.ts +0 -351
  243. package/src/testClient.ts +0 -42
  244. package/src/titan/titanClient.ts +0 -438
  245. package/src/token/index.ts +0 -13
  246. package/src/tokenFaucet.ts +0 -296
  247. package/src/tx/baseTxSender.ts +0 -651
  248. package/src/tx/blockhashFetcher/baseBlockhashFetcher.ts +0 -31
  249. package/src/tx/blockhashFetcher/cachedBlockhashFetcher.ts +0 -105
  250. package/src/tx/blockhashFetcher/types.ts +0 -9
  251. package/src/tx/fastSingleTxSender.ts +0 -200
  252. package/src/tx/forwardOnlyTxSender.ts +0 -193
  253. package/src/tx/priorityFeeCalculator.ts +0 -117
  254. package/src/tx/reportTransactionError.ts +0 -176
  255. package/src/tx/retryTxSender.ts +0 -177
  256. package/src/tx/txHandler.ts +0 -1009
  257. package/src/tx/txParamProcessor.ts +0 -225
  258. package/src/tx/types.ts +0 -117
  259. package/src/tx/utils.ts +0 -133
  260. package/src/tx/whileValidTxSender.ts +0 -377
  261. package/src/types.ts +0 -2575
  262. package/src/user.ts +0 -5316
  263. package/src/userConfig.ts +0 -38
  264. package/src/userMap/PollingSubscription.ts +0 -61
  265. package/src/userMap/WebsocketSubscription.ts +0 -93
  266. package/src/userMap/grpcSubscription.ts +0 -93
  267. package/src/userMap/referrerMap.ts +0 -360
  268. package/src/userMap/revenueShareEscrowMap.ts +0 -342
  269. package/src/userMap/userMap.ts +0 -784
  270. package/src/userMap/userMapConfig.ts +0 -82
  271. package/src/userMap/userStatsMap.ts +0 -393
  272. package/src/userName.ts +0 -37
  273. package/src/userStats.ts +0 -159
  274. package/src/userStatsConfig.ts +0 -35
  275. package/src/util/TransactionConfirmationManager.ts +0 -333
  276. package/src/util/chainClock.ts +0 -65
  277. package/src/util/computeUnits.ts +0 -101
  278. package/src/util/digest.ts +0 -33
  279. package/src/util/ed25519Utils.ts +0 -95
  280. package/src/util/promiseTimeout.ts +0 -23
  281. package/src/velocityClient.ts +0 -14802
  282. package/src/velocityClientConfig.ts +0 -119
  283. package/src/wallet.ts +0 -91
  284. package/tests/VelocityCore/builder_escrow.test.ts +0 -121
  285. package/tests/VelocityCore/decode.test.ts +0 -16
  286. package/tests/VelocityCore/fill_trigger.test.ts +0 -73
  287. package/tests/VelocityCore/instructions.test.ts +0 -46
  288. package/tests/VelocityCore/pdas.test.ts +0 -30
  289. package/tests/VelocityCore/perp_orders.test.ts +0 -205
  290. package/tests/VelocityCore/remainingAccounts.test.ts +0 -72
  291. package/tests/VelocityCore/settlement_liquidation.test.ts +0 -69
  292. package/tests/accounts/customizedCadenceBulkAccountLoader.test.ts +0 -211
  293. package/tests/amm/test.ts +0 -2402
  294. package/tests/auctions/test.ts +0 -81
  295. package/tests/bn/test.ts +0 -355
  296. package/tests/builder/builderFee.test.ts +0 -42
  297. package/tests/ci/verifyConstants.ts +0 -393
  298. package/tests/decode/test.ts +0 -262
  299. package/tests/decode/userAccountBufferStrings.ts +0 -102
  300. package/tests/dlob/helpers.ts +0 -748
  301. package/tests/dlob/test.ts +0 -6969
  302. package/tests/dlob/tickSizeStandardization.ts +0 -545
  303. package/tests/events/parseLogsForCuUsage.ts +0 -139
  304. package/tests/exchangeStatus/test.ts +0 -45
  305. package/tests/insurance/test.ts +0 -40
  306. package/tests/liquidation/test.ts +0 -125
  307. package/tests/oracles/mmOracleGate.test.ts +0 -379
  308. package/tests/oracles/pythPegSnap.test.ts +0 -76
  309. package/tests/sdkParity/enumParity.test.ts +0 -84
  310. package/tests/sdkParity/marginCategoryFill.test.ts +0 -143
  311. package/tests/sdkParity/memcmpOffsets.test.ts +0 -139
  312. package/tests/spot/test.ts +0 -281
  313. package/tests/tx/TransactionConfirmationManager.test.ts +0 -312
  314. package/tests/tx/cachedBlockhashFetcher.test.ts +0 -96
  315. package/tests/tx/priorityFeeCalculator.ts +0 -77
  316. package/tests/tx/priorityFeeStrategy.ts +0 -95
  317. package/tests/user/bankruptcy.ts +0 -165
  318. package/tests/user/feeAndWithdrawLimits.ts +0 -284
  319. package/tests/user/getMarginCalculation.ts +0 -586
  320. package/tests/user/helpers.ts +0 -184
  321. package/tests/user/liquidations.ts +0 -129
  322. package/tests/user/marginCalculations.test.ts +0 -321
  323. package/tests/user/test.ts +0 -833
  324. package/tsconfig.browser.json +0 -18
  325. package/tsconfig.json +0 -36
package/tests/amm/test.ts DELETED
@@ -1,2402 +0,0 @@
1
- import {
2
- BN,
3
- PEG_PRECISION,
4
- PRICE_PRECISION,
5
- AMM_RESERVE_PRECISION,
6
- QUOTE_PRECISION,
7
- PERCENTAGE_PRECISION,
8
- calculateSpread,
9
- calculateSpreadBN,
10
- calculateSpreadFundingBiasScale,
11
- ZERO,
12
- sigNum,
13
- ONE,
14
- calculateLiveOracleStd,
15
- calculateLiveOracleTwap,
16
- calculateInventoryScale,
17
- calculateAllEstimatedFundingRate,
18
- calculateLongShortFundingRateAndLiveTwaps,
19
- getVammL2Generator,
20
- BASE_PRECISION,
21
- PerpMarketAccount,
22
- L2Level,
23
- calculateUpdatedAMM,
24
- calculateMarketOpenBidAsk,
25
- calculateSpreadReserves,
26
- calculatePrice,
27
- BID_ASK_SPREAD_PRECISION,
28
- squareRootBN,
29
- calculateReferencePriceOffset,
30
- calculateInventoryLiquidityRatio,
31
- ContractTier,
32
- isOracleValid,
33
- OracleGuardRails,
34
- getNewOracleConfPct,
35
- MMOraclePriceData,
36
- OraclePriceData,
37
- calculateAmmReservesAfterSwap,
38
- getSwapDirection,
39
- PositionDirection,
40
- // calculateReservePrice,
41
- } from '../../src';
42
- import { mockPerpMarkets } from '../dlob/helpers';
43
-
44
- import { assert } from '../../src/assert/assert';
45
- import * as _ from 'lodash';
46
-
47
- class AMMSpreadTerms {
48
- longVolSpread: number;
49
- shortVolSpread: number;
50
- longSpreadwPS: number;
51
- shortSpreadwPS: number;
52
- maxTargetSpread: number;
53
- inventorySpreadScale: number;
54
- longSpreadwInvScale: number;
55
- shortSpreadwInvScale: number;
56
- effectiveLeverage: number;
57
- effectiveLeverageCapped: number;
58
- longSpreadwEL: number;
59
- shortSpreadwEL: number;
60
- revenueRetreatAmount: number;
61
- halfRevenueRetreatAmount: number;
62
- longSpreadwRevRetreat: number;
63
- shortSpreadwRevRetreat: number;
64
- fundingBiasScale: number;
65
- longSpreadwFundingBias: number;
66
- shortSpreadwFundingBias: number;
67
- totalSpread: number;
68
- longSpread: number;
69
- shortSpread: number;
70
- }
71
-
72
- describe('AMM Tests', () => {
73
- it('Spread Maths', () => {
74
- let iscale = calculateInventoryScale(
75
- ZERO,
76
- AMM_RESERVE_PRECISION,
77
- AMM_RESERVE_PRECISION.div(new BN(2)),
78
- AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
79
- 250,
80
- 30000
81
- );
82
- assert(iscale == 1);
83
-
84
- iscale = calculateInventoryScale(
85
- ONE,
86
- AMM_RESERVE_PRECISION,
87
- AMM_RESERVE_PRECISION.div(new BN(2)),
88
- AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
89
- 250,
90
- 30000
91
- );
92
- assert(iscale == 1);
93
-
94
- let baa = new BN(1000);
95
- iscale = calculateInventoryScale(
96
- baa,
97
- AMM_RESERVE_PRECISION.add(baa),
98
- AMM_RESERVE_PRECISION.div(new BN(2)),
99
- AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
100
- 250,
101
- 30000
102
- );
103
- console.log(iscale);
104
- assert(iscale == 1.00024);
105
-
106
- baa = new BN(100000);
107
- iscale = calculateInventoryScale(
108
- baa,
109
- AMM_RESERVE_PRECISION.add(baa),
110
- AMM_RESERVE_PRECISION.div(new BN(2)),
111
- AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
112
- 250,
113
- 30000
114
- );
115
- console.log(iscale);
116
- assert(iscale == 1.024);
117
-
118
- baa = new BN(1000000);
119
- iscale = calculateInventoryScale(
120
- baa,
121
- AMM_RESERVE_PRECISION.add(baa),
122
- AMM_RESERVE_PRECISION.div(new BN(2)),
123
- AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
124
- 250,
125
- 30000
126
- );
127
- console.log(iscale);
128
- assert(iscale == 1.24048);
129
-
130
- baa = new BN(10000000); // 2%
131
- iscale = calculateInventoryScale(
132
- baa,
133
- AMM_RESERVE_PRECISION.add(baa),
134
- AMM_RESERVE_PRECISION.div(new BN(2)),
135
- AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
136
- 250,
137
- 30000
138
- );
139
- console.log(iscale);
140
- assert(iscale == 3.44896);
141
-
142
- baa = new BN(50000000); // 10%
143
- iscale = calculateInventoryScale(
144
- baa,
145
- AMM_RESERVE_PRECISION.add(baa),
146
- AMM_RESERVE_PRECISION.div(new BN(2)),
147
- AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
148
- 250,
149
- 30000
150
- );
151
- console.log(iscale);
152
- assert(iscale == 14.33332);
153
-
154
- baa = AMM_RESERVE_PRECISION.div(new BN(4)); // 50%
155
- iscale = calculateInventoryScale(
156
- baa,
157
- AMM_RESERVE_PRECISION.add(baa),
158
- AMM_RESERVE_PRECISION.div(new BN(2)),
159
- AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
160
- 250,
161
- 30000
162
- );
163
- console.log(iscale);
164
- assert(iscale == 120); //100%
165
-
166
- baa = AMM_RESERVE_PRECISION.div(new BN(4)); // 50%
167
- iscale = calculateInventoryScale(
168
- baa,
169
- AMM_RESERVE_PRECISION.add(baa),
170
- AMM_RESERVE_PRECISION.div(new BN(2)),
171
- AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
172
- 250,
173
- 30000 * 2
174
- );
175
- console.log(iscale);
176
- assert(iscale == 120 * 2); //100%
177
-
178
- baa = AMM_RESERVE_PRECISION.div(new BN(5)); // <50%
179
- iscale = calculateInventoryScale(
180
- baa,
181
- AMM_RESERVE_PRECISION.add(baa),
182
- AMM_RESERVE_PRECISION.div(new BN(2)),
183
- AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
184
- 250,
185
- 30000 * 2
186
- );
187
- assert(iscale == 160.99984);
188
-
189
- baa = new BN(855329058);
190
- iscale = calculateInventoryScale(
191
- baa,
192
- AMM_RESERVE_PRECISION.add(baa),
193
- AMM_RESERVE_PRECISION.div(new BN(2)),
194
- AMM_RESERVE_PRECISION,
195
- 250,
196
- 30000
197
- ); // >100%
198
- assert(iscale == 120);
199
- assert(250 * iscale == 30000);
200
-
201
- iscale = calculateInventoryScale(
202
- baa,
203
- AMM_RESERVE_PRECISION.add(baa), // ~85%
204
- AMM_RESERVE_PRECISION.div(new BN(2)),
205
- AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
206
- 250,
207
- 30000
208
- );
209
- assert(iscale == 120);
210
- assert(250 * iscale == 30000);
211
-
212
- baa = new BN(-855329058); // ~85%
213
- iscale = calculateInventoryScale(
214
- baa,
215
- AMM_RESERVE_PRECISION.add(baa),
216
- AMM_RESERVE_PRECISION.div(new BN(2)),
217
- AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
218
- 250,
219
- 30000
220
- );
221
- assert(iscale == 120);
222
- assert(250 * iscale == 30000);
223
-
224
- // 'bonk' scale
225
- iscale = calculateInventoryScale(
226
- new BN('30228000000000000'),
227
- new BN('2496788386034912600'),
228
- new BN('2443167585342470000'),
229
- new BN('2545411471321696000'),
230
- 3500,
231
- 100000
232
- );
233
- console.log(iscale);
234
- console.log((3500 * iscale) / 1e6);
235
- assert(iscale == 18.762285);
236
- assert((3500 * iscale) / 1e6 == 0.06566799749999999); //6.5%
237
- });
238
-
239
- it('Funding Bias Scale', () => {
240
- // values pinned to the program's calculate_spread_funding_bias_scale tests
241
- const twap = new BN(100).mul(PRICE_PRECISION); // $100
242
- // hourly rate matching the funding offset floor f_ref (~10.95%/yr):
243
- // fNorm = 1_250_000 * 1e6 / 1e8 * 24 = 300_000
244
- const saturatingRate = new BN(1_250_000);
245
- const qAmmLong = BASE_PRECISION.neg(); // users net short
246
- const qAmmShort = BASE_PRECISION; // users net long
247
- const one = BID_ASK_SPREAD_PRECISION.toNumber();
248
-
249
- // s = 0 disables
250
- assert(
251
- calculateSpreadFundingBiasScale(qAmmLong, saturatingRate, twap, 0) == one
252
- );
253
-
254
- // f * q >= 0: vAMM receives (or zero rate/inventory), β = 1
255
- assert(
256
- calculateSpreadFundingBiasScale(qAmmShort, saturatingRate, twap, 50) ==
257
- one
258
- );
259
- assert(
260
- calculateSpreadFundingBiasScale(
261
- qAmmLong,
262
- saturatingRate.neg(),
263
- twap,
264
- 50
265
- ) == one
266
- );
267
- assert(
268
- calculateSpreadFundingBiasScale(ZERO, saturatingRate, twap, 50) == one
269
- );
270
- assert(calculateSpreadFundingBiasScale(qAmmLong, ZERO, twap, 50) == one);
271
-
272
- // paying at f_ref: ρ ~= 1, β ~= 1 + s/100
273
- assert(
274
- calculateSpreadFundingBiasScale(qAmmLong, saturatingRate, twap, 50) ==
275
- 1_499_950
276
- );
277
- assert(
278
- calculateSpreadFundingBiasScale(
279
- qAmmShort,
280
- saturatingRate.neg(),
281
- twap,
282
- 50
283
- ) == 1_499_950
284
- );
285
-
286
- // half ramp: β = 1 + s/100 * 0.5
287
- assert(
288
- calculateSpreadFundingBiasScale(
289
- qAmmLong,
290
- saturatingRate.divn(2),
291
- twap,
292
- 50
293
- ) == 1_249_975
294
- );
295
-
296
- // past f_ref the ramp clamps at 1: β = 1 + s/100 exactly
297
- assert(
298
- calculateSpreadFundingBiasScale(
299
- qAmmLong,
300
- saturatingRate.muln(10),
301
- twap,
302
- 100
303
- ) ==
304
- 2 * one
305
- );
306
-
307
- // integration: paying side doubles at s = 100, other side untouched,
308
- // mirrors the program's calculate_spread_funding_bias_tests
309
- const calc = (rate: BN, s: number) =>
310
- calculateSpreadBN(
311
- 1000, // baseSpread
312
- ZERO,
313
- ZERO,
314
- 2000, // maxSpread
315
- AMM_RESERVE_PRECISION.muln(10),
316
- AMM_RESERVE_PRECISION.muln(10),
317
- new BN(34000000),
318
- new BN(-1000), // tiny vAMM-long inventory so σ = λ = 1
319
- new BN(34562304),
320
- QUOTE_PRECISION.muln(10),
321
- ZERO,
322
- AMM_RESERVE_PRECISION.muln(10),
323
- ZERO,
324
- AMM_RESERVE_PRECISION.muln(100000),
325
- ZERO,
326
- ZERO,
327
- ZERO,
328
- ZERO,
329
- ZERO,
330
- 0,
331
- rate,
332
- twap,
333
- s
334
- ) as [number, number];
335
-
336
- const [long0, short0] = calc(saturatingRate.muln(10), 0);
337
- assert(long0 == 500);
338
- assert(short0 == 500);
339
-
340
- const [long1, short1] = calc(saturatingRate.muln(10), 100);
341
- assert(long1 == long0);
342
- assert(short1 == short0 * 2);
343
-
344
- const [long2, short2] = calc(saturatingRate.muln(10).neg(), 100);
345
- assert(long2 == long0);
346
- assert(short2 == short0);
347
- });
348
-
349
- it('Various Spreads', () => {
350
- const baseSpread: number = 0.025 * 1e6;
351
- const lastOracleReservePriceSpreadPct: BN = ZERO;
352
- const lastOracleConfPct: BN = ZERO;
353
- const maxSpread: number = 0.03 * 1e6;
354
- const quoteAssetReserve: BN = new BN(
355
- AMM_RESERVE_PRECISION.toNumber() * 100
356
- );
357
- const terminalQuoteAssetReserve: BN = new BN(
358
- AMM_RESERVE_PRECISION.toNumber() * 100
359
- );
360
- const pegMultiplier: BN = new BN(13.455 * PEG_PRECISION.toNumber());
361
- const baseAssetAmountWithAmm: BN = ZERO;
362
- const reservePrice: BN = new BN(13.455 * PRICE_PRECISION.toNumber());
363
- const totalFeeMinusDistributions: BN = new BN(1);
364
- const netRevenueSinceLastFunding: BN = new BN(
365
- QUOTE_PRECISION.toNumber() * 2
366
- );
367
- const baseAssetReserve: BN = new BN(AMM_RESERVE_PRECISION.toNumber() * 100);
368
- const minBaseAssetReserve: BN = new BN(
369
- AMM_RESERVE_PRECISION.toNumber() * 90
370
- );
371
- const maxBaseAssetReserve: BN = new BN(
372
- AMM_RESERVE_PRECISION.toNumber() * 110
373
- );
374
- const markStd: BN = new BN(0.45 * PRICE_PRECISION.toNumber());
375
- const oracleStd: BN = new BN(0.55 * PRICE_PRECISION.toNumber());
376
- const longIntensity: BN = new BN(QUOTE_PRECISION.toNumber() * 20);
377
- const shortIntensity: BN = new BN(QUOTE_PRECISION.toNumber() * 2);
378
- const volume24H: BN = new BN(QUOTE_PRECISION.toNumber() * 25);
379
-
380
- const spreads = calculateSpreadBN(
381
- baseSpread,
382
- lastOracleReservePriceSpreadPct,
383
- lastOracleConfPct,
384
- maxSpread,
385
- quoteAssetReserve,
386
- terminalQuoteAssetReserve,
387
- pegMultiplier,
388
- baseAssetAmountWithAmm,
389
- reservePrice,
390
- totalFeeMinusDistributions,
391
- netRevenueSinceLastFunding,
392
- baseAssetReserve,
393
- minBaseAssetReserve,
394
- maxBaseAssetReserve,
395
- markStd,
396
- oracleStd,
397
- longIntensity,
398
- shortIntensity,
399
- volume24H,
400
- 0
401
- );
402
- const l1 = spreads[0];
403
- const s1 = spreads[1];
404
-
405
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
406
- // @ts-ignore
407
- const terms1: AMMSpreadTerms = calculateSpreadBN(
408
- baseSpread,
409
- lastOracleReservePriceSpreadPct,
410
- lastOracleConfPct,
411
- maxSpread,
412
- quoteAssetReserve,
413
- terminalQuoteAssetReserve,
414
- pegMultiplier,
415
- baseAssetAmountWithAmm,
416
- reservePrice,
417
- totalFeeMinusDistributions,
418
- netRevenueSinceLastFunding,
419
- baseAssetReserve,
420
- minBaseAssetReserve,
421
- maxBaseAssetReserve,
422
- markStd,
423
- oracleStd,
424
- longIntensity,
425
- shortIntensity,
426
- volume24H,
427
- 0,
428
- ZERO,
429
- ZERO,
430
- 0,
431
- true
432
- );
433
- // console.log(terms1);
434
-
435
- console.log('long/short spread:', l1, s1);
436
- assert(l1 == 12500);
437
- assert(s1 == 12500);
438
- assert(l1 == terms1.longSpread);
439
- assert(s1 == terms1.shortSpread);
440
-
441
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
442
- // @ts-ignore
443
- const terms2: AMMSpreadTerms = calculateSpreadBN(
444
- 300,
445
- new BN(0),
446
- new BN(484),
447
- 47500,
448
- new BN(923807816209694),
449
- new BN(925117623772584),
450
- new BN(13731157),
451
- new BN(-1314027016625),
452
- new BN(13667686),
453
- new BN(115876379475),
454
- new BN(91316628),
455
- new BN(928097825691666),
456
- new BN(907979542352912),
457
- new BN(945977491145601),
458
- new BN(161188), // mark std
459
- new BN(145963), // oracle std
460
- new BN(12358265776),
461
- new BN(72230366233),
462
- new BN(432067603632),
463
- 0,
464
- ZERO,
465
- ZERO,
466
- 0,
467
- true
468
- );
469
-
470
- assert(terms2.effectiveLeverageCapped >= 1.0002);
471
- assert(terms2.inventorySpreadScale == 8.443219);
472
- assert(terms2.longSpread == 150);
473
- assert(terms2.shortSpread == 3960);
474
-
475
- // add spread offset
476
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
477
- // @ts-ignore
478
- const terms3: AMMSpreadTerms = calculateSpreadBN(
479
- 300,
480
- new BN(0),
481
- new BN(484),
482
- 47500,
483
- new BN(923807816209694),
484
- new BN(925117623772584),
485
- new BN(13731157),
486
- new BN(-1314027016625),
487
- new BN(13667686),
488
- new BN(115876379475),
489
- new BN(91316628),
490
- new BN(928097825691666),
491
- new BN(907979542352912),
492
- new BN(945977491145601),
493
- new BN(161188),
494
- new BN(145963), // oracle std
495
- new BN(12358265776),
496
- new BN(72230366233),
497
- new BN(432067603632),
498
- 0,
499
- ZERO,
500
- ZERO,
501
- 0,
502
- true
503
- );
504
-
505
- // console.log(terms3);
506
- assert(terms3.effectiveLeverageCapped >= 1.0002);
507
- assert(terms3.inventorySpreadScale == 8.443219);
508
- assert(terms3.longSpread == 150);
509
- assert(terms3.shortSpread == 3960);
510
- assert(terms3.longSpread + terms3.shortSpread == 3960 + 150);
511
-
512
- // add spread offset
513
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
514
- // @ts-ignore
515
- const terms4: AMMSpreadTerms = calculateSpreadBN(
516
- 300,
517
- new BN(0),
518
- new BN(484),
519
- 47500,
520
- new BN(923807816209694),
521
- new BN(925117623772584),
522
- new BN(13731157),
523
- new BN(-1314027016625),
524
- new BN(13667686),
525
- new BN(115876379475),
526
- new BN(91316628),
527
- new BN(928097825691666),
528
- new BN(907979542352912),
529
- new BN(945977491145601),
530
- new BN(161188),
531
- new BN(1459632439), // oracle std (unchanged)
532
- new BN(12358265776),
533
- new BN(72230366233),
534
- new BN(432067603632),
535
- 0,
536
- ZERO,
537
- ZERO,
538
- 0,
539
- true
540
- );
541
-
542
- assert(terms4.effectiveLeverageCapped >= 1.0002);
543
- assert(terms4.inventorySpreadScale == 1.73492);
544
- assert(terms4.longSpread == 89746);
545
- assert(terms4.shortSpread == 910254);
546
- assert(terms4.longSpread + terms4.shortSpread == 1000000);
547
- });
548
-
549
- it('Corner Case Spreads', () => {
550
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
551
- // @ts-ignore
552
- const terms2: AMMSpreadTerms = calculateSpreadBN(
553
- 1000,
554
- new BN(5555),
555
- new BN(1131),
556
- 20000,
557
- new BN(1009967115003047),
558
- new BN(1009811402660255),
559
- new BN(13460124),
560
- new BN(15328930153),
561
- new BN(13667686),
562
- new BN(1235066973),
563
- new BN(88540713),
564
- new BN(994097717724176),
565
- new BN(974077854655784),
566
- new BN(1014841945381208),
567
- new BN(103320),
568
- new BN(59975),
569
- new BN(768323534),
570
- new BN(243875031),
571
- new BN(130017761029),
572
- 0,
573
- ZERO,
574
- ZERO,
575
- 0,
576
- true
577
- );
578
-
579
- assert(terms2.effectiveLeverageCapped <= 1.000001);
580
- assert(terms2.inventorySpreadScale == 1.0306);
581
- assert(terms2.longSpread == 515);
582
- assert(terms2.shortSpread == 5611);
583
-
584
- const suiExample = {
585
- status: 'active',
586
- contractType: 'perpetual',
587
- contractTier: 'c',
588
- expiryTs: '0',
589
- expiryPrice: '0',
590
- marketIndex: 9,
591
- pubkey: '91NsaUmTNNdLGbYtwmoiYSn9SgWHCsZiChfMYMYZ2nQx',
592
- name: 'SUI-PERP',
593
- amm: {
594
- baseAssetReserve: '234381482764434',
595
- sqrtK: '109260723000000001',
596
- lastFundingRate: '-16416',
597
- lastFundingRateTs: '1705845755',
598
- lastMarkPriceTwap: '1105972',
599
- lastMarkPriceTwap5Min: '1101202',
600
- lastMarkPriceTwapTs: '1705846920',
601
- lastTradeTs: '1705846920',
602
- oracle: '3Qub3HaAJaa2xNY7SUqPKd3vVwTqDfDDkEUMPjXD2c1q',
603
- oracleSource: 'pyth',
604
- historicalOracleData: {
605
- lastOraclePrice: '1099778',
606
- lastOracleDelay: '2',
607
- lastOracleConf: '0',
608
- lastOraclePriceTwap: '1106680',
609
- lastOraclePriceTwap5Min: '1102634',
610
- lastOraclePriceTwapTs: '1705846920',
611
- },
612
- lastOracleReservePriceSpreadPct: '-262785',
613
- lastOracleConfPct: '1359',
614
- fundingPeriod: '3600',
615
- quoteAssetReserve: '50933655038273508156',
616
- pegMultiplier: '4',
617
- cumulativeFundingRateLong: '186069301',
618
- cumulativeFundingRateShort: '186007157',
619
- last24HAvgFundingRate: '35147',
620
- lastFundingRateShort: '-16416',
621
- lastFundingRateLong: '-16416',
622
- totalLiquidationFee: '4889264000',
623
- totalFeeMinusDistributions: '-29523583393',
624
- totalFeeWithdrawn: '5251194706',
625
- totalFee: '7896066035',
626
- totalFeeEarnedPerLp: '77063238',
627
- orderStepSize: '1000000000',
628
- orderTickSize: '100',
629
- maxFillReserveFraction: '100',
630
- maxSlippageRatio: '50',
631
- baseSpread: '5000',
632
- curveUpdateIntensity: '100',
633
- baseAssetAmountWithAmm: '306519581',
634
- baseAssetAmountLong: '223405000000000',
635
- baseAssetAmountShort: '-224167000000000',
636
- quoteAssetAmount: '57945607973',
637
- terminalQuoteAssetReserve: '50933588428309274920',
638
- concentrationCoef: '1207100',
639
- feePool: '[object Object]',
640
- totalExchangeFee: '10110336057',
641
- totalMmFee: '-1870961568',
642
- netRevenueSinceLastFunding: '-141830281',
643
- lastUpdateSlot: '243204071',
644
- lastOracleNormalisedPrice: '1098594',
645
- lastOracleValid: 'true',
646
- lastBidPriceTwap: '1105864',
647
- lastAskPriceTwap: '1106081',
648
- longSpread: '259471',
649
- shortSpread: '3314',
650
- maxSpread: '29500',
651
- ammJitIntensity: '200',
652
- maxOpenInterest: '2000000000000000',
653
- maxBaseAssetReserve: '282922257844734',
654
- minBaseAssetReserve: '194169322578092',
655
- totalSocialLoss: '0',
656
- quoteBreakEvenAmountLong: '-237442196125',
657
- quoteBreakEvenAmountShort: '243508341566',
658
- quoteEntryAmountLong: '-234074123777',
659
- quoteEntryAmountShort: '240215285058',
660
- markStd: '237945',
661
- oracleStd: '8086',
662
- longIntensityCount: '0',
663
- longIntensityVolume: '162204',
664
- shortIntensityCount: '995',
665
- shortIntensityVolume: '2797331131',
666
- volume24H: '91370028405',
667
- minOrderSize: '1000000000',
668
- maxPositionSize: '0',
669
- bidBaseAssetReserve: '234770820775670',
670
- bidQuoteAssetReserve: '50849187948657797529',
671
- askBaseAssetReserve: '205083797418879',
672
- askQuoteAssetReserve: '58209891472312580749',
673
- },
674
- numberOfUsersWithBase: '279',
675
- numberOfUsers: '436',
676
- marginRatioInitial: '1000',
677
- marginRatioMaintenance: '500',
678
- nextFillRecordId: '69433',
679
- nextFundingRateRecordId: '6221',
680
- nextCurveRecordId: '1731',
681
- pnlPool: {
682
- scaledBalance: '61514197782399',
683
- marketIndex: '0',
684
- },
685
- liquidatorFee: '10000',
686
- ifLiquidationFee: '20000',
687
- imfFactor: '450',
688
- unrealizedPnlImfFactor: '450',
689
- unrealizedPnlMaxImbalance: '200000000',
690
- unrealizedPnlInitialAssetWeight: '0',
691
- unrealizedPnlMaintenanceAssetWeight: '10000',
692
- insuranceClaim: {
693
- revenueWithdrawSinceLastSettle: '100000000',
694
- maxRevenueWithdrawPerPeriod: '100000000',
695
- lastRevenueWithdrawTs: '1705846454',
696
- quoteSettledInsurance: '164388488',
697
- quoteMaxInsurance: '1000000000',
698
- },
699
- quoteSpotMarketIndex: '0',
700
- feeAdjustment: '0',
701
- };
702
-
703
- const reservePrice = calculatePrice(
704
- new BN(suiExample.amm.baseAssetReserve),
705
- new BN(suiExample.amm.quoteAssetReserve),
706
- new BN(suiExample.amm.pegMultiplier)
707
- );
708
- console.log('reservePrice', reservePrice.toString());
709
- assert(reservePrice.eq(new BN('869243')));
710
-
711
- const reservePriceMod = calculatePrice(
712
- new BN(suiExample.amm.baseAssetReserve),
713
- new BN(suiExample.amm.quoteAssetReserve),
714
- new BN(suiExample.amm.pegMultiplier).add(ONE)
715
- );
716
- console.log('reservePriceMod', reservePriceMod.toString());
717
- assert(reservePriceMod.eq(new BN('1086554')));
718
-
719
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
720
- // @ts-ignore
721
- const termsSuiExample: AMMSpreadTerms = calculateSpreadBN(
722
- Number(suiExample.amm.baseSpread.toString()),
723
- new BN(suiExample.amm.lastOracleReservePriceSpreadPct),
724
- new BN(suiExample.amm.lastOracleConfPct),
725
- Number(suiExample.amm.maxSpread.toString()),
726
- new BN(suiExample.amm.quoteAssetReserve),
727
- new BN(suiExample.amm.terminalQuoteAssetReserve),
728
- new BN(suiExample.amm.pegMultiplier),
729
- new BN(suiExample.amm.baseAssetAmountWithAmm),
730
- reservePrice, // reserve price
731
- new BN(suiExample.amm.totalFeeMinusDistributions),
732
- new BN(suiExample.amm.netRevenueSinceLastFunding),
733
- new BN(suiExample.amm.baseAssetReserve),
734
- new BN(suiExample.amm.minBaseAssetReserve),
735
- new BN(suiExample.amm.maxBaseAssetReserve),
736
- new BN(suiExample.amm.markStd),
737
- new BN(suiExample.amm.oracleStd),
738
- new BN(suiExample.amm.longIntensityVolume),
739
- new BN(suiExample.amm.shortIntensityVolume),
740
- new BN(suiExample.amm.volume24H),
741
- 0,
742
- ZERO,
743
- ZERO,
744
- 0,
745
- true
746
- );
747
-
748
- assert(termsSuiExample.effectiveLeverageCapped <= 1.000001);
749
- assert(termsSuiExample.inventorySpreadScale == 1.00007);
750
- assert(
751
- termsSuiExample.longSpread == 269813,
752
- `SUI long spread got ${termsSuiExample.longSpread}`
753
- );
754
- assert(
755
- termsSuiExample.shortSpread == 3925,
756
- `SUI short spread got ${termsSuiExample.shortSpread}`
757
- );
758
-
759
- // reset amm reserves/peg to balanced values s.t. liquidity/price is the same
760
- // to avoid error prone int math
761
-
762
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
763
- // @ts-ignore
764
- const termsSuiExampleMod1: AMMSpreadTerms = calculateSpreadBN(
765
- Number(suiExample.amm.baseSpread.toString()),
766
- ZERO,
767
- new BN(suiExample.amm.lastOracleConfPct),
768
- Number(suiExample.amm.maxSpread.toString()),
769
- new BN(suiExample.amm.quoteAssetReserve),
770
- new BN(suiExample.amm.terminalQuoteAssetReserve),
771
- new BN(suiExample.amm.pegMultiplier),
772
- new BN(suiExample.amm.baseAssetAmountWithAmm),
773
- reservePriceMod, // reserve price
774
- new BN(suiExample.amm.totalFeeMinusDistributions),
775
- new BN(suiExample.amm.netRevenueSinceLastFunding),
776
- new BN(suiExample.amm.baseAssetReserve),
777
- new BN(suiExample.amm.minBaseAssetReserve),
778
- new BN(suiExample.amm.maxBaseAssetReserve),
779
- new BN(suiExample.amm.markStd),
780
- new BN(suiExample.amm.oracleStd),
781
- new BN(suiExample.amm.longIntensityVolume),
782
- new BN(suiExample.amm.shortIntensityVolume),
783
- new BN(suiExample.amm.volume24H),
784
- 0,
785
- ZERO,
786
- ZERO,
787
- 0,
788
- true
789
- );
790
- console.log(termsSuiExampleMod1);
791
-
792
- // todo: add sdk recenter function?
793
-
794
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
795
- // @ts-ignore
796
- const termsSuiExampleMod2: AMMSpreadTerms = calculateSpreadBN(
797
- Number(suiExample.amm.baseSpread.toString()),
798
- ZERO,
799
- new BN(suiExample.amm.lastOracleConfPct),
800
- Number(suiExample.amm.maxSpread.toString()),
801
- new BN(suiExample.amm.sqrtK),
802
- new BN(suiExample.amm.terminalQuoteAssetReserve),
803
- reservePriceMod, // peg
804
- new BN(suiExample.amm.baseAssetAmountWithAmm),
805
- reservePriceMod, // reserve price
806
- new BN(suiExample.amm.totalFeeMinusDistributions),
807
- new BN(suiExample.amm.netRevenueSinceLastFunding),
808
- new BN(suiExample.amm.sqrtK),
809
- new BN(suiExample.amm.sqrtK),
810
- new BN(suiExample.amm.maxBaseAssetReserve),
811
- new BN(suiExample.amm.markStd),
812
- new BN(suiExample.amm.oracleStd),
813
- new BN(suiExample.amm.longIntensityVolume),
814
- new BN(suiExample.amm.shortIntensityVolume),
815
- new BN(suiExample.amm.volume24H),
816
- 0,
817
- ZERO,
818
- ZERO,
819
- 0,
820
- true
821
- );
822
-
823
- console.log(termsSuiExampleMod2);
824
- assert(
825
- _.isEqual(
826
- termsSuiExampleMod2.maxTargetSpread,
827
- termsSuiExampleMod1.maxTargetSpread
828
- )
829
- );
830
- assert(
831
- _.isEqual(
832
- termsSuiExampleMod2.shortSpreadwPS,
833
- termsSuiExampleMod1.shortSpreadwPS
834
- )
835
- );
836
- assert(
837
- _.isEqual(
838
- termsSuiExampleMod2.longSpreadwPS,
839
- termsSuiExampleMod1.longSpreadwPS
840
- )
841
- );
842
-
843
- // note: effectiveLeverage as currently implemented is sensitive to peg change
844
- });
845
-
846
- it('Spread Reserves (with offset)', () => {
847
- const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
848
- const mockMarket1 = myMockPerpMarkets[0];
849
- const mockAmm = mockMarket1.amm;
850
- const mockMarketStats = mockMarket1.marketStats;
851
- const now = new BN(new Date().getTime() / 1000); //todo
852
-
853
- const oraclePriceData = {
854
- price: new BN(13.553 * PRICE_PRECISION.toNumber()),
855
- slot: new BN(68 + 1),
856
- confidence: new BN(1),
857
- hasSufficientNumberOfDataPoints: true,
858
- isMMOracleActive: true,
859
- } as MMOraclePriceData;
860
-
861
- const reserves = calculateSpreadReserves(
862
- mockAmm,
863
- mockMarketStats,
864
- oraclePriceData,
865
- now
866
- );
867
- assert(reserves[0].baseAssetReserve.eq(new BN('1000000000')));
868
- assert(reserves[0].quoteAssetReserve.eq(new BN('12000000000')));
869
- assert(reserves[1].baseAssetReserve.eq(new BN('1000000000')));
870
- assert(reserves[1].quoteAssetReserve.eq(new BN('12000000000')));
871
-
872
- mockAmm.baseAssetReserve = new BN(1000000000);
873
- mockAmm.quoteAssetReserve = new BN(1000000000);
874
- mockAmm.sqrtK = new BN(1000000000);
875
-
876
- mockAmm.baseAssetAmountWithAmm = new BN(0);
877
- mockAmm.pegMultiplier = new BN(13.553 * PEG_PRECISION.toNumber());
878
- mockAmm.ammJitIntensity = 200;
879
- mockAmm.curveUpdateIntensity = 200;
880
- mockAmm.baseSpread = 2500;
881
- mockAmm.maxSpread = 25000;
882
-
883
- mockMarketStats.last24HAvgFundingRate = new BN(7590328523);
884
-
885
- mockMarketStats.lastMarkPriceTwap = new BN(
886
- (oraclePriceData.price.toNumber() / 1e6 - 0.01) * 1e6
887
- );
888
- mockMarketStats.historicalOracleData.lastOraclePriceTwap = new BN(
889
- (oraclePriceData.price.toNumber() / 1e6 + 0.015) * 1e6
890
- );
891
-
892
- mockMarketStats.historicalOracleData.lastOraclePriceTwap5Min = new BN(
893
- (oraclePriceData.price.toNumber() / 1e6 + 0.005) * 1e6
894
- );
895
- mockMarketStats.lastMarkPriceTwap5Min = new BN(
896
- (oraclePriceData.price.toNumber() / 1e6 - 0.005) * 1e6
897
- );
898
-
899
- console.log('starting rr:');
900
- let reservePrice: BN | undefined = undefined;
901
- if (!reservePrice) {
902
- reservePrice = calculatePrice(
903
- mockAmm.baseAssetReserve,
904
- mockAmm.quoteAssetReserve,
905
- mockAmm.pegMultiplier
906
- );
907
- }
908
-
909
- const targetPrice = oraclePriceData?.price || reservePrice;
910
- const confInterval = oraclePriceData.confidence || ZERO;
911
- const targetMarkSpreadPct = reservePrice
912
- .sub(targetPrice)
913
- .mul(BID_ASK_SPREAD_PRECISION)
914
- .div(reservePrice);
915
-
916
- const confIntervalPct = confInterval
917
- .mul(BID_ASK_SPREAD_PRECISION)
918
- .div(reservePrice);
919
-
920
- // now = now || new BN(new Date().getTime() / 1000); //todo
921
- const liveOracleStd = calculateLiveOracleStd(
922
- mockMarketStats,
923
- oraclePriceData,
924
- now
925
- );
926
- console.log('reservePrice:', reservePrice.toString());
927
- console.log('targetMarkSpreadPct:', targetMarkSpreadPct.toString());
928
- console.log('confIntervalPct:', confIntervalPct.toString());
929
- console.log('liveOracleStd:', liveOracleStd.toString());
930
-
931
- const tt = calculateSpread(mockAmm, mockMarketStats, oraclePriceData, now);
932
- console.log(tt);
933
-
934
- console.log('amm.baseAssetReserve:', mockAmm.baseAssetReserve.toString());
935
- assert(mockAmm.baseAssetReserve.eq(new BN('1000000000')));
936
- const reserves2 = calculateSpreadReserves(
937
- mockAmm,
938
- mockMarketStats,
939
- oraclePriceData,
940
- now
941
- );
942
- console.log(reserves2[0].baseAssetReserve.toString());
943
- console.log(reserves2[0].quoteAssetReserve.toString());
944
-
945
- assert(reserves2[0].baseAssetReserve.eq(new BN('1006289308')));
946
- assert(reserves2[0].quoteAssetReserve.eq(new BN('993750000')));
947
- assert(reserves2[1].baseAssetReserve.eq(new BN('993788819')));
948
- assert(reserves2[1].quoteAssetReserve.eq(new BN('1006250000')));
949
-
950
- // create imbalance for reference price offset
951
- mockAmm.baseAssetReserve = new BN(1000000000 * 1.1);
952
- mockAmm.quoteAssetReserve = new BN(1000000000 / 1.1);
953
- mockAmm.sqrtK = squareRootBN(
954
- mockAmm.baseAssetReserve.mul(mockAmm.quoteAssetReserve)
955
- );
956
-
957
- mockAmm.baseAssetAmountWithAmm = new BN(1000000000 * 0.1);
958
-
959
- const maxOffset = Math.max(
960
- mockAmm.maxSpread / 5,
961
- (PERCENTAGE_PRECISION.toNumber() / 10000) *
962
- (mockAmm.curveUpdateIntensity - 100)
963
- );
964
- const liquidityFraction = calculateInventoryLiquidityRatio(
965
- mockAmm.baseAssetAmountWithAmm,
966
- mockAmm.baseAssetReserve,
967
- mockAmm.minBaseAssetReserve,
968
- mockAmm.maxBaseAssetReserve
969
- );
970
- console.log('liquidityFraction:', liquidityFraction.toString());
971
- assert(liquidityFraction.eq(new BN(1000000))); // full
972
- const liquidityFractionSigned = liquidityFraction.mul(
973
- sigNum(mockAmm.baseAssetAmountWithAmm)
974
- );
975
- const referencePriceOffset = calculateReferencePriceOffset(
976
- reservePrice,
977
- mockMarketStats.last24HAvgFundingRate,
978
- liquidityFractionSigned,
979
- mockMarketStats.historicalOracleData.lastOraclePriceTwap5Min,
980
- mockMarketStats.lastMarkPriceTwap5Min,
981
- mockMarketStats.historicalOracleData.lastOraclePriceTwap,
982
- mockMarketStats.lastMarkPriceTwap,
983
- maxOffset
984
- );
985
- console.log('referencePriceOffset:', referencePriceOffset.toString());
986
- assert(referencePriceOffset.eq(new BN(10000)));
987
- assert(referencePriceOffset.eq(new BN(maxOffset)));
988
-
989
- // mockAmm.curveUpdateIntensity = 100;
990
- const reserves3 = calculateSpreadReserves(
991
- mockAmm,
992
- mockMarketStats,
993
- oraclePriceData,
994
- now
995
- );
996
- console.log(reserves3[0].baseAssetReserve.toString());
997
- console.log(reserves3[0].quoteAssetReserve.toString());
998
-
999
- assert(reserves3[0].baseAssetReserve.eq(new BN('1100068201')));
1000
- assert(reserves3[0].quoteAssetReserve.eq(new BN('909034546')));
1001
- assert(reserves3[1].baseAssetReserve.eq(new BN('989999998')));
1002
- assert(reserves3[1].quoteAssetReserve.eq(new BN('1010101010')));
1003
-
1004
- const p1 = calculatePrice(
1005
- reserves3[0].baseAssetReserve,
1006
- reserves3[0].quoteAssetReserve,
1007
- mockAmm.pegMultiplier
1008
- );
1009
-
1010
- const p2 = calculatePrice(
1011
- reserves3[1].baseAssetReserve,
1012
- reserves3[1].quoteAssetReserve,
1013
- mockAmm.pegMultiplier
1014
- );
1015
-
1016
- assert(p1.eq(new BN(11199437)));
1017
- assert(p2.eq(new BN(13828180)));
1018
-
1019
- mockAmm.curveUpdateIntensity = 110;
1020
- const reserves4 = calculateSpreadReserves(
1021
- mockAmm,
1022
- mockMarketStats,
1023
- oraclePriceData,
1024
- now
1025
- );
1026
-
1027
- assert(reserves4[0].baseAssetReserve.eq(new BN('1100068201')));
1028
- assert(reserves4[0].quoteAssetReserve.eq(new BN('909034546')));
1029
- assert(reserves4[1].baseAssetReserve.eq(new BN('989999998')));
1030
- assert(reserves4[1].quoteAssetReserve.eq(new BN('1010101010')));
1031
-
1032
- const p1RF = calculatePrice(
1033
- reserves4[0].baseAssetReserve,
1034
- reserves4[0].quoteAssetReserve,
1035
- mockAmm.pegMultiplier
1036
- );
1037
-
1038
- const p2RF = calculatePrice(
1039
- reserves4[1].baseAssetReserve,
1040
- reserves4[1].quoteAssetReserve,
1041
- mockAmm.pegMultiplier
1042
- );
1043
-
1044
- assert(p1RF.eq(new BN(11199437)));
1045
- assert(p2RF.eq(new BN(13828180)));
1046
- // no ref price offset at 100
1047
- mockAmm.curveUpdateIntensity = 100;
1048
- const reserves5 = calculateSpreadReserves(
1049
- mockAmm,
1050
- mockMarketStats,
1051
- oraclePriceData,
1052
- now
1053
- );
1054
-
1055
- assert(reserves5[0].baseAssetReserve.eq(new BN('1100068201')));
1056
- assert(reserves5[0].quoteAssetReserve.eq(new BN('909034546')));
1057
- assert(reserves5[1].baseAssetReserve.eq(new BN('989999998')));
1058
- assert(reserves5[1].quoteAssetReserve.eq(new BN('1010101010')));
1059
-
1060
- const p1RFNone = calculatePrice(
1061
- reserves5[0].baseAssetReserve,
1062
- reserves5[0].quoteAssetReserve,
1063
- mockAmm.pegMultiplier
1064
- );
1065
-
1066
- const p2RFNone = calculatePrice(
1067
- reserves5[1].baseAssetReserve,
1068
- reserves5[1].quoteAssetReserve,
1069
- mockAmm.pegMultiplier
1070
- );
1071
-
1072
- assert(p1RFNone.eq(new BN(11199437)));
1073
- assert(p2RFNone.eq(new BN(13828180)));
1074
- assert(p1RF.sub(p1RFNone).eq(new BN(0)));
1075
- assert(p2RF.sub(p2RFNone).eq(new BN(0))); // todo?
1076
- });
1077
- it('Spread Reserves (with negative offset)', () => {
1078
- const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
1079
- const mockMarket1 = myMockPerpMarkets[0];
1080
- const mockAmm = mockMarket1.amm;
1081
- const mockMarketStats = mockMarket1.marketStats;
1082
- const now = new BN(new Date().getTime() / 1000); //todo
1083
-
1084
- const oraclePriceData = {
1085
- price: new BN(13.553 * PRICE_PRECISION.toNumber()),
1086
- slot: new BN(68 + 1),
1087
- confidence: new BN(1),
1088
- hasSufficientNumberOfDataPoints: true,
1089
- isMMOracleActive: true,
1090
- } as MMOraclePriceData;
1091
-
1092
- const reserves = calculateSpreadReserves(
1093
- mockAmm,
1094
- mockMarketStats,
1095
- oraclePriceData,
1096
- now
1097
- );
1098
- assert(reserves[0].baseAssetReserve.eq(new BN('1000000000')));
1099
- assert(reserves[0].quoteAssetReserve.eq(new BN('12000000000')));
1100
- assert(reserves[1].baseAssetReserve.eq(new BN('1000000000')));
1101
- assert(reserves[1].quoteAssetReserve.eq(new BN('12000000000')));
1102
-
1103
- mockAmm.baseAssetReserve = new BN(1000000000);
1104
- mockAmm.quoteAssetReserve = new BN(1000000000);
1105
- mockAmm.sqrtK = new BN(1000000000);
1106
-
1107
- mockAmm.baseAssetAmountWithAmm = new BN(0);
1108
- mockAmm.pegMultiplier = new BN(13.553 * PEG_PRECISION.toNumber());
1109
- mockAmm.ammJitIntensity = 200;
1110
- mockAmm.curveUpdateIntensity = 200;
1111
- mockAmm.baseSpread = 2500;
1112
- mockAmm.maxSpread = 25000;
1113
-
1114
- mockMarketStats.last24HAvgFundingRate = new BN(-7590328523);
1115
-
1116
- mockMarketStats.lastMarkPriceTwap = new BN(
1117
- (oraclePriceData.price.toNumber() / 1e6 + 0.01) * 1e6
1118
- );
1119
- mockMarketStats.historicalOracleData.lastOraclePriceTwap = new BN(
1120
- (oraclePriceData.price.toNumber() / 1e6 - 0.015) * 1e6
1121
- );
1122
-
1123
- mockMarketStats.historicalOracleData.lastOraclePriceTwap5Min = new BN(
1124
- (oraclePriceData.price.toNumber() / 1e6 + 0.005) * 1e6
1125
- );
1126
- mockMarketStats.lastMarkPriceTwap5Min = new BN(
1127
- (oraclePriceData.price.toNumber() / 1e6 - 0.005) * 1e6
1128
- );
1129
-
1130
- console.log('starting rr:');
1131
- let reservePrice = undefined;
1132
- if (!reservePrice) {
1133
- reservePrice = calculatePrice(
1134
- mockAmm.baseAssetReserve,
1135
- mockAmm.quoteAssetReserve,
1136
- mockAmm.pegMultiplier
1137
- );
1138
- }
1139
-
1140
- const targetPrice = oraclePriceData?.price || reservePrice;
1141
- const confInterval = oraclePriceData.confidence || ZERO;
1142
- const targetMarkSpreadPct = reservePrice
1143
- .sub(targetPrice)
1144
- .mul(BID_ASK_SPREAD_PRECISION)
1145
- .div(reservePrice);
1146
-
1147
- const confIntervalPct = confInterval
1148
- .mul(BID_ASK_SPREAD_PRECISION)
1149
- .div(reservePrice);
1150
-
1151
- // now = now || new BN(new Date().getTime() / 1000); //todo
1152
- const liveOracleStd = calculateLiveOracleStd(
1153
- mockMarketStats,
1154
- oraclePriceData,
1155
- now
1156
- );
1157
- console.log('reservePrice:', reservePrice.toString());
1158
- console.log('targetMarkSpreadPct:', targetMarkSpreadPct.toString());
1159
- console.log('confIntervalPct:', confIntervalPct.toString());
1160
-
1161
- console.log('liveOracleStd:', liveOracleStd.toString());
1162
-
1163
- const tt = calculateSpread(mockAmm, mockMarketStats, oraclePriceData, now);
1164
- console.log(tt);
1165
-
1166
- console.log('amm.baseAssetReserve:', mockAmm.baseAssetReserve.toString());
1167
- assert(mockAmm.baseAssetReserve.eq(new BN('1000000000')));
1168
- const reserves2 = calculateSpreadReserves(
1169
- mockAmm,
1170
- mockMarketStats,
1171
- oraclePriceData,
1172
- now
1173
- );
1174
- console.log(reserves2[1].baseAssetReserve.toString());
1175
- console.log(reserves2[1].quoteAssetReserve.toString());
1176
-
1177
- assert(reserves2[0].baseAssetReserve.eq(new BN('1006289308')));
1178
- assert(reserves2[0].quoteAssetReserve.eq(new BN('993750000')));
1179
- assert(reserves2[1].baseAssetReserve.eq(new BN('993788819')));
1180
- assert(reserves2[1].quoteAssetReserve.eq(new BN('1006250000')));
1181
-
1182
- // create imbalance for reference price offset
1183
- mockAmm.baseAssetReserve = new BN(1000000000 / 1.1);
1184
- mockAmm.quoteAssetReserve = new BN(1000000000 * 1.1);
1185
- mockAmm.sqrtK = squareRootBN(
1186
- mockAmm.baseAssetReserve.mul(mockAmm.quoteAssetReserve)
1187
- );
1188
-
1189
- mockAmm.baseAssetAmountWithAmm = new BN(-1000000000 * 0.1);
1190
-
1191
- const maxOffset = Math.max(
1192
- mockAmm.maxSpread / 5,
1193
- (PERCENTAGE_PRECISION.toNumber() / 10000) *
1194
- (mockAmm.curveUpdateIntensity - 100)
1195
- );
1196
- const liquidityFraction = calculateInventoryLiquidityRatio(
1197
- mockAmm.baseAssetAmountWithAmm,
1198
- mockAmm.baseAssetReserve,
1199
- mockAmm.minBaseAssetReserve,
1200
- mockAmm.maxBaseAssetReserve
1201
- );
1202
- console.log('liquidityFraction:', liquidityFraction.toString());
1203
- assert(liquidityFraction.eq(new BN(1000000))); // full
1204
- const liquidityFractionSigned = liquidityFraction.mul(
1205
- sigNum(mockAmm.baseAssetAmountWithAmm)
1206
- );
1207
- const referencePriceOffset = calculateReferencePriceOffset(
1208
- reservePrice,
1209
- mockMarketStats.last24HAvgFundingRate,
1210
- liquidityFractionSigned,
1211
- mockMarketStats.historicalOracleData.lastOraclePriceTwap5Min,
1212
- mockMarketStats.lastMarkPriceTwap5Min,
1213
- mockMarketStats.historicalOracleData.lastOraclePriceTwap,
1214
- mockMarketStats.lastMarkPriceTwap,
1215
- maxOffset
1216
- );
1217
- console.log('referencePriceOffset:', referencePriceOffset.toString());
1218
- assert(referencePriceOffset.eq(new BN(-10000))); // neg
1219
-
1220
- // assert(referencePriceOffset.eq(new BN(maxOffset)));
1221
-
1222
- // mockAmm.curveUpdateIntensity = 100;
1223
- const reserves3 = calculateSpreadReserves(
1224
- mockAmm,
1225
- mockMarketStats,
1226
- oraclePriceData,
1227
- now
1228
- );
1229
- console.log(reserves3[0].baseAssetReserve.toString());
1230
- console.log(reserves3[0].quoteAssetReserve.toString());
1231
-
1232
- assert(reserves3[0].baseAssetReserve.eq(new BN('999999998')));
1233
- assert(reserves3[0].quoteAssetReserve.eq(new BN('1000000000')));
1234
- assert(reserves3[1].baseAssetReserve.eq(new BN('909034547')));
1235
- assert(reserves3[1].quoteAssetReserve.eq(new BN('1100068200')));
1236
-
1237
- const p1 = calculatePrice(
1238
- reserves3[0].baseAssetReserve,
1239
- reserves3[0].quoteAssetReserve,
1240
- mockAmm.pegMultiplier
1241
- );
1242
-
1243
- const p2 = calculatePrice(
1244
- reserves3[1].baseAssetReserve,
1245
- reserves3[1].quoteAssetReserve,
1246
- mockAmm.pegMultiplier
1247
- );
1248
-
1249
- assert(p1.eq(new BN(13553000)));
1250
- assert(p2.eq(new BN(16401163)));
1251
-
1252
- mockAmm.curveUpdateIntensity = 110;
1253
- const reserves4 = calculateSpreadReserves(
1254
- mockAmm,
1255
- mockMarketStats,
1256
- oraclePriceData,
1257
- now
1258
- );
1259
-
1260
- assert(reserves4[0].baseAssetReserve.eq(new BN('999999998')));
1261
- assert(reserves4[0].quoteAssetReserve.eq(new BN('1000000000')));
1262
- assert(reserves4[1].baseAssetReserve.eq(new BN('909034547')));
1263
- assert(reserves4[1].quoteAssetReserve.eq(new BN('1100068200')));
1264
-
1265
- const p1RF = calculatePrice(
1266
- reserves4[0].baseAssetReserve,
1267
- reserves4[0].quoteAssetReserve,
1268
- mockAmm.pegMultiplier
1269
- );
1270
-
1271
- const p2RF = calculatePrice(
1272
- reserves4[1].baseAssetReserve,
1273
- reserves4[1].quoteAssetReserve,
1274
- mockAmm.pegMultiplier
1275
- );
1276
-
1277
- assert(p1RF.eq(new BN(13553000)));
1278
- assert(p2RF.eq(new BN(16401163)));
1279
-
1280
- // no ref price offset at 100
1281
- mockAmm.curveUpdateIntensity = 100;
1282
- const reserves5 = calculateSpreadReserves(
1283
- mockAmm,
1284
- mockMarketStats,
1285
- oraclePriceData,
1286
- now
1287
- );
1288
-
1289
- assert(reserves5[0].baseAssetReserve.eq(new BN('999999998')));
1290
- assert(reserves5[0].quoteAssetReserve.eq(new BN('1000000000')));
1291
- assert(reserves5[1].baseAssetReserve.eq(new BN('909034547')));
1292
- assert(reserves5[1].quoteAssetReserve.eq(new BN('1100068200')));
1293
-
1294
- const p1RFNone = calculatePrice(
1295
- reserves5[0].baseAssetReserve,
1296
- reserves5[0].quoteAssetReserve,
1297
- mockAmm.pegMultiplier
1298
- );
1299
-
1300
- const p2RFNone = calculatePrice(
1301
- reserves5[1].baseAssetReserve,
1302
- reserves5[1].quoteAssetReserve,
1303
- mockAmm.pegMultiplier
1304
- );
1305
-
1306
- const rr = p2RF.sub(p2RFNone).mul(PERCENTAGE_PRECISION).div(p2RF);
1307
- assert(p1RFNone.eq(new BN(13553000)));
1308
- assert(p2RFNone.eq(new BN(16401163)));
1309
- assert(p1RF.sub(p1RFNone).eq(new BN(0))); // todo?
1310
- assert(rr.eq(new BN(0)));
1311
- });
1312
-
1313
- it('live update functions', () => {
1314
- const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
1315
- const mockMarket1 = myMockPerpMarkets[0];
1316
- const mockMarketStats = mockMarket1.marketStats;
1317
- const now = new BN(new Date().getTime() / 1000); //todo
1318
- const slot = 999999999;
1319
-
1320
- const oraclePriceData = {
1321
- price: new BN(13.553 * PRICE_PRECISION.toNumber()),
1322
- slot: new BN(slot),
1323
- confidence: new BN(1000),
1324
- hasSufficientNumberOfDataPoints: true,
1325
- isMMOracleActive: true,
1326
- } as MMOraclePriceData;
1327
- mockMarketStats.oracleStd = new BN(0.18 * PRICE_PRECISION.toNumber());
1328
- mockMarketStats.fundingPeriod = new BN(3600);
1329
- mockMarketStats.historicalOracleData.lastOraclePriceTwap =
1330
- oraclePriceData.price.mul(new BN(999)).div(new BN(1000));
1331
- mockMarketStats.historicalOracleData.lastOraclePriceTwapTs = now.sub(
1332
- new BN(11)
1333
- );
1334
-
1335
- const liveOracleTwap = calculateLiveOracleTwap(
1336
- mockMarketStats.historicalOracleData,
1337
- oraclePriceData,
1338
- now,
1339
- mockMarketStats.fundingPeriod
1340
- );
1341
- console.log('liveOracleTwap:', liveOracleTwap.toNumber());
1342
- assert(liveOracleTwap.eq(new BN(13539488)));
1343
-
1344
- const liveOracleStd = calculateLiveOracleStd(
1345
- mockMarketStats,
1346
- oraclePriceData,
1347
- now
1348
- );
1349
- assert(liveOracleStd.eq(new BN(13732450)));
1350
-
1351
- mockMarketStats.lastOracleConfPct = new BN(150000);
1352
- const reservePrice = new BN(13.553 * PRICE_PRECISION.toNumber());
1353
- const newConfPct = getNewOracleConfPct(
1354
- mockMarketStats,
1355
- oraclePriceData,
1356
- reservePrice,
1357
- now
1358
- );
1359
- console.log('newConfPct:', newConfPct.toString());
1360
-
1361
- assert(
1362
- now
1363
- .sub(mockMarketStats.historicalOracleData.lastOraclePriceTwapTs)
1364
- .gt(ZERO)
1365
- );
1366
-
1367
- assert(newConfPct.eq(new BN(135000)));
1368
-
1369
- const oracleGuardRails: OracleGuardRails = {
1370
- priceDivergence: {
1371
- markOraclePercentDivergence: PERCENTAGE_PRECISION.divn(10),
1372
- oracleTwap5MinPercentDivergence: PERCENTAGE_PRECISION.divn(10),
1373
- },
1374
- validity: {
1375
- slotsBeforeStaleForAmm: new BN(10),
1376
- slotsBeforeStaleForMargin: new BN(60),
1377
- confidenceIntervalMaxSize: new BN(20000),
1378
- tooVolatileRatio: new BN(5),
1379
- },
1380
- };
1381
-
1382
- // good oracle
1383
- assert(
1384
- isOracleValid(mockMarket1, oraclePriceData, oracleGuardRails, slot + 5)
1385
- );
1386
-
1387
- // conf too high
1388
- assert(
1389
- !isOracleValid(
1390
- mockMarket1,
1391
- {
1392
- price: new BN(13.553 * PRICE_PRECISION.toNumber()),
1393
- slot: new BN(slot),
1394
- confidence: new BN(13.553 * PRICE_PRECISION.toNumber() * 0.021),
1395
- hasSufficientNumberOfDataPoints: true,
1396
- isMMOracleActive: true,
1397
- } as MMOraclePriceData,
1398
- oracleGuardRails,
1399
- slot
1400
- )
1401
- );
1402
-
1403
- // not hasSufficientNumberOfDataPoints
1404
- assert(
1405
- !isOracleValid(
1406
- mockMarket1,
1407
- {
1408
- price: new BN(13.553 * PRICE_PRECISION.toNumber()),
1409
- slot: new BN(slot),
1410
- confidence: new BN(1),
1411
- hasSufficientNumberOfDataPoints: false,
1412
- isMMOracleActive: true,
1413
- } as MMOraclePriceData,
1414
- oracleGuardRails,
1415
- slot
1416
- )
1417
- );
1418
-
1419
- // negative oracle price
1420
- assert(
1421
- !isOracleValid(
1422
- mockMarket1,
1423
- {
1424
- price: new BN(-1 * PRICE_PRECISION.toNumber()),
1425
- slot: new BN(slot),
1426
- confidence: new BN(1),
1427
- hasSufficientNumberOfDataPoints: true,
1428
- isMMOracleActive: true,
1429
- } as MMOraclePriceData,
1430
- oracleGuardRails,
1431
- slot
1432
- )
1433
- );
1434
-
1435
- // too delayed for amm
1436
- assert(
1437
- !isOracleValid(
1438
- mockMarket1,
1439
- {
1440
- price: new BN(13.553 * PRICE_PRECISION.toNumber()),
1441
- slot: new BN(slot),
1442
- confidence: new BN(1),
1443
- hasSufficientNumberOfDataPoints: true,
1444
- isMMOracleActive: true,
1445
- } as MMOraclePriceData,
1446
- oracleGuardRails,
1447
- slot + 100
1448
- )
1449
- );
1450
-
1451
- // im passing stale slot (should not call oracle invalid)
1452
- assert(
1453
- isOracleValid(
1454
- mockMarket1,
1455
- {
1456
- price: new BN(13.553 * PRICE_PRECISION.toNumber()),
1457
- slot: new BN(slot + 100),
1458
- confidence: new BN(1),
1459
- hasSufficientNumberOfDataPoints: true,
1460
- isMMOracleActive: true,
1461
- } as MMOraclePriceData,
1462
- oracleGuardRails,
1463
- slot
1464
- )
1465
- );
1466
-
1467
- // too volatile (more than 5x higher)
1468
- assert(
1469
- !isOracleValid(
1470
- mockMarket1,
1471
- {
1472
- price: new BN(113.553 * PRICE_PRECISION.toNumber()),
1473
- slot: new BN(slot + 5),
1474
- confidence: new BN(1),
1475
- hasSufficientNumberOfDataPoints: true,
1476
- isMMOracleActive: true,
1477
- } as MMOraclePriceData,
1478
- oracleGuardRails,
1479
- slot
1480
- )
1481
- );
1482
-
1483
- // too volatile (more than 1/5 lower)
1484
- assert(
1485
- !isOracleValid(
1486
- mockMarket1,
1487
- {
1488
- price: new BN(0.553 * PRICE_PRECISION.toNumber()),
1489
- slot: new BN(slot + 5),
1490
- confidence: new BN(1),
1491
- hasSufficientNumberOfDataPoints: true,
1492
- isMMOracleActive: true,
1493
- } as MMOraclePriceData,
1494
- oracleGuardRails,
1495
- slot
1496
- )
1497
- );
1498
- });
1499
-
1500
- it('predicted funding rate mock1', () => {
1501
- const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
1502
- const mockMarket1 = myMockPerpMarkets[0];
1503
-
1504
- // make it like RNDR
1505
- const now = new BN(1688878353);
1506
-
1507
- mockMarket1.marketStats.fundingPeriod = new BN(3600);
1508
- mockMarket1.lastFundingRateTs = new BN(1688860817);
1509
-
1510
- const currentMarkPrice = new BN(1.9843 * PRICE_PRECISION.toNumber()); // trading at a premium
1511
- const mmOraclePriceData: MMOraclePriceData = {
1512
- price: new BN(1.9535 * PRICE_PRECISION.toNumber()),
1513
- slot: new BN(0),
1514
- confidence: new BN(1),
1515
- hasSufficientNumberOfDataPoints: true,
1516
- isMMOracleActive: true,
1517
- };
1518
- mockMarket1.marketStats.historicalOracleData.lastOraclePrice = new BN(
1519
- 1.9535 * PRICE_PRECISION.toNumber()
1520
- );
1521
-
1522
- // mockMarket1.amm.pegMultiplier = new BN(1.897573 * 1e3);
1523
-
1524
- mockMarket1.marketStats.lastMarkPriceTwap = new BN(
1525
- 1.945594 * PRICE_PRECISION.toNumber()
1526
- );
1527
- mockMarket1.marketStats.lastBidPriceTwap = new BN(
1528
- 1.941629 * PRICE_PRECISION.toNumber()
1529
- );
1530
- mockMarket1.marketStats.lastAskPriceTwap = new BN(
1531
- 1.94956 * PRICE_PRECISION.toNumber()
1532
- );
1533
- mockMarket1.marketStats.lastMarkPriceTwapTs = new BN(1688877729);
1534
-
1535
- mockMarket1.marketStats.historicalOracleData.lastOraclePriceTwap = new BN(
1536
- 1.942449 * PRICE_PRECISION.toNumber()
1537
- );
1538
- mockMarket1.marketStats.historicalOracleData.lastOraclePriceTwapTs = new BN(
1539
- 1688878333
1540
- );
1541
-
1542
- const [
1543
- _markTwapLive,
1544
- _oracleTwapLive,
1545
- _lowerboundEst,
1546
- _cappedAltEst,
1547
- _interpEst,
1548
- ] = calculateAllEstimatedFundingRate(
1549
- mockMarket1,
1550
- mmOraclePriceData,
1551
- mmOraclePriceData as unknown as OraclePriceData,
1552
- currentMarkPrice,
1553
- now
1554
- );
1555
-
1556
- const [markTwapLive, oracleTwapLive, est1, est2] =
1557
- calculateLongShortFundingRateAndLiveTwaps(
1558
- mockMarket1,
1559
- mmOraclePriceData,
1560
- mmOraclePriceData as unknown as OraclePriceData,
1561
- currentMarkPrice,
1562
- now
1563
- );
1564
-
1565
- // console.log(markTwapLive.toString());
1566
- // console.log(oracleTwapLive.toString());
1567
- // console.log(est1.toString());
1568
- // console.log(est2.toString());
1569
-
1570
- assert(markTwapLive.eq(new BN('1949826')));
1571
- assert(oracleTwapLive.eq(new BN('1942510')));
1572
- assert(est1.eq(new BN('14858')));
1573
- assert(est2.eq(new BN('14858')));
1574
- });
1575
-
1576
- it('predicted funding rate mock2', () => {
1577
- const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
1578
- const mockMarket1 = myMockPerpMarkets[0];
1579
-
1580
- // make it like OP
1581
- const now = new BN(1688881915);
1582
-
1583
- mockMarket1.marketStats.fundingPeriod = new BN(3600);
1584
- mockMarket1.lastFundingRateTs = new BN(1688864415);
1585
-
1586
- const currentMarkPrice = new BN(1.2242 * PRICE_PRECISION.toNumber()); // trading at a premium
1587
- const mmOraclePriceData: MMOraclePriceData = {
1588
- price: new BN(1.224 * PRICE_PRECISION.toNumber()),
1589
- slot: new BN(0),
1590
- confidence: new BN(1),
1591
- hasSufficientNumberOfDataPoints: true,
1592
- isMMOracleActive: true,
1593
- };
1594
- mockMarket1.marketStats.historicalOracleData.lastOraclePrice = new BN(
1595
- 1.9535 * PRICE_PRECISION.toNumber()
1596
- );
1597
-
1598
- // mockMarket1.amm.pegMultiplier = new BN(1.897573 * 1e3);
1599
-
1600
- mockMarket1.marketStats.lastMarkPriceTwap = new BN(
1601
- 1.218363 * PRICE_PRECISION.toNumber()
1602
- );
1603
- mockMarket1.marketStats.lastBidPriceTwap = new BN(
1604
- 1.218363 * PRICE_PRECISION.toNumber()
1605
- );
1606
- mockMarket1.marketStats.lastAskPriceTwap = new BN(
1607
- 1.218364 * PRICE_PRECISION.toNumber()
1608
- );
1609
- mockMarket1.marketStats.lastMarkPriceTwapTs = new BN(1688878815);
1610
-
1611
- mockMarket1.marketStats.historicalOracleData.lastOraclePriceTwap = new BN(
1612
- 1.220964 * PRICE_PRECISION.toNumber()
1613
- );
1614
- mockMarket1.marketStats.historicalOracleData.lastOraclePriceTwapTs = new BN(
1615
- 1688879991
1616
- );
1617
-
1618
- const [
1619
- _markTwapLive,
1620
- _oracleTwapLive,
1621
- _lowerboundEst,
1622
- _cappedAltEst,
1623
- _interpEst,
1624
- ] = calculateAllEstimatedFundingRate(
1625
- mockMarket1,
1626
- mmOraclePriceData,
1627
- mmOraclePriceData as unknown as OraclePriceData,
1628
- currentMarkPrice,
1629
- now
1630
- );
1631
-
1632
- // console.log(_markTwapLive.toString());
1633
- // console.log(_oracleTwapLive.toString());
1634
- // console.log(_lowerboundEst.toString());
1635
- // console.log(_cappedAltEst.toString());
1636
- // console.log(_interpEst.toString());
1637
- // console.log('-----');
1638
-
1639
- const [markTwapLive, oracleTwapLive, est1, est2] =
1640
- calculateLongShortFundingRateAndLiveTwaps(
1641
- mockMarket1,
1642
- mmOraclePriceData,
1643
- mmOraclePriceData as unknown as OraclePriceData,
1644
- currentMarkPrice,
1645
- now
1646
- );
1647
-
1648
- console.log(
1649
- 'markTwapLive:',
1650
- mockMarket1.marketStats.lastMarkPriceTwap.toString(),
1651
- '->',
1652
- markTwapLive.toString()
1653
- );
1654
- console.log(
1655
- 'oracTwapLive:',
1656
- mockMarket1.marketStats.historicalOracleData.lastOraclePriceTwap.toString(),
1657
- '->',
1658
- oracleTwapLive.toString()
1659
- );
1660
- console.log('pred funding:', est1.toString(), est2.toString());
1661
-
1662
- assert(markTwapLive.eq(new BN('1222131')));
1663
- assert(oracleTwapLive.eq(new BN('1222586')));
1664
- assert(est1.eq(est2));
1665
- assert(est2.eq(new BN('1247')));
1666
- });
1667
-
1668
- it('predicted funding rate mock clamp', () => {
1669
- const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
1670
- const mockMarket1 = myMockPerpMarkets[0];
1671
-
1672
- // make it like OP
1673
- const now = new BN(1688881915);
1674
-
1675
- mockMarket1.marketStats.fundingPeriod = new BN(3600);
1676
- mockMarket1.lastFundingRateTs = new BN(1688864415);
1677
-
1678
- const currentMarkPrice = new BN(1.2242 * PRICE_PRECISION.toNumber()); // trading at a premium
1679
- const mmOraclePriceData: MMOraclePriceData = {
1680
- price: new BN(1.924 * PRICE_PRECISION.toNumber()),
1681
- slot: new BN(0),
1682
- confidence: new BN(1),
1683
- hasSufficientNumberOfDataPoints: true,
1684
- isMMOracleActive: true,
1685
- } as MMOraclePriceData;
1686
- mockMarket1.marketStats.historicalOracleData.lastOraclePrice = new BN(
1687
- 1.9535 * PRICE_PRECISION.toNumber()
1688
- );
1689
-
1690
- // mockMarket1.amm.pegMultiplier = new BN(1.897573 * 1e3);
1691
-
1692
- mockMarket1.marketStats.lastMarkPriceTwap = new BN(
1693
- 1.218363 * PRICE_PRECISION.toNumber()
1694
- );
1695
- mockMarket1.marketStats.lastBidPriceTwap = new BN(
1696
- 1.218363 * PRICE_PRECISION.toNumber()
1697
- );
1698
- mockMarket1.marketStats.lastAskPriceTwap = new BN(
1699
- 1.218364 * PRICE_PRECISION.toNumber()
1700
- );
1701
- mockMarket1.marketStats.lastMarkPriceTwapTs = new BN(1688878815);
1702
-
1703
- mockMarket1.marketStats.historicalOracleData.lastOraclePriceTwap = new BN(
1704
- 1.820964 * PRICE_PRECISION.toNumber()
1705
- );
1706
- mockMarket1.marketStats.historicalOracleData.lastOraclePriceTwapTs = new BN(
1707
- 1688879991
1708
- );
1709
- mockMarket1.contractTier = ContractTier.A;
1710
-
1711
- const [
1712
- _markTwapLive,
1713
- _oracleTwapLive,
1714
- _lowerboundEst,
1715
- _cappedAltEst,
1716
- _interpEst,
1717
- ] = calculateAllEstimatedFundingRate(
1718
- mockMarket1,
1719
- mmOraclePriceData,
1720
- mmOraclePriceData as unknown as OraclePriceData,
1721
- currentMarkPrice,
1722
- now
1723
- );
1724
-
1725
- // console.log(_markTwapLive.toString());
1726
- // console.log(_oracleTwapLive.toString());
1727
- // console.log(_lowerboundEst.toString());
1728
- // console.log(_cappedAltEst.toString());
1729
- // console.log(_interpEst.toString());
1730
- // console.log('-----');
1731
-
1732
- let [markTwapLive, oracleTwapLive, est1, est2] =
1733
- calculateLongShortFundingRateAndLiveTwaps(
1734
- mockMarket1,
1735
- mmOraclePriceData,
1736
- mmOraclePriceData as unknown as OraclePriceData,
1737
- currentMarkPrice,
1738
- now
1739
- );
1740
-
1741
- console.log(
1742
- 'markTwapLive:',
1743
- mockMarket1.marketStats.lastMarkPriceTwap.toString(),
1744
- '->',
1745
- markTwapLive.toString()
1746
- );
1747
- console.log(
1748
- 'oracTwapLive:',
1749
- mockMarket1.marketStats.historicalOracleData.lastOraclePriceTwap.toString(),
1750
- '->',
1751
- oracleTwapLive.toString()
1752
- );
1753
- console.log('pred funding:', est1.toString(), est2.toString());
1754
-
1755
- assert(markTwapLive.eq(new BN('1680634')));
1756
- assert(oracleTwapLive.eq(new BN('1876031')));
1757
- assert(est1.eq(est2));
1758
- assert(est2.eq(new BN('-126261')));
1759
-
1760
- mockMarket1.contractTier = ContractTier.C;
1761
-
1762
- [markTwapLive, oracleTwapLive, est1, est2] =
1763
- calculateLongShortFundingRateAndLiveTwaps(
1764
- mockMarket1,
1765
- mmOraclePriceData,
1766
- mmOraclePriceData as unknown as OraclePriceData,
1767
- currentMarkPrice,
1768
- now
1769
- );
1770
-
1771
- console.log(
1772
- 'markTwapLive:',
1773
- mockMarket1.marketStats.lastMarkPriceTwap.toString(),
1774
- '->',
1775
- markTwapLive.toString()
1776
- );
1777
- console.log(
1778
- 'oracTwapLive:',
1779
- mockMarket1.marketStats.historicalOracleData.lastOraclePriceTwap.toString(),
1780
- '->',
1781
- oracleTwapLive.toString()
1782
- );
1783
- console.log('pred funding:', est1.toString(), est2.toString());
1784
-
1785
- assert(markTwapLive.eq(new BN('1680634')));
1786
- assert(oracleTwapLive.eq(new BN('1876031')));
1787
- assert(est1.eq(est2));
1788
- assert(est2.eq(new BN('-208332')));
1789
-
1790
- mockMarket1.contractTier = ContractTier.SPECULATIVE;
1791
-
1792
- [markTwapLive, oracleTwapLive, est1, est2] =
1793
- calculateLongShortFundingRateAndLiveTwaps(
1794
- mockMarket1,
1795
- mmOraclePriceData,
1796
- mmOraclePriceData as unknown as OraclePriceData,
1797
- currentMarkPrice,
1798
- now
1799
- );
1800
-
1801
- console.log(
1802
- 'markTwapLive:',
1803
- mockMarket1.marketStats.lastMarkPriceTwap.toString(),
1804
- '->',
1805
- markTwapLive.toString()
1806
- );
1807
- console.log(
1808
- 'oracTwapLive:',
1809
- mockMarket1.marketStats.historicalOracleData.lastOraclePriceTwap.toString(),
1810
- '->',
1811
- oracleTwapLive.toString()
1812
- );
1813
- console.log('pred funding:', est1.toString(), est2.toString());
1814
-
1815
- assert(markTwapLive.eq(new BN('1680634')));
1816
- assert(oracleTwapLive.eq(new BN('1876031')));
1817
- assert(est1.eq(est2));
1818
- assert(est2.eq(new BN('-416666')));
1819
- });
1820
-
1821
- it('orderbook L2 gen (no topOfBookQuoteAmounts, 10 numOrders, low liquidity)', async () => {
1822
- const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
1823
-
1824
- const mockMarket1: PerpMarketAccount = myMockPerpMarkets[0];
1825
- const cc = 38104569;
1826
- mockMarket1.amm.baseAssetReserve = new BN(cc).mul(BASE_PRECISION);
1827
- mockMarket1.amm.maxBaseAssetReserve = mockMarket1.amm.baseAssetReserve.add(
1828
- new BN(1234835)
1829
- );
1830
- mockMarket1.amm.minBaseAssetReserve =
1831
- mockMarket1.amm.baseAssetReserve.sub(BASE_PRECISION);
1832
- mockMarket1.amm.quoteAssetReserve = new BN(cc).mul(BASE_PRECISION);
1833
- mockMarket1.amm.pegMultiplier = new BN(18.32 * PEG_PRECISION.toNumber());
1834
- mockMarket1.amm.sqrtK = new BN(cc).mul(BASE_PRECISION);
1835
-
1836
- const now = new BN(1688881915);
1837
-
1838
- const mmOraclePriceData: MMOraclePriceData = {
1839
- price: new BN(18.624 * PRICE_PRECISION.toNumber()),
1840
- slot: new BN(0),
1841
- confidence: new BN(1),
1842
- hasSufficientNumberOfDataPoints: true,
1843
- isMMOracleActive: true,
1844
- } as MMOraclePriceData;
1845
- mockMarket1.marketStats.historicalOracleData.lastOraclePrice = new BN(
1846
- 18.5535 * PRICE_PRECISION.toNumber()
1847
- );
1848
-
1849
- const updatedAmm = calculateUpdatedAMM(mockMarket1.amm, mmOraclePriceData);
1850
-
1851
- const [openBids, openAsks] = calculateMarketOpenBidAsk(
1852
- updatedAmm.baseAssetReserve,
1853
- updatedAmm.minBaseAssetReserve,
1854
- updatedAmm.maxBaseAssetReserve,
1855
- mockMarket1.orderStepSize
1856
- );
1857
-
1858
- const generator = getVammL2Generator({
1859
- marketAccount: mockMarket1,
1860
- mmOraclePriceData,
1861
- numOrders: 10,
1862
- now,
1863
- topOfBookQuoteAmounts: [],
1864
- });
1865
-
1866
- const bids = Array.from(generator.getL2Bids());
1867
- // console.log(bids);
1868
-
1869
- const totalBidSize = bids.reduce((total: BN, order: L2Level) => {
1870
- return total.add(order.size);
1871
- }, ZERO);
1872
-
1873
- console.log(
1874
- 'totalBidSize:',
1875
- totalBidSize.toString(),
1876
- 'openBids:',
1877
- openBids.toString()
1878
- );
1879
- assert(totalBidSize.sub(openBids).abs().lt(new BN(10))); // smol err
1880
- assert(totalBidSize.sub(openBids).lt(ZERO)); // under estimation
1881
-
1882
- const asks = Array.from(generator.getL2Asks());
1883
- // console.log(asks);
1884
-
1885
- const totalAskSize = asks.reduce((total: BN, order: L2Level) => {
1886
- return total.add(order.size);
1887
- }, ZERO);
1888
- console.log(
1889
- 'totalAskSize:',
1890
- totalAskSize.toString(),
1891
- 'openAsks:',
1892
- openAsks.toString()
1893
- );
1894
- assert(totalAskSize.sub(openAsks.abs()).lte(new BN(5))); // only tiny rounding errors
1895
- });
1896
-
1897
- it('orderbook L2 gen (no topOfBookQuoteAmounts, 10 numOrders)', async () => {
1898
- const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
1899
-
1900
- const mockMarket1: PerpMarketAccount = myMockPerpMarkets[0];
1901
- const cc = 38104569;
1902
- mockMarket1.amm.baseAssetReserve = new BN(cc).mul(BASE_PRECISION);
1903
- mockMarket1.amm.maxBaseAssetReserve = mockMarket1.amm.baseAssetReserve.mul(
1904
- new BN(2)
1905
- );
1906
- mockMarket1.amm.minBaseAssetReserve = mockMarket1.amm.baseAssetReserve.div(
1907
- new BN(2)
1908
- );
1909
- mockMarket1.amm.quoteAssetReserve = new BN(cc).mul(BASE_PRECISION);
1910
- mockMarket1.amm.pegMultiplier = new BN(18.32 * PEG_PRECISION.toNumber());
1911
- mockMarket1.amm.sqrtK = new BN(cc).mul(BASE_PRECISION);
1912
-
1913
- const now = new BN(1688881915);
1914
-
1915
- const mmOraclePriceData: MMOraclePriceData = {
1916
- price: new BN(18.624 * PRICE_PRECISION.toNumber()),
1917
- slot: new BN(0),
1918
- confidence: new BN(1),
1919
- hasSufficientNumberOfDataPoints: true,
1920
- isMMOracleActive: true,
1921
- } as MMOraclePriceData;
1922
- mockMarket1.marketStats.historicalOracleData.lastOraclePrice = new BN(
1923
- 18.5535 * PRICE_PRECISION.toNumber()
1924
- );
1925
-
1926
- const updatedAmm = calculateUpdatedAMM(mockMarket1.amm, mmOraclePriceData);
1927
-
1928
- const [openBids, openAsks] = calculateMarketOpenBidAsk(
1929
- updatedAmm.baseAssetReserve,
1930
- updatedAmm.minBaseAssetReserve,
1931
- updatedAmm.maxBaseAssetReserve,
1932
- mockMarket1.orderStepSize
1933
- );
1934
-
1935
- const generator = getVammL2Generator({
1936
- marketAccount: mockMarket1,
1937
- mmOraclePriceData,
1938
- numOrders: 10,
1939
- now,
1940
- topOfBookQuoteAmounts: [],
1941
- });
1942
-
1943
- const bids = Array.from(generator.getL2Bids());
1944
- // console.log(bids);
1945
-
1946
- const totalBidSize = bids.reduce((total: BN, order: L2Level) => {
1947
- return total.add(order.size);
1948
- }, ZERO);
1949
-
1950
- console.log(
1951
- 'totalBidSize:',
1952
- totalBidSize.toString(),
1953
- 'openBids:',
1954
- openBids.toString()
1955
- );
1956
- assert(totalBidSize.eq(openBids));
1957
-
1958
- const asks = Array.from(generator.getL2Asks());
1959
- // console.log(asks);
1960
-
1961
- const totalAskSize = asks.reduce((total: BN, order: L2Level) => {
1962
- return total.add(order.size);
1963
- }, ZERO);
1964
- console.log(
1965
- 'totalAskSize:',
1966
- totalAskSize.toString(),
1967
- 'openAsks:',
1968
- openAsks.toString()
1969
- );
1970
- assert(totalAskSize.sub(openAsks.abs()).lte(new BN(5))); // only tiny rounding errors
1971
- });
1972
-
1973
- it('orderbook L2 gen (4 topOfBookQuoteAmounts, 10 numOrders)', async () => {
1974
- const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
1975
-
1976
- const mockMarket1: PerpMarketAccount = myMockPerpMarkets[0];
1977
- const cc = 38104569;
1978
- mockMarket1.amm.baseAssetReserve = new BN(cc).mul(BASE_PRECISION);
1979
- mockMarket1.amm.maxBaseAssetReserve = mockMarket1.amm.baseAssetReserve.mul(
1980
- new BN(2)
1981
- );
1982
- mockMarket1.amm.minBaseAssetReserve = mockMarket1.amm.baseAssetReserve.div(
1983
- new BN(2)
1984
- );
1985
- mockMarket1.amm.quoteAssetReserve = new BN(cc).mul(BASE_PRECISION);
1986
- mockMarket1.amm.pegMultiplier = new BN(18.32 * PEG_PRECISION.toNumber());
1987
- mockMarket1.amm.sqrtK = new BN(cc).mul(BASE_PRECISION);
1988
-
1989
- const now = new BN(1688881915);
1990
-
1991
- const mmOraclePriceData: MMOraclePriceData = {
1992
- price: new BN(18.624 * PRICE_PRECISION.toNumber()),
1993
- slot: new BN(0),
1994
- confidence: new BN(1),
1995
- hasSufficientNumberOfDataPoints: true,
1996
- isMMOracleActive: true,
1997
- } as MMOraclePriceData;
1998
- mockMarket1.marketStats.historicalOracleData.lastOraclePrice = new BN(
1999
- 18.5535 * PRICE_PRECISION.toNumber()
2000
- );
2001
-
2002
- const updatedAmm = calculateUpdatedAMM(mockMarket1.amm, mmOraclePriceData);
2003
-
2004
- const [openBids, openAsks] = calculateMarketOpenBidAsk(
2005
- updatedAmm.baseAssetReserve,
2006
- updatedAmm.minBaseAssetReserve,
2007
- updatedAmm.maxBaseAssetReserve,
2008
- mockMarket1.orderStepSize
2009
- );
2010
-
2011
- assert(!openAsks.eq(openBids));
2012
-
2013
- const generator = getVammL2Generator({
2014
- marketAccount: mockMarket1,
2015
- mmOraclePriceData,
2016
- numOrders: 10,
2017
- now,
2018
- topOfBookQuoteAmounts: [
2019
- new BN(10).mul(QUOTE_PRECISION),
2020
- new BN(100).mul(QUOTE_PRECISION),
2021
- new BN(1000).mul(QUOTE_PRECISION),
2022
- new BN(10000).mul(QUOTE_PRECISION),
2023
- ],
2024
- });
2025
-
2026
- const bids = Array.from(generator.getL2Bids());
2027
- // console.log(bids);
2028
-
2029
- const totalBidSize = bids.reduce((total: BN, order: L2Level) => {
2030
- return total.add(order.size);
2031
- }, ZERO);
2032
-
2033
- console.log(
2034
- 'totalBidSize:',
2035
- totalBidSize.toString(),
2036
- 'openBids:',
2037
- openBids.toString()
2038
- );
2039
- assert(totalBidSize.eq(openBids));
2040
-
2041
- const asks = Array.from(generator.getL2Asks());
2042
- // console.log(asks);
2043
-
2044
- const totalAskSize = asks.reduce((total: BN, order: L2Level) => {
2045
- return total.add(order.size);
2046
- }, ZERO);
2047
- console.log(
2048
- 'totalAskSize:',
2049
- totalAskSize.toString(),
2050
- 'openAsks:',
2051
- openAsks.toString()
2052
- );
2053
- assert(totalAskSize.sub(openAsks.abs()).lte(new BN(5))); // only tiny rounding errors
2054
- });
2055
-
2056
- it('orderbook L2 gen (4 topOfBookQuoteAmounts, 10 numOrders, low bid liquidity)', async () => {
2057
- const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
2058
-
2059
- const mockMarket1: PerpMarketAccount = myMockPerpMarkets[0];
2060
- const cc = 38104569;
2061
- mockMarket1.amm.baseAssetReserve = new BN(cc).mul(BASE_PRECISION);
2062
- mockMarket1.amm.maxBaseAssetReserve =
2063
- mockMarket1.amm.baseAssetReserve.add(BASE_PRECISION); // only 1 base
2064
- mockMarket1.amm.minBaseAssetReserve = mockMarket1.amm.baseAssetReserve.div(
2065
- new BN(2)
2066
- );
2067
- mockMarket1.amm.quoteAssetReserve = new BN(cc).mul(BASE_PRECISION);
2068
- mockMarket1.amm.pegMultiplier = new BN(18.32 * PEG_PRECISION.toNumber());
2069
- mockMarket1.amm.sqrtK = new BN(cc).mul(BASE_PRECISION);
2070
-
2071
- const now = new BN(1688881915);
2072
-
2073
- const mmOraclePriceData: MMOraclePriceData = {
2074
- price: new BN(18.624 * PRICE_PRECISION.toNumber()),
2075
- slot: new BN(0),
2076
- confidence: new BN(1),
2077
- hasSufficientNumberOfDataPoints: true,
2078
- isMMOracleActive: true,
2079
- } as MMOraclePriceData;
2080
- mockMarket1.marketStats.historicalOracleData.lastOraclePrice = new BN(
2081
- 18.5535 * PRICE_PRECISION.toNumber()
2082
- );
2083
-
2084
- const updatedAmm = calculateUpdatedAMM(mockMarket1.amm, mmOraclePriceData);
2085
-
2086
- const [openBids, openAsks] = calculateMarketOpenBidAsk(
2087
- updatedAmm.baseAssetReserve,
2088
- updatedAmm.minBaseAssetReserve,
2089
- updatedAmm.maxBaseAssetReserve,
2090
- mockMarket1.orderStepSize
2091
- );
2092
-
2093
- assert(!openAsks.eq(openBids));
2094
-
2095
- const generator = getVammL2Generator({
2096
- marketAccount: mockMarket1,
2097
- mmOraclePriceData,
2098
- numOrders: 10,
2099
- now,
2100
- topOfBookQuoteAmounts: [
2101
- new BN(10).mul(QUOTE_PRECISION),
2102
- new BN(100).mul(QUOTE_PRECISION),
2103
- new BN(1000).mul(QUOTE_PRECISION),
2104
- new BN(10000).mul(QUOTE_PRECISION),
2105
- ],
2106
- });
2107
-
2108
- const bids = Array.from(generator.getL2Bids());
2109
- assert(bids.length == 2);
2110
- console.log(bids[0].size.toString());
2111
- console.log(bids[1].size.toString());
2112
-
2113
- const totalBidSize = bids.reduce((total: BN, order: L2Level) => {
2114
- return total.add(order.size);
2115
- }, ZERO);
2116
-
2117
- console.log(
2118
- 'totalBidSize:',
2119
- totalBidSize.toString(),
2120
- 'openBids:',
2121
- openBids.toString()
2122
- );
2123
- assert(totalBidSize.eq(openBids));
2124
-
2125
- const asks = Array.from(generator.getL2Asks());
2126
- // console.log(asks);
2127
-
2128
- const totalAskSize = asks.reduce((total: BN, order: L2Level) => {
2129
- return total.add(order.size);
2130
- }, ZERO);
2131
- console.log(
2132
- 'totalAskSize:',
2133
- totalAskSize.toString(),
2134
- 'openAsks:',
2135
- openAsks.toString()
2136
- );
2137
- assert(totalAskSize.sub(openAsks.abs()).lte(new BN(5))); // only tiny rounding errors
2138
- });
2139
-
2140
- it('orderbook L2 gen (4 topOfBookQuoteAmounts, 10 numOrders, low ask liquidity)', async () => {
2141
- const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
2142
-
2143
- const mockMarket1: PerpMarketAccount = myMockPerpMarkets[0];
2144
- const cc = 38104569;
2145
- mockMarket1.amm.baseAssetReserve = new BN(cc).mul(BASE_PRECISION);
2146
- mockMarket1.amm.maxBaseAssetReserve = mockMarket1.amm.baseAssetReserve.add(
2147
- BASE_PRECISION.mul(new BN(1000))
2148
- ); // 1000 base
2149
- mockMarket1.amm.minBaseAssetReserve = mockMarket1.amm.baseAssetReserve.sub(
2150
- BASE_PRECISION.div(new BN(2))
2151
- ); // only .5 base
2152
- mockMarket1.amm.quoteAssetReserve = new BN(cc).mul(BASE_PRECISION);
2153
- mockMarket1.amm.pegMultiplier = new BN(18.32 * PEG_PRECISION.toNumber());
2154
- mockMarket1.amm.sqrtK = new BN(cc).mul(BASE_PRECISION);
2155
-
2156
- const now = new BN(1688881915);
2157
-
2158
- const mmOraclePriceData: MMOraclePriceData = {
2159
- price: new BN(18.624 * PRICE_PRECISION.toNumber()),
2160
- slot: new BN(0),
2161
- confidence: new BN(1),
2162
- hasSufficientNumberOfDataPoints: true,
2163
- isMMOracleActive: true,
2164
- };
2165
- mockMarket1.marketStats.historicalOracleData.lastOraclePrice = new BN(
2166
- 18.5535 * PRICE_PRECISION.toNumber()
2167
- );
2168
-
2169
- const updatedAmm = calculateUpdatedAMM(mockMarket1.amm, mmOraclePriceData);
2170
-
2171
- const [openBids, openAsks] = calculateMarketOpenBidAsk(
2172
- updatedAmm.baseAssetReserve,
2173
- updatedAmm.minBaseAssetReserve,
2174
- updatedAmm.maxBaseAssetReserve,
2175
- mockMarket1.orderStepSize
2176
- );
2177
-
2178
- assert(!openAsks.eq(openBids));
2179
-
2180
- const generator = getVammL2Generator({
2181
- marketAccount: mockMarket1,
2182
- mmOraclePriceData,
2183
- numOrders: 10,
2184
- now,
2185
- topOfBookQuoteAmounts: [
2186
- new BN(10).mul(QUOTE_PRECISION),
2187
- new BN(100).mul(QUOTE_PRECISION),
2188
- new BN(1000).mul(QUOTE_PRECISION),
2189
- new BN(10000).mul(QUOTE_PRECISION),
2190
- ],
2191
- });
2192
-
2193
- const bids = Array.from(generator.getL2Bids());
2194
-
2195
- const totalBidSize = bids.reduce((total: BN, order: L2Level) => {
2196
- return total.add(order.size);
2197
- }, ZERO);
2198
-
2199
- console.log(
2200
- 'totalBidSize:',
2201
- totalBidSize.toString(),
2202
- 'openBids:',
2203
- openBids.toString()
2204
- );
2205
- assert(totalBidSize.sub(openBids).abs().lt(new BN(5)));
2206
-
2207
- const asks = Array.from(generator.getL2Asks());
2208
- // console.log(asks);
2209
-
2210
- assert(asks.length == 1);
2211
- console.log(asks[0].size.toString());
2212
- const totalAskSize = asks.reduce((total: BN, order: L2Level) => {
2213
- return total.add(order.size);
2214
- }, ZERO);
2215
- console.log(
2216
- 'totalAskSize:',
2217
- totalAskSize.toString(),
2218
- 'openAsks:',
2219
- openAsks.toString()
2220
- );
2221
- assert(totalAskSize.sub(openAsks.abs()).lte(new BN(5))); // only tiny rounding errors
2222
- });
2223
-
2224
- it('orderbook L2 gen (no topOfBookQuoteAmounts, 10 numOrders, no liquidity)', async () => {
2225
- const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
2226
-
2227
- const mockMarket1: PerpMarketAccount = myMockPerpMarkets[0];
2228
- const cc = 38104569;
2229
- mockMarket1.amm.baseAssetReserve = new BN(cc).mul(BASE_PRECISION);
2230
- mockMarket1.marketStats.minOrderSize = new BN(5);
2231
- mockMarket1.amm.maxBaseAssetReserve = mockMarket1.amm.baseAssetReserve.add(
2232
- new BN(9)
2233
- );
2234
- mockMarket1.amm.minBaseAssetReserve = mockMarket1.amm.baseAssetReserve.sub(
2235
- new BN(9)
2236
- );
2237
- mockMarket1.amm.quoteAssetReserve = new BN(cc).mul(BASE_PRECISION);
2238
- mockMarket1.amm.pegMultiplier = new BN(18.32 * PEG_PRECISION.toNumber());
2239
- mockMarket1.amm.sqrtK = new BN(cc).mul(BASE_PRECISION);
2240
-
2241
- const now = new BN(1688881915);
2242
-
2243
- const mmOraclePriceData: MMOraclePriceData = {
2244
- price: new BN(18.624 * PRICE_PRECISION.toNumber()),
2245
- slot: new BN(0),
2246
- confidence: new BN(1),
2247
- hasSufficientNumberOfDataPoints: true,
2248
- isMMOracleActive: true,
2249
- } as MMOraclePriceData;
2250
- mockMarket1.marketStats.historicalOracleData.lastOraclePrice = new BN(
2251
- 18.5535 * PRICE_PRECISION.toNumber()
2252
- );
2253
-
2254
- const updatedAmm = calculateUpdatedAMM(mockMarket1.amm, mmOraclePriceData);
2255
-
2256
- const [openBids, openAsks] = calculateMarketOpenBidAsk(
2257
- updatedAmm.baseAssetReserve,
2258
- updatedAmm.minBaseAssetReserve,
2259
- updatedAmm.maxBaseAssetReserve,
2260
- mockMarket1.orderStepSize
2261
- );
2262
-
2263
- const generator = getVammL2Generator({
2264
- marketAccount: mockMarket1,
2265
- mmOraclePriceData,
2266
- numOrders: 10,
2267
- now,
2268
- topOfBookQuoteAmounts: [],
2269
- });
2270
-
2271
- const bids = Array.from(generator.getL2Bids());
2272
- // console.log(bids);
2273
-
2274
- const totalBidSize = bids.reduce((total: BN, order: L2Level) => {
2275
- return total.add(order.size);
2276
- }, ZERO);
2277
-
2278
- console.log(
2279
- 'totalBidSize:',
2280
- totalBidSize.toString(),
2281
- 'openBids:',
2282
- openBids.toString()
2283
- );
2284
- assert(openBids.eq(new BN(9)));
2285
- assert(totalBidSize.eq(ZERO));
2286
-
2287
- const asks = Array.from(generator.getL2Asks());
2288
- // console.log(asks);
2289
-
2290
- const totalAskSize = asks.reduce((total: BN, order: L2Level) => {
2291
- return total.add(order.size);
2292
- }, ZERO);
2293
- console.log(
2294
- 'totalAskSize:',
2295
- totalAskSize.toString(),
2296
- 'openAsks:',
2297
- openAsks.toString()
2298
- );
2299
-
2300
- assert(openAsks.eq(new BN(-9)));
2301
- assert(totalAskSize.eq(ZERO));
2302
- });
2303
-
2304
- it('Reference Price Offset accounts for oracle twap slow floor term', () => {
2305
- // day-premium leg before averaging: 100000/1000*24 = 2400, then the
2306
- // program subtracts oracleTwapSlow.abs()/FUNDING_RATE_OFFSET_DENOMINATOR
2307
- // (500000/3333 = 150) => 2250. Without that term the average would be
2308
- // 1800 instead of 1750.
2309
- const reservePrice = PRICE_PRECISION;
2310
- const last24hAvgFundingRate = new BN(100000);
2311
- const liquidityFraction = new BN(2);
2312
- const oracleTwapFast = new BN(500000);
2313
- const markTwapFast = oracleTwapFast.add(new BN(1000));
2314
- const oracleTwapSlow = new BN(500000);
2315
- const markTwapSlow = oracleTwapSlow.add(new BN(2000));
2316
- const maxOffsetPct = 100000;
2317
-
2318
- const referencePriceOffset = calculateReferencePriceOffset(
2319
- reservePrice,
2320
- last24hAvgFundingRate,
2321
- liquidityFraction,
2322
- oracleTwapFast,
2323
- markTwapFast,
2324
- oracleTwapSlow,
2325
- markTwapSlow,
2326
- maxOffsetPct
2327
- );
2328
-
2329
- assert(referencePriceOffset.eq(new BN(1750)));
2330
- });
2331
-
2332
- it('calculateUpdatedAMM is a passthrough when the repeg debit fails the affordability floor', () => {
2333
- const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
2334
- const mockMarket1 = myMockPerpMarkets[0];
2335
- const mockAmm = mockMarket1.amm;
2336
-
2337
- mockAmm.baseAssetReserve = new BN(1000).mul(BASE_PRECISION);
2338
- mockAmm.quoteAssetReserve = new BN(1000).mul(BASE_PRECISION);
2339
- mockAmm.sqrtK = new BN(1000).mul(BASE_PRECISION);
2340
- mockAmm.pegMultiplier = new BN(10).mul(PEG_PRECISION);
2341
- mockAmm.baseAssetAmountWithAmm = new BN(100).mul(BASE_PRECISION);
2342
- mockAmm.curveUpdateIntensity = 100;
2343
- mockAmm.maxSpread = 25000;
2344
- // tiny positive equity: any positive repeg cost blows through it
2345
- mockAmm.totalFeeMinusDistributions = new BN(10);
2346
- mockAmm.netRevenueSinceLastFunding = new BN(0);
2347
-
2348
- const directionToClose = mockAmm.baseAssetAmountWithAmm.gt(ZERO)
2349
- ? PositionDirection.SHORT
2350
- : PositionDirection.LONG;
2351
- const [terminalQuoteAssetReserve] = calculateAmmReservesAfterSwap(
2352
- mockAmm,
2353
- 'base',
2354
- mockAmm.baseAssetAmountWithAmm.abs(),
2355
- getSwapDirection('base', directionToClose)
2356
- );
2357
- mockAmm.terminalQuoteAssetReserve = terminalQuoteAssetReserve;
2358
-
2359
- // a 1% oracle move is well inside half of maxSpread (1.25%), so the
2360
- // optimal-peg/budget calc doesn't take the large-price-gap escape
2361
- // hatch that would otherwise clear checkLowerBound
2362
- const mmOraclePriceData: MMOraclePriceData = {
2363
- price: new BN(101).mul(PRICE_PRECISION).divn(10),
2364
- slot: new BN(0),
2365
- confidence: new BN(1),
2366
- hasSufficientNumberOfDataPoints: true,
2367
- isMMOracleActive: true,
2368
- } as MMOraclePriceData;
2369
-
2370
- const updatedAmm = calculateUpdatedAMM(mockAmm, mmOraclePriceData);
2371
-
2372
- assert(updatedAmm.pegMultiplier.eq(mockAmm.pegMultiplier));
2373
- assert(updatedAmm.baseAssetReserve.eq(mockAmm.baseAssetReserve));
2374
- assert(updatedAmm.quoteAssetReserve.eq(mockAmm.quoteAssetReserve));
2375
- assert(updatedAmm.sqrtK.eq(mockAmm.sqrtK));
2376
- assert(
2377
- updatedAmm.totalFeeMinusDistributions.eq(
2378
- mockAmm.totalFeeMinusDistributions
2379
- )
2380
- );
2381
- });
2382
-
2383
- it('calculateUpdatedAMM is a passthrough when the oracle price is non-positive', () => {
2384
- const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
2385
- const mockMarket1 = myMockPerpMarkets[0];
2386
- const mockAmm = mockMarket1.amm;
2387
- mockAmm.curveUpdateIntensity = 100;
2388
-
2389
- const mmOraclePriceData: MMOraclePriceData = {
2390
- price: ZERO,
2391
- slot: new BN(0),
2392
- confidence: new BN(1),
2393
- hasSufficientNumberOfDataPoints: true,
2394
- isMMOracleActive: true,
2395
- } as MMOraclePriceData;
2396
-
2397
- const updatedAmm = calculateUpdatedAMM(mockAmm, mmOraclePriceData);
2398
- assert(updatedAmm.pegMultiplier.eq(mockAmm.pegMultiplier));
2399
- assert(updatedAmm.baseAssetReserve.eq(mockAmm.baseAssetReserve));
2400
- assert(updatedAmm.quoteAssetReserve.eq(mockAmm.quoteAssetReserve));
2401
- });
2402
- });