@velocity-exchange/sdk 0.4.0 → 0.6.0

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 (323) hide show
  1. package/README.md +3 -3
  2. package/lib/browser/adminClient.d.ts +35 -0
  3. package/lib/browser/adminClient.js +65 -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 +146 -3
  9. package/lib/browser/idl/velocity.json +147 -4
  10. package/lib/browser/orderSubscriber/OrderSubscriber.js +3 -0
  11. package/lib/browser/pyth/pythLazerSubscriber.js +37 -27
  12. package/lib/browser/types.d.ts +4 -0
  13. package/lib/browser/user.d.ts +15 -0
  14. package/lib/browser/user.js +37 -1
  15. package/lib/browser/velocityClient.d.ts +46 -10
  16. package/lib/browser/velocityClient.js +107 -35
  17. package/lib/node/adminClient.d.ts +35 -0
  18. package/lib/node/adminClient.d.ts.map +1 -1
  19. package/lib/node/adminClient.js +65 -0
  20. package/lib/node/config.d.ts.map +1 -1
  21. package/lib/node/config.js +6 -7
  22. package/lib/node/constants/numericConstants.d.ts +1 -1
  23. package/lib/node/constants/numericConstants.d.ts.map +1 -1
  24. package/lib/node/constants/numericConstants.js +1 -1
  25. package/lib/node/decode/user.d.ts.map +1 -1
  26. package/lib/node/decode/user.js +5 -1
  27. package/lib/node/idl/velocity.d.ts +146 -3
  28. package/lib/node/idl/velocity.d.ts.map +1 -1
  29. package/lib/node/idl/velocity.json +147 -4
  30. package/lib/node/orderSubscriber/OrderSubscriber.d.ts.map +1 -1
  31. package/lib/node/orderSubscriber/OrderSubscriber.js +3 -0
  32. package/lib/node/pyth/pythLazerSubscriber.d.ts.map +1 -1
  33. package/lib/node/pyth/pythLazerSubscriber.js +37 -27
  34. package/lib/node/types.d.ts +4 -0
  35. package/lib/node/types.d.ts.map +1 -1
  36. package/lib/node/user.d.ts +15 -0
  37. package/lib/node/user.d.ts.map +1 -1
  38. package/lib/node/user.js +37 -1
  39. package/lib/node/velocityClient.d.ts +46 -10
  40. package/lib/node/velocityClient.d.ts.map +1 -1
  41. package/lib/node/velocityClient.js +107 -35
  42. package/package.json +7 -3
  43. package/.prettierignore +0 -1
  44. package/CHANGELOG.md +0 -132
  45. package/build-browser.js +0 -58
  46. package/bunfig.toml +0 -3
  47. package/esbuild-shims.js +0 -12
  48. package/scripts/deposit-isolated-positions.ts +0 -110
  49. package/scripts/find-flagged-users.ts +0 -213
  50. package/scripts/grpc-client-test-comparison.ts +0 -372
  51. package/scripts/grpc-multiuser-client-test-comparison.ts +0 -158
  52. package/scripts/postbuild.js +0 -95
  53. package/scripts/single-grpc-client-test.ts +0 -284
  54. package/scripts/withdraw-isolated-positions.ts +0 -174
  55. package/src/accounts/README_WebSocketAccountSubscriberV2.md +0 -95
  56. package/src/accounts/README_WebSocketProgramAccountSubscriberV2.md +0 -135
  57. package/src/accounts/basicUserAccountSubscriber.ts +0 -79
  58. package/src/accounts/basicUserStatsAccountSubscriber.ts +0 -87
  59. package/src/accounts/bulkAccountLoader.ts +0 -358
  60. package/src/accounts/bulkUserStatsSubscription.ts +0 -40
  61. package/src/accounts/bulkUserSubscription.ts +0 -39
  62. package/src/accounts/customizedCadenceBulkAccountLoader.ts +0 -250
  63. package/src/accounts/fetch.ts +0 -200
  64. package/src/accounts/grpcAccountSubscriber.ts +0 -225
  65. package/src/accounts/grpcInsuranceFundStakeAccountSubscriber.ts +0 -73
  66. package/src/accounts/grpcMultiAccountSubscriber.ts +0 -566
  67. package/src/accounts/grpcMultiUserAccountSubscriber.ts +0 -328
  68. package/src/accounts/grpcProgramAccountSubscriber.ts +0 -264
  69. package/src/accounts/grpcUserAccountSubscriber.ts +0 -63
  70. package/src/accounts/grpcUserStatsAccountSubscriber.ts +0 -65
  71. package/src/accounts/grpcVelocityClientAccountSubscriber.ts +0 -257
  72. package/src/accounts/grpcVelocityClientAccountSubscriberV2.ts +0 -941
  73. package/src/accounts/laserProgramAccountSubscriber.ts +0 -266
  74. package/src/accounts/oneShotUserAccountSubscriber.ts +0 -88
  75. package/src/accounts/oneShotUserStatsAccountSubscriber.ts +0 -94
  76. package/src/accounts/pollingInsuranceFundStakeAccountSubscriber.ts +0 -223
  77. package/src/accounts/pollingOracleAccountSubscriber.ts +0 -151
  78. package/src/accounts/pollingTokenAccountSubscriber.ts +0 -147
  79. package/src/accounts/pollingUserAccountSubscriber.ts +0 -198
  80. package/src/accounts/pollingUserStatsAccountSubscriber.ts +0 -180
  81. package/src/accounts/pollingVelocityClientAccountSubscriber.ts +0 -774
  82. package/src/accounts/testBulkAccountLoader.ts +0 -59
  83. package/src/accounts/types.ts +0 -428
  84. package/src/accounts/utils.ts +0 -90
  85. package/src/accounts/webSocketAccountSubscriber.ts +0 -304
  86. package/src/accounts/webSocketAccountSubscriberV2.ts +0 -536
  87. package/src/accounts/webSocketInsuranceFundStakeAccountSubscriber.ts +0 -171
  88. package/src/accounts/webSocketProgramAccountSubscriber.ts +0 -244
  89. package/src/accounts/webSocketProgramAccountSubscriberV2.ts +0 -1048
  90. package/src/accounts/webSocketProgramAccountsSubscriberV2.ts +0 -1042
  91. package/src/accounts/webSocketUserAccountSubscriber.ts +0 -139
  92. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +0 -131
  93. package/src/accounts/webSocketVelocityClientAccountSubscriber.ts +0 -865
  94. package/src/accounts/webSocketVelocityClientAccountSubscriberV2.ts +0 -897
  95. package/src/accounts/websocketProgramUserAccountSubscriber.ts +0 -127
  96. package/src/addresses/marketAddresses.ts +0 -28
  97. package/src/addresses/pda.ts +0 -620
  98. package/src/adminClient.ts +0 -8136
  99. package/src/assert/assert.ts +0 -5
  100. package/src/auctionSubscriber/auctionSubscriber.ts +0 -86
  101. package/src/auctionSubscriber/auctionSubscriberGrpc.ts +0 -99
  102. package/src/auctionSubscriber/index.ts +0 -9
  103. package/src/auctionSubscriber/types.ts +0 -30
  104. package/src/bankrun/bankrunConnection.ts +0 -630
  105. package/src/blockhashSubscriber/BlockhashSubscriber.ts +0 -160
  106. package/src/blockhashSubscriber/index.ts +0 -6
  107. package/src/blockhashSubscriber/types.ts +0 -13
  108. package/src/clock/clockSubscriber.ts +0 -146
  109. package/src/config.ts +0 -312
  110. package/src/constants/index.ts +0 -9
  111. package/src/constants/numericConstants.ts +0 -194
  112. package/src/constants/perpMarkets.ts +0 -127
  113. package/src/constants/spotMarkets.ts +0 -104
  114. package/src/constants/txConstants.ts +0 -2
  115. package/src/constituentMap/constituentMap.ts +0 -305
  116. package/src/constituentMap/pollingConstituentAccountSubscriber.ts +0 -99
  117. package/src/constituentMap/webSocketConstituentAccountSubscriber.ts +0 -121
  118. package/src/core/VelocityCore.ts +0 -606
  119. package/src/core/index.ts +0 -12
  120. package/src/core/instructions/deposit.ts +0 -64
  121. package/src/core/instructions/fill.ts +0 -51
  122. package/src/core/instructions/funding.ts +0 -33
  123. package/src/core/instructions/liquidation.ts +0 -55
  124. package/src/core/instructions/orders.ts +0 -84
  125. package/src/core/instructions/perpOrders.ts +0 -312
  126. package/src/core/instructions/settlement.ts +0 -40
  127. package/src/core/instructions/trigger.ts +0 -41
  128. package/src/core/instructions/withdraw.ts +0 -65
  129. package/src/core/remainingAccounts.ts +0 -320
  130. package/src/core/signedMsg.ts +0 -109
  131. package/src/decode/customCoder.ts +0 -148
  132. package/src/decode/user.ts +0 -401
  133. package/src/dlob/DLOB.ts +0 -2793
  134. package/src/dlob/DLOBNode.ts +0 -305
  135. package/src/dlob/DLOBSubscriber.ts +0 -269
  136. package/src/dlob/NodeList.ts +0 -244
  137. package/src/dlob/orderBookLevels.ts +0 -695
  138. package/src/dlob/types.ts +0 -37
  139. package/src/events/eventList.ts +0 -114
  140. package/src/events/eventSubscriber.ts +0 -521
  141. package/src/events/eventsServerLogProvider.ts +0 -189
  142. package/src/events/fetchLogs.ts +0 -219
  143. package/src/events/parse.ts +0 -271
  144. package/src/events/pollingLogProvider.ts +0 -113
  145. package/src/events/sort.ts +0 -51
  146. package/src/events/txEventCache.ts +0 -92
  147. package/src/events/types.ts +0 -337
  148. package/src/events/webSocketLogProvider.ts +0 -152
  149. package/src/factory/bigNum.ts +0 -709
  150. package/src/factory/oracleClient.ts +0 -73
  151. package/src/idl/pyth.json +0 -142
  152. package/src/idl/pyth.ts +0 -97
  153. package/src/idl/pyth_solana_receiver.json +0 -628
  154. package/src/idl/token_faucet.json +0 -229
  155. package/src/idl/token_faucet.ts +0 -197
  156. package/src/idl/velocity.json +0 -23974
  157. package/src/idl/velocity.ts +0 -23980
  158. package/src/index.ts +0 -150
  159. package/src/indicative-quotes/indicativeQuotesSender.ts +0 -233
  160. package/src/isomorphic/README.md +0 -19
  161. package/src/isomorphic/anchor.browser.ts +0 -44
  162. package/src/isomorphic/anchor.node.ts +0 -1
  163. package/src/isomorphic/anchor.ts +0 -1
  164. package/src/isomorphic/anchor29.browser.ts +0 -24
  165. package/src/isomorphic/anchor29.node.ts +0 -1
  166. package/src/isomorphic/anchor29.ts +0 -1
  167. package/src/isomorphic/grpc.browser.ts +0 -4
  168. package/src/isomorphic/grpc.node.ts +0 -130
  169. package/src/isomorphic/grpc.ts +0 -1
  170. package/src/jupiter/jupiterClient.ts +0 -502
  171. package/src/keypair.ts +0 -32
  172. package/src/margin/README.md +0 -138
  173. package/src/marginCalculation.ts +0 -407
  174. package/src/marinade/idl/idl.json +0 -1962
  175. package/src/marinade/index.ts +0 -73
  176. package/src/marinade/types.ts +0 -3925
  177. package/src/math/amm.ts +0 -1758
  178. package/src/math/auction.ts +0 -480
  179. package/src/math/bankruptcy.ts +0 -138
  180. package/src/math/builder.ts +0 -130
  181. package/src/math/conversion.ts +0 -45
  182. package/src/math/exchangeStatus.ts +0 -261
  183. package/src/math/funding.ts +0 -498
  184. package/src/math/insurance.ts +0 -171
  185. package/src/math/liquidation.ts +0 -433
  186. package/src/math/margin.ts +0 -327
  187. package/src/math/market.ts +0 -487
  188. package/src/math/oracles.ts +0 -477
  189. package/src/math/orders.ts +0 -500
  190. package/src/math/position.ts +0 -381
  191. package/src/math/repeg.ts +0 -223
  192. package/src/math/spotBalance.ts +0 -996
  193. package/src/math/spotMarket.ts +0 -115
  194. package/src/math/spotPosition.ts +0 -263
  195. package/src/math/state.ts +0 -71
  196. package/src/math/superStake.ts +0 -602
  197. package/src/math/tiers.ts +0 -73
  198. package/src/math/trade.ts +0 -879
  199. package/src/math/utils.ts +0 -183
  200. package/src/memcmp.ts +0 -279
  201. package/src/oracles/oracleClientCache.ts +0 -41
  202. package/src/oracles/oracleId.ts +0 -99
  203. package/src/oracles/prelaunchOracleClient.ts +0 -63
  204. package/src/oracles/pythClient.ts +0 -125
  205. package/src/oracles/pythLazerClient.ts +0 -141
  206. package/src/oracles/quoteAssetOracleClient.ts +0 -43
  207. package/src/oracles/strictOraclePrice.ts +0 -40
  208. package/src/oracles/types.ts +0 -82
  209. package/src/oracles/utils.ts +0 -45
  210. package/src/orderParams.ts +0 -117
  211. package/src/orderSubscriber/OrderSubscriber.ts +0 -378
  212. package/src/orderSubscriber/PollingSubscription.ts +0 -50
  213. package/src/orderSubscriber/WebsocketSubscription.ts +0 -137
  214. package/src/orderSubscriber/grpcSubscription.ts +0 -155
  215. package/src/orderSubscriber/index.ts +0 -7
  216. package/src/orderSubscriber/types.ts +0 -64
  217. package/src/priorityFee/averageOverSlotsStrategy.ts +0 -17
  218. package/src/priorityFee/averageStrategy.ts +0 -13
  219. package/src/priorityFee/ewmaStrategy.ts +0 -51
  220. package/src/priorityFee/heliusPriorityFeeMethod.ts +0 -68
  221. package/src/priorityFee/index.ts +0 -16
  222. package/src/priorityFee/maxOverSlotsStrategy.ts +0 -18
  223. package/src/priorityFee/maxStrategy.ts +0 -8
  224. package/src/priorityFee/priorityFeeSubscriber.ts +0 -328
  225. package/src/priorityFee/priorityFeeSubscriberMap.ts +0 -134
  226. package/src/priorityFee/solanaPriorityFeeMethod.ts +0 -46
  227. package/src/priorityFee/types.ts +0 -82
  228. package/src/priorityFee/velocityPriorityFeeMethod.ts +0 -53
  229. package/src/pyth/constants.ts +0 -9
  230. package/src/pyth/index.ts +0 -15
  231. package/src/pyth/pythLazerSubscriber.ts +0 -365
  232. package/src/pyth/types.ts +0 -4451
  233. package/src/pyth/utils.ts +0 -13
  234. package/src/slot/SlotSubscriber.ts +0 -126
  235. package/src/slot/SlothashSubscriber.ts +0 -163
  236. package/src/swap/UnifiedSwapClient.ts +0 -315
  237. package/src/swift/grpcSignedMsgUserAccountSubscriber.ts +0 -81
  238. package/src/swift/index.ts +0 -10
  239. package/src/swift/signedMsgUserAccountSubscriber.ts +0 -251
  240. package/src/swift/swiftOrderSubscriber.ts +0 -351
  241. package/src/testClient.ts +0 -42
  242. package/src/titan/titanClient.ts +0 -438
  243. package/src/token/index.ts +0 -13
  244. package/src/tokenFaucet.ts +0 -296
  245. package/src/tx/baseTxSender.ts +0 -651
  246. package/src/tx/blockhashFetcher/baseBlockhashFetcher.ts +0 -31
  247. package/src/tx/blockhashFetcher/cachedBlockhashFetcher.ts +0 -105
  248. package/src/tx/blockhashFetcher/types.ts +0 -9
  249. package/src/tx/fastSingleTxSender.ts +0 -200
  250. package/src/tx/forwardOnlyTxSender.ts +0 -193
  251. package/src/tx/priorityFeeCalculator.ts +0 -117
  252. package/src/tx/reportTransactionError.ts +0 -176
  253. package/src/tx/retryTxSender.ts +0 -177
  254. package/src/tx/txHandler.ts +0 -1009
  255. package/src/tx/txParamProcessor.ts +0 -225
  256. package/src/tx/types.ts +0 -117
  257. package/src/tx/utils.ts +0 -133
  258. package/src/tx/whileValidTxSender.ts +0 -377
  259. package/src/types.ts +0 -2575
  260. package/src/user.ts +0 -5316
  261. package/src/userConfig.ts +0 -38
  262. package/src/userMap/PollingSubscription.ts +0 -61
  263. package/src/userMap/WebsocketSubscription.ts +0 -93
  264. package/src/userMap/grpcSubscription.ts +0 -93
  265. package/src/userMap/referrerMap.ts +0 -360
  266. package/src/userMap/revenueShareEscrowMap.ts +0 -342
  267. package/src/userMap/userMap.ts +0 -784
  268. package/src/userMap/userMapConfig.ts +0 -82
  269. package/src/userMap/userStatsMap.ts +0 -393
  270. package/src/userName.ts +0 -37
  271. package/src/userStats.ts +0 -159
  272. package/src/userStatsConfig.ts +0 -35
  273. package/src/util/TransactionConfirmationManager.ts +0 -333
  274. package/src/util/chainClock.ts +0 -65
  275. package/src/util/computeUnits.ts +0 -101
  276. package/src/util/digest.ts +0 -33
  277. package/src/util/ed25519Utils.ts +0 -95
  278. package/src/util/promiseTimeout.ts +0 -23
  279. package/src/velocityClient.ts +0 -14802
  280. package/src/velocityClientConfig.ts +0 -119
  281. package/src/wallet.ts +0 -91
  282. package/tests/VelocityCore/builder_escrow.test.ts +0 -121
  283. package/tests/VelocityCore/decode.test.ts +0 -16
  284. package/tests/VelocityCore/fill_trigger.test.ts +0 -73
  285. package/tests/VelocityCore/instructions.test.ts +0 -46
  286. package/tests/VelocityCore/pdas.test.ts +0 -30
  287. package/tests/VelocityCore/perp_orders.test.ts +0 -205
  288. package/tests/VelocityCore/remainingAccounts.test.ts +0 -72
  289. package/tests/VelocityCore/settlement_liquidation.test.ts +0 -69
  290. package/tests/accounts/customizedCadenceBulkAccountLoader.test.ts +0 -211
  291. package/tests/amm/test.ts +0 -2402
  292. package/tests/auctions/test.ts +0 -81
  293. package/tests/bn/test.ts +0 -355
  294. package/tests/builder/builderFee.test.ts +0 -42
  295. package/tests/ci/verifyConstants.ts +0 -393
  296. package/tests/decode/test.ts +0 -262
  297. package/tests/decode/userAccountBufferStrings.ts +0 -102
  298. package/tests/dlob/helpers.ts +0 -748
  299. package/tests/dlob/test.ts +0 -6969
  300. package/tests/dlob/tickSizeStandardization.ts +0 -545
  301. package/tests/events/parseLogsForCuUsage.ts +0 -139
  302. package/tests/exchangeStatus/test.ts +0 -45
  303. package/tests/insurance/test.ts +0 -40
  304. package/tests/liquidation/test.ts +0 -125
  305. package/tests/oracles/mmOracleGate.test.ts +0 -379
  306. package/tests/oracles/pythPegSnap.test.ts +0 -76
  307. package/tests/sdkParity/enumParity.test.ts +0 -84
  308. package/tests/sdkParity/marginCategoryFill.test.ts +0 -143
  309. package/tests/sdkParity/memcmpOffsets.test.ts +0 -139
  310. package/tests/spot/test.ts +0 -281
  311. package/tests/tx/TransactionConfirmationManager.test.ts +0 -312
  312. package/tests/tx/cachedBlockhashFetcher.test.ts +0 -96
  313. package/tests/tx/priorityFeeCalculator.ts +0 -77
  314. package/tests/tx/priorityFeeStrategy.ts +0 -95
  315. package/tests/user/bankruptcy.ts +0 -165
  316. package/tests/user/feeAndWithdrawLimits.ts +0 -284
  317. package/tests/user/getMarginCalculation.ts +0 -586
  318. package/tests/user/helpers.ts +0 -184
  319. package/tests/user/liquidations.ts +0 -129
  320. package/tests/user/marginCalculations.test.ts +0 -321
  321. package/tests/user/test.ts +0 -833
  322. package/tsconfig.browser.json +0 -18
  323. package/tsconfig.json +0 -36
