@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.
- package/README.md +3 -3
- package/lib/browser/adminClient.d.ts +52 -0
- package/lib/browser/adminClient.js +97 -0
- package/lib/browser/config.js +6 -7
- package/lib/browser/constants/numericConstants.d.ts +1 -1
- package/lib/browser/constants/numericConstants.js +1 -1
- package/lib/browser/decode/user.js +5 -1
- package/lib/browser/idl/velocity.d.ts +191 -15
- package/lib/browser/idl/velocity.json +192 -16
- package/lib/browser/orderSubscriber/OrderSubscriber.d.ts +1 -0
- package/lib/browser/orderSubscriber/OrderSubscriber.js +10 -4
- package/lib/browser/pyth/pythLazerSubscriber.js +37 -27
- package/lib/browser/types.d.ts +6 -0
- package/lib/browser/user.d.ts +20 -3
- package/lib/browser/user.js +52 -4
- package/lib/browser/velocityClient.d.ts +46 -10
- package/lib/browser/velocityClient.js +107 -35
- package/lib/node/adminClient.d.ts +52 -0
- package/lib/node/adminClient.d.ts.map +1 -1
- package/lib/node/adminClient.js +97 -0
- package/lib/node/config.d.ts.map +1 -1
- package/lib/node/config.js +6 -7
- package/lib/node/constants/numericConstants.d.ts +1 -1
- package/lib/node/constants/numericConstants.d.ts.map +1 -1
- package/lib/node/constants/numericConstants.js +1 -1
- package/lib/node/decode/user.d.ts.map +1 -1
- package/lib/node/decode/user.js +5 -1
- package/lib/node/idl/velocity.d.ts +191 -15
- package/lib/node/idl/velocity.d.ts.map +1 -1
- package/lib/node/idl/velocity.json +192 -16
- package/lib/node/orderSubscriber/OrderSubscriber.d.ts +1 -0
- package/lib/node/orderSubscriber/OrderSubscriber.d.ts.map +1 -1
- package/lib/node/orderSubscriber/OrderSubscriber.js +10 -4
- package/lib/node/pyth/pythLazerSubscriber.d.ts.map +1 -1
- package/lib/node/pyth/pythLazerSubscriber.js +37 -27
- package/lib/node/types.d.ts +6 -0
- package/lib/node/types.d.ts.map +1 -1
- package/lib/node/user.d.ts +20 -3
- package/lib/node/user.d.ts.map +1 -1
- package/lib/node/user.js +52 -4
- package/lib/node/velocityClient.d.ts +46 -10
- package/lib/node/velocityClient.d.ts.map +1 -1
- package/lib/node/velocityClient.js +107 -35
- package/package.json +7 -3
- package/.prettierignore +0 -1
- package/CHANGELOG.md +0 -132
- package/build-browser.js +0 -58
- package/bunfig.toml +0 -3
- package/esbuild-shims.js +0 -12
- package/scripts/deposit-isolated-positions.ts +0 -110
- package/scripts/find-flagged-users.ts +0 -213
- package/scripts/grpc-client-test-comparison.ts +0 -372
- package/scripts/grpc-multiuser-client-test-comparison.ts +0 -158
- package/scripts/postbuild.js +0 -95
- package/scripts/single-grpc-client-test.ts +0 -284
- package/scripts/withdraw-isolated-positions.ts +0 -174
- package/src/accounts/README_WebSocketAccountSubscriberV2.md +0 -95
- package/src/accounts/README_WebSocketProgramAccountSubscriberV2.md +0 -135
- package/src/accounts/basicUserAccountSubscriber.ts +0 -79
- package/src/accounts/basicUserStatsAccountSubscriber.ts +0 -87
- package/src/accounts/bulkAccountLoader.ts +0 -358
- package/src/accounts/bulkUserStatsSubscription.ts +0 -40
- package/src/accounts/bulkUserSubscription.ts +0 -39
- package/src/accounts/customizedCadenceBulkAccountLoader.ts +0 -250
- package/src/accounts/fetch.ts +0 -200
- package/src/accounts/grpcAccountSubscriber.ts +0 -225
- package/src/accounts/grpcInsuranceFundStakeAccountSubscriber.ts +0 -73
- package/src/accounts/grpcMultiAccountSubscriber.ts +0 -566
- package/src/accounts/grpcMultiUserAccountSubscriber.ts +0 -328
- package/src/accounts/grpcProgramAccountSubscriber.ts +0 -264
- package/src/accounts/grpcUserAccountSubscriber.ts +0 -63
- package/src/accounts/grpcUserStatsAccountSubscriber.ts +0 -65
- package/src/accounts/grpcVelocityClientAccountSubscriber.ts +0 -257
- package/src/accounts/grpcVelocityClientAccountSubscriberV2.ts +0 -941
- package/src/accounts/laserProgramAccountSubscriber.ts +0 -266
- package/src/accounts/oneShotUserAccountSubscriber.ts +0 -88
- package/src/accounts/oneShotUserStatsAccountSubscriber.ts +0 -94
- package/src/accounts/pollingInsuranceFundStakeAccountSubscriber.ts +0 -223
- package/src/accounts/pollingOracleAccountSubscriber.ts +0 -151
- package/src/accounts/pollingTokenAccountSubscriber.ts +0 -147
- package/src/accounts/pollingUserAccountSubscriber.ts +0 -198
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +0 -180
- package/src/accounts/pollingVelocityClientAccountSubscriber.ts +0 -774
- package/src/accounts/testBulkAccountLoader.ts +0 -59
- package/src/accounts/types.ts +0 -428
- package/src/accounts/utils.ts +0 -90
- package/src/accounts/webSocketAccountSubscriber.ts +0 -304
- package/src/accounts/webSocketAccountSubscriberV2.ts +0 -536
- package/src/accounts/webSocketInsuranceFundStakeAccountSubscriber.ts +0 -171
- package/src/accounts/webSocketProgramAccountSubscriber.ts +0 -244
- package/src/accounts/webSocketProgramAccountSubscriberV2.ts +0 -1048
- package/src/accounts/webSocketProgramAccountsSubscriberV2.ts +0 -1042
- package/src/accounts/webSocketUserAccountSubscriber.ts +0 -139
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +0 -131
- package/src/accounts/webSocketVelocityClientAccountSubscriber.ts +0 -865
- package/src/accounts/webSocketVelocityClientAccountSubscriberV2.ts +0 -897
- package/src/accounts/websocketProgramUserAccountSubscriber.ts +0 -127
- package/src/addresses/marketAddresses.ts +0 -28
- package/src/addresses/pda.ts +0 -620
- package/src/adminClient.ts +0 -8136
- package/src/assert/assert.ts +0 -5
- package/src/auctionSubscriber/auctionSubscriber.ts +0 -86
- package/src/auctionSubscriber/auctionSubscriberGrpc.ts +0 -99
- package/src/auctionSubscriber/index.ts +0 -9
- package/src/auctionSubscriber/types.ts +0 -30
- package/src/bankrun/bankrunConnection.ts +0 -630
- package/src/blockhashSubscriber/BlockhashSubscriber.ts +0 -160
- package/src/blockhashSubscriber/index.ts +0 -6
- package/src/blockhashSubscriber/types.ts +0 -13
- package/src/clock/clockSubscriber.ts +0 -146
- package/src/config.ts +0 -312
- package/src/constants/index.ts +0 -9
- package/src/constants/numericConstants.ts +0 -194
- package/src/constants/perpMarkets.ts +0 -127
- package/src/constants/spotMarkets.ts +0 -104
- package/src/constants/txConstants.ts +0 -2
- package/src/constituentMap/constituentMap.ts +0 -305
- package/src/constituentMap/pollingConstituentAccountSubscriber.ts +0 -99
- package/src/constituentMap/webSocketConstituentAccountSubscriber.ts +0 -121
- package/src/core/VelocityCore.ts +0 -606
- package/src/core/index.ts +0 -12
- package/src/core/instructions/deposit.ts +0 -64
- package/src/core/instructions/fill.ts +0 -51
- package/src/core/instructions/funding.ts +0 -33
- package/src/core/instructions/liquidation.ts +0 -55
- package/src/core/instructions/orders.ts +0 -84
- package/src/core/instructions/perpOrders.ts +0 -312
- package/src/core/instructions/settlement.ts +0 -40
- package/src/core/instructions/trigger.ts +0 -41
- package/src/core/instructions/withdraw.ts +0 -65
- package/src/core/remainingAccounts.ts +0 -320
- package/src/core/signedMsg.ts +0 -109
- package/src/decode/customCoder.ts +0 -148
- package/src/decode/user.ts +0 -401
- package/src/dlob/DLOB.ts +0 -2793
- package/src/dlob/DLOBNode.ts +0 -305
- package/src/dlob/DLOBSubscriber.ts +0 -269
- package/src/dlob/NodeList.ts +0 -244
- package/src/dlob/orderBookLevels.ts +0 -695
- package/src/dlob/types.ts +0 -37
- package/src/events/eventList.ts +0 -114
- package/src/events/eventSubscriber.ts +0 -521
- package/src/events/eventsServerLogProvider.ts +0 -189
- package/src/events/fetchLogs.ts +0 -219
- package/src/events/parse.ts +0 -271
- package/src/events/pollingLogProvider.ts +0 -113
- package/src/events/sort.ts +0 -51
- package/src/events/txEventCache.ts +0 -92
- package/src/events/types.ts +0 -337
- package/src/events/webSocketLogProvider.ts +0 -152
- package/src/factory/bigNum.ts +0 -709
- package/src/factory/oracleClient.ts +0 -73
- package/src/idl/pyth.json +0 -142
- package/src/idl/pyth.ts +0 -97
- package/src/idl/pyth_solana_receiver.json +0 -628
- package/src/idl/token_faucet.json +0 -229
- package/src/idl/token_faucet.ts +0 -197
- package/src/idl/velocity.json +0 -23974
- package/src/idl/velocity.ts +0 -23980
- package/src/index.ts +0 -150
- package/src/indicative-quotes/indicativeQuotesSender.ts +0 -233
- package/src/isomorphic/README.md +0 -19
- package/src/isomorphic/anchor.browser.ts +0 -44
- package/src/isomorphic/anchor.node.ts +0 -1
- package/src/isomorphic/anchor.ts +0 -1
- package/src/isomorphic/anchor29.browser.ts +0 -24
- package/src/isomorphic/anchor29.node.ts +0 -1
- package/src/isomorphic/anchor29.ts +0 -1
- package/src/isomorphic/grpc.browser.ts +0 -4
- package/src/isomorphic/grpc.node.ts +0 -130
- package/src/isomorphic/grpc.ts +0 -1
- package/src/jupiter/jupiterClient.ts +0 -502
- package/src/keypair.ts +0 -32
- package/src/margin/README.md +0 -138
- package/src/marginCalculation.ts +0 -407
- package/src/marinade/idl/idl.json +0 -1962
- package/src/marinade/index.ts +0 -73
- package/src/marinade/types.ts +0 -3925
- package/src/math/amm.ts +0 -1758
- package/src/math/auction.ts +0 -480
- package/src/math/bankruptcy.ts +0 -138
- package/src/math/builder.ts +0 -130
- package/src/math/conversion.ts +0 -45
- package/src/math/exchangeStatus.ts +0 -261
- package/src/math/funding.ts +0 -498
- package/src/math/insurance.ts +0 -171
- package/src/math/liquidation.ts +0 -433
- package/src/math/margin.ts +0 -327
- package/src/math/market.ts +0 -487
- package/src/math/oracles.ts +0 -477
- package/src/math/orders.ts +0 -500
- package/src/math/position.ts +0 -381
- package/src/math/repeg.ts +0 -223
- package/src/math/spotBalance.ts +0 -996
- package/src/math/spotMarket.ts +0 -115
- package/src/math/spotPosition.ts +0 -263
- package/src/math/state.ts +0 -71
- package/src/math/superStake.ts +0 -602
- package/src/math/tiers.ts +0 -73
- package/src/math/trade.ts +0 -879
- package/src/math/utils.ts +0 -183
- package/src/memcmp.ts +0 -279
- package/src/oracles/oracleClientCache.ts +0 -41
- package/src/oracles/oracleId.ts +0 -99
- package/src/oracles/prelaunchOracleClient.ts +0 -63
- package/src/oracles/pythClient.ts +0 -125
- package/src/oracles/pythLazerClient.ts +0 -141
- package/src/oracles/quoteAssetOracleClient.ts +0 -43
- package/src/oracles/strictOraclePrice.ts +0 -40
- package/src/oracles/types.ts +0 -82
- package/src/oracles/utils.ts +0 -45
- package/src/orderParams.ts +0 -117
- package/src/orderSubscriber/OrderSubscriber.ts +0 -378
- package/src/orderSubscriber/PollingSubscription.ts +0 -50
- package/src/orderSubscriber/WebsocketSubscription.ts +0 -137
- package/src/orderSubscriber/grpcSubscription.ts +0 -155
- package/src/orderSubscriber/index.ts +0 -7
- package/src/orderSubscriber/types.ts +0 -64
- package/src/priorityFee/averageOverSlotsStrategy.ts +0 -17
- package/src/priorityFee/averageStrategy.ts +0 -13
- package/src/priorityFee/ewmaStrategy.ts +0 -51
- package/src/priorityFee/heliusPriorityFeeMethod.ts +0 -68
- package/src/priorityFee/index.ts +0 -16
- package/src/priorityFee/maxOverSlotsStrategy.ts +0 -18
- package/src/priorityFee/maxStrategy.ts +0 -8
- package/src/priorityFee/priorityFeeSubscriber.ts +0 -328
- package/src/priorityFee/priorityFeeSubscriberMap.ts +0 -134
- package/src/priorityFee/solanaPriorityFeeMethod.ts +0 -46
- package/src/priorityFee/types.ts +0 -82
- package/src/priorityFee/velocityPriorityFeeMethod.ts +0 -53
- package/src/pyth/constants.ts +0 -9
- package/src/pyth/index.ts +0 -15
- package/src/pyth/pythLazerSubscriber.ts +0 -365
- package/src/pyth/types.ts +0 -4451
- package/src/pyth/utils.ts +0 -13
- package/src/slot/SlotSubscriber.ts +0 -126
- package/src/slot/SlothashSubscriber.ts +0 -163
- package/src/swap/UnifiedSwapClient.ts +0 -315
- package/src/swift/grpcSignedMsgUserAccountSubscriber.ts +0 -81
- package/src/swift/index.ts +0 -10
- package/src/swift/signedMsgUserAccountSubscriber.ts +0 -251
- package/src/swift/swiftOrderSubscriber.ts +0 -351
- package/src/testClient.ts +0 -42
- package/src/titan/titanClient.ts +0 -438
- package/src/token/index.ts +0 -13
- package/src/tokenFaucet.ts +0 -296
- package/src/tx/baseTxSender.ts +0 -651
- package/src/tx/blockhashFetcher/baseBlockhashFetcher.ts +0 -31
- package/src/tx/blockhashFetcher/cachedBlockhashFetcher.ts +0 -105
- package/src/tx/blockhashFetcher/types.ts +0 -9
- package/src/tx/fastSingleTxSender.ts +0 -200
- package/src/tx/forwardOnlyTxSender.ts +0 -193
- package/src/tx/priorityFeeCalculator.ts +0 -117
- package/src/tx/reportTransactionError.ts +0 -176
- package/src/tx/retryTxSender.ts +0 -177
- package/src/tx/txHandler.ts +0 -1009
- package/src/tx/txParamProcessor.ts +0 -225
- package/src/tx/types.ts +0 -117
- package/src/tx/utils.ts +0 -133
- package/src/tx/whileValidTxSender.ts +0 -377
- package/src/types.ts +0 -2575
- package/src/user.ts +0 -5316
- package/src/userConfig.ts +0 -38
- package/src/userMap/PollingSubscription.ts +0 -61
- package/src/userMap/WebsocketSubscription.ts +0 -93
- package/src/userMap/grpcSubscription.ts +0 -93
- package/src/userMap/referrerMap.ts +0 -360
- package/src/userMap/revenueShareEscrowMap.ts +0 -342
- package/src/userMap/userMap.ts +0 -784
- package/src/userMap/userMapConfig.ts +0 -82
- package/src/userMap/userStatsMap.ts +0 -393
- package/src/userName.ts +0 -37
- package/src/userStats.ts +0 -159
- package/src/userStatsConfig.ts +0 -35
- package/src/util/TransactionConfirmationManager.ts +0 -333
- package/src/util/chainClock.ts +0 -65
- package/src/util/computeUnits.ts +0 -101
- package/src/util/digest.ts +0 -33
- package/src/util/ed25519Utils.ts +0 -95
- package/src/util/promiseTimeout.ts +0 -23
- package/src/velocityClient.ts +0 -14802
- package/src/velocityClientConfig.ts +0 -119
- package/src/wallet.ts +0 -91
- package/tests/VelocityCore/builder_escrow.test.ts +0 -121
- package/tests/VelocityCore/decode.test.ts +0 -16
- package/tests/VelocityCore/fill_trigger.test.ts +0 -73
- package/tests/VelocityCore/instructions.test.ts +0 -46
- package/tests/VelocityCore/pdas.test.ts +0 -30
- package/tests/VelocityCore/perp_orders.test.ts +0 -205
- package/tests/VelocityCore/remainingAccounts.test.ts +0 -72
- package/tests/VelocityCore/settlement_liquidation.test.ts +0 -69
- package/tests/accounts/customizedCadenceBulkAccountLoader.test.ts +0 -211
- package/tests/amm/test.ts +0 -2402
- package/tests/auctions/test.ts +0 -81
- package/tests/bn/test.ts +0 -355
- package/tests/builder/builderFee.test.ts +0 -42
- package/tests/ci/verifyConstants.ts +0 -393
- package/tests/decode/test.ts +0 -262
- package/tests/decode/userAccountBufferStrings.ts +0 -102
- package/tests/dlob/helpers.ts +0 -748
- package/tests/dlob/test.ts +0 -6969
- package/tests/dlob/tickSizeStandardization.ts +0 -545
- package/tests/events/parseLogsForCuUsage.ts +0 -139
- package/tests/exchangeStatus/test.ts +0 -45
- package/tests/insurance/test.ts +0 -40
- package/tests/liquidation/test.ts +0 -125
- package/tests/oracles/mmOracleGate.test.ts +0 -379
- package/tests/oracles/pythPegSnap.test.ts +0 -76
- package/tests/sdkParity/enumParity.test.ts +0 -84
- package/tests/sdkParity/marginCategoryFill.test.ts +0 -143
- package/tests/sdkParity/memcmpOffsets.test.ts +0 -139
- package/tests/spot/test.ts +0 -281
- package/tests/tx/TransactionConfirmationManager.test.ts +0 -312
- package/tests/tx/cachedBlockhashFetcher.test.ts +0 -96
- package/tests/tx/priorityFeeCalculator.ts +0 -77
- package/tests/tx/priorityFeeStrategy.ts +0 -95
- package/tests/user/bankruptcy.ts +0 -165
- package/tests/user/feeAndWithdrawLimits.ts +0 -284
- package/tests/user/getMarginCalculation.ts +0 -586
- package/tests/user/helpers.ts +0 -184
- package/tests/user/liquidations.ts +0 -129
- package/tests/user/marginCalculations.test.ts +0 -321
- package/tests/user/test.ts +0 -833
- package/tsconfig.browser.json +0 -18
- package/tsconfig.json +0 -36
package/src/math/superStake.ts
DELETED
|
@@ -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
|
-
}
|