@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
@@ -1,602 +0,0 @@
1
- import {
2
- AddressLookupTableAccount,
3
- LAMPORTS_PER_SOL,
4
- PublicKey,
5
- TransactionInstruction,
6
- } from '@solana/web3.js';
7
- import { JupiterClient, QuoteResponse } from '../jupiter/jupiterClient';
8
- import { VelocityClient } from '../velocityClient';
9
- import { getMarinadeFinanceProgram, getMarinadeMSolPrice } from '../marinade';
10
- import { BN } from '../isomorphic/anchor';
11
- import { User } from '../user';
12
- import { DepositRecord, isVariant } from '../types';
13
- import { LAMPORTS_PRECISION, ZERO } from '../constants/numericConstants';
14
- import fetch from 'node-fetch';
15
- import { checkSameDate } from './utils';
16
-
17
- /** Response shape of SolBlaze's `bsol/stats` endpoint (bSOL conversion ratio + APY breakdown). */
18
- export type BSOL_STATS_API_RESPONSE = {
19
- success: boolean;
20
- stats?: {
21
- conversion: {
22
- bsol_to_sol: number;
23
- sol_to_bsol: number;
24
- };
25
- apy: {
26
- base: number;
27
- blze: number;
28
- total: number;
29
- lending: number;
30
- liquidity: number;
31
- };
32
- };
33
- };
34
-
35
- /** Response shape of SolBlaze's Velocity-specific lending emissions endpoint. */
36
- export type BSOL_EMISSIONS_API_RESPONSE = {
37
- success: boolean;
38
- emissions?: {
39
- lend: number;
40
- };
41
- };
42
-
43
- /**
44
- * Fetches bSOL conversion/APY stats from SolBlaze's public API.
45
- *
46
- * @return {Promise<Response>} The raw `fetch` response; caller must check `.status` and parse
47
- * JSON as `BSOL_STATS_API_RESPONSE`
48
- */
49
- export async function fetchBSolMetrics() {
50
- return await fetch('https://stake.solblaze.org/api/v1/stats');
51
- }
52
-
53
- /**
54
- * Fetches bSOL lending-emissions data specific to Velocity from SolBlaze's public API.
55
- *
56
- * @return {Promise<Response>} The raw `fetch` response; caller must check `.status` and parse
57
- * JSON as `BSOL_EMISSIONS_API_RESPONSE`
58
- */
59
- export async function fetchBSolVelocityEmissions() {
60
- return await fetch('https://stake.solblaze.org/api/v1/velocity_emissions');
61
- }
62
-
63
- /**
64
- * Dispatches to the correct "super-stake" (deposit SOL, swap to an LST, deposit the LST as
65
- * leveraged collateral) instruction builder for a given LST spot market, routing by the SDK's
66
- * hardcoded market-index constants: `2` (mSOL) uses Marinade-or-Jupiter (`findBestMSolSuperStakeIxs`),
67
- * `6` (JitoSOL) and `8` (a generic LST, e.g. bSOL) both use Jupiter-only routing.
68
- *
69
- * @param {object} params
70
- * @param {number} params.marketIndex - The LST spot market index; must be `2`, `6`, or `8`
71
- * @param {BN} params.amount - SOL amount to stake, `LAMPORTS_PRECISION` (1e9)
72
- * @param {JupiterClient} params.jupiterClient - Jupiter aggregator client for swap routing
73
- * @param {VelocityClient} params.velocityClient - Velocity client (for market accounts + instruction building)
74
- * @param {PublicKey} [params.userAccountPublicKey] - The target sub-account; defaults to the
75
- * client's active sub-account if omitted
76
- * @param {number} [params.price] - Pre-fetched mSOL/SOL price (market index 2 only); fetched from
77
- * Marinade if omitted
78
- * @param {boolean} [params.forceMarinade] - Force the direct Marinade stake path over a Jupiter
79
- * swap even if Jupiter would be cheaper (market index 2 only)
80
- * @param {boolean} [params.onlyDirectRoutes] - Restrict Jupiter routing to direct swaps only
81
- * @param {QuoteResponse} [params.jupiterQuote] - A pre-fetched Jupiter quote to reuse instead of
82
- * fetching a fresh one
83
- * @return {Promise<{ ixs: TransactionInstruction[]; lookupTables: AddressLookupTableAccount[];
84
- * method: 'jupiter' | 'marinade'; price?: number }>} The instructions to submit, any address
85
- * lookup tables they require, which routing method was chosen, and (market index 2 only) the
86
- * price used for the routing decision
87
- * @throws {Error} If `marketIndex` is not one of the supported LST markets
88
- */
89
- export async function findBestSuperStakeIxs({
90
- marketIndex,
91
- amount,
92
- jupiterClient,
93
- velocityClient,
94
- userAccountPublicKey,
95
- price,
96
- forceMarinade,
97
- onlyDirectRoutes,
98
- jupiterQuote,
99
- }: {
100
- marketIndex: number;
101
- amount: BN;
102
- jupiterClient: JupiterClient;
103
- velocityClient: VelocityClient;
104
- price?: number;
105
- userAccountPublicKey?: PublicKey;
106
- forceMarinade?: boolean;
107
- onlyDirectRoutes?: boolean;
108
- jupiterQuote?: QuoteResponse;
109
- }): Promise<{
110
- ixs: TransactionInstruction[];
111
- lookupTables: AddressLookupTableAccount[];
112
- method: 'jupiter' | 'marinade';
113
- price?: number;
114
- }> {
115
- if (marketIndex === 2) {
116
- return findBestMSolSuperStakeIxs({
117
- amount,
118
- jupiterClient,
119
- velocityClient,
120
- userAccountPublicKey,
121
- price,
122
- forceMarinade,
123
- onlyDirectRoutes,
124
- jupiterQuote,
125
- });
126
- } else if (marketIndex === 6) {
127
- return findBestJitoSolSuperStakeIxs({
128
- amount,
129
- jupiterClient,
130
- velocityClient,
131
- userAccountPublicKey,
132
- onlyDirectRoutes,
133
- jupiterQuote,
134
- });
135
- } else if (marketIndex === 8) {
136
- return findBestLstSuperStakeIxs({
137
- amount,
138
- lstMint: velocityClient.getSpotMarketAccountOrThrow(8).mint,
139
- lstMarketIndex: 8,
140
- jupiterClient,
141
- velocityClient,
142
- userAccountPublicKey,
143
- onlyDirectRoutes,
144
- jupiterQuote,
145
- });
146
- } else {
147
- throw new Error(`Unsupported superstake market index: ${marketIndex}`);
148
- }
149
- }
150
-
151
- /**
152
- * Chooses between staking SOL directly with Marinade (mint mSOL 1:1 at the protocol rate) or
153
- * swapping SOL for mSOL via Jupiter, whichever is cheaper for the user, then returns the
154
- * resulting deposit instructions. Marinade is chosen when its price is lower than (i.e. gives
155
- * more mSOL per SOL than) the best Jupiter quote, when `forceMarinade` is set, or when a Jupiter
156
- * quote couldn't be obtained.
157
- *
158
- * @param {object} params
159
- * @param {BN} params.amount - SOL amount to stake, `LAMPORTS_PRECISION` (1e9)
160
- * @param {JupiterClient} params.jupiterClient - Jupiter aggregator client
161
- * @param {VelocityClient} params.velocityClient - Velocity client
162
- * @param {number} [params.price] - Pre-fetched mSOL/SOL Marinade rate; fetched live if omitted
163
- * @param {PublicKey} [params.userAccountPublicKey] - The target sub-account
164
- * @param {boolean} [params.forceMarinade] - Force the Marinade path regardless of Jupiter pricing
165
- * @param {boolean} [params.onlyDirectRoutes] - Restrict Jupiter routing to direct swaps only
166
- * @param {QuoteResponse} [params.jupiterQuote] - A pre-fetched Jupiter quote to reuse
167
- * @return {Promise<{ ixs: TransactionInstruction[]; lookupTables: AddressLookupTableAccount[];
168
- * method: 'jupiter' | 'marinade'; price: number }>} The chosen route's instructions, required
169
- * lookup tables, the method used, and the mSOL/SOL price used for the decision
170
- */
171
- export async function findBestMSolSuperStakeIxs({
172
- amount,
173
- jupiterClient,
174
- velocityClient,
175
- userAccountPublicKey,
176
- price,
177
- forceMarinade,
178
- onlyDirectRoutes,
179
- jupiterQuote,
180
- }: {
181
- amount: BN;
182
- jupiterClient: JupiterClient;
183
- velocityClient: VelocityClient;
184
- price?: number;
185
- userAccountPublicKey?: PublicKey;
186
- forceMarinade?: boolean;
187
- onlyDirectRoutes?: boolean;
188
- jupiterQuote?: QuoteResponse;
189
- }): Promise<{
190
- ixs: TransactionInstruction[];
191
- lookupTables: AddressLookupTableAccount[];
192
- method: 'jupiter' | 'marinade';
193
- price: number;
194
- }> {
195
- if (!price) {
196
- const marinadeProgram = getMarinadeFinanceProgram(velocityClient.provider);
197
- price = await getMarinadeMSolPrice(marinadeProgram);
198
- }
199
-
200
- const solSpotMarketAccount = velocityClient.getSpotMarketAccountOrThrow(1);
201
- const mSolSpotMarketAccount = velocityClient.getSpotMarketAccountOrThrow(2);
202
-
203
- let jupiterPrice: number | undefined;
204
- let quote = jupiterQuote;
205
- if (!jupiterQuote) {
206
- try {
207
- const fetchedQuote = await jupiterClient.getQuote({
208
- inputMint: solSpotMarketAccount.mint,
209
- outputMint: mSolSpotMarketAccount.mint,
210
- amount,
211
- slippageBps: 1000,
212
- onlyDirectRoutes,
213
- });
214
-
215
- jupiterPrice = +fetchedQuote.outAmount / +fetchedQuote.inAmount;
216
-
217
- quote = fetchedQuote;
218
- } catch (e) {
219
- console.error('Error getting jupiter price', e);
220
- }
221
- }
222
-
223
- if (!jupiterPrice || price <= jupiterPrice || forceMarinade) {
224
- const ixs = await velocityClient.getStakeForMSOLIx({
225
- amount,
226
- userAccountPublicKey,
227
- });
228
- return {
229
- method: 'marinade',
230
- ixs,
231
- lookupTables: [],
232
- price: price,
233
- };
234
- } else {
235
- const { ixs, lookupTables } = await velocityClient.getJupiterSwapIxV6({
236
- inMarketIndex: 1,
237
- outMarketIndex: 2,
238
- jupiterClient,
239
- amount,
240
- userAccountPublicKey,
241
- onlyDirectRoutes,
242
- quote,
243
- });
244
- return {
245
- method: 'jupiter',
246
- ixs,
247
- lookupTables,
248
- price: jupiterPrice,
249
- };
250
- }
251
- }
252
-
253
- /**
254
- * Builds instructions to super-stake into JitoSOL (spot market index `6`) by swapping SOL for
255
- * JitoSOL via Jupiter. Thin wrapper around `findBestLstSuperStakeIxs`.
256
- *
257
- * @param {object} params
258
- * @param {BN} params.amount - SOL amount to stake, `LAMPORTS_PRECISION` (1e9)
259
- * @param {JupiterClient} params.jupiterClient - Jupiter aggregator client
260
- * @param {VelocityClient} params.velocityClient - Velocity client
261
- * @param {PublicKey} [params.userAccountPublicKey] - The target sub-account
262
- * @param {boolean} [params.onlyDirectRoutes] - Restrict Jupiter routing to direct swaps only
263
- * @param {QuoteResponse} [params.jupiterQuote] - A pre-fetched Jupiter quote to reuse
264
- * @return {Promise<{ ixs: TransactionInstruction[]; lookupTables: AddressLookupTableAccount[];
265
- * method: 'jupiter' | 'marinade'; price?: number }>} Always resolves with `method: 'jupiter'`
266
- */
267
- export async function findBestJitoSolSuperStakeIxs({
268
- amount,
269
- jupiterClient,
270
- velocityClient,
271
- userAccountPublicKey,
272
- onlyDirectRoutes,
273
- jupiterQuote,
274
- }: {
275
- amount: BN;
276
- jupiterClient: JupiterClient;
277
- velocityClient: VelocityClient;
278
- userAccountPublicKey?: PublicKey;
279
- onlyDirectRoutes?: boolean;
280
- jupiterQuote?: QuoteResponse;
281
- }): Promise<{
282
- ixs: TransactionInstruction[];
283
- lookupTables: AddressLookupTableAccount[];
284
- method: 'jupiter' | 'marinade';
285
- price?: number;
286
- }> {
287
- return await findBestLstSuperStakeIxs({
288
- amount,
289
- jupiterClient,
290
- velocityClient,
291
- userAccountPublicKey,
292
- onlyDirectRoutes,
293
- lstMint: velocityClient.getSpotMarketAccountOrThrow(6).mint,
294
- lstMarketIndex: 6,
295
- jupiterQuote,
296
- });
297
- }
298
-
299
- /**
300
- * Builds instructions to super-stake into an arbitrary LST via a Jupiter swap from SOL. Unlike
301
- * `findBestMSolSuperStakeIxs`, this does not compare against a direct-stake rate with the LST's
302
- * own protocol — it always routes through Jupiter.
303
- *
304
- * @param {object} params
305
- * @param {BN} params.amount - SOL amount to stake, `LAMPORTS_PRECISION` (1e9)
306
- * @param {PublicKey} params.lstMint - The target LST's mint (unused directly here; kept for
307
- * caller symmetry with `lstMarketIndex`)
308
- * @param {number} params.lstMarketIndex - The target LST's spot market index
309
- * @param {JupiterClient} params.jupiterClient - Jupiter aggregator client
310
- * @param {VelocityClient} params.velocityClient - Velocity client
311
- * @param {PublicKey} [params.userAccountPublicKey] - The target sub-account
312
- * @param {boolean} [params.onlyDirectRoutes] - Restrict Jupiter routing to direct swaps only
313
- * @param {QuoteResponse} [params.jupiterQuote] - A pre-fetched Jupiter quote to reuse
314
- * @return {Promise<{ ixs: TransactionInstruction[]; lookupTables: AddressLookupTableAccount[];
315
- * method: 'jupiter' | 'marinade' }>} Always resolves with `method: 'jupiter'`
316
- */
317
- export async function findBestLstSuperStakeIxs({
318
- amount,
319
- jupiterClient,
320
- velocityClient,
321
- userAccountPublicKey,
322
- onlyDirectRoutes,
323
- lstMarketIndex,
324
- jupiterQuote,
325
- }: {
326
- amount: BN;
327
- lstMint: PublicKey;
328
- lstMarketIndex: number;
329
- jupiterClient: JupiterClient;
330
- velocityClient: VelocityClient;
331
- userAccountPublicKey?: PublicKey;
332
- onlyDirectRoutes?: boolean;
333
- jupiterQuote?: QuoteResponse;
334
- }): Promise<{
335
- ixs: TransactionInstruction[];
336
- lookupTables: AddressLookupTableAccount[];
337
- method: 'jupiter' | 'marinade';
338
- }> {
339
- const { ixs, lookupTables } = await velocityClient.getJupiterSwapIxV6({
340
- inMarketIndex: 1,
341
- outMarketIndex: lstMarketIndex,
342
- jupiterClient,
343
- amount,
344
- userAccountPublicKey,
345
- onlyDirectRoutes,
346
- quote: jupiterQuote,
347
- });
348
- return {
349
- method: 'jupiter',
350
- ixs,
351
- lookupTables,
352
- // price: jupiterPrice,
353
- };
354
- }
355
-
356
- /** Response shape of Jito's `stake_pool_stats` endpoint: daily TVL, jitoSOL supply, and APY series. */
357
- export type JITO_SOL_METRICS_ENDPOINT_RESPONSE = {
358
- tvl: {
359
- // TVL in SOL, BN
360
- data: number;
361
- date: string;
362
- }[];
363
- supply: {
364
- // jitoSOL supply
365
- data: number;
366
- date: string;
367
- }[];
368
- apy: {
369
- data: number;
370
- date: string;
371
- }[];
372
- };
373
-
374
- /**
375
- * Removes hours, minutes, seconds from a date, and returns the ISO string value (with milliseconds trimmed from the output (required by Jito API))
376
- * @param inDate
377
- * @returns
378
- */
379
- const getNormalizedDateString = (inDate: Date) => {
380
- const date = new Date(inDate.getTime());
381
- date.setUTCHours(0, 0, 0, 0);
382
- return date.toISOString().slice(0, 19) + 'Z';
383
- };
384
-
385
- const get30DAgo = () => {
386
- const date = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
387
- return date;
388
- };
389
-
390
- /**
391
- * Fetches daily jitoSOL TVL/supply/APY stats for the trailing 30 days from Jito's public API.
392
- *
393
- * @return {Promise<JITO_SOL_METRICS_ENDPOINT_RESPONSE>} The parsed JSON response
394
- */
395
- export async function fetchJitoSolMetrics() {
396
- const res = await fetch(
397
- 'https://kobe.mainnet.jito.network/api/v1/stake_pool_stats',
398
- {
399
- headers: {
400
- 'Content-Type': 'application/json',
401
- },
402
- body: JSON.stringify({
403
- bucket_type: 'Daily',
404
- range_filter: {
405
- start: getNormalizedDateString(get30DAgo()),
406
- end: getNormalizedDateString(new Date()),
407
- },
408
- sort_by: {
409
- order: 'Asc',
410
- field: 'BlockTime',
411
- },
412
- }),
413
- method: 'POST',
414
- }
415
- );
416
-
417
- const data: JITO_SOL_METRICS_ENDPOINT_RESPONSE = await res.json();
418
-
419
- return data;
420
- }
421
-
422
- const getJitoSolHistoricalPriceMap = async (timestamps: number[]) => {
423
- try {
424
- const data = await fetchJitoSolMetrics();
425
- const jitoSolHistoricalPriceMap = new Map<number, number>();
426
- const jitoSolHistoricalPriceInSol = [];
427
-
428
- for (let i = 0; i < data.supply.length; i++) {
429
- const priceInSol = data.tvl[i].data / 10 ** 9 / data.supply[i].data;
430
- jitoSolHistoricalPriceInSol.push({
431
- price: priceInSol,
432
- ts: data.tvl[i].date,
433
- });
434
- }
435
-
436
- for (const timestamp of timestamps) {
437
- const date = new Date(timestamp * 1000);
438
- const dateString = date.toISOString();
439
-
440
- const price = jitoSolHistoricalPriceInSol.find((p) =>
441
- checkSameDate(p.ts, dateString)
442
- );
443
-
444
- if (price) {
445
- jitoSolHistoricalPriceMap.set(timestamp, price.price);
446
- }
447
- }
448
-
449
- return jitoSolHistoricalPriceMap;
450
- } catch (err) {
451
- console.error(err);
452
- return undefined;
453
- }
454
- };
455
-
456
- /**
457
- * Estimates net SOL earned (or lost) from super-staking a given LST market over the user's full
458
- * deposit history, by converting every historical SOL and LST deposit/withdrawal record to a SOL
459
- * value at the LST/SOL ratio effective at that record's timestamp, then adding back the current
460
- * SOL-value of the user's present SOL and LST balances. Requires third-party price history APIs
461
- * per LST (Marinade for mSOL, Jito's stake pool stats for JitoSOL, SolBlaze's current-only rate
462
- * for bSOL — bSOL therefore uses one flat ratio for all historical records, not a true history).
463
- *
464
- * @param {object} params
465
- * @param {number} params.marketIndex - The LST spot market index (`2` mSOL, `6` JitoSOL, `8` bSOL)
466
- * @param {User} params.user - The user account to read current SOL/LST balances from
467
- * @param {DepositRecord[]} params.depositRecords - The user's historical deposit/withdraw records
468
- * across the SOL market (index `1`) and the LST market
469
- * @return {Promise<BN>} Estimated net SOL earned, `LAMPORTS_PRECISION` (1e9); can be negative
470
- * @throws {Error} If an LST/SOL ratio can't be resolved for a record's timestamp (or for "now")
471
- */
472
- export async function calculateSolEarned({
473
- marketIndex,
474
- user,
475
- depositRecords,
476
- }: {
477
- marketIndex: number;
478
- user: User;
479
- depositRecords: DepositRecord[];
480
- }): Promise<BN> {
481
- const now = Date.now() / 1000;
482
- const timestamps: number[] = [
483
- now,
484
- ...depositRecords
485
- .filter((r) => r.marketIndex === marketIndex)
486
- .map((r) => r.ts.toNumber()),
487
- ];
488
-
489
- let lstRatios = new Map<number, number>();
490
-
491
- const getMsolPrice = async (timestamp: number) => {
492
- const date = new Date(timestamp * 1000); // Convert Unix timestamp to milliseconds
493
- const swaggerApiDateTime = date.toISOString(); // Format date as swagger API date-time
494
- const url = `https://api.marinade.finance/msol/price_sol?time=${swaggerApiDateTime}`;
495
- const response = await fetch(url);
496
- if (response.status === 200) {
497
- const data = await response.json();
498
- lstRatios.set(timestamp, data);
499
- }
500
- };
501
-
502
- const getBSolPrice = async (timestamps: number[]) => {
503
- // Currently there's only one bSOL price, no timestamped data
504
- // So just use the same price for every timestamp for now
505
- const response = await fetchBSolMetrics();
506
- if (response.status === 200) {
507
- const data = (await response.json()) as BSOL_STATS_API_RESPONSE;
508
- const bSolRatio = data?.stats?.conversion?.bsol_to_sol;
509
- if (bSolRatio) {
510
- timestamps.forEach((timestamp) => lstRatios.set(timestamp, bSolRatio));
511
- }
512
- }
513
- };
514
-
515
- // This block kind of assumes the record are all from the same market
516
- // Otherwise the following code that checks the record.marketIndex would break
517
- if (marketIndex === 2) {
518
- await Promise.all(timestamps.map(getMsolPrice));
519
- } else if (marketIndex === 6) {
520
- const jitoSolRatios = await getJitoSolHistoricalPriceMap(timestamps);
521
- if (jitoSolRatios) {
522
- lstRatios = jitoSolRatios;
523
- }
524
- } else if (marketIndex === 8) {
525
- await getBSolPrice(timestamps);
526
- }
527
-
528
- let solEarned = ZERO;
529
- for (const record of depositRecords) {
530
- if (record.marketIndex === 1) {
531
- if (isVariant(record.direction, 'deposit')) {
532
- solEarned = solEarned.sub(record.amount);
533
- } else {
534
- solEarned = solEarned.add(record.amount);
535
- }
536
- } else if (
537
- record.marketIndex === 2 ||
538
- record.marketIndex === 6 ||
539
- record.marketIndex === 8
540
- ) {
541
- const lstRatio = lstRatios.get(record.ts.toNumber());
542
- if (lstRatio === undefined) {
543
- throw new Error(
544
- `Missing LST/SOL ratio for deposit record at timestamp ${record.ts.toNumber()}`
545
- );
546
- }
547
- const lstRatioBN = new BN(lstRatio * LAMPORTS_PER_SOL);
548
-
549
- const solAmount = record.amount.mul(lstRatioBN).div(LAMPORTS_PRECISION);
550
- if (isVariant(record.direction, 'deposit')) {
551
- solEarned = solEarned.sub(solAmount);
552
- } else {
553
- solEarned = solEarned.add(solAmount);
554
- }
555
- }
556
- }
557
-
558
- const currentLstTokenAmount = await user.getTokenAmount(marketIndex);
559
- const currentLstRatio = lstRatios.get(now);
560
- if (currentLstRatio === undefined) {
561
- throw new Error(`Missing current LST/SOL ratio for timestamp ${now}`);
562
- }
563
- const currentLstRatioBN = new BN(currentLstRatio * LAMPORTS_PER_SOL);
564
-
565
- solEarned = solEarned.add(
566
- currentLstTokenAmount.mul(currentLstRatioBN).div(LAMPORTS_PRECISION)
567
- );
568
-
569
- const currentSOLTokenAmount = await user.getTokenAmount(1);
570
- solEarned = solEarned.add(currentSOLTokenAmount);
571
-
572
- return solEarned;
573
- }
574
-
575
- /**
576
- * Estimates the LST/SOL price at which a super-staked (leveraged LST-collateral, SOL-borrow)
577
- * position would hit maintenance margin and become liquidatable: the price where
578
- * `lstMaintenanceAssetWeight * lstDepositAmount * price === solMaintenanceLiabilityWeight * solBorrowAmount`.
579
- * All inputs are plain (unscaled) numbers, not `BN` — weights are expected as fractions (e.g.
580
- * `0.8` for 80%, i.e. already divided by `SPOT_MARKET_WEIGHT_PRECISION`), and this is a
581
- * float-precision estimate for UI display, not a program-exact calculation.
582
- *
583
- * @param {number} lstDepositAmount - LST collateral amount, in whole LST tokens
584
- * @param {number} lstMaintenanceAssetWeight - The LST market's maintenance asset weight, as a fraction
585
- * @param {number} solBorrowAmount - SOL borrow amount, in whole SOL
586
- * @param {number} solMaintenanceLiabilityWeight - The SOL market's maintenance liability weight, as a fraction
587
- * @param {number} lstPriceRatio - Current LST/SOL price ratio
588
- * @return {number} Estimated liquidation LST/SOL price
589
- */
590
- export function calculateEstimatedSuperStakeLiquidationPrice(
591
- lstDepositAmount: number,
592
- lstMaintenanceAssetWeight: number,
593
- solBorrowAmount: number,
594
- solMaintenanceLiabilityWeight: number,
595
- lstPriceRatio: number
596
- ): number {
597
- const liquidationDivergence =
598
- (solMaintenanceLiabilityWeight * solBorrowAmount) /
599
- (lstMaintenanceAssetWeight * lstDepositAmount * lstPriceRatio);
600
- const liquidationPrice = lstPriceRatio * liquidationDivergence;
601
- return liquidationPrice;
602
- }
package/src/math/tiers.ts DELETED
@@ -1,73 +0,0 @@
1
- import { isVariant, PerpMarketAccount, SpotMarketAccount } from '../types';
2
-
3
- /**
4
- * Maps a perp market's `contractTier` to an ordinal safety rank, lower is safer. Matches the
5
- * declaration order of the Rust `ContractTier` enum (which derives `Ord` from declaration order,
6
- * used by `ContractTier::is_as_safe_as_contract`'s `self <= other`).
7
- *
8
- * @param {PerpMarketAccount} perpMarket - The perp market account
9
- * @return {number} `0` (A, safest) through `5` (Isolated, riskiest); `4` = HighlySpeculative
10
- */
11
- export function getPerpMarketTierNumber(perpMarket: PerpMarketAccount): number {
12
- if (isVariant(perpMarket.contractTier, 'a')) {
13
- return 0;
14
- } else if (isVariant(perpMarket.contractTier, 'b')) {
15
- return 1;
16
- } else if (isVariant(perpMarket.contractTier, 'c')) {
17
- return 2;
18
- } else if (isVariant(perpMarket.contractTier, 'speculative')) {
19
- return 3;
20
- } else if (isVariant(perpMarket.contractTier, 'highlySpeculative')) {
21
- return 4;
22
- } else {
23
- return 5;
24
- }
25
- }
26
-
27
- /**
28
- * Maps a spot market's `assetTier` to an ordinal safety rank, lower is safer. Matches the
29
- * declaration order of the Rust `AssetTier` enum, used by `ContractTier::is_as_safe_as_asset`.
30
- *
31
- * @param {SpotMarketAccount} spotMarket - The spot market account
32
- * @return {number} `0` (Collateral, safest) through `4` (Unlisted, riskiest); `5` is unreachable
33
- * (falls through only if `assetTier` matches none of the known variants)
34
- */
35
- export function getSpotMarketTierNumber(spotMarket: SpotMarketAccount): number {
36
- if (isVariant(spotMarket.assetTier, 'collateral')) {
37
- return 0;
38
- } else if (isVariant(spotMarket.assetTier, 'protected')) {
39
- return 1;
40
- } else if (isVariant(spotMarket.assetTier, 'cross')) {
41
- return 2;
42
- } else if (isVariant(spotMarket.assetTier, 'isolated')) {
43
- return 3;
44
- } else if (isVariant(spotMarket.assetTier, 'unlisted')) {
45
- return 4;
46
- } else {
47
- return 5;
48
- }
49
- }
50
-
51
- /**
52
- * True if a perp market's tier is at least as safe as both a reference perp tier and a reference
53
- * spot tier, mirroring `ContractTier::is_as_safe_as`. Used to gate cross-margining: a position in
54
- * a market riskier than the account's other collateral/positions can force isolated margin.
55
- * A perp tier is "as safe as" a spot tier if the spot tier is Unlisted (anything beats Unlisted);
56
- * otherwise, if the spot tier is Cross or Isolated, the perp tier must be C-or-safer (tiers 0-2).
57
- *
58
- * @param {number} perpTier - This market's tier number, from `getPerpMarketTierNumber`
59
- * @param {number} otherPerpTier - The reference perp tier number to compare against
60
- * @param {number} otherSpotTier - The reference spot tier number to compare against, from
61
- * `getSpotMarketTierNumber`
62
- * @return {boolean} Whether `perpTier` is as safe as both references
63
- */
64
- export function perpTierIsAsSafeAs(
65
- perpTier: number,
66
- otherPerpTier: number,
67
- otherSpotTier: number
68
- ): boolean {
69
- const asSafeAsPerp = perpTier <= otherPerpTier;
70
- const asSafeAsSpot =
71
- otherSpotTier === 4 || (otherSpotTier >= 2 && perpTier <= 2);
72
- return asSafeAsSpot && asSafeAsPerp;
73
- }