@@ -1,498 +0,0 @@
1
- import { BN } from '../isomorphic/anchor';
2
- import {
3
- AMM_RESERVE_PRECISION,
4
- PRICE_PRECISION,
5
- QUOTE_PRECISION,
6
- ZERO,
7
- ONE,
8
- FUNDING_RATE_OFFSET_DENOMINATOR,
9
- BPS_PRECISION,
10
- PERCENTAGE_PRECISION,
11
- } from '../constants/numericConstants';
12
- import { BigNum } from '../factory/bigNum';
13
- import { PerpMarketAccount, isVariant } from '../types';
14
- import { MMOraclePriceData, OraclePriceData } from '../oracles/types';
15
- import { calculateBidAskPrice } from './amm';
16
- import { calculateLiveOracleTwap } from './oracles';
17
- import { clampBN } from './utils';
18
- import {
19
- FUNDING_RATE_BUFFER_PRECISION,
20
- FUNDING_RATE_PRECISION_EXP,
21
- } from '../constants/numericConstants';
22
-
23
- function calculateLiveMarkTwap(
24
- market: PerpMarketAccount,
25
- mmOraclePriceData?: MMOraclePriceData,
26
- markPrice?: BN,
27
- now?: BN,
28
- period = new BN(3600)
29
- ): BN {
30
- now = now || new BN((Date.now() / 1000).toFixed(0));
31
-
32
- const lastMarkTwapWithMantissa = market.marketStats.lastMarkPriceTwap;
33
- const lastMarkPriceTwapTs = market.marketStats.lastMarkPriceTwapTs;
34
-
35
- const timeSinceLastMarkChange = now.sub(lastMarkPriceTwapTs);
36
- const markTwapTimeSinceLastUpdate = BN.max(
37
- period,
38
- BN.max(ZERO, period.sub(timeSinceLastMarkChange))
39
- );
40
-
41
- if (!markPrice) {
42
- const [bid, ask] = calculateBidAskPrice(
43
- market.amm,
44
- market.marketStats,
45
- mmOraclePriceData
46
- );
47
- markPrice = bid.add(ask).div(new BN(2));
48
- }
49
-
50
- const markTwapWithMantissa = markTwapTimeSinceLastUpdate
51
- .mul(lastMarkTwapWithMantissa)
52
- .add(timeSinceLastMarkChange.mul(markPrice))
53
- .div(timeSinceLastMarkChange.add(markTwapTimeSinceLastUpdate));
54
-
55
- return markTwapWithMantissa;
56
- }
57
-
58
- function shrinkStaleTwaps(
59
- market: PerpMarketAccount,
60
- markTwapWithMantissa: BN,
61
- oracleTwapWithMantissa: BN,
62
- now?: BN
63
- ) {
64
- now = now || new BN((Date.now() / 1000).toFixed(0));
65
- let newMarkTwap = markTwapWithMantissa;
66
- let newOracleTwap = oracleTwapWithMantissa;
67
- if (
68
- market.marketStats.lastMarkPriceTwapTs.gt(
69
- market.marketStats.historicalOracleData.lastOraclePriceTwapTs
70
- )
71
- ) {
72
- // shrink oracle based on invalid intervals
73
- const oracleInvalidDuration = BN.max(
74
- ZERO,
75
- market.marketStats.lastMarkPriceTwapTs.sub(
76
- market.marketStats.historicalOracleData.lastOraclePriceTwapTs
77
- )
78
- );
79
- const timeSinceLastOracleTwapUpdate = now.sub(
80
- market.marketStats.historicalOracleData.lastOraclePriceTwapTs
81
- );
82
- const oracleTwapTimeSinceLastUpdate = BN.max(
83
- ONE,
84
- BN.min(
85
- market.marketStats.fundingPeriod,
86
- BN.max(
87
- ONE,
88
- market.marketStats.fundingPeriod.sub(timeSinceLastOracleTwapUpdate)
89
- )
90
- )
91
- );
92
- newOracleTwap = oracleTwapTimeSinceLastUpdate
93
- .mul(oracleTwapWithMantissa)
94
- .add(oracleInvalidDuration.mul(markTwapWithMantissa))
95
- .div(oracleTwapTimeSinceLastUpdate.add(oracleInvalidDuration));
96
- } else if (
97
- market.marketStats.lastMarkPriceTwapTs.lt(
98
- market.marketStats.historicalOracleData.lastOraclePriceTwapTs
99
- )
100
- ) {
101
- // shrink mark to oracle twap over tradless intervals
102
- const tradelessDuration = BN.max(
103
- ZERO,
104
- market.marketStats.historicalOracleData.lastOraclePriceTwapTs.sub(
105
- market.marketStats.lastMarkPriceTwapTs
106
- )
107
- );
108
- const timeSinceLastMarkTwapUpdate = now.sub(
109
- market.marketStats.lastMarkPriceTwapTs
110
- );
111
- const markTwapTimeSinceLastUpdate = BN.max(
112
- ONE,
113
- BN.min(
114
- market.marketStats.fundingPeriod,
115
- BN.max(
116
- ONE,
117
- market.marketStats.fundingPeriod.sub(timeSinceLastMarkTwapUpdate)
118
- )
119
- )
120
- );
121
- newMarkTwap = markTwapTimeSinceLastUpdate
122
- .mul(markTwapWithMantissa)
123
- .add(tradelessDuration.mul(oracleTwapWithMantissa))
124
- .div(markTwapTimeSinceLastUpdate.add(tradelessDuration));
125
- }
126
-
127
- return [newMarkTwap, newOracleTwap];
128
- }
129
-
130
- /**
131
- * Client-side projection of the market's next funding rate, mirroring the pure-math portion
132
- * of `update_funding_rate` in `programs/velocity/src/controller/funding.rs` (live mark/oracle
133
- * TWAPs, the per-market dead-zone/ramp-slope premium, the baseline
134
- * `FUNDING_RATE_OFFSET_DENOMINATOR` offset, and the contract-tier divergence cap) without
135
- * requiring an on-chain funding update to have actually run. This is an estimate for display
136
- * or pre-trade planning — it does not settle anything and can differ slightly from what the
137
- * next on-chain `update_funding_rate` call computes if `now`/`oraclePriceData` have moved
138
- * since.
139
- * @param market Perp market to estimate funding for; must not be `uninitialized`.
140
- * @param mmOraclePriceData Current MM oracle price data, used to compute the live mark TWAP if `markPrice` isn't supplied.
141
- * @param oraclePriceData Current oracle price data — required unless the market is uninitialized.
142
- * @param markPrice Optional mark price override; if omitted, derived from the current bid/ask midpoint.
143
- * @param now Current unix timestamp (seconds); defaults to wall-clock time.
144
- * @returns `[markTwap, oracleTwap, lowerboundEst, cappedAltEst, interpEst]`:
145
- * - `markTwap` / `oracleTwap`: live-projected TWAPs, PRICE_PRECISION (1e6).
146
- * - `lowerboundEst`, `cappedAltEst`, `interpEst`: funding-rate-per-period estimates
147
- * expressed as `(price spread / oracle price) * 1e8` — feed these into
148
- * `getFundingRatePct`/`calculateFormattedLiveFundingRate` (which multiply by
149
- * `FUNDING_RATE_BUFFER_PRECISION` and read the result at `FUNDING_RATE_PRECISION_EXP`,
150
- * 1e9) to get a plain percentage. `cappedAltEst` is the smaller-open-interest side,
151
- * capped by how much the fee pool can top it up; `interpEst` is the uncapped
152
- * straight-line interpolation; `lowerboundEst` further scales the spread down by the
153
- * fraction of the current funding period that has elapsed since the last update.
154
- */
155
- export function calculateAllEstimatedFundingRate(
156
- market: PerpMarketAccount,
157
- mmOraclePriceData?: MMOraclePriceData,
158
- oraclePriceData?: OraclePriceData,
159
- markPrice?: BN,
160
- now?: BN
161
- ): [BN, BN, BN, BN, BN] {
162
- if (isVariant(market.status, 'uninitialized')) {
163
- return [ZERO, ZERO, ZERO, ZERO, ZERO];
164
- }
165
-
166
- // todo: sufficiently differs from blockchain timestamp?
167
- now = now || new BN((Date.now() / 1000).toFixed(0));
168
-
169
- // calculate real-time mark and oracle twap
170
- const liveMarkTwap = calculateLiveMarkTwap(
171
- market,
172
- mmOraclePriceData,
173
- markPrice,
174
- now,
175
- market.marketStats.fundingPeriod
176
- );
177
- if (!oraclePriceData) {
178
- throw new Error(
179
- 'calculateAllEstimatedFundingRate: oraclePriceData is required for an initialized market'
180
- );
181
- }
182
- const liveOracleTwap = calculateLiveOracleTwap(
183
- market.marketStats.historicalOracleData,
184
- oraclePriceData,
185
- now,
186
- market.marketStats.fundingPeriod
187
- );
188
- const [markTwap, oracleTwap] = shrinkStaleTwaps(
189
- market,
190
- liveMarkTwap,
191
- liveOracleTwap,
192
- now
193
- );
194
-
195
- // if(!markTwap.eq(liveMarkTwap)){
196
- // console.log('shrink mark:', liveMarkTwap.toString(), '->', markTwap.toString());
197
- // }
198
-
199
- // if(!oracleTwap.eq(liveOracleTwap)){
200
- // console.log('shrink orac:', liveOracleTwap.toString(), '->', oracleTwap.toString());
201
- // }
202
-
203
- const twapSpread = markTwap.sub(oracleTwap);
204
- const offset = oracleTwap.abs().div(FUNDING_RATE_OFFSET_DENOMINATOR);
205
-
206
- // dead-zone threshold (per-market bps) as a price delta off the oracle twap
207
- const clampThreshold = oracleTwap
208
- .abs()
209
- .mul(new BN(market.fundingClampThreshold))
210
- .div(BPS_PRECISION);
211
-
212
- let twapSpreadWithOffset: BN;
213
- if (twapSpread.abs().lte(clampThreshold)) {
214
- // inside the band: noise, no premium, baseline offset only
215
- twapSpreadWithOffset = offset;
216
- } else {
217
- // outside the band: shrink the spread toward zero by the band width
218
- // (keeping its sign), scale by the per-market ramp slope, add the offset
219
- const shrunk = twapSpread.isNeg()
220
- ? twapSpread.add(clampThreshold)
221
- : twapSpread.sub(clampThreshold);
222
- const ramped = shrunk
223
- .mul(new BN(market.fundingRampSlope))
224
- .div(PERCENTAGE_PRECISION);
225
- twapSpreadWithOffset = ramped.add(offset);
226
- }
227
-
228
- const maxSpread = getMaxPriceDivergenceForFundingRate(market, oracleTwap);
229
-
230
- const clampedSpreadWithOffset = clampBN(
231
- twapSpreadWithOffset,
232
- maxSpread.mul(new BN(-1)),
233
- maxSpread
234
- );
235
-
236
- const twapSpreadPct = clampedSpreadWithOffset
237
- .mul(PRICE_PRECISION)
238
- .mul(new BN(100))
239
- .div(oracleTwap);
240
-
241
- const secondsInHour = new BN(3600);
242
- const hoursInDay = new BN(24);
243
- const timeSinceLastUpdate = now.sub(market.lastFundingRateTs);
244
-
245
- const lowerboundEst = twapSpreadPct
246
- .mul(market.marketStats.fundingPeriod)
247
- .mul(BN.min(secondsInHour, timeSinceLastUpdate))
248
- .div(secondsInHour)
249
- .div(secondsInHour)
250
- .div(hoursInDay);
251
-
252
- const interpEst = twapSpreadPct.div(hoursInDay);
253
-
254
- const interpRateQuote = twapSpreadPct
255
- .div(hoursInDay)
256
- .div(PRICE_PRECISION.div(QUOTE_PRECISION));
257
-
258
- let feePoolSize = calculateFundingPool(market);
259
- if (interpRateQuote.lt(new BN(0))) {
260
- feePoolSize = feePoolSize.mul(new BN(-1));
261
- }
262
-
263
- let cappedAltEst: BN;
264
- let largerSide: BN;
265
- let smallerSide: BN;
266
- if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort.abs())) {
267
- largerSide = market.baseAssetAmountLong.abs();
268
- smallerSide = market.baseAssetAmountShort.abs();
269
- if (twapSpread.gt(new BN(0))) {
270
- return [markTwap, oracleTwap, lowerboundEst, interpEst, interpEst];
271
- }
272
- } else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort.abs())) {
273
- largerSide = market.baseAssetAmountShort.abs();
274
- smallerSide = market.baseAssetAmountLong.abs();
275
- if (twapSpread.lt(new BN(0))) {
276
- return [markTwap, oracleTwap, lowerboundEst, interpEst, interpEst];
277
- }
278
- } else {
279
- return [markTwap, oracleTwap, lowerboundEst, interpEst, interpEst];
280
- }
281
-
282
- if (largerSide.gt(ZERO)) {
283
- // funding smaller flow
284
- cappedAltEst = smallerSide.mul(twapSpread).div(hoursInDay);
285
- const feePoolTopOff = feePoolSize
286
- .mul(PRICE_PRECISION.div(QUOTE_PRECISION))
287
- .mul(AMM_RESERVE_PRECISION);
288
- cappedAltEst = cappedAltEst.add(feePoolTopOff).div(largerSide);
289
-
290
- cappedAltEst = cappedAltEst
291
- .mul(PRICE_PRECISION)
292
- .mul(new BN(100))
293
- .div(oracleTwap);
294
-
295
- if (cappedAltEst.abs().gte(interpEst.abs())) {
296
- cappedAltEst = interpEst;
297
- }
298
- } else {
299
- cappedAltEst = interpEst;
300
- }
301
-
302
- return [markTwap, oracleTwap, lowerboundEst, cappedAltEst, interpEst];
303
- }
304
-
305
- /**
306
- * Converts a raw funding-rate estimate (as produced by `calculateAllEstimatedFundingRate`,
307
- * scaled as `(price spread / oracle price) * 1e8`) into a plain human-readable percentage
308
- * number (e.g. `0.05` means 0.05%), by rescaling into `FUNDING_RATE_PRECISION_EXP` (1e9)
309
- * fixed-point via `FUNDING_RATE_BUFFER_PRECISION`.
310
- * @param rawFundingRate Raw funding rate estimate to convert.
311
- * @returns Plain percentage number (not a fraction — `1` means 1%, not 100%).
312
- */
313
- const getFundingRatePct = (rawFundingRate: BN) => {
314
- return BigNum.from(
315
- rawFundingRate.mul(FUNDING_RATE_BUFFER_PRECISION),
316
- FUNDING_RATE_PRECISION_EXP
317
- ).toNum();
318
- };
319
-
320
- /**
321
- * Calculates estimated funding rates in human-readable form (plain JS `number` percentages,
322
- * not BN), including a plain-English summary sentence. Values pass through floating-point
323
- * math and lose precision vs the underlying BN estimate — use `calculateAllEstimatedFundingRate`
324
- * or `calculateLongShortFundingRate` directly for anything that needs exact precision.
325
- * @param market Perp market to estimate funding for.
326
- * @param mmOraclePriceData Current MM oracle price data.
327
- * @param oraclePriceData Current oracle price data.
328
- * @param period `'hour'` for the hourly payment as a percentage, `'year'` for the payment annualized (assuming 24 funding payments/day) as an estimated APR.
329
- * @returns `longRate`/`shortRate`: signed percentage numbers from that side's own perspective — negative means that side pays funding, positive means that side receives it; `fundingRateUnit`: `'%'` or `'% APR'`; `formattedFundingRateSummary`: a human-readable sentence describing who pays whom.
330
- */
331
- export function calculateFormattedLiveFundingRate(
332
- market: PerpMarketAccount,
333
- mmOraclePriceData: MMOraclePriceData,
334
- oraclePriceData: OraclePriceData,
335
- period: 'hour' | 'year'
336
- ): {
337
- longRate: number;
338
- shortRate: number;
339
- fundingRateUnit: string;
340
- formattedFundingRateSummary: string;
341
- } {
342
- const nowBN = new BN(Date.now() / 1000);
343
-
344
- const [_markTwapLive, _oracleTwapLive, longFundingRate, shortFundingRate] =
345
- calculateLongShortFundingRateAndLiveTwaps(
346
- market,
347
- mmOraclePriceData,
348
- oraclePriceData,
349
- undefined,
350
- nowBN
351
- );
352
-
353
- let longFundingRateNum = getFundingRatePct(longFundingRate);
354
- let shortFundingRateNum = getFundingRatePct(shortFundingRate);
355
-
356
- if (period == 'year') {
357
- const paymentsPerYear = 24 * 365.25;
358
-
359
- longFundingRateNum *= paymentsPerYear;
360
- shortFundingRateNum *= paymentsPerYear;
361
- }
362
-
363
- const longsArePaying = longFundingRateNum > 0;
364
- const shortsArePaying = !(shortFundingRateNum > 0);
365
-
366
- const longsAreString = longsArePaying ? 'pay' : 'receive';
367
- const shortsAreString = !shortsArePaying ? 'receive' : 'pay';
368
-
369
- const absoluteLongFundingRateNum = Math.abs(longFundingRateNum);
370
- const absoluteShortFundingRateNum = Math.abs(shortFundingRateNum);
371
-
372
- const formattedLongRatePct = absoluteLongFundingRateNum.toFixed(
373
- period == 'hour' ? 5 : 2
374
- );
375
- const formattedShortRatePct = absoluteShortFundingRateNum.toFixed(
376
- period == 'hour' ? 5 : 2
377
- );
378
-
379
- const fundingRateUnit = period == 'year' ? '% APR' : '%';
380
-
381
- const formattedFundingRateSummary = `At this rate, longs would ${longsAreString} ${formattedLongRatePct} ${fundingRateUnit} and shorts would ${shortsAreString} ${formattedShortRatePct} ${fundingRateUnit} at the end of the hour.`;
382
-
383
- return {
384
- longRate: longsArePaying
385
- ? -absoluteLongFundingRateNum
386
- : absoluteLongFundingRateNum,
387
- shortRate: shortsArePaying
388
- ? -absoluteShortFundingRateNum
389
- : absoluteShortFundingRateNum,
390
- fundingRateUnit: fundingRateUnit,
391
- formattedFundingRateSummary,
392
- };
393
- }
394
-
395
- function getMaxPriceDivergenceForFundingRate(
396
- market: PerpMarketAccount,
397
- oracleTwap: BN
398
- ) {
399
- if (isVariant(market.contractTier, 'a')) {
400
- return oracleTwap.divn(33);
401
- } else if (isVariant(market.contractTier, 'b')) {
402
- return oracleTwap.divn(33);
403
- } else if (isVariant(market.contractTier, 'c')) {
404
- return oracleTwap.divn(20);
405
- } else {
406
- return oracleTwap.divn(10);
407
- }
408
- }
409
-
410
- /**
411
- * Convenience wrapper around `calculateAllEstimatedFundingRate` that assigns its capped
412
- * (`cappedAltEst`) vs. uncapped (`interpEst`) estimate to the long/short side by comparing
413
- * `market.baseAssetAmountLong` against `market.baseAssetAmountShort`. When both sides are
414
- * equal, both get `interpEst`.
415
- * @param market Perp market to estimate funding for.
416
- * @param mmOraclePriceData Current MM oracle price data.
417
- * @param oraclePriceData Current oracle price data.
418
- * @param markPrice Optional mark price override.
419
- * @param now Current unix timestamp (seconds); defaults to wall-clock time.
420
- * @returns `[longFundingRateEst, shortFundingRateEst]`, same scale as `calculateAllEstimatedFundingRate`'s rate outputs.
421
- */
422
- export function calculateLongShortFundingRate(
423
- market: PerpMarketAccount,
424
- mmOraclePriceData?: MMOraclePriceData,
425
- oraclePriceData?: OraclePriceData,
426
- markPrice?: BN,
427
- now?: BN
428
- ): [BN, BN] {
429
- const [_1, _2, _, cappedAltEst, interpEst] = calculateAllEstimatedFundingRate(
430
- market,
431
- mmOraclePriceData,
432
- oraclePriceData,
433
- markPrice,
434
- now
435
- );
436
-
437
- if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort)) {
438
- return [cappedAltEst, interpEst];
439
- } else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort)) {
440
- return [interpEst, cappedAltEst];
441
- } else {
442
- return [interpEst, interpEst];
443
- }
444
- }
445
-
446
- /**
447
- * Same estimate assignment as `calculateLongShortFundingRate` (using
448
- * `market.baseAssetAmountLong` vs `market.baseAssetAmountShort.abs()` this time) but also
449
- * returns the live-projected mark/oracle TWAPs alongside the rate estimates.
450
- * @param market Perp market to estimate funding for.
451
- * @param mmOraclePriceData Current MM oracle price data.
452
- * @param oraclePriceData Current oracle price data.
453
- * @param markPrice Optional mark price override.
454
- * @param now Current unix timestamp (seconds); defaults to wall-clock time.
455
- * @returns `[markTwapLive, oracleTwapLive, longFundingRateEst, shortFundingRateEst]` — TWAPs in PRICE_PRECISION (1e6), rate estimates in the same scale as `calculateAllEstimatedFundingRate`.
456
- */
457
- export function calculateLongShortFundingRateAndLiveTwaps(
458
- market: PerpMarketAccount,
459
- mmOraclePriceData?: MMOraclePriceData,
460
- oraclePriceData?: OraclePriceData,
461
- markPrice?: BN,
462
- now?: BN
463
- ): [BN, BN, BN, BN] {
464
- const [markTwapLive, oracleTwapLive, _2, cappedAltEst, interpEst] =
465
- calculateAllEstimatedFundingRate(
466
- market,
467
- mmOraclePriceData,
468
- oraclePriceData,
469
- markPrice,
470
- now
471
- );
472
-
473
- if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort.abs())) {
474
- return [markTwapLive, oracleTwapLive, cappedAltEst, interpEst];
475
- } else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort.abs())) {
476
- return [markTwapLive, oracleTwapLive, interpEst, cappedAltEst];
477
- } else {
478
- return [markTwapLive, oracleTwapLive, interpEst, interpEst];
479
- }
480
- }
481
-
482
- /**
483
- * Estimated quote pool available to top up the smaller side's funding payment shortfall:
484
- * one-third of the AMM's own retained equity (`totalFeeMinusDistributions`), floored at
485
- * zero. Post-isolation there is no separate protocol floor to reserve — the AMM's own
486
- * equity is the only buffer.
487
- * @param market Perp market to evaluate.
488
- * @returns Estimated fee pool size, QUOTE_PRECISION (1e6).
489
- */
490
- export function calculateFundingPool(market: PerpMarketAccount): BN {
491
- // todo
492
- // no protocol floor post-isolation: 1/3 of the AMM's own equity
493
- const feePool = BN.max(
494
- ZERO,
495
- market.amm.totalFeeMinusDistributions.mul(new BN(1)).div(new BN(3))
496
- );
497
- return feePool;
498
- }
@@ -1,171 +0,0 @@
1
- import { PERCENTAGE_PRECISION, ZERO } from '../constants/numericConstants';
2
- import { getTokenAmount } from '../math/spotBalance';
3
- import { BN } from '../isomorphic/anchor';
4
- import { SpotBalanceType, SpotMarketAccount } from '../types';
5
-
6
- /**
7
- * Estimates the annualized yield (APR) insurance fund stakers would earn if the market's revenue
8
- * pool were settled into the insurance fund vault right now, projected forward assuming the same
9
- * revenue pool size settles at the market's configured `revenueSettlePeriod` cadence for a year.
10
- * The insurance fund is entirely staker-owned (no protocol split): all settled revenue accrues to
11
- * stakers via share-price appreciation. Only 10% of the projected annual revenue (`payoutRatio`)
12
- * is assumed to actually reach the vault as yield; the result is capped at 1000% APR.
13
- *
14
- * @param {SpotMarketAccount} spotMarket - The spot market account (its `revenuePool` and
15
- * `insuranceFund.revenueSettlePeriod` drive the projection)
16
- * @param {BN} vaultBalance - Current insurance fund vault token amount, market's token decimals
17
- * @param {BN} amount - Hypothetical additional deposit/withdrawal token amount to apply to the
18
- * vault balance before computing the ratio (positive = deposit, negative = withdrawal),
19
- * market's token decimals
20
- * @return {number} Estimated APR as a plain JS percentage number (e.g. `12.5` = 12.5% APR), or
21
- * `0` if `revenueSettlePeriod` is unset or `vaultBalance + amount` is zero. This is a display
22
- * estimate, not a program mirror — it also inherits a small numerical imprecision from scaling
23
- * a `BN` by the fractional `payoutRatio` (0.1) via `BN.muln`, which multiplies fractionally
24
- * per-limb rather than performing exact fixed-point math.
25
- */
26
- export function nextRevenuePoolSettleApr(
27
- spotMarket: SpotMarketAccount,
28
- vaultBalance: BN, // vault token amount
29
- amount: BN // delta token amount
30
- ): number {
31
- const MAX_APR = new BN(10).mul(PERCENTAGE_PRECISION); // 1000% APR
32
-
33
- // Conmputing the APR:
34
- const revenuePoolBN = getTokenAmount(
35
- spotMarket.revenuePool.scaledBalance,
36
- spotMarket,
37
- SpotBalanceType.DEPOSIT
38
- );
39
-
40
- const payoutRatio = 0.1;
41
- // the insurance fund is 100% staker-owned: every settled token accrues to
42
- // stakers as share-price appreciation (no protocol split)
43
- const ratioForStakers = spotMarket.insuranceFund.revenueSettlePeriod.gt(ZERO)
44
- ? 1
45
- : 0;
46
-
47
- // Settle periods from on-chain data:
48
- const revSettlePeriod =
49
- spotMarket.insuranceFund.revenueSettlePeriod.toNumber() * 1000;
50
-
51
- const settlesPerYear = 31536000000 / revSettlePeriod;
52
-
53
- const projectedAnnualRev = revenuePoolBN
54
- .muln(settlesPerYear)
55
- .muln(payoutRatio);
56
-
57
- const uncappedApr = vaultBalance.add(amount).eq(ZERO)
58
- ? 0
59
- : projectedAnnualRev.muln(1000).div(vaultBalance.add(amount)).toNumber() *
60
- 100 *
61
- 1000;
62
- const cappedApr = Math.min(uncappedApr, MAX_APR.toNumber());
63
-
64
- const nextApr = cappedApr * ratioForStakers;
65
-
66
- return nextApr;
67
- }
68
-
69
- /**
70
- * Calculates how many insurance fund shares a deposit of `amount` would mint, mirroring
71
- * `vault_amount_to_if_shares`. Shares are minted proportionally to the deposit's fraction of the
72
- * vault (`amount * totalIfShares / insuranceFundVaultBalance`, floored); if the vault is
73
- * currently empty, 1 share is minted per token (bootstrapping the share price at 1:1).
74
- *
75
- * @param {BN} amount - Token amount being staked, market's token decimals
76
- * @param {BN} totalIfShares - Current total insurance fund shares outstanding
77
- * @param {BN} insuranceFundVaultBalance - Current insurance fund vault token amount, market's token decimals
78
- * @return {BN} Shares minted
79
- */
80
- export function stakeAmountToShares(
81
- amount: BN,
82
- totalIfShares: BN,
83
- insuranceFundVaultBalance: BN
84
- ): BN {
85
- let nShares: BN;
86
- if (insuranceFundVaultBalance.gt(ZERO)) {
87
- nShares = amount.mul(totalIfShares).div(insuranceFundVaultBalance);
88
- } else {
89
- nShares = amount;
90
- }
91
-
92
- return nShares;
93
- }
94
-
95
- /**
96
- * Calculates the token amount `nShares` of the insurance fund are currently worth, mirroring
97
- * `if_shares_to_vault_amount` (floored). Returns zero (rather than dividing by zero) if there are
98
- * no shares outstanding.
99
- *
100
- * @param {BN} nShares - Number of insurance fund shares
101
- * @param {BN} totalIfShares - Current total insurance fund shares outstanding
102
- * @param {BN} insuranceFundVaultBalance - Current insurance fund vault token amount, market's token decimals
103
- * @return {BN} Token value of `nShares`, market's token decimals; floored at zero
104
- */
105
- export function unstakeSharesToAmount(
106
- nShares: BN,
107
- totalIfShares: BN,
108
- insuranceFundVaultBalance: BN
109
- ): BN {
110
- let amount: BN;
111
- if (totalIfShares.gt(ZERO)) {
112
- amount = BN.max(
113
- ZERO,
114
- nShares.mul(insuranceFundVaultBalance).div(totalIfShares)
115
- );
116
- } else {
117
- amount = ZERO;
118
- }
119
-
120
- return amount;
121
- }
122
-
123
- /**
124
- * Calculates a staker's total current value — their remaining staked shares plus any pending
125
- * withdrawal request — accounting for the fact that a pending request's payout is locked in at
126
- * the vault-value snapshot taken when the request was made (`InsuranceFundStake.lastWithdrawRequestValue`),
127
- * not the vault's current value. This is what a user can expect to see if they cancel/complete a
128
- * pending unstake request without further vault movement.
129
- *
130
- * @param {BN} nShares - The staker's total shares (`InsuranceFundStake.ifShares`), including any
131
- * shares already earmarked by a pending withdrawal request
132
- * @param {BN} withdrawRequestShares - Shares locked by a pending withdrawal request
133
- * (`InsuranceFundStake.lastWithdrawRequestShares`), 0 if none is pending
134
- * @param {BN} withdrawRequestAmount - The token amount locked in at request time
135
- * (`InsuranceFundStake.lastWithdrawRequestValue`), market's token decimals
136
- * @param {BN} totalIfShares - Current total insurance fund shares outstanding
137
- * @param {BN} insuranceFundVaultBalance - Current insurance fund vault token amount, market's token decimals
138
- * @return {BN} `stakedAmount + withdrawAmount`: the current value of `nShares - withdrawRequestShares`
139
- * (floored at zero) at today's vault price, plus `min(withdrawRequestAmount, withdrawRequestShares'
140
- * value at today's vault price)` — the pending withdrawal is whichever is lower of its
141
- * locked-in amount and its current value, so vault depreciation since the request reduces the
142
- * payout but vault appreciation does not increase it
143
- */
144
- export function unstakeSharesToAmountWithOpenRequest(
145
- nShares: BN,
146
- withdrawRequestShares: BN,
147
- withdrawRequestAmount: BN,
148
- totalIfShares: BN,
149
- insuranceFundVaultBalance: BN
150
- ): BN {
151
- let stakedAmount: BN;
152
- if (totalIfShares.gt(ZERO)) {
153
- stakedAmount = BN.max(
154
- ZERO,
155
- nShares
156
- .sub(withdrawRequestShares)
157
- .mul(insuranceFundVaultBalance)
158
- .div(totalIfShares)
159
- );
160
- } else {
161
- stakedAmount = ZERO;
162
- }
163
-
164
- const withdrawAmount = BN.min(
165
- withdrawRequestAmount,
166
- withdrawRequestShares.mul(insuranceFundVaultBalance).div(totalIfShares)
167
- );
168
- const amount = withdrawAmount.add(stakedAmount);
169
-
170
- return amount;
171
- }