@drift-labs/sdk-browser 2.104.0-beta.21
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 +276 -0
- package/VERSION +1 -0
- package/bun.lockb +0 -0
- package/get_events.ts +47 -0
- package/lib/browser/accounts/basicUserAccountSubscriber.d.ts +27 -0
- package/lib/browser/accounts/basicUserAccountSubscriber.js +38 -0
- package/lib/browser/accounts/bulkAccountLoader.d.ts +37 -0
- package/lib/browser/accounts/bulkAccountLoader.js +222 -0
- package/lib/browser/accounts/bulkUserStatsSubscription.d.ts +7 -0
- package/lib/browser/accounts/bulkUserStatsSubscription.js +21 -0
- package/lib/browser/accounts/bulkUserSubscription.d.ts +7 -0
- package/lib/browser/accounts/bulkUserSubscription.js +21 -0
- package/lib/browser/accounts/fetch.d.ts +6 -0
- package/lib/browser/accounts/fetch.js +30 -0
- package/lib/browser/accounts/grpcAccountSubscriber.d.ts +16 -0
- package/lib/browser/accounts/grpcAccountSubscriber.js +154 -0
- package/lib/browser/accounts/grpcDriftClientAccountSubscriber.d.ts +12 -0
- package/lib/browser/accounts/grpcDriftClientAccountSubscriber.js +98 -0
- package/lib/browser/accounts/grpcInsuranceFundStakeAccountSubscriber.d.ts +10 -0
- package/lib/browser/accounts/grpcInsuranceFundStakeAccountSubscriber.js +30 -0
- package/lib/browser/accounts/grpcProgramAccountSubscriber.d.ts +18 -0
- package/lib/browser/accounts/grpcProgramAccountSubscriber.js +171 -0
- package/lib/browser/accounts/grpcUserAccountSubscriber.d.ts +10 -0
- package/lib/browser/accounts/grpcUserAccountSubscriber.js +28 -0
- package/lib/browser/accounts/grpcUserStatsAccountSubscriber.d.ts +10 -0
- package/lib/browser/accounts/grpcUserStatsAccountSubscriber.js +28 -0
- package/lib/browser/accounts/oneShotUserAccountSubscriber.d.ts +18 -0
- package/lib/browser/accounts/oneShotUserAccountSubscriber.js +48 -0
- package/lib/browser/accounts/pollingDriftClientAccountSubscriber.d.ts +69 -0
- package/lib/browser/accounts/pollingDriftClientAccountSubscriber.js +418 -0
- package/lib/browser/accounts/pollingHighLeverageModeConfigAccountSubscriber.d.ts +29 -0
- package/lib/browser/accounts/pollingHighLeverageModeConfigAccountSubscriber.js +111 -0
- package/lib/browser/accounts/pollingInsuranceFundStakeAccountSubscriber.d.ts +29 -0
- package/lib/browser/accounts/pollingInsuranceFundStakeAccountSubscriber.js +110 -0
- package/lib/browser/accounts/pollingOracleAccountSubscriber.d.ts +27 -0
- package/lib/browser/accounts/pollingOracleAccountSubscriber.js +78 -0
- package/lib/browser/accounts/pollingTokenAccountSubscriber.d.ts +26 -0
- package/lib/browser/accounts/pollingTokenAccountSubscriber.js +78 -0
- package/lib/browser/accounts/pollingUserAccountSubscriber.d.ts +29 -0
- package/lib/browser/accounts/pollingUserAccountSubscriber.js +102 -0
- package/lib/browser/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
- package/lib/browser/accounts/pollingUserStatsAccountSubscriber.js +94 -0
- package/lib/browser/accounts/testBulkAccountLoader.d.ts +4 -0
- package/lib/browser/accounts/testBulkAccountLoader.js +45 -0
- package/lib/browser/accounts/types.d.ts +168 -0
- package/lib/browser/accounts/types.js +16 -0
- package/lib/browser/accounts/utils.d.ts +8 -0
- package/lib/browser/accounts/utils.js +49 -0
- package/lib/browser/accounts/webSocketAccountSubscriber.d.ts +29 -0
- package/lib/browser/accounts/webSocketAccountSubscriber.js +149 -0
- package/lib/browser/accounts/webSocketDriftClientAccountSubscriber.d.ts +66 -0
- package/lib/browser/accounts/webSocketDriftClientAccountSubscriber.js +358 -0
- package/lib/browser/accounts/webSocketHighLeverageModeConfigAccountSubscriber.d.ts +23 -0
- package/lib/browser/accounts/webSocketHighLeverageModeConfigAccountSubscriber.js +69 -0
- package/lib/browser/accounts/webSocketInsuranceFundStakeAccountSubscriber.d.ts +23 -0
- package/lib/browser/accounts/webSocketInsuranceFundStakeAccountSubscriber.js +67 -0
- package/lib/browser/accounts/webSocketProgramAccountSubscriber.d.ts +32 -0
- package/lib/browser/accounts/webSocketProgramAccountSubscriber.js +120 -0
- package/lib/browser/accounts/webSocketUserAccountSubscriber.d.ts +23 -0
- package/lib/browser/accounts/webSocketUserAccountSubscriber.js +61 -0
- package/lib/browser/accounts/webSocketUserStatsAccountSubsriber.d.ts +22 -0
- package/lib/browser/accounts/webSocketUserStatsAccountSubsriber.js +52 -0
- package/lib/browser/addresses/marketAddresses.d.ts +2 -0
- package/lib/browser/addresses/marketAddresses.js +15 -0
- package/lib/browser/addresses/pda.d.ts +32 -0
- package/lib/browser/addresses/pda.js +211 -0
- package/lib/browser/adminClient.d.ts +206 -0
- package/lib/browser/adminClient.js +1858 -0
- package/lib/browser/assert/assert.d.ts +1 -0
- package/lib/browser/assert/assert.js +9 -0
- package/lib/browser/auctionSubscriber/auctionSubscriber.d.ts +14 -0
- package/lib/browser/auctionSubscriber/auctionSubscriber.js +32 -0
- package/lib/browser/auctionSubscriber/auctionSubscriberGrpc.d.ts +15 -0
- package/lib/browser/auctionSubscriber/auctionSubscriberGrpc.js +32 -0
- package/lib/browser/auctionSubscriber/index.d.ts +3 -0
- package/lib/browser/auctionSubscriber/index.js +19 -0
- package/lib/browser/auctionSubscriber/types.d.ts +14 -0
- package/lib/browser/auctionSubscriber/types.js +2 -0
- package/lib/browser/bankrun/bankrunConnection.d.ts +75 -0
- package/lib/browser/bankrun/bankrunConnection.js +332 -0
- package/lib/browser/blockhashSubscriber/BlockhashSubscriber.d.ts +27 -0
- package/lib/browser/blockhashSubscriber/BlockhashSubscriber.js +89 -0
- package/lib/browser/blockhashSubscriber/index.d.ts +1 -0
- package/lib/browser/blockhashSubscriber/index.js +17 -0
- package/lib/browser/blockhashSubscriber/types.d.ts +7 -0
- package/lib/browser/blockhashSubscriber/types.js +2 -0
- package/lib/browser/clock/clockSubscriber.d.ts +31 -0
- package/lib/browser/clock/clockSubscriber.js +80 -0
- package/lib/browser/config.d.ts +60 -0
- package/lib/browser/config.js +130 -0
- package/lib/browser/constants/numericConstants.d.ts +71 -0
- package/lib/browser/constants/numericConstants.js +75 -0
- package/lib/browser/constants/perpMarkets.d.ts +19 -0
- package/lib/browser/constants/perpMarkets.js +997 -0
- package/lib/browser/constants/spotMarkets.d.ts +24 -0
- package/lib/browser/constants/spotMarkets.js +470 -0
- package/lib/browser/constants/txConstants.d.ts +1 -0
- package/lib/browser/constants/txConstants.js +4 -0
- package/lib/browser/decode/phoenix.d.ts +7 -0
- package/lib/browser/decode/phoenix.js +159 -0
- package/lib/browser/decode/user.d.ts +4 -0
- package/lib/browser/decode/user.js +339 -0
- package/lib/browser/dlob/DLOB.d.ts +186 -0
- package/lib/browser/dlob/DLOB.js +1039 -0
- package/lib/browser/dlob/DLOBNode.d.ts +68 -0
- package/lib/browser/dlob/DLOBNode.js +100 -0
- package/lib/browser/dlob/DLOBSubscriber.d.ts +54 -0
- package/lib/browser/dlob/DLOBSubscriber.js +139 -0
- package/lib/browser/dlob/NodeList.d.ts +25 -0
- package/lib/browser/dlob/NodeList.js +126 -0
- package/lib/browser/dlob/orderBookLevels.d.ts +72 -0
- package/lib/browser/dlob/orderBookLevels.js +438 -0
- package/lib/browser/dlob/types.d.ts +18 -0
- package/lib/browser/dlob/types.js +2 -0
- package/lib/browser/driftClient.d.ts +861 -0
- package/lib/browser/driftClient.js +4768 -0
- package/lib/browser/driftClientConfig.d.ts +49 -0
- package/lib/browser/driftClientConfig.js +2 -0
- package/lib/browser/events/eventList.d.ts +22 -0
- package/lib/browser/events/eventList.js +80 -0
- package/lib/browser/events/eventSubscriber.d.ts +46 -0
- package/lib/browser/events/eventSubscriber.js +223 -0
- package/lib/browser/events/eventsServerLogProvider.d.ts +21 -0
- package/lib/browser/events/eventsServerLogProvider.js +121 -0
- package/lib/browser/events/fetchLogs.d.ts +25 -0
- package/lib/browser/events/fetchLogs.js +99 -0
- package/lib/browser/events/parse.d.ts +6 -0
- package/lib/browser/events/parse.js +106 -0
- package/lib/browser/events/pollingLogProvider.d.ts +17 -0
- package/lib/browser/events/pollingLogProvider.js +58 -0
- package/lib/browser/events/sort.d.ts +2 -0
- package/lib/browser/events/sort.js +24 -0
- package/lib/browser/events/txEventCache.d.ts +24 -0
- package/lib/browser/events/txEventCache.js +71 -0
- package/lib/browser/events/types.d.ts +79 -0
- package/lib/browser/events/types.js +32 -0
- package/lib/browser/events/webSocketLogProvider.d.ts +24 -0
- package/lib/browser/events/webSocketLogProvider.js +96 -0
- package/lib/browser/factory/bigNum.d.ts +122 -0
- package/lib/browser/factory/bigNum.js +457 -0
- package/lib/browser/factory/oracleClient.d.ts +5 -0
- package/lib/browser/factory/oracleClient.js +56 -0
- package/lib/browser/idl/drift.json +14440 -0
- package/lib/browser/idl/openbook.json +3854 -0
- package/lib/browser/idl/pyth_solana_receiver.json +628 -0
- package/lib/browser/idl/switchboard.json +8354 -0
- package/lib/browser/idl/switchboard_on_demand_30.json +4546 -0
- package/lib/browser/idl/token_faucet.json +142 -0
- package/lib/browser/index.d.ts +125 -0
- package/lib/browser/index.js +147 -0
- package/lib/browser/isomorphic/grpc.browser.d.ts +1 -0
- package/lib/browser/isomorphic/grpc.browser.js +8 -0
- package/lib/browser/isomorphic/grpc.d.ts +1 -0
- package/lib/browser/isomorphic/grpc.js +8 -0
- package/lib/browser/jupiter/jupiterClient.d.ts +302 -0
- package/lib/browser/jupiter/jupiterClient.js +178 -0
- package/lib/browser/keypair.d.ts +2 -0
- package/lib/browser/keypair.js +28 -0
- package/lib/browser/marinade/index.d.ts +12 -0
- package/lib/browser/marinade/index.js +36 -0
- package/lib/browser/marinade/types.d.ts +1963 -0
- package/lib/browser/marinade/types.js +1965 -0
- package/lib/browser/math/amm.d.ts +98 -0
- package/lib/browser/math/amm.js +626 -0
- package/lib/browser/math/auction.d.ts +23 -0
- package/lib/browser/math/auction.js +130 -0
- package/lib/browser/math/bankruptcy.d.ts +2 -0
- package/lib/browser/math/bankruptcy.js +31 -0
- package/lib/browser/math/conversion.d.ts +2 -0
- package/lib/browser/math/conversion.js +11 -0
- package/lib/browser/math/exchangeStatus.d.ts +6 -0
- package/lib/browser/math/exchangeStatus.js +77 -0
- package/lib/browser/math/fuel.d.ts +6 -0
- package/lib/browser/math/fuel.js +55 -0
- package/lib/browser/math/funding.d.ts +34 -0
- package/lib/browser/math/funding.js +209 -0
- package/lib/browser/math/insurance.d.ts +7 -0
- package/lib/browser/math/insurance.js +73 -0
- package/lib/browser/math/margin.d.ts +39 -0
- package/lib/browser/math/margin.js +184 -0
- package/lib/browser/math/market.d.ts +39 -0
- package/lib/browser/math/market.js +163 -0
- package/lib/browser/math/oracles.d.ts +14 -0
- package/lib/browser/math/oracles.js +134 -0
- package/lib/browser/math/orders.d.ts +23 -0
- package/lib/browser/math/orders.js +216 -0
- package/lib/browser/math/position.d.ts +70 -0
- package/lib/browser/math/position.js +225 -0
- package/lib/browser/math/repeg.d.ts +22 -0
- package/lib/browser/math/repeg.js +164 -0
- package/lib/browser/math/spotBalance.d.ts +83 -0
- package/lib/browser/math/spotBalance.js +373 -0
- package/lib/browser/math/spotMarket.d.ts +11 -0
- package/lib/browser/math/spotMarket.js +49 -0
- package/lib/browser/math/spotPosition.d.ts +19 -0
- package/lib/browser/math/spotPosition.js +78 -0
- package/lib/browser/math/state.d.ts +5 -0
- package/lib/browser/math/state.js +30 -0
- package/lib/browser/math/superStake.d.ts +167 -0
- package/lib/browser/math/superStake.js +306 -0
- package/lib/browser/math/tiers.d.ts +4 -0
- package/lib/browser/math/tiers.js +52 -0
- package/lib/browser/math/trade.d.ts +117 -0
- package/lib/browser/math/trade.js +637 -0
- package/lib/browser/math/userStatus.d.ts +2 -0
- package/lib/browser/math/userStatus.js +8 -0
- package/lib/browser/math/utils.d.ts +23 -0
- package/lib/browser/math/utils.js +112 -0
- package/lib/browser/memcmp.d.ts +11 -0
- package/lib/browser/memcmp.js +99 -0
- package/lib/browser/openbook/openbookV2FulfillmentConfigMap.d.ts +10 -0
- package/lib/browser/openbook/openbookV2FulfillmentConfigMap.js +17 -0
- package/lib/browser/openbook/openbookV2Subscriber.d.ts +36 -0
- package/lib/browser/openbook/openbookV2Subscriber.js +104 -0
- package/lib/browser/oracles/oracleClientCache.d.ts +9 -0
- package/lib/browser/oracles/oracleClientCache.js +19 -0
- package/lib/browser/oracles/oracleId.d.ts +4 -0
- package/lib/browser/oracles/oracleId.js +38 -0
- package/lib/browser/oracles/prelaunchOracleClient.d.ts +12 -0
- package/lib/browser/oracles/prelaunchOracleClient.js +24 -0
- package/lib/browser/oracles/pythClient.d.ts +14 -0
- package/lib/browser/oracles/pythClient.js +51 -0
- package/lib/browser/oracles/pythLazerClient.d.ts +16 -0
- package/lib/browser/oracles/pythLazerClient.js +61 -0
- package/lib/browser/oracles/pythPullClient.d.ts +19 -0
- package/lib/browser/oracles/pythPullClient.js +60 -0
- package/lib/browser/oracles/quoteAssetOracleClient.d.ts +10 -0
- package/lib/browser/oracles/quoteAssetOracleClient.js +21 -0
- package/lib/browser/oracles/strictOraclePrice.d.ts +9 -0
- package/lib/browser/oracles/strictOraclePrice.js +17 -0
- package/lib/browser/oracles/switchboardClient.d.ts +12 -0
- package/lib/browser/oracles/switchboardClient.js +40 -0
- package/lib/browser/oracles/switchboardOnDemandClient.d.ts +12 -0
- package/lib/browser/oracles/switchboardOnDemandClient.js +32 -0
- package/lib/browser/oracles/types.d.ts +23 -0
- package/lib/browser/oracles/types.js +2 -0
- package/lib/browser/orderParams.d.ts +29 -0
- package/lib/browser/orderParams.js +44 -0
- package/lib/browser/orderSubscriber/OrderSubscriber.d.ts +42 -0
- package/lib/browser/orderSubscriber/OrderSubscriber.js +172 -0
- package/lib/browser/orderSubscriber/PollingSubscription.d.ts +12 -0
- package/lib/browser/orderSubscriber/PollingSubscription.js +23 -0
- package/lib/browser/orderSubscriber/WebsocketSubscription.d.ts +23 -0
- package/lib/browser/orderSubscriber/WebsocketSubscription.js +67 -0
- package/lib/browser/orderSubscriber/grpcSubscription.d.ts +22 -0
- package/lib/browser/orderSubscriber/grpcSubscription.js +66 -0
- package/lib/browser/orderSubscriber/index.d.ts +2 -0
- package/lib/browser/orderSubscriber/index.js +18 -0
- package/lib/browser/orderSubscriber/types.d.ts +34 -0
- package/lib/browser/orderSubscriber/types.js +2 -0
- package/lib/browser/phoenix/phoenixFulfillmentConfigMap.d.ts +10 -0
- package/lib/browser/phoenix/phoenixFulfillmentConfigMap.js +17 -0
- package/lib/browser/phoenix/phoenixSubscriber.d.ts +41 -0
- package/lib/browser/phoenix/phoenixSubscriber.js +152 -0
- package/lib/browser/priorityFee/averageOverSlotsStrategy.d.ts +5 -0
- package/lib/browser/priorityFee/averageOverSlotsStrategy.js +16 -0
- package/lib/browser/priorityFee/averageStrategy.d.ts +5 -0
- package/lib/browser/priorityFee/averageStrategy.js +11 -0
- package/lib/browser/priorityFee/driftPriorityFeeMethod.d.ts +13 -0
- package/lib/browser/priorityFee/driftPriorityFeeMethod.js +26 -0
- package/lib/browser/priorityFee/ewmaStrategy.d.ts +11 -0
- package/lib/browser/priorityFee/ewmaStrategy.js +33 -0
- package/lib/browser/priorityFee/heliusPriorityFeeMethod.d.ts +20 -0
- package/lib/browser/priorityFee/heliusPriorityFeeMethod.js +46 -0
- package/lib/browser/priorityFee/index.d.ts +11 -0
- package/lib/browser/priorityFee/index.js +27 -0
- package/lib/browser/priorityFee/maxOverSlotsStrategy.d.ts +5 -0
- package/lib/browser/priorityFee/maxOverSlotsStrategy.js +17 -0
- package/lib/browser/priorityFee/maxStrategy.d.ts +7 -0
- package/lib/browser/priorityFee/maxStrategy.js +9 -0
- package/lib/browser/priorityFee/priorityFeeSubscriber.d.ts +46 -0
- package/lib/browser/priorityFee/priorityFeeSubscriber.js +188 -0
- package/lib/browser/priorityFee/priorityFeeSubscriberMap.d.ts +48 -0
- package/lib/browser/priorityFee/priorityFeeSubscriberMap.js +88 -0
- package/lib/browser/priorityFee/solanaPriorityFeeMethod.d.ts +6 -0
- package/lib/browser/priorityFee/solanaPriorityFeeMethod.js +21 -0
- package/lib/browser/priorityFee/types.d.ts +31 -0
- package/lib/browser/priorityFee/types.js +10 -0
- package/lib/browser/serum/serumFulfillmentConfigMap.d.ts +10 -0
- package/lib/browser/serum/serumFulfillmentConfigMap.js +17 -0
- package/lib/browser/serum/serumSubscriber.d.ts +32 -0
- package/lib/browser/serum/serumSubscriber.js +107 -0
- package/lib/browser/serum/types.d.ts +13 -0
- package/lib/browser/serum/types.js +2 -0
- package/lib/browser/slot/SlotSubscriber.d.ts +27 -0
- package/lib/browser/slot/SlotSubscriber.js +71 -0
- package/lib/browser/slot/SlothashSubscriber.d.ts +26 -0
- package/lib/browser/slot/SlothashSubscriber.js +85 -0
- package/lib/browser/testClient.d.ts +8 -0
- package/lib/browser/testClient.js +23 -0
- package/lib/browser/token/index.d.ts +5 -0
- package/lib/browser/token/index.js +15 -0
- package/lib/browser/tokenFaucet.d.ts +41 -0
- package/lib/browser/tokenFaucet.js +188 -0
- package/lib/browser/tx/baseTxSender.d.ts +59 -0
- package/lib/browser/tx/baseTxSender.js +294 -0
- package/lib/browser/tx/blockhashFetcher/baseBlockhashFetcher.d.ts +8 -0
- package/lib/browser/tx/blockhashFetcher/baseBlockhashFetcher.js +13 -0
- package/lib/browser/tx/blockhashFetcher/cachedBlockhashFetcher.d.ts +28 -0
- package/lib/browser/tx/blockhashFetcher/cachedBlockhashFetcher.js +73 -0
- package/lib/browser/tx/blockhashFetcher/types.d.ts +4 -0
- package/lib/browser/tx/blockhashFetcher/types.js +2 -0
- package/lib/browser/tx/fastSingleTxSender.d.ts +41 -0
- package/lib/browser/tx/fastSingleTxSender.js +86 -0
- package/lib/browser/tx/forwardOnlyTxSender.d.ts +37 -0
- package/lib/browser/tx/forwardOnlyTxSender.js +92 -0
- package/lib/browser/tx/priorityFeeCalculator.d.ts +44 -0
- package/lib/browser/tx/priorityFeeCalculator.js +85 -0
- package/lib/browser/tx/reportTransactionError.d.ts +20 -0
- package/lib/browser/tx/reportTransactionError.js +103 -0
- package/lib/browser/tx/retryTxSender.d.ts +37 -0
- package/lib/browser/tx/retryTxSender.js +86 -0
- package/lib/browser/tx/txHandler.d.ts +154 -0
- package/lib/browser/tx/txHandler.js +453 -0
- package/lib/browser/tx/txParamProcessor.d.ts +25 -0
- package/lib/browser/tx/txParamProcessor.js +88 -0
- package/lib/browser/tx/types.d.ts +29 -0
- package/lib/browser/tx/types.js +20 -0
- package/lib/browser/tx/utils.d.ts +2 -0
- package/lib/browser/tx/utils.js +10 -0
- package/lib/browser/tx/whileValidTxSender.d.ts +45 -0
- package/lib/browser/tx/whileValidTxSender.js +167 -0
- package/lib/browser/types.d.ts +1385 -0
- package/lib/browser/types.js +366 -0
- package/lib/browser/user.d.ts +411 -0
- package/lib/browser/user.js +2151 -0
- package/lib/browser/userConfig.d.ts +26 -0
- package/lib/browser/userConfig.js +2 -0
- package/lib/browser/userMap/PollingSubscription.d.ts +16 -0
- package/lib/browser/userMap/PollingSubscription.js +30 -0
- package/lib/browser/userMap/WebsocketSubscription.d.ts +27 -0
- package/lib/browser/userMap/WebsocketSubscription.js +45 -0
- package/lib/browser/userMap/grpcSubscription.d.ts +27 -0
- package/lib/browser/userMap/grpcSubscription.js +44 -0
- package/lib/browser/userMap/referrerMap.d.ts +45 -0
- package/lib/browser/userMap/referrerMap.js +181 -0
- package/lib/browser/userMap/userMap.d.ts +90 -0
- package/lib/browser/userMap/userMap.js +467 -0
- package/lib/browser/userMap/userMapConfig.d.ts +39 -0
- package/lib/browser/userMap/userMapConfig.js +2 -0
- package/lib/browser/userMap/userStatsMap.d.ts +46 -0
- package/lib/browser/userMap/userStatsMap.js +165 -0
- package/lib/browser/userName.d.ts +5 -0
- package/lib/browser/userName.js +21 -0
- package/lib/browser/userStats.d.ts +22 -0
- package/lib/browser/userStats.js +91 -0
- package/lib/browser/userStatsConfig.d.ts +25 -0
- package/lib/browser/userStatsConfig.js +2 -0
- package/lib/browser/util/TransactionConfirmationManager.d.ts +16 -0
- package/lib/browser/util/TransactionConfirmationManager.js +174 -0
- package/lib/browser/util/chainClock.d.ts +17 -0
- package/lib/browser/util/chainClock.js +29 -0
- package/lib/browser/util/computeUnits.d.ts +8 -0
- package/lib/browser/util/computeUnits.js +48 -0
- package/lib/browser/util/digest.d.ts +4 -0
- package/lib/browser/util/digest.js +14 -0
- package/lib/browser/util/promiseTimeout.d.ts +1 -0
- package/lib/browser/util/promiseTimeout.js +14 -0
- package/lib/browser/util/pythOracleUtils.d.ts +17 -0
- package/lib/browser/util/pythOracleUtils.js +107 -0
- package/lib/browser/util/tps.d.ts +2 -0
- package/lib/browser/util/tps.js +16 -0
- package/lib/browser/wallet.d.ts +11 -0
- package/lib/browser/wallet.js +32 -0
- package/lib/node/accounts/basicUserAccountSubscriber.d.ts +27 -0
- package/lib/node/accounts/basicUserAccountSubscriber.js +38 -0
- package/lib/node/accounts/bulkAccountLoader.d.ts +37 -0
- package/lib/node/accounts/bulkAccountLoader.js +222 -0
- package/lib/node/accounts/bulkUserStatsSubscription.d.ts +7 -0
- package/lib/node/accounts/bulkUserStatsSubscription.js +21 -0
- package/lib/node/accounts/bulkUserSubscription.d.ts +7 -0
- package/lib/node/accounts/bulkUserSubscription.js +21 -0
- package/lib/node/accounts/fetch.d.ts +6 -0
- package/lib/node/accounts/fetch.js +30 -0
- package/lib/node/accounts/grpcAccountSubscriber.d.ts +16 -0
- package/lib/node/accounts/grpcAccountSubscriber.js +154 -0
- package/lib/node/accounts/grpcDriftClientAccountSubscriber.d.ts +12 -0
- package/lib/node/accounts/grpcDriftClientAccountSubscriber.js +98 -0
- package/lib/node/accounts/grpcInsuranceFundStakeAccountSubscriber.d.ts +10 -0
- package/lib/node/accounts/grpcInsuranceFundStakeAccountSubscriber.js +30 -0
- package/lib/node/accounts/grpcProgramAccountSubscriber.d.ts +18 -0
- package/lib/node/accounts/grpcProgramAccountSubscriber.js +171 -0
- package/lib/node/accounts/grpcUserAccountSubscriber.d.ts +10 -0
- package/lib/node/accounts/grpcUserAccountSubscriber.js +28 -0
- package/lib/node/accounts/grpcUserStatsAccountSubscriber.d.ts +10 -0
- package/lib/node/accounts/grpcUserStatsAccountSubscriber.js +28 -0
- package/lib/node/accounts/oneShotUserAccountSubscriber.d.ts +18 -0
- package/lib/node/accounts/oneShotUserAccountSubscriber.js +48 -0
- package/lib/node/accounts/pollingDriftClientAccountSubscriber.d.ts +69 -0
- package/lib/node/accounts/pollingDriftClientAccountSubscriber.js +418 -0
- package/lib/node/accounts/pollingHighLeverageModeConfigAccountSubscriber.d.ts +29 -0
- package/lib/node/accounts/pollingHighLeverageModeConfigAccountSubscriber.js +111 -0
- package/lib/node/accounts/pollingInsuranceFundStakeAccountSubscriber.d.ts +29 -0
- package/lib/node/accounts/pollingInsuranceFundStakeAccountSubscriber.js +110 -0
- package/lib/node/accounts/pollingOracleAccountSubscriber.d.ts +27 -0
- package/lib/node/accounts/pollingOracleAccountSubscriber.js +78 -0
- package/lib/node/accounts/pollingTokenAccountSubscriber.d.ts +26 -0
- package/lib/node/accounts/pollingTokenAccountSubscriber.js +78 -0
- package/lib/node/accounts/pollingUserAccountSubscriber.d.ts +29 -0
- package/lib/node/accounts/pollingUserAccountSubscriber.js +102 -0
- package/lib/node/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
- package/lib/node/accounts/pollingUserStatsAccountSubscriber.js +94 -0
- package/lib/node/accounts/testBulkAccountLoader.d.ts +4 -0
- package/lib/node/accounts/testBulkAccountLoader.js +45 -0
- package/lib/node/accounts/types.d.ts +168 -0
- package/lib/node/accounts/types.js +16 -0
- package/lib/node/accounts/utils.d.ts +8 -0
- package/lib/node/accounts/utils.js +49 -0
- package/lib/node/accounts/webSocketAccountSubscriber.d.ts +29 -0
- package/lib/node/accounts/webSocketAccountSubscriber.js +149 -0
- package/lib/node/accounts/webSocketDriftClientAccountSubscriber.d.ts +66 -0
- package/lib/node/accounts/webSocketDriftClientAccountSubscriber.js +358 -0
- package/lib/node/accounts/webSocketHighLeverageModeConfigAccountSubscriber.d.ts +23 -0
- package/lib/node/accounts/webSocketHighLeverageModeConfigAccountSubscriber.js +69 -0
- package/lib/node/accounts/webSocketInsuranceFundStakeAccountSubscriber.d.ts +23 -0
- package/lib/node/accounts/webSocketInsuranceFundStakeAccountSubscriber.js +67 -0
- package/lib/node/accounts/webSocketProgramAccountSubscriber.d.ts +32 -0
- package/lib/node/accounts/webSocketProgramAccountSubscriber.js +120 -0
- package/lib/node/accounts/webSocketUserAccountSubscriber.d.ts +23 -0
- package/lib/node/accounts/webSocketUserAccountSubscriber.js +61 -0
- package/lib/node/accounts/webSocketUserStatsAccountSubsriber.d.ts +22 -0
- package/lib/node/accounts/webSocketUserStatsAccountSubsriber.js +52 -0
- package/lib/node/addresses/marketAddresses.d.ts +2 -0
- package/lib/node/addresses/marketAddresses.js +15 -0
- package/lib/node/addresses/pda.d.ts +32 -0
- package/lib/node/addresses/pda.js +211 -0
- package/lib/node/adminClient.d.ts +206 -0
- package/lib/node/adminClient.js +1858 -0
- package/lib/node/assert/assert.d.ts +1 -0
- package/lib/node/assert/assert.js +9 -0
- package/lib/node/auctionSubscriber/auctionSubscriber.d.ts +14 -0
- package/lib/node/auctionSubscriber/auctionSubscriber.js +32 -0
- package/lib/node/auctionSubscriber/auctionSubscriberGrpc.d.ts +15 -0
- package/lib/node/auctionSubscriber/auctionSubscriberGrpc.js +32 -0
- package/lib/node/auctionSubscriber/index.d.ts +3 -0
- package/lib/node/auctionSubscriber/index.js +19 -0
- package/lib/node/auctionSubscriber/types.d.ts +14 -0
- package/lib/node/auctionSubscriber/types.js +2 -0
- package/lib/node/bankrun/bankrunConnection.d.ts +75 -0
- package/lib/node/bankrun/bankrunConnection.js +332 -0
- package/lib/node/blockhashSubscriber/BlockhashSubscriber.d.ts +27 -0
- package/lib/node/blockhashSubscriber/BlockhashSubscriber.js +89 -0
- package/lib/node/blockhashSubscriber/index.d.ts +1 -0
- package/lib/node/blockhashSubscriber/index.js +17 -0
- package/lib/node/blockhashSubscriber/types.d.ts +7 -0
- package/lib/node/blockhashSubscriber/types.js +2 -0
- package/lib/node/clock/clockSubscriber.d.ts +31 -0
- package/lib/node/clock/clockSubscriber.js +80 -0
- package/lib/node/config.d.ts +60 -0
- package/lib/node/config.js +130 -0
- package/lib/node/constants/numericConstants.d.ts +71 -0
- package/lib/node/constants/numericConstants.js +75 -0
- package/lib/node/constants/perpMarkets.d.ts +19 -0
- package/lib/node/constants/perpMarkets.js +997 -0
- package/lib/node/constants/spotMarkets.d.ts +24 -0
- package/lib/node/constants/spotMarkets.js +470 -0
- package/lib/node/constants/txConstants.d.ts +1 -0
- package/lib/node/constants/txConstants.js +4 -0
- package/lib/node/decode/phoenix.d.ts +7 -0
- package/lib/node/decode/phoenix.js +159 -0
- package/lib/node/decode/user.d.ts +4 -0
- package/lib/node/decode/user.js +339 -0
- package/lib/node/dlob/DLOB.d.ts +186 -0
- package/lib/node/dlob/DLOB.js +1039 -0
- package/lib/node/dlob/DLOBNode.d.ts +68 -0
- package/lib/node/dlob/DLOBNode.js +100 -0
- package/lib/node/dlob/DLOBSubscriber.d.ts +54 -0
- package/lib/node/dlob/DLOBSubscriber.js +139 -0
- package/lib/node/dlob/NodeList.d.ts +25 -0
- package/lib/node/dlob/NodeList.js +126 -0
- package/lib/node/dlob/orderBookLevels.d.ts +72 -0
- package/lib/node/dlob/orderBookLevels.js +438 -0
- package/lib/node/dlob/types.d.ts +18 -0
- package/lib/node/dlob/types.js +2 -0
- package/lib/node/driftClient.d.ts +861 -0
- package/lib/node/driftClient.js +4768 -0
- package/lib/node/driftClientConfig.d.ts +49 -0
- package/lib/node/driftClientConfig.js +2 -0
- package/lib/node/events/eventList.d.ts +22 -0
- package/lib/node/events/eventList.js +80 -0
- package/lib/node/events/eventSubscriber.d.ts +46 -0
- package/lib/node/events/eventSubscriber.js +223 -0
- package/lib/node/events/eventsServerLogProvider.d.ts +21 -0
- package/lib/node/events/eventsServerLogProvider.js +121 -0
- package/lib/node/events/fetchLogs.d.ts +25 -0
- package/lib/node/events/fetchLogs.js +99 -0
- package/lib/node/events/parse.d.ts +6 -0
- package/lib/node/events/parse.js +106 -0
- package/lib/node/events/pollingLogProvider.d.ts +17 -0
- package/lib/node/events/pollingLogProvider.js +58 -0
- package/lib/node/events/sort.d.ts +2 -0
- package/lib/node/events/sort.js +24 -0
- package/lib/node/events/txEventCache.d.ts +24 -0
- package/lib/node/events/txEventCache.js +71 -0
- package/lib/node/events/types.d.ts +79 -0
- package/lib/node/events/types.js +32 -0
- package/lib/node/events/webSocketLogProvider.d.ts +24 -0
- package/lib/node/events/webSocketLogProvider.js +96 -0
- package/lib/node/factory/bigNum.d.ts +122 -0
- package/lib/node/factory/bigNum.js +457 -0
- package/lib/node/factory/oracleClient.d.ts +5 -0
- package/lib/node/factory/oracleClient.js +56 -0
- package/lib/node/idl/drift.json +14440 -0
- package/lib/node/idl/openbook.json +3854 -0
- package/lib/node/idl/pyth_solana_receiver.json +628 -0
- package/lib/node/idl/switchboard.json +8354 -0
- package/lib/node/idl/switchboard_on_demand_30.json +4546 -0
- package/lib/node/idl/token_faucet.json +142 -0
- package/lib/node/index.d.ts +125 -0
- package/lib/node/index.js +147 -0
- package/lib/node/isomorphic/grpc.browser.d.ts +1 -0
- package/lib/node/isomorphic/grpc.browser.js +8 -0
- package/lib/node/isomorphic/grpc.d.ts +1 -0
- package/lib/node/isomorphic/grpc.js +8 -0
- package/lib/node/jupiter/jupiterClient.d.ts +302 -0
- package/lib/node/jupiter/jupiterClient.js +178 -0
- package/lib/node/keypair.d.ts +2 -0
- package/lib/node/keypair.js +28 -0
- package/lib/node/marinade/index.d.ts +12 -0
- package/lib/node/marinade/index.js +36 -0
- package/lib/node/marinade/types.d.ts +1963 -0
- package/lib/node/marinade/types.js +1965 -0
- package/lib/node/math/amm.d.ts +98 -0
- package/lib/node/math/amm.js +626 -0
- package/lib/node/math/auction.d.ts +23 -0
- package/lib/node/math/auction.js +130 -0
- package/lib/node/math/bankruptcy.d.ts +2 -0
- package/lib/node/math/bankruptcy.js +31 -0
- package/lib/node/math/conversion.d.ts +2 -0
- package/lib/node/math/conversion.js +11 -0
- package/lib/node/math/exchangeStatus.d.ts +6 -0
- package/lib/node/math/exchangeStatus.js +77 -0
- package/lib/node/math/fuel.d.ts +6 -0
- package/lib/node/math/fuel.js +55 -0
- package/lib/node/math/funding.d.ts +34 -0
- package/lib/node/math/funding.js +209 -0
- package/lib/node/math/insurance.d.ts +7 -0
- package/lib/node/math/insurance.js +73 -0
- package/lib/node/math/margin.d.ts +39 -0
- package/lib/node/math/margin.js +184 -0
- package/lib/node/math/market.d.ts +39 -0
- package/lib/node/math/market.js +163 -0
- package/lib/node/math/oracles.d.ts +14 -0
- package/lib/node/math/oracles.js +134 -0
- package/lib/node/math/orders.d.ts +23 -0
- package/lib/node/math/orders.js +216 -0
- package/lib/node/math/position.d.ts +70 -0
- package/lib/node/math/position.js +225 -0
- package/lib/node/math/repeg.d.ts +22 -0
- package/lib/node/math/repeg.js +164 -0
- package/lib/node/math/spotBalance.d.ts +83 -0
- package/lib/node/math/spotBalance.js +373 -0
- package/lib/node/math/spotMarket.d.ts +11 -0
- package/lib/node/math/spotMarket.js +49 -0
- package/lib/node/math/spotPosition.d.ts +19 -0
- package/lib/node/math/spotPosition.js +78 -0
- package/lib/node/math/state.d.ts +5 -0
- package/lib/node/math/state.js +30 -0
- package/lib/node/math/superStake.d.ts +167 -0
- package/lib/node/math/superStake.js +306 -0
- package/lib/node/math/tiers.d.ts +4 -0
- package/lib/node/math/tiers.js +52 -0
- package/lib/node/math/trade.d.ts +117 -0
- package/lib/node/math/trade.js +637 -0
- package/lib/node/math/userStatus.d.ts +2 -0
- package/lib/node/math/userStatus.js +8 -0
- package/lib/node/math/utils.d.ts +23 -0
- package/lib/node/math/utils.js +112 -0
- package/lib/node/memcmp.d.ts +11 -0
- package/lib/node/memcmp.js +99 -0
- package/lib/node/openbook/openbookV2FulfillmentConfigMap.d.ts +10 -0
- package/lib/node/openbook/openbookV2FulfillmentConfigMap.js +17 -0
- package/lib/node/openbook/openbookV2Subscriber.d.ts +36 -0
- package/lib/node/openbook/openbookV2Subscriber.js +104 -0
- package/lib/node/oracles/oracleClientCache.d.ts +9 -0
- package/lib/node/oracles/oracleClientCache.js +19 -0
- package/lib/node/oracles/oracleId.d.ts +4 -0
- package/lib/node/oracles/oracleId.js +38 -0
- package/lib/node/oracles/prelaunchOracleClient.d.ts +12 -0
- package/lib/node/oracles/prelaunchOracleClient.js +24 -0
- package/lib/node/oracles/pythClient.d.ts +14 -0
- package/lib/node/oracles/pythClient.js +51 -0
- package/lib/node/oracles/pythLazerClient.d.ts +16 -0
- package/lib/node/oracles/pythLazerClient.js +61 -0
- package/lib/node/oracles/pythPullClient.d.ts +19 -0
- package/lib/node/oracles/pythPullClient.js +60 -0
- package/lib/node/oracles/quoteAssetOracleClient.d.ts +10 -0
- package/lib/node/oracles/quoteAssetOracleClient.js +21 -0
- package/lib/node/oracles/strictOraclePrice.d.ts +9 -0
- package/lib/node/oracles/strictOraclePrice.js +17 -0
- package/lib/node/oracles/switchboardClient.d.ts +12 -0
- package/lib/node/oracles/switchboardClient.js +40 -0
- package/lib/node/oracles/switchboardOnDemandClient.d.ts +12 -0
- package/lib/node/oracles/switchboardOnDemandClient.js +32 -0
- package/lib/node/oracles/types.d.ts +23 -0
- package/lib/node/oracles/types.js +2 -0
- package/lib/node/orderParams.d.ts +29 -0
- package/lib/node/orderParams.js +44 -0
- package/lib/node/orderSubscriber/OrderSubscriber.d.ts +42 -0
- package/lib/node/orderSubscriber/OrderSubscriber.js +172 -0
- package/lib/node/orderSubscriber/PollingSubscription.d.ts +12 -0
- package/lib/node/orderSubscriber/PollingSubscription.js +23 -0
- package/lib/node/orderSubscriber/WebsocketSubscription.d.ts +23 -0
- package/lib/node/orderSubscriber/WebsocketSubscription.js +67 -0
- package/lib/node/orderSubscriber/grpcSubscription.d.ts +22 -0
- package/lib/node/orderSubscriber/grpcSubscription.js +66 -0
- package/lib/node/orderSubscriber/index.d.ts +2 -0
- package/lib/node/orderSubscriber/index.js +18 -0
- package/lib/node/orderSubscriber/types.d.ts +34 -0
- package/lib/node/orderSubscriber/types.js +2 -0
- package/lib/node/phoenix/phoenixFulfillmentConfigMap.d.ts +10 -0
- package/lib/node/phoenix/phoenixFulfillmentConfigMap.js +17 -0
- package/lib/node/phoenix/phoenixSubscriber.d.ts +41 -0
- package/lib/node/phoenix/phoenixSubscriber.js +152 -0
- package/lib/node/priorityFee/averageOverSlotsStrategy.d.ts +5 -0
- package/lib/node/priorityFee/averageOverSlotsStrategy.js +16 -0
- package/lib/node/priorityFee/averageStrategy.d.ts +5 -0
- package/lib/node/priorityFee/averageStrategy.js +11 -0
- package/lib/node/priorityFee/driftPriorityFeeMethod.d.ts +13 -0
- package/lib/node/priorityFee/driftPriorityFeeMethod.js +26 -0
- package/lib/node/priorityFee/ewmaStrategy.d.ts +11 -0
- package/lib/node/priorityFee/ewmaStrategy.js +33 -0
- package/lib/node/priorityFee/heliusPriorityFeeMethod.d.ts +20 -0
- package/lib/node/priorityFee/heliusPriorityFeeMethod.js +46 -0
- package/lib/node/priorityFee/index.d.ts +11 -0
- package/lib/node/priorityFee/index.js +27 -0
- package/lib/node/priorityFee/maxOverSlotsStrategy.d.ts +5 -0
- package/lib/node/priorityFee/maxOverSlotsStrategy.js +17 -0
- package/lib/node/priorityFee/maxStrategy.d.ts +7 -0
- package/lib/node/priorityFee/maxStrategy.js +9 -0
- package/lib/node/priorityFee/priorityFeeSubscriber.d.ts +46 -0
- package/lib/node/priorityFee/priorityFeeSubscriber.js +188 -0
- package/lib/node/priorityFee/priorityFeeSubscriberMap.d.ts +48 -0
- package/lib/node/priorityFee/priorityFeeSubscriberMap.js +88 -0
- package/lib/node/priorityFee/solanaPriorityFeeMethod.d.ts +6 -0
- package/lib/node/priorityFee/solanaPriorityFeeMethod.js +21 -0
- package/lib/node/priorityFee/types.d.ts +31 -0
- package/lib/node/priorityFee/types.js +10 -0
- package/lib/node/serum/serumFulfillmentConfigMap.d.ts +10 -0
- package/lib/node/serum/serumFulfillmentConfigMap.js +17 -0
- package/lib/node/serum/serumSubscriber.d.ts +32 -0
- package/lib/node/serum/serumSubscriber.js +107 -0
- package/lib/node/serum/types.d.ts +13 -0
- package/lib/node/serum/types.js +2 -0
- package/lib/node/slot/SlotSubscriber.d.ts +27 -0
- package/lib/node/slot/SlotSubscriber.js +71 -0
- package/lib/node/slot/SlothashSubscriber.d.ts +26 -0
- package/lib/node/slot/SlothashSubscriber.js +85 -0
- package/lib/node/testClient.d.ts +8 -0
- package/lib/node/testClient.js +23 -0
- package/lib/node/token/index.d.ts +5 -0
- package/lib/node/token/index.js +15 -0
- package/lib/node/tokenFaucet.d.ts +41 -0
- package/lib/node/tokenFaucet.js +188 -0
- package/lib/node/tx/baseTxSender.d.ts +59 -0
- package/lib/node/tx/baseTxSender.js +294 -0
- package/lib/node/tx/blockhashFetcher/baseBlockhashFetcher.d.ts +8 -0
- package/lib/node/tx/blockhashFetcher/baseBlockhashFetcher.js +13 -0
- package/lib/node/tx/blockhashFetcher/cachedBlockhashFetcher.d.ts +28 -0
- package/lib/node/tx/blockhashFetcher/cachedBlockhashFetcher.js +73 -0
- package/lib/node/tx/blockhashFetcher/types.d.ts +4 -0
- package/lib/node/tx/blockhashFetcher/types.js +2 -0
- package/lib/node/tx/fastSingleTxSender.d.ts +41 -0
- package/lib/node/tx/fastSingleTxSender.js +86 -0
- package/lib/node/tx/forwardOnlyTxSender.d.ts +37 -0
- package/lib/node/tx/forwardOnlyTxSender.js +92 -0
- package/lib/node/tx/priorityFeeCalculator.d.ts +44 -0
- package/lib/node/tx/priorityFeeCalculator.js +85 -0
- package/lib/node/tx/reportTransactionError.d.ts +20 -0
- package/lib/node/tx/reportTransactionError.js +103 -0
- package/lib/node/tx/retryTxSender.d.ts +37 -0
- package/lib/node/tx/retryTxSender.js +86 -0
- package/lib/node/tx/txHandler.d.ts +154 -0
- package/lib/node/tx/txHandler.js +453 -0
- package/lib/node/tx/txParamProcessor.d.ts +25 -0
- package/lib/node/tx/txParamProcessor.js +88 -0
- package/lib/node/tx/types.d.ts +29 -0
- package/lib/node/tx/types.js +20 -0
- package/lib/node/tx/utils.d.ts +2 -0
- package/lib/node/tx/utils.js +10 -0
- package/lib/node/tx/whileValidTxSender.d.ts +45 -0
- package/lib/node/tx/whileValidTxSender.js +167 -0
- package/lib/node/types.d.ts +1385 -0
- package/lib/node/types.js +366 -0
- package/lib/node/user.d.ts +411 -0
- package/lib/node/user.js +2151 -0
- package/lib/node/userConfig.d.ts +26 -0
- package/lib/node/userConfig.js +2 -0
- package/lib/node/userMap/PollingSubscription.d.ts +16 -0
- package/lib/node/userMap/PollingSubscription.js +30 -0
- package/lib/node/userMap/WebsocketSubscription.d.ts +27 -0
- package/lib/node/userMap/WebsocketSubscription.js +45 -0
- package/lib/node/userMap/grpcSubscription.d.ts +27 -0
- package/lib/node/userMap/grpcSubscription.js +44 -0
- package/lib/node/userMap/referrerMap.d.ts +45 -0
- package/lib/node/userMap/referrerMap.js +181 -0
- package/lib/node/userMap/userMap.d.ts +90 -0
- package/lib/node/userMap/userMap.js +467 -0
- package/lib/node/userMap/userMapConfig.d.ts +39 -0
- package/lib/node/userMap/userMapConfig.js +2 -0
- package/lib/node/userMap/userStatsMap.d.ts +46 -0
- package/lib/node/userMap/userStatsMap.js +165 -0
- package/lib/node/userName.d.ts +5 -0
- package/lib/node/userName.js +21 -0
- package/lib/node/userStats.d.ts +22 -0
- package/lib/node/userStats.js +91 -0
- package/lib/node/userStatsConfig.d.ts +25 -0
- package/lib/node/userStatsConfig.js +2 -0
- package/lib/node/util/TransactionConfirmationManager.d.ts +16 -0
- package/lib/node/util/TransactionConfirmationManager.js +174 -0
- package/lib/node/util/chainClock.d.ts +17 -0
- package/lib/node/util/chainClock.js +29 -0
- package/lib/node/util/computeUnits.d.ts +8 -0
- package/lib/node/util/computeUnits.js +48 -0
- package/lib/node/util/digest.d.ts +4 -0
- package/lib/node/util/digest.js +14 -0
- package/lib/node/util/promiseTimeout.d.ts +1 -0
- package/lib/node/util/promiseTimeout.js +14 -0
- package/lib/node/util/pythOracleUtils.d.ts +17 -0
- package/lib/node/util/pythOracleUtils.js +107 -0
- package/lib/node/util/tps.d.ts +2 -0
- package/lib/node/util/tps.js +16 -0
- package/lib/node/wallet.d.ts +11 -0
- package/lib/node/wallet.js +32 -0
- package/package.json +92 -0
- package/scripts/postbuild.js +95 -0
- package/scripts/updateVersion.js +28 -0
- package/src/accounts/basicUserAccountSubscriber.ts +59 -0
- package/src/accounts/bulkAccountLoader.ts +294 -0
- package/src/accounts/bulkUserStatsSubscription.ts +33 -0
- package/src/accounts/bulkUserSubscription.ts +33 -0
- package/src/accounts/fetch.ts +66 -0
- package/src/accounts/grpcAccountSubscriber.ts +160 -0
- package/src/accounts/grpcDriftClientAccountSubscriber.ts +203 -0
- package/src/accounts/grpcInsuranceFundStakeAccountSubscriber.ts +56 -0
- package/src/accounts/grpcProgramAccountSubscriber.ts +190 -0
- package/src/accounts/grpcUserAccountSubscriber.ts +48 -0
- package/src/accounts/grpcUserStatsAccountSubscriber.ts +50 -0
- package/src/accounts/oneShotUserAccountSubscriber.ts +68 -0
- package/src/accounts/pollingDriftClientAccountSubscriber.ts +644 -0
- package/src/accounts/pollingHighLeverageModeConfigAccountSubscriber.ts +189 -0
- package/src/accounts/pollingInsuranceFundStakeAccountSubscriber.ts +185 -0
- package/src/accounts/pollingOracleAccountSubscriber.ts +125 -0
- package/src/accounts/pollingTokenAccountSubscriber.ts +118 -0
- package/src/accounts/pollingUserAccountSubscriber.ts +160 -0
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +156 -0
- package/src/accounts/testBulkAccountLoader.ts +53 -0
- package/src/accounts/types.ts +245 -0
- package/src/accounts/utils.ts +62 -0
- package/src/accounts/webSocketAccountSubscriber.ts +205 -0
- package/src/accounts/webSocketDriftClientAccountSubscriber.ts +621 -0
- package/src/accounts/webSocketHighLeverageModeConfigAccountSubscriber.ts +131 -0
- package/src/accounts/webSocketInsuranceFundStakeAccountSubscriber.ts +129 -0
- package/src/accounts/webSocketProgramAccountSubscriber.ts +182 -0
- package/src/accounts/webSocketUserAccountSubscriber.ts +104 -0
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +98 -0
- package/src/addresses/marketAddresses.ts +17 -0
- package/src/addresses/pda.ts +355 -0
- package/src/adminClient.ts +4030 -0
- package/src/assert/assert.ts +5 -0
- package/src/auctionSubscriber/auctionSubscriber.ts +66 -0
- package/src/auctionSubscriber/auctionSubscriberGrpc.ts +70 -0
- package/src/auctionSubscriber/index.ts +3 -0
- package/src/auctionSubscriber/types.ts +20 -0
- package/src/bankrun/bankrunConnection.ts +534 -0
- package/src/blockhashSubscriber/BlockhashSubscriber.ts +126 -0
- package/src/blockhashSubscriber/index.ts +1 -0
- package/src/blockhashSubscriber/types.ts +12 -0
- package/src/clock/clockSubscriber.ts +121 -0
- package/src/config.ts +212 -0
- package/src/constants/numericConstants.ts +113 -0
- package/src/constants/perpMarkets.ts +1084 -0
- package/src/constants/spotMarkets.ts +565 -0
- package/src/constants/txConstants.ts +1 -0
- package/src/decode/phoenix.ts +207 -0
- package/src/decode/user.ts +368 -0
- package/src/dlob/DLOB.ts +1897 -0
- package/src/dlob/DLOBNode.ts +197 -0
- package/src/dlob/DLOBSubscriber.ts +201 -0
- package/src/dlob/NodeList.ts +173 -0
- package/src/dlob/orderBookLevels.ts +643 -0
- package/src/dlob/types.ts +22 -0
- package/src/driftClient.ts +9032 -0
- package/src/driftClientConfig.ts +60 -0
- package/src/events/eventList.ts +97 -0
- package/src/events/eventSubscriber.ts +364 -0
- package/src/events/eventsServerLogProvider.ts +152 -0
- package/src/events/fetchLogs.ts +169 -0
- package/src/events/parse.ts +133 -0
- package/src/events/pollingLogProvider.ts +89 -0
- package/src/events/sort.ts +39 -0
- package/src/events/txEventCache.ts +74 -0
- package/src/events/types.ts +185 -0
- package/src/events/webSocketLogProvider.ts +121 -0
- package/src/factory/bigNum.ts +660 -0
- package/src/factory/oracleClient.ts +72 -0
- package/src/idl/drift.json +14440 -0
- package/src/idl/openbook.json +3854 -0
- package/src/idl/pyth.json +142 -0
- package/src/idl/pyth_solana_receiver.json +628 -0
- package/src/idl/switchboard.json +8354 -0
- package/src/idl/switchboard_on_demand_30.json +4546 -0
- package/src/idl/token_faucet.json +142 -0
- package/src/index.ts +127 -0
- package/src/isomorphic/README.md +19 -0
- package/src/isomorphic/grpc.browser.ts +4 -0
- package/src/isomorphic/grpc.node.ts +23 -0
- package/src/isomorphic/grpc.ts +1 -0
- package/src/jupiter/jupiterClient.ts +510 -0
- package/src/keypair.ts +24 -0
- package/src/marinade/idl/idl.json +1962 -0
- package/src/marinade/index.ts +64 -0
- package/src/marinade/types.ts +3925 -0
- package/src/math/amm.ts +1162 -0
- package/src/math/auction.ts +173 -0
- package/src/math/bankruptcy.ts +34 -0
- package/src/math/conversion.ts +13 -0
- package/src/math/exchangeStatus.ts +121 -0
- package/src/math/fuel.ts +70 -0
- package/src/math/funding.ts +342 -0
- package/src/math/insurance.ts +110 -0
- package/src/math/margin.ts +340 -0
- package/src/math/market.ts +336 -0
- package/src/math/oracles.ts +228 -0
- package/src/math/orders.ts +343 -0
- package/src/math/position.ts +324 -0
- package/src/math/repeg.ts +214 -0
- package/src/math/spotBalance.ts +630 -0
- package/src/math/spotMarket.ts +82 -0
- package/src/math/spotPosition.ts +184 -0
- package/src/math/state.ts +29 -0
- package/src/math/superStake.ts +525 -0
- package/src/math/tiers.ts +44 -0
- package/src/math/trade.ts +993 -0
- package/src/math/userStatus.ts +5 -0
- package/src/math/utils.ts +120 -0
- package/src/memcmp.ts +94 -0
- package/src/openbook/openbookV2FulfillmentConfigMap.ts +29 -0
- package/src/openbook/openbookV2Subscriber.ts +165 -0
- package/src/oracles/oracleClientCache.ts +25 -0
- package/src/oracles/oracleId.ts +28 -0
- package/src/oracles/prelaunchOracleClient.ts +37 -0
- package/src/oracles/pythClient.ts +85 -0
- package/src/oracles/pythLazerClient.ts +102 -0
- package/src/oracles/pythPullClient.ts +111 -0
- package/src/oracles/quoteAssetOracleClient.ts +25 -0
- package/src/oracles/strictOraclePrice.ts +19 -0
- package/src/oracles/switchboardClient.ts +77 -0
- package/src/oracles/switchboardOnDemandClient.ts +56 -0
- package/src/oracles/types.ts +23 -0
- package/src/orderParams.ts +79 -0
- package/src/orderSubscriber/OrderSubscriber.ts +249 -0
- package/src/orderSubscriber/PollingSubscription.ts +39 -0
- package/src/orderSubscriber/WebsocketSubscription.ts +119 -0
- package/src/orderSubscriber/grpcSubscription.ts +121 -0
- package/src/orderSubscriber/index.ts +2 -0
- package/src/orderSubscriber/types.ts +54 -0
- package/src/phoenix/phoenixFulfillmentConfigMap.ts +26 -0
- package/src/phoenix/phoenixSubscriber.ts +235 -0
- package/src/priorityFee/averageOverSlotsStrategy.ts +16 -0
- package/src/priorityFee/averageStrategy.ts +12 -0
- package/src/priorityFee/driftPriorityFeeMethod.ts +42 -0
- package/src/priorityFee/ewmaStrategy.ts +41 -0
- package/src/priorityFee/heliusPriorityFeeMethod.ts +57 -0
- package/src/priorityFee/index.ts +11 -0
- package/src/priorityFee/maxOverSlotsStrategy.ts +17 -0
- package/src/priorityFee/maxStrategy.ts +7 -0
- package/src/priorityFee/priorityFeeSubscriber.ts +251 -0
- package/src/priorityFee/priorityFeeSubscriberMap.ts +112 -0
- package/src/priorityFee/solanaPriorityFeeMethod.ts +34 -0
- package/src/priorityFee/types.ts +60 -0
- package/src/serum/serumFulfillmentConfigMap.ts +26 -0
- package/src/serum/serumSubscriber.ts +169 -0
- package/src/serum/types.ts +17 -0
- package/src/slot/SlotSubscriber.ts +101 -0
- package/src/slot/SlothashSubscriber.ts +126 -0
- package/src/testClient.ts +41 -0
- package/src/token/index.ts +13 -0
- package/src/tokenFaucet.ts +269 -0
- package/src/tx/baseTxSender.ts +477 -0
- package/src/tx/blockhashFetcher/baseBlockhashFetcher.ts +19 -0
- package/src/tx/blockhashFetcher/cachedBlockhashFetcher.ts +90 -0
- package/src/tx/blockhashFetcher/types.ts +5 -0
- package/src/tx/fastSingleTxSender.ts +142 -0
- package/src/tx/forwardOnlyTxSender.ts +145 -0
- package/src/tx/priorityFeeCalculator.ts +117 -0
- package/src/tx/reportTransactionError.ts +159 -0
- package/src/tx/retryTxSender.ts +135 -0
- package/src/tx/txHandler.ts +737 -0
- package/src/tx/txParamProcessor.ts +155 -0
- package/src/tx/types.ts +71 -0
- package/src/tx/utils.ts +11 -0
- package/src/tx/whileValidTxSender.ts +265 -0
- package/src/types.ts +1386 -0
- package/src/user.ts +4054 -0
- package/src/userConfig.ts +32 -0
- package/src/userMap/PollingSubscription.ts +47 -0
- package/src/userMap/WebsocketSubscription.ts +84 -0
- package/src/userMap/grpcSubscription.ts +85 -0
- package/src/userMap/referrerMap.ts +267 -0
- package/src/userMap/userMap.ts +654 -0
- package/src/userMap/userMapConfig.ts +63 -0
- package/src/userMap/userStatsMap.ts +218 -0
- package/src/userName.ts +21 -0
- package/src/userStats.ts +174 -0
- package/src/userStatsConfig.ts +31 -0
- package/src/util/TransactionConfirmationManager.ts +292 -0
- package/src/util/chainClock.ts +41 -0
- package/src/util/computeUnits.ts +65 -0
- package/src/util/digest.ts +11 -0
- package/src/util/promiseTimeout.ts +14 -0
- package/src/util/pythOracleUtils.ts +136 -0
- package/src/util/tps.ts +27 -0
- package/src/wallet.ts +43 -0
- package/tests/amm/test.ts +2092 -0
- package/tests/auctions/test.ts +81 -0
- package/tests/bn/test.ts +341 -0
- package/tests/ci/idl.ts +101 -0
- package/tests/ci/verifyConstants.ts +278 -0
- package/tests/decode/phoenix.ts +71 -0
- package/tests/decode/test.ts +266 -0
- package/tests/decode/userAccountBufferStrings.ts +102 -0
- package/tests/dlob/helpers.ts +749 -0
- package/tests/dlob/test.ts +6623 -0
- package/tests/insurance/test.ts +40 -0
- package/tests/spot/test.ts +226 -0
- package/tests/subscriber/openbook.ts +62 -0
- package/tests/tx/TransactionConfirmationManager.test.ts +305 -0
- package/tests/tx/cachedBlockhashFetcher.test.ts +96 -0
- package/tests/tx/priorityFeeCalculator.ts +77 -0
- package/tests/tx/priorityFeeStrategy.ts +95 -0
- package/tests/user/helpers.ts +92 -0
- package/tests/user/test.ts +517 -0
- package/tsconfig.browser.json +13 -0
- package/tsconfig.json +13 -0
package/lib/node/user.js
ADDED
|
@@ -0,0 +1,2151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.User = void 0;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
const position_1 = require("./math/position");
|
|
6
|
+
const numericConstants_1 = require("./constants/numericConstants");
|
|
7
|
+
const _1 = require(".");
|
|
8
|
+
const spotBalance_1 = require("./math/spotBalance");
|
|
9
|
+
const amm_1 = require("./math/amm");
|
|
10
|
+
const margin_1 = require("./math/margin");
|
|
11
|
+
const pollingUserAccountSubscriber_1 = require("./accounts/pollingUserAccountSubscriber");
|
|
12
|
+
const webSocketUserAccountSubscriber_1 = require("./accounts/webSocketUserAccountSubscriber");
|
|
13
|
+
const spotPosition_1 = require("./math/spotPosition");
|
|
14
|
+
const oracles_1 = require("./math/oracles");
|
|
15
|
+
const tiers_1 = require("./math/tiers");
|
|
16
|
+
const strictOraclePrice_1 = require("./oracles/strictOraclePrice");
|
|
17
|
+
const fuel_1 = require("./math/fuel");
|
|
18
|
+
const grpcUserAccountSubscriber_1 = require("./accounts/grpcUserAccountSubscriber");
|
|
19
|
+
class User {
|
|
20
|
+
get isSubscribed() {
|
|
21
|
+
return this._isSubscribed && this.accountSubscriber.isSubscribed;
|
|
22
|
+
}
|
|
23
|
+
set isSubscribed(val) {
|
|
24
|
+
this._isSubscribed = val;
|
|
25
|
+
}
|
|
26
|
+
constructor(config) {
|
|
27
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
28
|
+
this._isSubscribed = false;
|
|
29
|
+
this.driftClient = config.driftClient;
|
|
30
|
+
this.userAccountPublicKey = config.userAccountPublicKey;
|
|
31
|
+
if (((_a = config.accountSubscription) === null || _a === void 0 ? void 0 : _a.type) === 'polling') {
|
|
32
|
+
this.accountSubscriber = new pollingUserAccountSubscriber_1.PollingUserAccountSubscriber(config.driftClient.connection, config.userAccountPublicKey, config.accountSubscription.accountLoader, this.driftClient.program.account.user.coder.accounts.decodeUnchecked.bind(this.driftClient.program.account.user.coder.accounts));
|
|
33
|
+
}
|
|
34
|
+
else if (((_b = config.accountSubscription) === null || _b === void 0 ? void 0 : _b.type) === 'custom') {
|
|
35
|
+
this.accountSubscriber = config.accountSubscription.userAccountSubscriber;
|
|
36
|
+
}
|
|
37
|
+
else if (((_c = config.accountSubscription) === null || _c === void 0 ? void 0 : _c.type) === 'grpc') {
|
|
38
|
+
this.accountSubscriber = new grpcUserAccountSubscriber_1.grpcUserAccountSubscriber(config.accountSubscription.grpcConfigs, config.driftClient.program, config.userAccountPublicKey, {
|
|
39
|
+
resubTimeoutMs: (_d = config.accountSubscription) === null || _d === void 0 ? void 0 : _d.resubTimeoutMs,
|
|
40
|
+
logResubMessages: (_e = config.accountSubscription) === null || _e === void 0 ? void 0 : _e.logResubMessages,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
this.accountSubscriber = new webSocketUserAccountSubscriber_1.WebSocketUserAccountSubscriber(config.driftClient.program, config.userAccountPublicKey, {
|
|
45
|
+
resubTimeoutMs: (_f = config.accountSubscription) === null || _f === void 0 ? void 0 : _f.resubTimeoutMs,
|
|
46
|
+
logResubMessages: (_g = config.accountSubscription) === null || _g === void 0 ? void 0 : _g.logResubMessages,
|
|
47
|
+
}, (_h = config.accountSubscription) === null || _h === void 0 ? void 0 : _h.commitment);
|
|
48
|
+
}
|
|
49
|
+
this.eventEmitter = this.accountSubscriber.eventEmitter;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Subscribe to User state accounts
|
|
53
|
+
* @returns SusbcriptionSuccess result
|
|
54
|
+
*/
|
|
55
|
+
async subscribe(userAccount) {
|
|
56
|
+
this.isSubscribed = await this.accountSubscriber.subscribe(userAccount);
|
|
57
|
+
return this.isSubscribed;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Forces the accountSubscriber to fetch account updates from rpc
|
|
61
|
+
*/
|
|
62
|
+
async fetchAccounts() {
|
|
63
|
+
await this.accountSubscriber.fetch();
|
|
64
|
+
}
|
|
65
|
+
async unsubscribe() {
|
|
66
|
+
await this.accountSubscriber.unsubscribe();
|
|
67
|
+
this.isSubscribed = false;
|
|
68
|
+
}
|
|
69
|
+
getUserAccount() {
|
|
70
|
+
return this.accountSubscriber.getUserAccountAndSlot().data;
|
|
71
|
+
}
|
|
72
|
+
async forceGetUserAccount() {
|
|
73
|
+
await this.fetchAccounts();
|
|
74
|
+
return this.accountSubscriber.getUserAccountAndSlot().data;
|
|
75
|
+
}
|
|
76
|
+
getUserAccountAndSlot() {
|
|
77
|
+
return this.accountSubscriber.getUserAccountAndSlot();
|
|
78
|
+
}
|
|
79
|
+
getPerpPositionForUserAccount(userAccount, marketIndex) {
|
|
80
|
+
return this.getActivePerpPositionsForUserAccount(userAccount).find((position) => position.marketIndex === marketIndex);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Gets the user's current position for a given perp market. If the user has no position returns undefined
|
|
84
|
+
* @param marketIndex
|
|
85
|
+
* @returns userPerpPosition
|
|
86
|
+
*/
|
|
87
|
+
getPerpPosition(marketIndex) {
|
|
88
|
+
const userAccount = this.getUserAccount();
|
|
89
|
+
return this.getPerpPositionForUserAccount(userAccount, marketIndex);
|
|
90
|
+
}
|
|
91
|
+
getPerpPositionAndSlot(marketIndex) {
|
|
92
|
+
const userAccount = this.getUserAccountAndSlot();
|
|
93
|
+
const perpPosition = this.getPerpPositionForUserAccount(userAccount.data, marketIndex);
|
|
94
|
+
return {
|
|
95
|
+
data: perpPosition,
|
|
96
|
+
slot: userAccount.slot,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
getSpotPositionForUserAccount(userAccount, marketIndex) {
|
|
100
|
+
return userAccount.spotPositions.find((position) => position.marketIndex === marketIndex);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Gets the user's current position for a given spot market. If the user has no position returns undefined
|
|
104
|
+
* @param marketIndex
|
|
105
|
+
* @returns userSpotPosition
|
|
106
|
+
*/
|
|
107
|
+
getSpotPosition(marketIndex) {
|
|
108
|
+
const userAccount = this.getUserAccount();
|
|
109
|
+
return this.getSpotPositionForUserAccount(userAccount, marketIndex);
|
|
110
|
+
}
|
|
111
|
+
getSpotPositionAndSlot(marketIndex) {
|
|
112
|
+
const userAccount = this.getUserAccountAndSlot();
|
|
113
|
+
const spotPosition = this.getSpotPositionForUserAccount(userAccount.data, marketIndex);
|
|
114
|
+
return {
|
|
115
|
+
data: spotPosition,
|
|
116
|
+
slot: userAccount.slot,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
getEmptySpotPosition(marketIndex) {
|
|
120
|
+
return {
|
|
121
|
+
marketIndex,
|
|
122
|
+
scaledBalance: numericConstants_1.ZERO,
|
|
123
|
+
balanceType: _1.SpotBalanceType.DEPOSIT,
|
|
124
|
+
cumulativeDeposits: numericConstants_1.ZERO,
|
|
125
|
+
openAsks: numericConstants_1.ZERO,
|
|
126
|
+
openBids: numericConstants_1.ZERO,
|
|
127
|
+
openOrders: 0,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Returns the token amount for a given market. The spot market precision is based on the token mint decimals.
|
|
132
|
+
* Positive if it is a deposit, negative if it is a borrow.
|
|
133
|
+
*
|
|
134
|
+
* @param marketIndex
|
|
135
|
+
*/
|
|
136
|
+
getTokenAmount(marketIndex) {
|
|
137
|
+
const spotPosition = this.getSpotPosition(marketIndex);
|
|
138
|
+
if (spotPosition === undefined) {
|
|
139
|
+
return numericConstants_1.ZERO;
|
|
140
|
+
}
|
|
141
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(marketIndex);
|
|
142
|
+
return (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarket, spotPosition.balanceType), spotPosition.balanceType);
|
|
143
|
+
}
|
|
144
|
+
getEmptyPosition(marketIndex) {
|
|
145
|
+
return {
|
|
146
|
+
baseAssetAmount: numericConstants_1.ZERO,
|
|
147
|
+
remainderBaseAssetAmount: 0,
|
|
148
|
+
lastCumulativeFundingRate: numericConstants_1.ZERO,
|
|
149
|
+
marketIndex,
|
|
150
|
+
quoteAssetAmount: numericConstants_1.ZERO,
|
|
151
|
+
quoteEntryAmount: numericConstants_1.ZERO,
|
|
152
|
+
quoteBreakEvenAmount: numericConstants_1.ZERO,
|
|
153
|
+
openOrders: 0,
|
|
154
|
+
openBids: numericConstants_1.ZERO,
|
|
155
|
+
openAsks: numericConstants_1.ZERO,
|
|
156
|
+
settledPnl: numericConstants_1.ZERO,
|
|
157
|
+
lpShares: numericConstants_1.ZERO,
|
|
158
|
+
lastBaseAssetAmountPerLp: numericConstants_1.ZERO,
|
|
159
|
+
lastQuoteAssetAmountPerLp: numericConstants_1.ZERO,
|
|
160
|
+
perLpBase: 0,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
getClonedPosition(position) {
|
|
164
|
+
const clonedPosition = Object.assign({}, position);
|
|
165
|
+
return clonedPosition;
|
|
166
|
+
}
|
|
167
|
+
getOrderForUserAccount(userAccount, orderId) {
|
|
168
|
+
return userAccount.orders.find((order) => order.orderId === orderId);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* @param orderId
|
|
172
|
+
* @returns Order
|
|
173
|
+
*/
|
|
174
|
+
getOrder(orderId) {
|
|
175
|
+
const userAccount = this.getUserAccount();
|
|
176
|
+
return this.getOrderForUserAccount(userAccount, orderId);
|
|
177
|
+
}
|
|
178
|
+
getOrderAndSlot(orderId) {
|
|
179
|
+
const userAccount = this.getUserAccountAndSlot();
|
|
180
|
+
const order = this.getOrderForUserAccount(userAccount.data, orderId);
|
|
181
|
+
return {
|
|
182
|
+
data: order,
|
|
183
|
+
slot: userAccount.slot,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
getOrderByUserIdForUserAccount(userAccount, userOrderId) {
|
|
187
|
+
return userAccount.orders.find((order) => order.userOrderId === userOrderId);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* @param userOrderId
|
|
191
|
+
* @returns Order
|
|
192
|
+
*/
|
|
193
|
+
getOrderByUserOrderId(userOrderId) {
|
|
194
|
+
const userAccount = this.getUserAccount();
|
|
195
|
+
return this.getOrderByUserIdForUserAccount(userAccount, userOrderId);
|
|
196
|
+
}
|
|
197
|
+
getOrderByUserOrderIdAndSlot(userOrderId) {
|
|
198
|
+
const userAccount = this.getUserAccountAndSlot();
|
|
199
|
+
const order = this.getOrderByUserIdForUserAccount(userAccount.data, userOrderId);
|
|
200
|
+
return {
|
|
201
|
+
data: order,
|
|
202
|
+
slot: userAccount.slot,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
getOpenOrdersForUserAccount(userAccount) {
|
|
206
|
+
return userAccount === null || userAccount === void 0 ? void 0 : userAccount.orders.filter((order) => (0, types_1.isVariant)(order.status, 'open'));
|
|
207
|
+
}
|
|
208
|
+
getOpenOrders() {
|
|
209
|
+
const userAccount = this.getUserAccount();
|
|
210
|
+
return this.getOpenOrdersForUserAccount(userAccount);
|
|
211
|
+
}
|
|
212
|
+
getOpenOrdersAndSlot() {
|
|
213
|
+
const userAccount = this.getUserAccountAndSlot();
|
|
214
|
+
const openOrders = this.getOpenOrdersForUserAccount(userAccount.data);
|
|
215
|
+
return {
|
|
216
|
+
data: openOrders,
|
|
217
|
+
slot: userAccount.slot,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
getUserAccountPublicKey() {
|
|
221
|
+
return this.userAccountPublicKey;
|
|
222
|
+
}
|
|
223
|
+
async exists() {
|
|
224
|
+
const userAccountRPCResponse = await this.driftClient.connection.getParsedAccountInfo(this.userAccountPublicKey);
|
|
225
|
+
return userAccountRPCResponse.value !== null;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* calculates the total open bids/asks in a perp market (including lps)
|
|
229
|
+
* @returns : open bids
|
|
230
|
+
* @returns : open asks
|
|
231
|
+
*/
|
|
232
|
+
getPerpBidAsks(marketIndex) {
|
|
233
|
+
const position = this.getPerpPosition(marketIndex);
|
|
234
|
+
const [lpOpenBids, lpOpenAsks] = this.getLPBidAsks(marketIndex);
|
|
235
|
+
const totalOpenBids = lpOpenBids.add(position.openBids);
|
|
236
|
+
const totalOpenAsks = lpOpenAsks.add(position.openAsks);
|
|
237
|
+
return [totalOpenBids, totalOpenAsks];
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* calculates the open bids and asks for an lp
|
|
241
|
+
* optionally pass in lpShares to see what bid/asks a user *would* take on
|
|
242
|
+
* @returns : lp open bids
|
|
243
|
+
* @returns : lp open asks
|
|
244
|
+
*/
|
|
245
|
+
getLPBidAsks(marketIndex, lpShares) {
|
|
246
|
+
const position = this.getPerpPosition(marketIndex);
|
|
247
|
+
const lpSharesToCalc = lpShares !== null && lpShares !== void 0 ? lpShares : position === null || position === void 0 ? void 0 : position.lpShares;
|
|
248
|
+
if (!lpSharesToCalc || lpSharesToCalc.eq(numericConstants_1.ZERO)) {
|
|
249
|
+
return [numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
250
|
+
}
|
|
251
|
+
const market = this.driftClient.getPerpMarketAccount(marketIndex);
|
|
252
|
+
const [marketOpenBids, marketOpenAsks] = (0, amm_1.calculateMarketOpenBidAsk)(market.amm.baseAssetReserve, market.amm.minBaseAssetReserve, market.amm.maxBaseAssetReserve, market.amm.orderStepSize);
|
|
253
|
+
const lpOpenBids = marketOpenBids.mul(lpSharesToCalc).div(market.amm.sqrtK);
|
|
254
|
+
const lpOpenAsks = marketOpenAsks.mul(lpSharesToCalc).div(market.amm.sqrtK);
|
|
255
|
+
return [lpOpenBids, lpOpenAsks];
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* calculates the market position if the lp position was settled
|
|
259
|
+
* @returns : the settled userPosition
|
|
260
|
+
* @returns : the dust base asset amount (ie, < stepsize)
|
|
261
|
+
* @returns : pnl from settle
|
|
262
|
+
*/
|
|
263
|
+
getPerpPositionWithLPSettle(marketIndex, originalPosition, burnLpShares = false, includeRemainderInBaseAmount = false) {
|
|
264
|
+
var _a;
|
|
265
|
+
originalPosition =
|
|
266
|
+
(_a = originalPosition !== null && originalPosition !== void 0 ? originalPosition : this.getPerpPosition(marketIndex)) !== null && _a !== void 0 ? _a : this.getEmptyPosition(marketIndex);
|
|
267
|
+
if (originalPosition.lpShares.eq(numericConstants_1.ZERO)) {
|
|
268
|
+
return [originalPosition, numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
269
|
+
}
|
|
270
|
+
const position = this.getClonedPosition(originalPosition);
|
|
271
|
+
const market = this.driftClient.getPerpMarketAccount(position.marketIndex);
|
|
272
|
+
if (market.amm.perLpBase != position.perLpBase) {
|
|
273
|
+
// perLpBase = 1 => per 10 LP shares, perLpBase = -1 => per 0.1 LP shares
|
|
274
|
+
const expoDiff = market.amm.perLpBase - position.perLpBase;
|
|
275
|
+
const marketPerLpRebaseScalar = new _1.BN(10 ** Math.abs(expoDiff));
|
|
276
|
+
if (expoDiff > 0) {
|
|
277
|
+
position.lastBaseAssetAmountPerLp =
|
|
278
|
+
position.lastBaseAssetAmountPerLp.mul(marketPerLpRebaseScalar);
|
|
279
|
+
position.lastQuoteAssetAmountPerLp =
|
|
280
|
+
position.lastQuoteAssetAmountPerLp.mul(marketPerLpRebaseScalar);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
position.lastBaseAssetAmountPerLp =
|
|
284
|
+
position.lastBaseAssetAmountPerLp.div(marketPerLpRebaseScalar);
|
|
285
|
+
position.lastQuoteAssetAmountPerLp =
|
|
286
|
+
position.lastQuoteAssetAmountPerLp.div(marketPerLpRebaseScalar);
|
|
287
|
+
}
|
|
288
|
+
position.perLpBase = position.perLpBase + expoDiff;
|
|
289
|
+
}
|
|
290
|
+
const nShares = position.lpShares;
|
|
291
|
+
// incorp unsettled funding on pre settled position
|
|
292
|
+
const quoteFundingPnl = (0, position_1.calculateUnsettledFundingPnl)(market, position);
|
|
293
|
+
let baseUnit = numericConstants_1.AMM_RESERVE_PRECISION;
|
|
294
|
+
if (market.amm.perLpBase == position.perLpBase) {
|
|
295
|
+
if (position.perLpBase >= 0 &&
|
|
296
|
+
position.perLpBase <= numericConstants_1.AMM_RESERVE_PRECISION_EXP.toNumber()) {
|
|
297
|
+
const marketPerLpRebase = new _1.BN(10 ** market.amm.perLpBase);
|
|
298
|
+
baseUnit = baseUnit.mul(marketPerLpRebase);
|
|
299
|
+
}
|
|
300
|
+
else if (position.perLpBase < 0 &&
|
|
301
|
+
position.perLpBase >= -numericConstants_1.AMM_RESERVE_PRECISION_EXP.toNumber()) {
|
|
302
|
+
const marketPerLpRebase = new _1.BN(10 ** Math.abs(market.amm.perLpBase));
|
|
303
|
+
baseUnit = baseUnit.div(marketPerLpRebase);
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
throw 'cannot calc';
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
throw 'market.amm.perLpBase != position.perLpBase';
|
|
311
|
+
}
|
|
312
|
+
const deltaBaa = market.amm.baseAssetAmountPerLp
|
|
313
|
+
.sub(position.lastBaseAssetAmountPerLp)
|
|
314
|
+
.mul(nShares)
|
|
315
|
+
.div(baseUnit);
|
|
316
|
+
const deltaQaa = market.amm.quoteAssetAmountPerLp
|
|
317
|
+
.sub(position.lastQuoteAssetAmountPerLp)
|
|
318
|
+
.mul(nShares)
|
|
319
|
+
.div(baseUnit);
|
|
320
|
+
function sign(v) {
|
|
321
|
+
return v.isNeg() ? new _1.BN(-1) : new _1.BN(1);
|
|
322
|
+
}
|
|
323
|
+
function standardize(amount, stepSize) {
|
|
324
|
+
const remainder = amount.abs().mod(stepSize).mul(sign(amount));
|
|
325
|
+
const standardizedAmount = amount.sub(remainder);
|
|
326
|
+
return [standardizedAmount, remainder];
|
|
327
|
+
}
|
|
328
|
+
const [standardizedBaa, remainderBaa] = standardize(deltaBaa, market.amm.orderStepSize);
|
|
329
|
+
position.remainderBaseAssetAmount += remainderBaa.toNumber();
|
|
330
|
+
if (Math.abs(position.remainderBaseAssetAmount) >
|
|
331
|
+
market.amm.orderStepSize.toNumber()) {
|
|
332
|
+
const [newStandardizedBaa, newRemainderBaa] = standardize(new _1.BN(position.remainderBaseAssetAmount), market.amm.orderStepSize);
|
|
333
|
+
position.baseAssetAmount =
|
|
334
|
+
position.baseAssetAmount.add(newStandardizedBaa);
|
|
335
|
+
position.remainderBaseAssetAmount = newRemainderBaa.toNumber();
|
|
336
|
+
}
|
|
337
|
+
let dustBaseAssetValue = numericConstants_1.ZERO;
|
|
338
|
+
if (burnLpShares && position.remainderBaseAssetAmount != 0) {
|
|
339
|
+
const oraclePriceData = this.driftClient.getOracleDataForPerpMarket(position.marketIndex);
|
|
340
|
+
dustBaseAssetValue = new _1.BN(Math.abs(position.remainderBaseAssetAmount))
|
|
341
|
+
.mul(oraclePriceData.price)
|
|
342
|
+
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
343
|
+
.add(numericConstants_1.ONE);
|
|
344
|
+
}
|
|
345
|
+
let updateType;
|
|
346
|
+
if (position.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
347
|
+
updateType = 'open';
|
|
348
|
+
}
|
|
349
|
+
else if (sign(position.baseAssetAmount).eq(sign(deltaBaa))) {
|
|
350
|
+
updateType = 'increase';
|
|
351
|
+
}
|
|
352
|
+
else if (position.baseAssetAmount.abs().gt(deltaBaa.abs())) {
|
|
353
|
+
updateType = 'reduce';
|
|
354
|
+
}
|
|
355
|
+
else if (position.baseAssetAmount.abs().eq(deltaBaa.abs())) {
|
|
356
|
+
updateType = 'close';
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
updateType = 'flip';
|
|
360
|
+
}
|
|
361
|
+
let newQuoteEntry;
|
|
362
|
+
let pnl;
|
|
363
|
+
if (updateType == 'open' || updateType == 'increase') {
|
|
364
|
+
newQuoteEntry = position.quoteEntryAmount.add(deltaQaa);
|
|
365
|
+
pnl = numericConstants_1.ZERO;
|
|
366
|
+
}
|
|
367
|
+
else if (updateType == 'reduce' || updateType == 'close') {
|
|
368
|
+
newQuoteEntry = position.quoteEntryAmount.sub(position.quoteEntryAmount
|
|
369
|
+
.mul(deltaBaa.abs())
|
|
370
|
+
.div(position.baseAssetAmount.abs()));
|
|
371
|
+
pnl = position.quoteEntryAmount.sub(newQuoteEntry).add(deltaQaa);
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
newQuoteEntry = deltaQaa.sub(deltaQaa.mul(position.baseAssetAmount.abs()).div(deltaBaa.abs()));
|
|
375
|
+
pnl = position.quoteEntryAmount.add(deltaQaa.sub(newQuoteEntry));
|
|
376
|
+
}
|
|
377
|
+
position.quoteEntryAmount = newQuoteEntry;
|
|
378
|
+
position.baseAssetAmount = position.baseAssetAmount.add(standardizedBaa);
|
|
379
|
+
position.quoteAssetAmount = position.quoteAssetAmount
|
|
380
|
+
.add(deltaQaa)
|
|
381
|
+
.add(quoteFundingPnl)
|
|
382
|
+
.sub(dustBaseAssetValue);
|
|
383
|
+
position.quoteBreakEvenAmount = position.quoteBreakEvenAmount
|
|
384
|
+
.add(deltaQaa)
|
|
385
|
+
.add(quoteFundingPnl)
|
|
386
|
+
.sub(dustBaseAssetValue);
|
|
387
|
+
// update open bids/asks
|
|
388
|
+
const [marketOpenBids, marketOpenAsks] = (0, amm_1.calculateMarketOpenBidAsk)(market.amm.baseAssetReserve, market.amm.minBaseAssetReserve, market.amm.maxBaseAssetReserve, market.amm.orderStepSize);
|
|
389
|
+
const lpOpenBids = marketOpenBids
|
|
390
|
+
.mul(position.lpShares)
|
|
391
|
+
.div(market.amm.sqrtK);
|
|
392
|
+
const lpOpenAsks = marketOpenAsks
|
|
393
|
+
.mul(position.lpShares)
|
|
394
|
+
.div(market.amm.sqrtK);
|
|
395
|
+
position.openBids = lpOpenBids.add(position.openBids);
|
|
396
|
+
position.openAsks = lpOpenAsks.add(position.openAsks);
|
|
397
|
+
// eliminate counting funding on settled position
|
|
398
|
+
if (position.baseAssetAmount.gt(numericConstants_1.ZERO)) {
|
|
399
|
+
position.lastCumulativeFundingRate = market.amm.cumulativeFundingRateLong;
|
|
400
|
+
}
|
|
401
|
+
else if (position.baseAssetAmount.lt(numericConstants_1.ZERO)) {
|
|
402
|
+
position.lastCumulativeFundingRate =
|
|
403
|
+
market.amm.cumulativeFundingRateShort;
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
position.lastCumulativeFundingRate = numericConstants_1.ZERO;
|
|
407
|
+
}
|
|
408
|
+
const remainderBeforeRemoval = new _1.BN(position.remainderBaseAssetAmount);
|
|
409
|
+
if (includeRemainderInBaseAmount) {
|
|
410
|
+
position.baseAssetAmount = position.baseAssetAmount.add(remainderBeforeRemoval);
|
|
411
|
+
position.remainderBaseAssetAmount = 0;
|
|
412
|
+
}
|
|
413
|
+
return [position, remainderBeforeRemoval, pnl];
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* calculates Buying Power = free collateral / initial margin ratio
|
|
417
|
+
* @returns : Precision QUOTE_PRECISION
|
|
418
|
+
*/
|
|
419
|
+
getPerpBuyingPower(marketIndex, collateralBuffer = numericConstants_1.ZERO) {
|
|
420
|
+
const perpPosition = this.getPerpPositionWithLPSettle(marketIndex, undefined, true)[0];
|
|
421
|
+
const perpMarket = this.driftClient.getPerpMarketAccount(marketIndex);
|
|
422
|
+
const oraclePriceData = this.getOracleDataForPerpMarket(marketIndex);
|
|
423
|
+
const worstCaseBaseAssetAmount = perpPosition
|
|
424
|
+
? (0, margin_1.calculateWorstCaseBaseAssetAmount)(perpPosition, perpMarket, oraclePriceData.price)
|
|
425
|
+
: numericConstants_1.ZERO;
|
|
426
|
+
const freeCollateral = this.getFreeCollateral().sub(collateralBuffer);
|
|
427
|
+
return this.getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex, freeCollateral, worstCaseBaseAssetAmount);
|
|
428
|
+
}
|
|
429
|
+
getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex, freeCollateral, baseAssetAmount) {
|
|
430
|
+
const marginRatio = (0, _1.calculateMarketMarginRatio)(this.driftClient.getPerpMarketAccount(marketIndex), baseAssetAmount, 'Initial', this.getUserAccount().maxMarginRatio, this.isHighLeverageMode());
|
|
431
|
+
return freeCollateral.mul(numericConstants_1.MARGIN_PRECISION).div(new _1.BN(marginRatio));
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* calculates Free Collateral = Total collateral - margin requirement
|
|
435
|
+
* @returns : Precision QUOTE_PRECISION
|
|
436
|
+
*/
|
|
437
|
+
getFreeCollateral(marginCategory = 'Initial') {
|
|
438
|
+
const totalCollateral = this.getTotalCollateral(marginCategory, true);
|
|
439
|
+
const marginRequirement = marginCategory === 'Initial'
|
|
440
|
+
? this.getInitialMarginRequirement()
|
|
441
|
+
: this.getMaintenanceMarginRequirement();
|
|
442
|
+
const freeCollateral = totalCollateral.sub(marginRequirement);
|
|
443
|
+
return freeCollateral.gte(numericConstants_1.ZERO) ? freeCollateral : numericConstants_1.ZERO;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* @returns The margin requirement of a certain type (Initial or Maintenance) in USDC. : QUOTE_PRECISION
|
|
447
|
+
*/
|
|
448
|
+
getMarginRequirement(marginCategory, liquidationBuffer, strict = false, includeOpenOrders = true) {
|
|
449
|
+
return this.getTotalPerpPositionLiability(marginCategory, liquidationBuffer, includeOpenOrders, strict).add(this.getSpotMarketLiabilityValue(undefined, marginCategory, liquidationBuffer, includeOpenOrders, strict));
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* @returns The initial margin requirement in USDC. : QUOTE_PRECISION
|
|
453
|
+
*/
|
|
454
|
+
getInitialMarginRequirement() {
|
|
455
|
+
return this.getMarginRequirement('Initial', undefined, true);
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* @returns The maintenance margin requirement in USDC. : QUOTE_PRECISION
|
|
459
|
+
*/
|
|
460
|
+
getMaintenanceMarginRequirement() {
|
|
461
|
+
// if user being liq'd, can continue to be liq'd until total collateral above the margin requirement plus buffer
|
|
462
|
+
let liquidationBuffer = undefined;
|
|
463
|
+
if (this.isBeingLiquidated()) {
|
|
464
|
+
liquidationBuffer = new _1.BN(this.driftClient.getStateAccount().liquidationMarginBufferRatio);
|
|
465
|
+
}
|
|
466
|
+
return this.getMarginRequirement('Maintenance', liquidationBuffer);
|
|
467
|
+
}
|
|
468
|
+
getActivePerpPositionsForUserAccount(userAccount) {
|
|
469
|
+
return userAccount.perpPositions.filter((pos) => !pos.baseAssetAmount.eq(numericConstants_1.ZERO) ||
|
|
470
|
+
!pos.quoteAssetAmount.eq(numericConstants_1.ZERO) ||
|
|
471
|
+
!(pos.openOrders == 0) ||
|
|
472
|
+
!pos.lpShares.eq(numericConstants_1.ZERO));
|
|
473
|
+
}
|
|
474
|
+
getActivePerpPositions() {
|
|
475
|
+
const userAccount = this.getUserAccount();
|
|
476
|
+
return this.getActivePerpPositionsForUserAccount(userAccount);
|
|
477
|
+
}
|
|
478
|
+
getActivePerpPositionsAndSlot() {
|
|
479
|
+
const userAccount = this.getUserAccountAndSlot();
|
|
480
|
+
const positions = this.getActivePerpPositionsForUserAccount(userAccount.data);
|
|
481
|
+
return {
|
|
482
|
+
data: positions,
|
|
483
|
+
slot: userAccount.slot,
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
getActiveSpotPositionsForUserAccount(userAccount) {
|
|
487
|
+
return userAccount.spotPositions.filter((pos) => !(0, spotPosition_1.isSpotPositionAvailable)(pos));
|
|
488
|
+
}
|
|
489
|
+
getActiveSpotPositions() {
|
|
490
|
+
const userAccount = this.getUserAccount();
|
|
491
|
+
return this.getActiveSpotPositionsForUserAccount(userAccount);
|
|
492
|
+
}
|
|
493
|
+
getActiveSpotPositionsAndSlot() {
|
|
494
|
+
const userAccount = this.getUserAccountAndSlot();
|
|
495
|
+
const positions = this.getActiveSpotPositionsForUserAccount(userAccount.data);
|
|
496
|
+
return {
|
|
497
|
+
data: positions,
|
|
498
|
+
slot: userAccount.slot,
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* calculates unrealized position price pnl
|
|
503
|
+
* @returns : Precision QUOTE_PRECISION
|
|
504
|
+
*/
|
|
505
|
+
getUnrealizedPNL(withFunding, marketIndex, withWeightMarginCategory, strict = false) {
|
|
506
|
+
return this.getActivePerpPositions()
|
|
507
|
+
.filter((pos) => marketIndex !== undefined ? pos.marketIndex === marketIndex : true)
|
|
508
|
+
.reduce((unrealizedPnl, perpPosition) => {
|
|
509
|
+
const market = this.driftClient.getPerpMarketAccount(perpPosition.marketIndex);
|
|
510
|
+
const oraclePriceData = this.getOracleDataForPerpMarket(market.marketIndex);
|
|
511
|
+
const quoteSpotMarket = this.driftClient.getSpotMarketAccount(market.quoteSpotMarketIndex);
|
|
512
|
+
const quoteOraclePriceData = this.getOracleDataForSpotMarket(market.quoteSpotMarketIndex);
|
|
513
|
+
if (perpPosition.lpShares.gt(numericConstants_1.ZERO)) {
|
|
514
|
+
perpPosition = this.getPerpPositionWithLPSettle(perpPosition.marketIndex, undefined, !!withWeightMarginCategory)[0];
|
|
515
|
+
}
|
|
516
|
+
let positionUnrealizedPnl = (0, _1.calculatePositionPNL)(market, perpPosition, withFunding, oraclePriceData);
|
|
517
|
+
let quotePrice;
|
|
518
|
+
if (strict && positionUnrealizedPnl.gt(numericConstants_1.ZERO)) {
|
|
519
|
+
quotePrice = _1.BN.min(quoteOraclePriceData.price, quoteSpotMarket.historicalOracleData.lastOraclePriceTwap5Min);
|
|
520
|
+
}
|
|
521
|
+
else if (strict && positionUnrealizedPnl.lt(numericConstants_1.ZERO)) {
|
|
522
|
+
quotePrice = _1.BN.max(quoteOraclePriceData.price, quoteSpotMarket.historicalOracleData.lastOraclePriceTwap5Min);
|
|
523
|
+
}
|
|
524
|
+
else {
|
|
525
|
+
quotePrice = quoteOraclePriceData.price;
|
|
526
|
+
}
|
|
527
|
+
positionUnrealizedPnl = positionUnrealizedPnl
|
|
528
|
+
.mul(quotePrice)
|
|
529
|
+
.div(numericConstants_1.PRICE_PRECISION);
|
|
530
|
+
if (withWeightMarginCategory !== undefined) {
|
|
531
|
+
if (positionUnrealizedPnl.gt(numericConstants_1.ZERO)) {
|
|
532
|
+
positionUnrealizedPnl = positionUnrealizedPnl
|
|
533
|
+
.mul((0, _1.calculateUnrealizedAssetWeight)(market, quoteSpotMarket, positionUnrealizedPnl, withWeightMarginCategory, oraclePriceData))
|
|
534
|
+
.div(new _1.BN(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION));
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
return unrealizedPnl.add(positionUnrealizedPnl);
|
|
538
|
+
}, numericConstants_1.ZERO);
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* calculates unrealized funding payment pnl
|
|
542
|
+
* @returns : Precision QUOTE_PRECISION
|
|
543
|
+
*/
|
|
544
|
+
getUnrealizedFundingPNL(marketIndex) {
|
|
545
|
+
return this.getUserAccount()
|
|
546
|
+
.perpPositions.filter((pos) => marketIndex !== undefined ? pos.marketIndex === marketIndex : true)
|
|
547
|
+
.reduce((pnl, perpPosition) => {
|
|
548
|
+
const market = this.driftClient.getPerpMarketAccount(perpPosition.marketIndex);
|
|
549
|
+
return pnl.add((0, position_1.calculateUnsettledFundingPnl)(market, perpPosition));
|
|
550
|
+
}, numericConstants_1.ZERO);
|
|
551
|
+
}
|
|
552
|
+
getFuelBonus(now, includeSettled = true, includeUnsettled = true) {
|
|
553
|
+
const userAccount = this.getUserAccount();
|
|
554
|
+
const result = {
|
|
555
|
+
insuranceFuel: numericConstants_1.ZERO,
|
|
556
|
+
takerFuel: numericConstants_1.ZERO,
|
|
557
|
+
makerFuel: numericConstants_1.ZERO,
|
|
558
|
+
depositFuel: numericConstants_1.ZERO,
|
|
559
|
+
borrowFuel: numericConstants_1.ZERO,
|
|
560
|
+
positionFuel: numericConstants_1.ZERO,
|
|
561
|
+
};
|
|
562
|
+
const userStats = this.driftClient.getUserStats();
|
|
563
|
+
const userStatsAccount = userStats.getAccount();
|
|
564
|
+
if (includeSettled) {
|
|
565
|
+
result.takerFuel = result.takerFuel.add(new _1.BN(userStatsAccount.fuelTaker));
|
|
566
|
+
result.makerFuel = result.makerFuel.add(new _1.BN(userStatsAccount.fuelMaker));
|
|
567
|
+
result.depositFuel = result.depositFuel.add(new _1.BN(userStatsAccount.fuelDeposits));
|
|
568
|
+
result.borrowFuel = result.borrowFuel.add(new _1.BN(userStatsAccount.fuelBorrows));
|
|
569
|
+
result.positionFuel = result.positionFuel.add(new _1.BN(userStatsAccount.fuelPositions));
|
|
570
|
+
}
|
|
571
|
+
if (includeUnsettled) {
|
|
572
|
+
const fuelBonusNumerator = _1.BN.max(now.sub(_1.BN.max(new _1.BN(userAccount.lastFuelBonusUpdateTs), numericConstants_1.FUEL_START_TS)), numericConstants_1.ZERO);
|
|
573
|
+
if (fuelBonusNumerator.gt(numericConstants_1.ZERO)) {
|
|
574
|
+
for (const spotPosition of this.getActiveSpotPositions()) {
|
|
575
|
+
const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
576
|
+
const tokenAmount = this.getTokenAmount(spotPosition.marketIndex);
|
|
577
|
+
const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
|
|
578
|
+
const twap5min = (0, oracles_1.calculateLiveOracleTwap)(spotMarketAccount.historicalOracleData, oraclePriceData, now, numericConstants_1.FIVE_MINUTE // 5MIN
|
|
579
|
+
);
|
|
580
|
+
const strictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(oraclePriceData.price, twap5min);
|
|
581
|
+
const signedTokenValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice);
|
|
582
|
+
if (signedTokenValue.gt(numericConstants_1.ZERO)) {
|
|
583
|
+
result.depositFuel = result.depositFuel.add((0, fuel_1.calculateSpotFuelBonus)(spotMarketAccount, signedTokenValue, fuelBonusNumerator));
|
|
584
|
+
}
|
|
585
|
+
else {
|
|
586
|
+
result.borrowFuel = result.borrowFuel.add((0, fuel_1.calculateSpotFuelBonus)(spotMarketAccount, signedTokenValue, fuelBonusNumerator));
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
for (const perpPosition of this.getActivePerpPositions()) {
|
|
590
|
+
const oraclePriceData = this.getOracleDataForPerpMarket(perpPosition.marketIndex);
|
|
591
|
+
const perpMarketAccount = this.driftClient.getPerpMarketAccount(perpPosition.marketIndex);
|
|
592
|
+
const baseAssetValue = this.getPerpPositionValue(perpPosition.marketIndex, oraclePriceData, false);
|
|
593
|
+
result.positionFuel = result.positionFuel.add((0, fuel_1.calculatePerpFuelBonus)(perpMarketAccount, baseAssetValue, fuelBonusNumerator));
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
result.insuranceFuel = userStats.getInsuranceFuelBonus(now, includeSettled, includeUnsettled);
|
|
598
|
+
return result;
|
|
599
|
+
}
|
|
600
|
+
getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict = false, now) {
|
|
601
|
+
now = now || new _1.BN(new Date().getTime() / 1000);
|
|
602
|
+
let netQuoteValue = numericConstants_1.ZERO;
|
|
603
|
+
let totalAssetValue = numericConstants_1.ZERO;
|
|
604
|
+
let totalLiabilityValue = numericConstants_1.ZERO;
|
|
605
|
+
for (const spotPosition of this.getUserAccount().spotPositions) {
|
|
606
|
+
const countForBase = marketIndex === undefined || spotPosition.marketIndex === marketIndex;
|
|
607
|
+
const countForQuote = marketIndex === undefined ||
|
|
608
|
+
marketIndex === numericConstants_1.QUOTE_SPOT_MARKET_INDEX ||
|
|
609
|
+
(includeOpenOrders && spotPosition.openOrders !== 0);
|
|
610
|
+
if ((0, spotPosition_1.isSpotPositionAvailable)(spotPosition) ||
|
|
611
|
+
(!countForBase && !countForQuote)) {
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
615
|
+
const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
|
|
616
|
+
let twap5min;
|
|
617
|
+
if (strict) {
|
|
618
|
+
twap5min = (0, oracles_1.calculateLiveOracleTwap)(spotMarketAccount.historicalOracleData, oraclePriceData, now, numericConstants_1.FIVE_MINUTE // 5MIN
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
const strictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(oraclePriceData.price, twap5min);
|
|
622
|
+
if (spotPosition.marketIndex === numericConstants_1.QUOTE_SPOT_MARKET_INDEX &&
|
|
623
|
+
countForQuote) {
|
|
624
|
+
const tokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
|
|
625
|
+
if ((0, types_1.isVariant)(spotPosition.balanceType, 'borrow')) {
|
|
626
|
+
const weightedTokenValue = this.getSpotLiabilityValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory, liquidationBuffer).abs();
|
|
627
|
+
netQuoteValue = netQuoteValue.sub(weightedTokenValue);
|
|
628
|
+
}
|
|
629
|
+
else {
|
|
630
|
+
const weightedTokenValue = this.getSpotAssetValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory);
|
|
631
|
+
netQuoteValue = netQuoteValue.add(weightedTokenValue);
|
|
632
|
+
}
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
if (!includeOpenOrders && countForBase) {
|
|
636
|
+
if ((0, types_1.isVariant)(spotPosition.balanceType, 'borrow')) {
|
|
637
|
+
const tokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), _1.SpotBalanceType.BORROW);
|
|
638
|
+
const liabilityValue = this.getSpotLiabilityValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory, liquidationBuffer).abs();
|
|
639
|
+
totalLiabilityValue = totalLiabilityValue.add(liabilityValue);
|
|
640
|
+
continue;
|
|
641
|
+
}
|
|
642
|
+
else {
|
|
643
|
+
const tokenAmount = (0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType);
|
|
644
|
+
const assetValue = this.getSpotAssetValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory);
|
|
645
|
+
totalAssetValue = totalAssetValue.add(assetValue);
|
|
646
|
+
continue;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
const { tokenAmount: worstCaseTokenAmount, ordersValue: worstCaseQuoteTokenAmount, } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory, this.getUserAccount().maxMarginRatio);
|
|
650
|
+
if (worstCaseTokenAmount.gt(numericConstants_1.ZERO) && countForBase) {
|
|
651
|
+
const baseAssetValue = this.getSpotAssetValue(worstCaseTokenAmount, strictOraclePrice, spotMarketAccount, marginCategory);
|
|
652
|
+
totalAssetValue = totalAssetValue.add(baseAssetValue);
|
|
653
|
+
}
|
|
654
|
+
if (worstCaseTokenAmount.lt(numericConstants_1.ZERO) && countForBase) {
|
|
655
|
+
const baseLiabilityValue = this.getSpotLiabilityValue(worstCaseTokenAmount, strictOraclePrice, spotMarketAccount, marginCategory, liquidationBuffer).abs();
|
|
656
|
+
totalLiabilityValue = totalLiabilityValue.add(baseLiabilityValue);
|
|
657
|
+
}
|
|
658
|
+
if (worstCaseQuoteTokenAmount.gt(numericConstants_1.ZERO) && countForQuote) {
|
|
659
|
+
netQuoteValue = netQuoteValue.add(worstCaseQuoteTokenAmount);
|
|
660
|
+
}
|
|
661
|
+
if (worstCaseQuoteTokenAmount.lt(numericConstants_1.ZERO) && countForQuote) {
|
|
662
|
+
let weight = numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION;
|
|
663
|
+
if (marginCategory === 'Initial') {
|
|
664
|
+
weight = _1.BN.max(weight, new _1.BN(this.getUserAccount().maxMarginRatio));
|
|
665
|
+
}
|
|
666
|
+
const weightedTokenValue = worstCaseQuoteTokenAmount
|
|
667
|
+
.abs()
|
|
668
|
+
.mul(weight)
|
|
669
|
+
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
670
|
+
netQuoteValue = netQuoteValue.sub(weightedTokenValue);
|
|
671
|
+
}
|
|
672
|
+
totalLiabilityValue = totalLiabilityValue.add(new _1.BN(spotPosition.openOrders).mul(numericConstants_1.OPEN_ORDER_MARGIN_REQUIREMENT));
|
|
673
|
+
}
|
|
674
|
+
if (marketIndex === undefined || marketIndex === numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
|
|
675
|
+
if (netQuoteValue.gt(numericConstants_1.ZERO)) {
|
|
676
|
+
totalAssetValue = totalAssetValue.add(netQuoteValue);
|
|
677
|
+
}
|
|
678
|
+
else {
|
|
679
|
+
totalLiabilityValue = totalLiabilityValue.add(netQuoteValue.abs());
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
return { totalAssetValue, totalLiabilityValue };
|
|
683
|
+
}
|
|
684
|
+
getSpotMarketLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict = false, now) {
|
|
685
|
+
const { totalLiabilityValue } = this.getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict, now);
|
|
686
|
+
return totalLiabilityValue;
|
|
687
|
+
}
|
|
688
|
+
getSpotLiabilityValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory, liquidationBuffer) {
|
|
689
|
+
let liabilityValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice);
|
|
690
|
+
if (marginCategory !== undefined) {
|
|
691
|
+
let weight = (0, spotBalance_1.calculateLiabilityWeight)(tokenAmount, spotMarketAccount, marginCategory);
|
|
692
|
+
if (marginCategory === 'Initial' &&
|
|
693
|
+
spotMarketAccount.marketIndex !== numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
|
|
694
|
+
weight = _1.BN.max(weight, numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION.addn(this.getUserAccount().maxMarginRatio));
|
|
695
|
+
}
|
|
696
|
+
if (liquidationBuffer !== undefined) {
|
|
697
|
+
weight = weight.add(liquidationBuffer);
|
|
698
|
+
}
|
|
699
|
+
liabilityValue = liabilityValue
|
|
700
|
+
.mul(weight)
|
|
701
|
+
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
702
|
+
}
|
|
703
|
+
return liabilityValue;
|
|
704
|
+
}
|
|
705
|
+
getSpotMarketAssetValue(marketIndex, marginCategory, includeOpenOrders, strict = false, now) {
|
|
706
|
+
const { totalAssetValue } = this.getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, undefined, includeOpenOrders, strict, now);
|
|
707
|
+
return totalAssetValue;
|
|
708
|
+
}
|
|
709
|
+
getSpotAssetValue(tokenAmount, strictOraclePrice, spotMarketAccount, marginCategory) {
|
|
710
|
+
let assetValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice);
|
|
711
|
+
if (marginCategory !== undefined) {
|
|
712
|
+
let weight = (0, spotBalance_1.calculateAssetWeight)(tokenAmount, strictOraclePrice.current, spotMarketAccount, marginCategory);
|
|
713
|
+
if (marginCategory === 'Initial' &&
|
|
714
|
+
spotMarketAccount.marketIndex !== numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
|
|
715
|
+
const userCustomAssetWeight = _1.BN.max(numericConstants_1.ZERO, numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION.subn(this.getUserAccount().maxMarginRatio));
|
|
716
|
+
weight = _1.BN.min(weight, userCustomAssetWeight);
|
|
717
|
+
}
|
|
718
|
+
assetValue = assetValue.mul(weight).div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
719
|
+
}
|
|
720
|
+
return assetValue;
|
|
721
|
+
}
|
|
722
|
+
getSpotPositionValue(marketIndex, marginCategory, includeOpenOrders, strict = false, now) {
|
|
723
|
+
const { totalAssetValue, totalLiabilityValue } = this.getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, undefined, includeOpenOrders, strict, now);
|
|
724
|
+
return totalAssetValue.sub(totalLiabilityValue);
|
|
725
|
+
}
|
|
726
|
+
getNetSpotMarketValue(withWeightMarginCategory) {
|
|
727
|
+
const { totalAssetValue, totalLiabilityValue } = this.getSpotMarketAssetAndLiabilityValue(undefined, withWeightMarginCategory);
|
|
728
|
+
return totalAssetValue.sub(totalLiabilityValue);
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* calculates TotalCollateral: collateral + unrealized pnl
|
|
732
|
+
* @returns : Precision QUOTE_PRECISION
|
|
733
|
+
*/
|
|
734
|
+
getTotalCollateral(marginCategory = 'Initial', strict = false, includeOpenOrders = true) {
|
|
735
|
+
return this.getSpotMarketAssetValue(undefined, marginCategory, includeOpenOrders, strict).add(this.getUnrealizedPNL(true, undefined, marginCategory, strict));
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* calculates User Health by comparing total collateral and maint. margin requirement
|
|
739
|
+
* @returns : number (value from [0, 100])
|
|
740
|
+
*/
|
|
741
|
+
getHealth() {
|
|
742
|
+
if (this.isBeingLiquidated()) {
|
|
743
|
+
return 0;
|
|
744
|
+
}
|
|
745
|
+
const totalCollateral = this.getTotalCollateral('Maintenance');
|
|
746
|
+
const maintenanceMarginReq = this.getMaintenanceMarginRequirement();
|
|
747
|
+
let health;
|
|
748
|
+
if (maintenanceMarginReq.eq(numericConstants_1.ZERO) && totalCollateral.gte(numericConstants_1.ZERO)) {
|
|
749
|
+
health = 100;
|
|
750
|
+
}
|
|
751
|
+
else if (totalCollateral.lte(numericConstants_1.ZERO)) {
|
|
752
|
+
health = 0;
|
|
753
|
+
}
|
|
754
|
+
else {
|
|
755
|
+
health = Math.round(Math.min(100, Math.max(0, (1 - maintenanceMarginReq.toNumber() / totalCollateral.toNumber()) *
|
|
756
|
+
100)));
|
|
757
|
+
}
|
|
758
|
+
return health;
|
|
759
|
+
}
|
|
760
|
+
calculateWeightedPerpPositionLiability(perpPosition, marginCategory, liquidationBuffer, includeOpenOrders, strict = false) {
|
|
761
|
+
const market = this.driftClient.getPerpMarketAccount(perpPosition.marketIndex);
|
|
762
|
+
if (perpPosition.lpShares.gt(numericConstants_1.ZERO)) {
|
|
763
|
+
// is an lp, clone so we dont mutate the position
|
|
764
|
+
perpPosition = this.getPerpPositionWithLPSettle(market.marketIndex, this.getClonedPosition(perpPosition), !!marginCategory)[0];
|
|
765
|
+
}
|
|
766
|
+
let valuationPrice = this.getOracleDataForPerpMarket(market.marketIndex).price;
|
|
767
|
+
if ((0, types_1.isVariant)(market.status, 'settlement')) {
|
|
768
|
+
valuationPrice = market.expiryPrice;
|
|
769
|
+
}
|
|
770
|
+
let baseAssetAmount;
|
|
771
|
+
let liabilityValue;
|
|
772
|
+
if (includeOpenOrders) {
|
|
773
|
+
const { worstCaseBaseAssetAmount, worstCaseLiabilityValue } = (0, _1.calculateWorstCasePerpLiabilityValue)(perpPosition, market, valuationPrice);
|
|
774
|
+
baseAssetAmount = worstCaseBaseAssetAmount;
|
|
775
|
+
liabilityValue = worstCaseLiabilityValue;
|
|
776
|
+
}
|
|
777
|
+
else {
|
|
778
|
+
baseAssetAmount = perpPosition.baseAssetAmount;
|
|
779
|
+
liabilityValue = (0, _1.calculatePerpLiabilityValue)(baseAssetAmount, valuationPrice, (0, types_1.isVariant)(market.contractType, 'prediction'));
|
|
780
|
+
}
|
|
781
|
+
if (marginCategory) {
|
|
782
|
+
let marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(market, baseAssetAmount.abs(), marginCategory, this.getUserAccount().maxMarginRatio, this.isHighLeverageMode()));
|
|
783
|
+
if (liquidationBuffer !== undefined) {
|
|
784
|
+
marginRatio = marginRatio.add(liquidationBuffer);
|
|
785
|
+
}
|
|
786
|
+
if ((0, types_1.isVariant)(market.status, 'settlement')) {
|
|
787
|
+
marginRatio = numericConstants_1.ZERO;
|
|
788
|
+
}
|
|
789
|
+
const quoteSpotMarket = this.driftClient.getSpotMarketAccount(market.quoteSpotMarketIndex);
|
|
790
|
+
const quoteOraclePriceData = this.driftClient.getOracleDataForSpotMarket(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
|
|
791
|
+
let quotePrice;
|
|
792
|
+
if (strict) {
|
|
793
|
+
quotePrice = _1.BN.max(quoteOraclePriceData.price, quoteSpotMarket.historicalOracleData.lastOraclePriceTwap5Min);
|
|
794
|
+
}
|
|
795
|
+
else {
|
|
796
|
+
quotePrice = quoteOraclePriceData.price;
|
|
797
|
+
}
|
|
798
|
+
liabilityValue = liabilityValue
|
|
799
|
+
.mul(quotePrice)
|
|
800
|
+
.div(numericConstants_1.PRICE_PRECISION)
|
|
801
|
+
.mul(marginRatio)
|
|
802
|
+
.div(numericConstants_1.MARGIN_PRECISION);
|
|
803
|
+
if (includeOpenOrders) {
|
|
804
|
+
liabilityValue = liabilityValue.add(new _1.BN(perpPosition.openOrders).mul(numericConstants_1.OPEN_ORDER_MARGIN_REQUIREMENT));
|
|
805
|
+
if (perpPosition.lpShares.gt(numericConstants_1.ZERO)) {
|
|
806
|
+
liabilityValue = liabilityValue.add(_1.BN.max(numericConstants_1.QUOTE_PRECISION, valuationPrice
|
|
807
|
+
.mul(market.amm.orderStepSize)
|
|
808
|
+
.mul(numericConstants_1.QUOTE_PRECISION)
|
|
809
|
+
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
810
|
+
.div(numericConstants_1.PRICE_PRECISION)));
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
return liabilityValue;
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* calculates position value of a single perp market in margin system
|
|
818
|
+
* @returns : Precision QUOTE_PRECISION
|
|
819
|
+
*/
|
|
820
|
+
getPerpMarketLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict = false) {
|
|
821
|
+
const perpPosition = this.getPerpPosition(marketIndex);
|
|
822
|
+
return this.calculateWeightedPerpPositionLiability(perpPosition, marginCategory, liquidationBuffer, includeOpenOrders, strict);
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
* calculates sum of position value across all positions in margin system
|
|
826
|
+
* @returns : Precision QUOTE_PRECISION
|
|
827
|
+
*/
|
|
828
|
+
getTotalPerpPositionLiability(marginCategory, liquidationBuffer, includeOpenOrders, strict = false) {
|
|
829
|
+
return this.getActivePerpPositions().reduce((totalPerpValue, perpPosition) => {
|
|
830
|
+
const baseAssetValue = this.calculateWeightedPerpPositionLiability(perpPosition, marginCategory, liquidationBuffer, includeOpenOrders, strict);
|
|
831
|
+
return totalPerpValue.add(baseAssetValue);
|
|
832
|
+
}, numericConstants_1.ZERO);
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* calculates position value based on oracle
|
|
836
|
+
* @returns : Precision QUOTE_PRECISION
|
|
837
|
+
*/
|
|
838
|
+
getPerpPositionValue(marketIndex, oraclePriceData, includeOpenOrders = false) {
|
|
839
|
+
const userPosition = this.getPerpPositionWithLPSettle(marketIndex, undefined, false, true)[0] || this.getEmptyPosition(marketIndex);
|
|
840
|
+
const market = this.driftClient.getPerpMarketAccount(userPosition.marketIndex);
|
|
841
|
+
return (0, margin_1.calculateBaseAssetValueWithOracle)(market, userPosition, oraclePriceData, includeOpenOrders);
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* calculates position liabiltiy value in margin system
|
|
845
|
+
* @returns : Precision QUOTE_PRECISION
|
|
846
|
+
*/
|
|
847
|
+
getPerpLiabilityValue(marketIndex, oraclePriceData, includeOpenOrders = false) {
|
|
848
|
+
const userPosition = this.getPerpPositionWithLPSettle(marketIndex, undefined, false, true)[0] || this.getEmptyPosition(marketIndex);
|
|
849
|
+
const market = this.driftClient.getPerpMarketAccount(userPosition.marketIndex);
|
|
850
|
+
if (includeOpenOrders) {
|
|
851
|
+
return (0, _1.calculateWorstCasePerpLiabilityValue)(userPosition, market, oraclePriceData.price).worstCaseLiabilityValue;
|
|
852
|
+
}
|
|
853
|
+
else {
|
|
854
|
+
return (0, _1.calculatePerpLiabilityValue)(userPosition.baseAssetAmount, oraclePriceData.price, (0, types_1.isVariant)(market.contractType, 'prediction'));
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
getPositionSide(currentPosition) {
|
|
858
|
+
if (currentPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
|
|
859
|
+
return _1.PositionDirection.LONG;
|
|
860
|
+
}
|
|
861
|
+
else if (currentPosition.baseAssetAmount.lt(numericConstants_1.ZERO)) {
|
|
862
|
+
return _1.PositionDirection.SHORT;
|
|
863
|
+
}
|
|
864
|
+
else {
|
|
865
|
+
return undefined;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* calculates average exit price (optionally for closing up to 100% of position)
|
|
870
|
+
* @returns : Precision PRICE_PRECISION
|
|
871
|
+
*/
|
|
872
|
+
getPositionEstimatedExitPriceAndPnl(position, amountToClose, useAMMClose = false) {
|
|
873
|
+
const market = this.driftClient.getPerpMarketAccount(position.marketIndex);
|
|
874
|
+
const entryPrice = (0, position_1.calculateEntryPrice)(position);
|
|
875
|
+
const oraclePriceData = this.getOracleDataForPerpMarket(position.marketIndex);
|
|
876
|
+
if (amountToClose) {
|
|
877
|
+
if (amountToClose.eq(numericConstants_1.ZERO)) {
|
|
878
|
+
return [(0, _1.calculateReservePrice)(market, oraclePriceData), numericConstants_1.ZERO];
|
|
879
|
+
}
|
|
880
|
+
position = {
|
|
881
|
+
baseAssetAmount: amountToClose,
|
|
882
|
+
lastCumulativeFundingRate: position.lastCumulativeFundingRate,
|
|
883
|
+
marketIndex: position.marketIndex,
|
|
884
|
+
quoteAssetAmount: position.quoteAssetAmount,
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
let baseAssetValue;
|
|
888
|
+
if (useAMMClose) {
|
|
889
|
+
baseAssetValue = (0, _1.calculateBaseAssetValue)(market, position, oraclePriceData);
|
|
890
|
+
}
|
|
891
|
+
else {
|
|
892
|
+
baseAssetValue = (0, margin_1.calculateBaseAssetValueWithOracle)(market, position, oraclePriceData);
|
|
893
|
+
}
|
|
894
|
+
if (position.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
895
|
+
return [numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
896
|
+
}
|
|
897
|
+
const exitPrice = baseAssetValue
|
|
898
|
+
.mul(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO)
|
|
899
|
+
.mul(numericConstants_1.PRICE_PRECISION)
|
|
900
|
+
.div(position.baseAssetAmount.abs());
|
|
901
|
+
const pnlPerBase = exitPrice.sub(entryPrice);
|
|
902
|
+
const pnl = pnlPerBase
|
|
903
|
+
.mul(position.baseAssetAmount)
|
|
904
|
+
.div(numericConstants_1.PRICE_PRECISION)
|
|
905
|
+
.div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO);
|
|
906
|
+
return [exitPrice, pnl];
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* calculates current user leverage which is (total liability size) / (net asset value)
|
|
910
|
+
* @returns : Precision TEN_THOUSAND
|
|
911
|
+
*/
|
|
912
|
+
getLeverage(includeOpenOrders = true) {
|
|
913
|
+
return this.calculateLeverageFromComponents(this.getLeverageComponents(includeOpenOrders));
|
|
914
|
+
}
|
|
915
|
+
calculateLeverageFromComponents({ perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue, }) {
|
|
916
|
+
const totalLiabilityValue = perpLiabilityValue.add(spotLiabilityValue);
|
|
917
|
+
const totalAssetValue = spotAssetValue.add(perpPnl);
|
|
918
|
+
const netAssetValue = totalAssetValue.sub(spotLiabilityValue);
|
|
919
|
+
if (netAssetValue.eq(numericConstants_1.ZERO)) {
|
|
920
|
+
return numericConstants_1.ZERO;
|
|
921
|
+
}
|
|
922
|
+
return totalLiabilityValue.mul(numericConstants_1.TEN_THOUSAND).div(netAssetValue);
|
|
923
|
+
}
|
|
924
|
+
getLeverageComponents(includeOpenOrders = true, marginCategory = undefined) {
|
|
925
|
+
const perpLiability = this.getTotalPerpPositionLiability(marginCategory, undefined, includeOpenOrders);
|
|
926
|
+
const perpPnl = this.getUnrealizedPNL(true, undefined, marginCategory);
|
|
927
|
+
const { totalAssetValue: spotAssetValue, totalLiabilityValue: spotLiabilityValue, } = this.getSpotMarketAssetAndLiabilityValue(undefined, marginCategory, undefined, includeOpenOrders);
|
|
928
|
+
return {
|
|
929
|
+
perpLiabilityValue: perpLiability,
|
|
930
|
+
perpPnl,
|
|
931
|
+
spotAssetValue,
|
|
932
|
+
spotLiabilityValue,
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
isDustDepositPosition(spotMarketAccount) {
|
|
936
|
+
const marketIndex = spotMarketAccount.marketIndex;
|
|
937
|
+
const spotPosition = this.getSpotPosition(spotMarketAccount.marketIndex);
|
|
938
|
+
if ((0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
|
|
939
|
+
return false;
|
|
940
|
+
}
|
|
941
|
+
const depositAmount = this.getTokenAmount(spotMarketAccount.marketIndex);
|
|
942
|
+
if (depositAmount.lte(numericConstants_1.ZERO)) {
|
|
943
|
+
return false;
|
|
944
|
+
}
|
|
945
|
+
const oraclePriceData = this.getOracleDataForSpotMarket(marketIndex);
|
|
946
|
+
const strictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(oraclePriceData.price, oraclePriceData.twap);
|
|
947
|
+
const balanceValue = this.getSpotAssetValue(depositAmount, strictOraclePrice, spotMarketAccount);
|
|
948
|
+
if (balanceValue.lt(numericConstants_1.DUST_POSITION_SIZE)) {
|
|
949
|
+
return true;
|
|
950
|
+
}
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
953
|
+
getSpotMarketAccountsWithDustPosition() {
|
|
954
|
+
const spotMarketAccounts = this.driftClient.getSpotMarketAccounts();
|
|
955
|
+
const dustPositionAccounts = [];
|
|
956
|
+
for (const spotMarketAccount of spotMarketAccounts) {
|
|
957
|
+
const isDust = this.isDustDepositPosition(spotMarketAccount);
|
|
958
|
+
if (isDust) {
|
|
959
|
+
dustPositionAccounts.push(spotMarketAccount);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
return dustPositionAccounts;
|
|
963
|
+
}
|
|
964
|
+
getTotalLiabilityValue(marginCategory) {
|
|
965
|
+
return this.getTotalPerpPositionLiability(marginCategory, undefined, true).add(this.getSpotMarketLiabilityValue(undefined, marginCategory, undefined, true));
|
|
966
|
+
}
|
|
967
|
+
getTotalAssetValue(marginCategory) {
|
|
968
|
+
return this.getSpotMarketAssetValue(undefined, marginCategory, true).add(this.getUnrealizedPNL(true, undefined, marginCategory));
|
|
969
|
+
}
|
|
970
|
+
getNetUsdValue() {
|
|
971
|
+
const netSpotValue = this.getNetSpotMarketValue();
|
|
972
|
+
const unrealizedPnl = this.getUnrealizedPNL(true, undefined, undefined);
|
|
973
|
+
return netSpotValue.add(unrealizedPnl);
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
976
|
+
* Calculates the all time P&L of the user.
|
|
977
|
+
*
|
|
978
|
+
* Net withdraws + Net spot market value + Net unrealized P&L -
|
|
979
|
+
*/
|
|
980
|
+
getTotalAllTimePnl() {
|
|
981
|
+
const netUsdValue = this.getNetUsdValue();
|
|
982
|
+
const totalDeposits = this.getUserAccount().totalDeposits;
|
|
983
|
+
const totalWithdraws = this.getUserAccount().totalWithdraws;
|
|
984
|
+
const totalPnl = netUsdValue.add(totalWithdraws).sub(totalDeposits);
|
|
985
|
+
return totalPnl;
|
|
986
|
+
}
|
|
987
|
+
/**
|
|
988
|
+
* calculates max allowable leverage exceeding hitting requirement category
|
|
989
|
+
* for large sizes where imf factor activates, result is a lower bound
|
|
990
|
+
* @param marginCategory {Initial, Maintenance}
|
|
991
|
+
* @param isLp if calculating max leveraging for adding lp, need to add buffer
|
|
992
|
+
* @returns : Precision TEN_THOUSAND
|
|
993
|
+
*/
|
|
994
|
+
getMaxLeverageForPerp(perpMarketIndex, marginCategory = 'Initial', isLp = false) {
|
|
995
|
+
const market = this.driftClient.getPerpMarketAccount(perpMarketIndex);
|
|
996
|
+
const marketPrice = this.driftClient.getOracleDataForPerpMarket(perpMarketIndex).price;
|
|
997
|
+
const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
|
|
998
|
+
const totalAssetValue = spotAssetValue.add(perpPnl);
|
|
999
|
+
const netAssetValue = totalAssetValue.sub(spotLiabilityValue);
|
|
1000
|
+
if (netAssetValue.eq(numericConstants_1.ZERO)) {
|
|
1001
|
+
return numericConstants_1.ZERO;
|
|
1002
|
+
}
|
|
1003
|
+
const totalLiabilityValue = perpLiabilityValue.add(spotLiabilityValue);
|
|
1004
|
+
const lpBuffer = isLp
|
|
1005
|
+
? marketPrice.mul(market.amm.orderStepSize).div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
1006
|
+
: numericConstants_1.ZERO;
|
|
1007
|
+
const freeCollateral = this.getFreeCollateral().sub(lpBuffer);
|
|
1008
|
+
let rawMarginRatio;
|
|
1009
|
+
switch (marginCategory) {
|
|
1010
|
+
case 'Initial':
|
|
1011
|
+
rawMarginRatio = Math.max(market.marginRatioInitial, this.getUserAccount().maxMarginRatio);
|
|
1012
|
+
break;
|
|
1013
|
+
case 'Maintenance':
|
|
1014
|
+
rawMarginRatio = market.marginRatioMaintenance;
|
|
1015
|
+
break;
|
|
1016
|
+
default:
|
|
1017
|
+
rawMarginRatio = market.marginRatioInitial;
|
|
1018
|
+
break;
|
|
1019
|
+
}
|
|
1020
|
+
// absolute max fesible size (upper bound)
|
|
1021
|
+
const maxSize = _1.BN.max(numericConstants_1.ZERO, freeCollateral
|
|
1022
|
+
.mul(numericConstants_1.MARGIN_PRECISION)
|
|
1023
|
+
.div(new _1.BN(rawMarginRatio))
|
|
1024
|
+
.mul(numericConstants_1.PRICE_PRECISION)
|
|
1025
|
+
.div(marketPrice));
|
|
1026
|
+
// margin ratio incorporting upper bound on size
|
|
1027
|
+
let marginRatio = (0, _1.calculateMarketMarginRatio)(market, maxSize, marginCategory, this.getUserAccount().maxMarginRatio, this.isHighLeverageMode());
|
|
1028
|
+
// use more fesible size since imf factor activated
|
|
1029
|
+
let attempts = 0;
|
|
1030
|
+
while (marginRatio > rawMarginRatio + 1e-4 && attempts < 10) {
|
|
1031
|
+
// more fesible size (upper bound)
|
|
1032
|
+
const targetSize = _1.BN.max(numericConstants_1.ZERO, freeCollateral
|
|
1033
|
+
.mul(numericConstants_1.MARGIN_PRECISION)
|
|
1034
|
+
.div(new _1.BN(marginRatio))
|
|
1035
|
+
.mul(numericConstants_1.PRICE_PRECISION)
|
|
1036
|
+
.div(marketPrice));
|
|
1037
|
+
// margin ratio incorporting more fesible target size
|
|
1038
|
+
marginRatio = (0, _1.calculateMarketMarginRatio)(market, targetSize, marginCategory, this.getUserAccount().maxMarginRatio, this.isHighLeverageMode());
|
|
1039
|
+
attempts += 1;
|
|
1040
|
+
}
|
|
1041
|
+
// how much more liabilities can be opened w remaining free collateral
|
|
1042
|
+
const additionalLiabilities = freeCollateral
|
|
1043
|
+
.mul(numericConstants_1.MARGIN_PRECISION)
|
|
1044
|
+
.div(new _1.BN(marginRatio));
|
|
1045
|
+
return totalLiabilityValue
|
|
1046
|
+
.add(additionalLiabilities)
|
|
1047
|
+
.mul(numericConstants_1.TEN_THOUSAND)
|
|
1048
|
+
.div(netAssetValue);
|
|
1049
|
+
}
|
|
1050
|
+
/**
|
|
1051
|
+
* calculates max allowable leverage exceeding hitting requirement category
|
|
1052
|
+
* @param spotMarketIndex
|
|
1053
|
+
* @param direction
|
|
1054
|
+
* @returns : Precision TEN_THOUSAND
|
|
1055
|
+
*/
|
|
1056
|
+
getMaxLeverageForSpot(spotMarketIndex, direction) {
|
|
1057
|
+
const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
|
|
1058
|
+
const totalLiabilityValue = perpLiabilityValue.add(spotLiabilityValue);
|
|
1059
|
+
const totalAssetValue = spotAssetValue.add(perpPnl);
|
|
1060
|
+
const netAssetValue = totalAssetValue.sub(spotLiabilityValue);
|
|
1061
|
+
if (netAssetValue.eq(numericConstants_1.ZERO)) {
|
|
1062
|
+
return numericConstants_1.ZERO;
|
|
1063
|
+
}
|
|
1064
|
+
const currentQuoteAssetValue = this.getSpotMarketAssetValue(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
|
|
1065
|
+
const currentQuoteLiabilityValue = this.getSpotMarketLiabilityValue(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
|
|
1066
|
+
const currentQuoteValue = currentQuoteAssetValue.sub(currentQuoteLiabilityValue);
|
|
1067
|
+
const currentSpotMarketAssetValue = this.getSpotMarketAssetValue(spotMarketIndex);
|
|
1068
|
+
const currentSpotMarketLiabilityValue = this.getSpotMarketLiabilityValue(spotMarketIndex);
|
|
1069
|
+
const currentSpotMarketNetValue = currentSpotMarketAssetValue.sub(currentSpotMarketLiabilityValue);
|
|
1070
|
+
const tradeQuoteAmount = this.getMaxTradeSizeUSDCForSpot(spotMarketIndex, direction, currentQuoteAssetValue, currentSpotMarketNetValue);
|
|
1071
|
+
let assetValueToAdd = numericConstants_1.ZERO;
|
|
1072
|
+
let liabilityValueToAdd = numericConstants_1.ZERO;
|
|
1073
|
+
const newQuoteNetValue = (0, types_1.isVariant)(direction, 'short')
|
|
1074
|
+
? currentQuoteValue.add(tradeQuoteAmount)
|
|
1075
|
+
: currentQuoteValue.sub(tradeQuoteAmount);
|
|
1076
|
+
const newQuoteAssetValue = _1.BN.max(newQuoteNetValue, numericConstants_1.ZERO);
|
|
1077
|
+
const newQuoteLiabilityValue = _1.BN.min(newQuoteNetValue, numericConstants_1.ZERO).abs();
|
|
1078
|
+
assetValueToAdd = assetValueToAdd.add(newQuoteAssetValue.sub(currentQuoteAssetValue));
|
|
1079
|
+
liabilityValueToAdd = liabilityValueToAdd.add(newQuoteLiabilityValue.sub(currentQuoteLiabilityValue));
|
|
1080
|
+
const newSpotMarketNetValue = (0, types_1.isVariant)(direction, 'long')
|
|
1081
|
+
? currentSpotMarketNetValue.add(tradeQuoteAmount)
|
|
1082
|
+
: currentSpotMarketNetValue.sub(tradeQuoteAmount);
|
|
1083
|
+
const newSpotMarketAssetValue = _1.BN.max(newSpotMarketNetValue, numericConstants_1.ZERO);
|
|
1084
|
+
const newSpotMarketLiabilityValue = _1.BN.min(newSpotMarketNetValue, numericConstants_1.ZERO).abs();
|
|
1085
|
+
assetValueToAdd = assetValueToAdd.add(newSpotMarketAssetValue.sub(currentSpotMarketAssetValue));
|
|
1086
|
+
liabilityValueToAdd = liabilityValueToAdd.add(newSpotMarketLiabilityValue.sub(currentSpotMarketLiabilityValue));
|
|
1087
|
+
const finalTotalAssetValue = totalAssetValue.add(assetValueToAdd);
|
|
1088
|
+
const finalTotalSpotLiability = spotLiabilityValue.add(liabilityValueToAdd);
|
|
1089
|
+
const finalTotalLiabilityValue = totalLiabilityValue.add(liabilityValueToAdd);
|
|
1090
|
+
const finalNetAssetValue = finalTotalAssetValue.sub(finalTotalSpotLiability);
|
|
1091
|
+
return finalTotalLiabilityValue.mul(numericConstants_1.TEN_THOUSAND).div(finalNetAssetValue);
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* calculates margin ratio: 1 / leverage
|
|
1095
|
+
* @returns : Precision TEN_THOUSAND
|
|
1096
|
+
*/
|
|
1097
|
+
getMarginRatio() {
|
|
1098
|
+
const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
|
|
1099
|
+
const totalLiabilityValue = perpLiabilityValue.add(spotLiabilityValue);
|
|
1100
|
+
const totalAssetValue = spotAssetValue.add(perpPnl);
|
|
1101
|
+
if (totalLiabilityValue.eq(numericConstants_1.ZERO)) {
|
|
1102
|
+
return numericConstants_1.BN_MAX;
|
|
1103
|
+
}
|
|
1104
|
+
const netAssetValue = totalAssetValue.sub(spotLiabilityValue);
|
|
1105
|
+
return netAssetValue.mul(numericConstants_1.TEN_THOUSAND).div(totalLiabilityValue);
|
|
1106
|
+
}
|
|
1107
|
+
canBeLiquidated() {
|
|
1108
|
+
const totalCollateral = this.getTotalCollateral('Maintenance');
|
|
1109
|
+
const marginRequirement = this.getMaintenanceMarginRequirement();
|
|
1110
|
+
const canBeLiquidated = totalCollateral.lt(marginRequirement);
|
|
1111
|
+
return {
|
|
1112
|
+
canBeLiquidated,
|
|
1113
|
+
marginRequirement,
|
|
1114
|
+
totalCollateral,
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
isBeingLiquidated() {
|
|
1118
|
+
return ((this.getUserAccount().status &
|
|
1119
|
+
(types_1.UserStatus.BEING_LIQUIDATED | types_1.UserStatus.BANKRUPT)) >
|
|
1120
|
+
0);
|
|
1121
|
+
}
|
|
1122
|
+
hasStatus(status) {
|
|
1123
|
+
return (this.getUserAccount().status & status) > 0;
|
|
1124
|
+
}
|
|
1125
|
+
isBankrupt() {
|
|
1126
|
+
return (this.getUserAccount().status & types_1.UserStatus.BANKRUPT) > 0;
|
|
1127
|
+
}
|
|
1128
|
+
isHighLeverageMode() {
|
|
1129
|
+
return (0, types_1.isVariant)(this.getUserAccount().marginMode, 'highLeverage');
|
|
1130
|
+
}
|
|
1131
|
+
/**
|
|
1132
|
+
* Checks if any user position cumulative funding differs from respective market cumulative funding
|
|
1133
|
+
* @returns
|
|
1134
|
+
*/
|
|
1135
|
+
needsToSettleFundingPayment() {
|
|
1136
|
+
for (const userPosition of this.getUserAccount().perpPositions) {
|
|
1137
|
+
if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
1138
|
+
continue;
|
|
1139
|
+
}
|
|
1140
|
+
const market = this.driftClient.getPerpMarketAccount(userPosition.marketIndex);
|
|
1141
|
+
if (market.amm.cumulativeFundingRateLong.eq(userPosition.lastCumulativeFundingRate) ||
|
|
1142
|
+
market.amm.cumulativeFundingRateShort.eq(userPosition.lastCumulativeFundingRate)) {
|
|
1143
|
+
continue;
|
|
1144
|
+
}
|
|
1145
|
+
return true;
|
|
1146
|
+
}
|
|
1147
|
+
return false;
|
|
1148
|
+
}
|
|
1149
|
+
/**
|
|
1150
|
+
* Calculate the liquidation price of a spot position
|
|
1151
|
+
* @param marketIndex
|
|
1152
|
+
* @returns Precision : PRICE_PRECISION
|
|
1153
|
+
*/
|
|
1154
|
+
spotLiquidationPrice(marketIndex, positionBaseSizeChange = numericConstants_1.ZERO) {
|
|
1155
|
+
const currentSpotPosition = this.getSpotPosition(marketIndex);
|
|
1156
|
+
if (!currentSpotPosition) {
|
|
1157
|
+
return new _1.BN(-1);
|
|
1158
|
+
}
|
|
1159
|
+
const totalCollateral = this.getTotalCollateral('Maintenance');
|
|
1160
|
+
const maintenanceMarginRequirement = this.getMaintenanceMarginRequirement();
|
|
1161
|
+
const freeCollateral = _1.BN.max(numericConstants_1.ZERO, totalCollateral.sub(maintenanceMarginRequirement));
|
|
1162
|
+
const market = this.driftClient.getSpotMarketAccount(marketIndex);
|
|
1163
|
+
let signedTokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(currentSpotPosition.scaledBalance, market, currentSpotPosition.balanceType), currentSpotPosition.balanceType);
|
|
1164
|
+
signedTokenAmount = signedTokenAmount.add(positionBaseSizeChange);
|
|
1165
|
+
if (signedTokenAmount.eq(numericConstants_1.ZERO)) {
|
|
1166
|
+
return new _1.BN(-1);
|
|
1167
|
+
}
|
|
1168
|
+
let freeCollateralDelta = this.calculateFreeCollateralDeltaForSpot(market, signedTokenAmount);
|
|
1169
|
+
const oracle = market.oracle;
|
|
1170
|
+
const perpMarketWithSameOracle = this.driftClient
|
|
1171
|
+
.getPerpMarketAccounts()
|
|
1172
|
+
.find((market) => market.amm.oracle.equals(oracle));
|
|
1173
|
+
const oraclePrice = this.driftClient.getOracleDataForSpotMarket(marketIndex).price;
|
|
1174
|
+
if (perpMarketWithSameOracle) {
|
|
1175
|
+
const perpPosition = this.getPerpPositionWithLPSettle(perpMarketWithSameOracle.marketIndex, undefined, true)[0];
|
|
1176
|
+
if (perpPosition) {
|
|
1177
|
+
const freeCollateralDeltaForPerp = this.calculateFreeCollateralDeltaForPerp(perpMarketWithSameOracle, perpPosition, numericConstants_1.ZERO, oraclePrice);
|
|
1178
|
+
freeCollateralDelta = freeCollateralDelta.add(freeCollateralDeltaForPerp || numericConstants_1.ZERO);
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
if (freeCollateralDelta.eq(numericConstants_1.ZERO)) {
|
|
1182
|
+
return new _1.BN(-1);
|
|
1183
|
+
}
|
|
1184
|
+
const liqPriceDelta = freeCollateral
|
|
1185
|
+
.mul(numericConstants_1.QUOTE_PRECISION)
|
|
1186
|
+
.div(freeCollateralDelta);
|
|
1187
|
+
const liqPrice = oraclePrice.sub(liqPriceDelta);
|
|
1188
|
+
if (liqPrice.lt(numericConstants_1.ZERO)) {
|
|
1189
|
+
return new _1.BN(-1);
|
|
1190
|
+
}
|
|
1191
|
+
return liqPrice;
|
|
1192
|
+
}
|
|
1193
|
+
/**
|
|
1194
|
+
* Calculate the liquidation price of a perp position, with optional parameter to calculate the liquidation price after a trade
|
|
1195
|
+
* @param marketIndex
|
|
1196
|
+
* @param positionBaseSizeChange // change in position size to calculate liquidation price for : Precision 10^9
|
|
1197
|
+
* @param estimatedEntryPrice
|
|
1198
|
+
* @param marginCategory // allow Initial to be passed in if we are trying to calculate price for DLP de-risking
|
|
1199
|
+
* @param includeOpenOrders
|
|
1200
|
+
* @param offsetCollateral // allows calculating the liquidation price after this offset collateral is added to the user's account (e.g. : what will the liquidation price be for this position AFTER I deposit $x worth of collateral)
|
|
1201
|
+
* @returns Precision : PRICE_PRECISION
|
|
1202
|
+
*/
|
|
1203
|
+
liquidationPrice(marketIndex, positionBaseSizeChange = numericConstants_1.ZERO, estimatedEntryPrice = numericConstants_1.ZERO, marginCategory = 'Maintenance', includeOpenOrders = false, offsetCollateral = numericConstants_1.ZERO) {
|
|
1204
|
+
const totalCollateral = this.getTotalCollateral(marginCategory, false, includeOpenOrders);
|
|
1205
|
+
const marginRequirement = this.getMarginRequirement(marginCategory, undefined, false, includeOpenOrders);
|
|
1206
|
+
let freeCollateral = _1.BN.max(numericConstants_1.ZERO, totalCollateral.sub(marginRequirement)).add(offsetCollateral);
|
|
1207
|
+
const oracle = this.driftClient.getPerpMarketAccount(marketIndex).amm.oracle;
|
|
1208
|
+
const oraclePrice = this.driftClient.getOracleDataForPerpMarket(marketIndex).price;
|
|
1209
|
+
const market = this.driftClient.getPerpMarketAccount(marketIndex);
|
|
1210
|
+
const currentPerpPosition = this.getPerpPositionWithLPSettle(marketIndex, undefined, true)[0] ||
|
|
1211
|
+
this.getEmptyPosition(marketIndex);
|
|
1212
|
+
positionBaseSizeChange = (0, _1.standardizeBaseAssetAmount)(positionBaseSizeChange, market.amm.orderStepSize);
|
|
1213
|
+
const freeCollateralChangeFromNewPosition = this.calculateEntriesEffectOnFreeCollateral(market, oraclePrice, currentPerpPosition, positionBaseSizeChange, estimatedEntryPrice, includeOpenOrders);
|
|
1214
|
+
freeCollateral = freeCollateral.add(freeCollateralChangeFromNewPosition);
|
|
1215
|
+
let freeCollateralDelta = this.calculateFreeCollateralDeltaForPerp(market, currentPerpPosition, positionBaseSizeChange, oraclePrice, marginCategory, includeOpenOrders);
|
|
1216
|
+
if (!freeCollateralDelta) {
|
|
1217
|
+
return new _1.BN(-1);
|
|
1218
|
+
}
|
|
1219
|
+
const spotMarketWithSameOracle = this.driftClient
|
|
1220
|
+
.getSpotMarketAccounts()
|
|
1221
|
+
.find((market) => market.oracle.equals(oracle));
|
|
1222
|
+
if (spotMarketWithSameOracle) {
|
|
1223
|
+
const spotPosition = this.getSpotPosition(spotMarketWithSameOracle.marketIndex);
|
|
1224
|
+
if (spotPosition) {
|
|
1225
|
+
const signedTokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketWithSameOracle, spotPosition.balanceType), spotPosition.balanceType);
|
|
1226
|
+
const spotFreeCollateralDelta = this.calculateFreeCollateralDeltaForSpot(spotMarketWithSameOracle, signedTokenAmount, marginCategory);
|
|
1227
|
+
freeCollateralDelta = freeCollateralDelta.add(spotFreeCollateralDelta || numericConstants_1.ZERO);
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
if (freeCollateralDelta.eq(numericConstants_1.ZERO)) {
|
|
1231
|
+
return new _1.BN(-1);
|
|
1232
|
+
}
|
|
1233
|
+
const liqPriceDelta = freeCollateral
|
|
1234
|
+
.mul(numericConstants_1.QUOTE_PRECISION)
|
|
1235
|
+
.div(freeCollateralDelta);
|
|
1236
|
+
const liqPrice = oraclePrice.sub(liqPriceDelta);
|
|
1237
|
+
if (liqPrice.lt(numericConstants_1.ZERO)) {
|
|
1238
|
+
return new _1.BN(-1);
|
|
1239
|
+
}
|
|
1240
|
+
return liqPrice;
|
|
1241
|
+
}
|
|
1242
|
+
calculateEntriesEffectOnFreeCollateral(market, oraclePrice, perpPosition, positionBaseSizeChange, estimatedEntryPrice, includeOpenOrders) {
|
|
1243
|
+
let freeCollateralChange = numericConstants_1.ZERO;
|
|
1244
|
+
// update free collateral to account for change in pnl from new position
|
|
1245
|
+
if (!estimatedEntryPrice.eq(numericConstants_1.ZERO) && !positionBaseSizeChange.eq(numericConstants_1.ZERO)) {
|
|
1246
|
+
const costBasis = oraclePrice
|
|
1247
|
+
.mul(positionBaseSizeChange.abs())
|
|
1248
|
+
.div(numericConstants_1.BASE_PRECISION);
|
|
1249
|
+
const newPositionValue = estimatedEntryPrice
|
|
1250
|
+
.mul(positionBaseSizeChange.abs())
|
|
1251
|
+
.div(numericConstants_1.BASE_PRECISION);
|
|
1252
|
+
if (positionBaseSizeChange.gt(numericConstants_1.ZERO)) {
|
|
1253
|
+
freeCollateralChange = costBasis.sub(newPositionValue);
|
|
1254
|
+
}
|
|
1255
|
+
else {
|
|
1256
|
+
freeCollateralChange = newPositionValue.sub(costBasis);
|
|
1257
|
+
}
|
|
1258
|
+
// assume worst fee tier
|
|
1259
|
+
const takerFeeTier = this.driftClient.getStateAccount().perpFeeStructure.feeTiers[0];
|
|
1260
|
+
const takerFee = newPositionValue
|
|
1261
|
+
.muln(takerFeeTier.feeNumerator)
|
|
1262
|
+
.divn(takerFeeTier.feeDenominator);
|
|
1263
|
+
freeCollateralChange = freeCollateralChange.sub(takerFee);
|
|
1264
|
+
}
|
|
1265
|
+
const calculateMarginRequirement = (perpPosition) => {
|
|
1266
|
+
let baseAssetAmount;
|
|
1267
|
+
let liabilityValue;
|
|
1268
|
+
if (includeOpenOrders) {
|
|
1269
|
+
const { worstCaseBaseAssetAmount, worstCaseLiabilityValue } = (0, _1.calculateWorstCasePerpLiabilityValue)(perpPosition, market, oraclePrice);
|
|
1270
|
+
baseAssetAmount = worstCaseBaseAssetAmount;
|
|
1271
|
+
liabilityValue = worstCaseLiabilityValue;
|
|
1272
|
+
}
|
|
1273
|
+
else {
|
|
1274
|
+
baseAssetAmount = perpPosition.baseAssetAmount;
|
|
1275
|
+
liabilityValue = (0, _1.calculatePerpLiabilityValue)(baseAssetAmount, oraclePrice, (0, types_1.isVariant)(market.contractType, 'prediction'));
|
|
1276
|
+
}
|
|
1277
|
+
const marginRatio = (0, _1.calculateMarketMarginRatio)(market, baseAssetAmount.abs(), 'Maintenance', this.getUserAccount().maxMarginRatio, this.isHighLeverageMode());
|
|
1278
|
+
return liabilityValue.mul(new _1.BN(marginRatio)).div(numericConstants_1.MARGIN_PRECISION);
|
|
1279
|
+
};
|
|
1280
|
+
const freeCollateralConsumptionBefore = calculateMarginRequirement(perpPosition);
|
|
1281
|
+
const perpPositionAfter = Object.assign({}, perpPosition);
|
|
1282
|
+
perpPositionAfter.baseAssetAmount = perpPositionAfter.baseAssetAmount.add(positionBaseSizeChange);
|
|
1283
|
+
const freeCollateralConsumptionAfter = calculateMarginRequirement(perpPositionAfter);
|
|
1284
|
+
return freeCollateralChange.sub(freeCollateralConsumptionAfter.sub(freeCollateralConsumptionBefore));
|
|
1285
|
+
}
|
|
1286
|
+
calculateFreeCollateralDeltaForPerp(market, perpPosition, positionBaseSizeChange, oraclePrice, marginCategory = 'Maintenance', includeOpenOrders = false) {
|
|
1287
|
+
const baseAssetAmount = includeOpenOrders
|
|
1288
|
+
? (0, margin_1.calculateWorstCaseBaseAssetAmount)(perpPosition, market, oraclePrice)
|
|
1289
|
+
: perpPosition.baseAssetAmount;
|
|
1290
|
+
// zero if include orders == false
|
|
1291
|
+
const orderBaseAssetAmount = baseAssetAmount.sub(perpPosition.baseAssetAmount);
|
|
1292
|
+
const proposedBaseAssetAmount = baseAssetAmount.add(positionBaseSizeChange);
|
|
1293
|
+
const marginRatio = (0, _1.calculateMarketMarginRatio)(market, proposedBaseAssetAmount.abs(), marginCategory, this.getUserAccount().maxMarginRatio, this.isHighLeverageMode());
|
|
1294
|
+
const marginRatioQuotePrecision = new _1.BN(marginRatio)
|
|
1295
|
+
.mul(numericConstants_1.QUOTE_PRECISION)
|
|
1296
|
+
.div(numericConstants_1.MARGIN_PRECISION);
|
|
1297
|
+
if (proposedBaseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
1298
|
+
return undefined;
|
|
1299
|
+
}
|
|
1300
|
+
let freeCollateralDelta = numericConstants_1.ZERO;
|
|
1301
|
+
if ((0, types_1.isVariant)(market.contractType, 'prediction')) {
|
|
1302
|
+
// for prediction market, increase in pnl and margin requirement will net out for position
|
|
1303
|
+
// open order margin requirement will change with price though
|
|
1304
|
+
if (orderBaseAssetAmount.gt(numericConstants_1.ZERO)) {
|
|
1305
|
+
freeCollateralDelta = marginRatioQuotePrecision.neg();
|
|
1306
|
+
}
|
|
1307
|
+
else if (orderBaseAssetAmount.lt(numericConstants_1.ZERO)) {
|
|
1308
|
+
freeCollateralDelta = marginRatioQuotePrecision;
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
else {
|
|
1312
|
+
if (proposedBaseAssetAmount.gt(numericConstants_1.ZERO)) {
|
|
1313
|
+
freeCollateralDelta = numericConstants_1.QUOTE_PRECISION.sub(marginRatioQuotePrecision)
|
|
1314
|
+
.mul(proposedBaseAssetAmount)
|
|
1315
|
+
.div(numericConstants_1.BASE_PRECISION);
|
|
1316
|
+
}
|
|
1317
|
+
else {
|
|
1318
|
+
freeCollateralDelta = numericConstants_1.QUOTE_PRECISION.neg()
|
|
1319
|
+
.sub(marginRatioQuotePrecision)
|
|
1320
|
+
.mul(proposedBaseAssetAmount.abs())
|
|
1321
|
+
.div(numericConstants_1.BASE_PRECISION);
|
|
1322
|
+
}
|
|
1323
|
+
if (!orderBaseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
1324
|
+
freeCollateralDelta = freeCollateralDelta.sub(marginRatioQuotePrecision
|
|
1325
|
+
.mul(orderBaseAssetAmount.abs())
|
|
1326
|
+
.div(numericConstants_1.BASE_PRECISION));
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
return freeCollateralDelta;
|
|
1330
|
+
}
|
|
1331
|
+
calculateFreeCollateralDeltaForSpot(market, signedTokenAmount, marginCategory = 'Maintenance') {
|
|
1332
|
+
const tokenPrecision = new _1.BN(Math.pow(10, market.decimals));
|
|
1333
|
+
if (signedTokenAmount.gt(numericConstants_1.ZERO)) {
|
|
1334
|
+
const assetWeight = (0, spotBalance_1.calculateAssetWeight)(signedTokenAmount, this.driftClient.getOracleDataForSpotMarket(market.marketIndex).price, market, marginCategory);
|
|
1335
|
+
return numericConstants_1.QUOTE_PRECISION.mul(assetWeight)
|
|
1336
|
+
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION)
|
|
1337
|
+
.mul(signedTokenAmount)
|
|
1338
|
+
.div(tokenPrecision);
|
|
1339
|
+
}
|
|
1340
|
+
else {
|
|
1341
|
+
const liabilityWeight = (0, spotBalance_1.calculateLiabilityWeight)(signedTokenAmount.abs(), market, marginCategory);
|
|
1342
|
+
return numericConstants_1.QUOTE_PRECISION.neg()
|
|
1343
|
+
.mul(liabilityWeight)
|
|
1344
|
+
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION)
|
|
1345
|
+
.mul(signedTokenAmount.abs())
|
|
1346
|
+
.div(tokenPrecision);
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
/**
|
|
1350
|
+
* Calculates the estimated liquidation price for a position after closing a quote amount of the position.
|
|
1351
|
+
* @param positionMarketIndex
|
|
1352
|
+
* @param closeQuoteAmount
|
|
1353
|
+
* @returns : Precision PRICE_PRECISION
|
|
1354
|
+
*/
|
|
1355
|
+
liquidationPriceAfterClose(positionMarketIndex, closeQuoteAmount, estimatedEntryPrice = numericConstants_1.ZERO) {
|
|
1356
|
+
const currentPosition = this.getPerpPositionWithLPSettle(positionMarketIndex, undefined, true)[0] || this.getEmptyPosition(positionMarketIndex);
|
|
1357
|
+
const closeBaseAmount = currentPosition.baseAssetAmount
|
|
1358
|
+
.mul(closeQuoteAmount)
|
|
1359
|
+
.div(currentPosition.quoteAssetAmount.abs())
|
|
1360
|
+
.add(currentPosition.baseAssetAmount
|
|
1361
|
+
.mul(closeQuoteAmount)
|
|
1362
|
+
.mod(currentPosition.quoteAssetAmount.abs()))
|
|
1363
|
+
.neg();
|
|
1364
|
+
return this.liquidationPrice(positionMarketIndex, closeBaseAmount, estimatedEntryPrice);
|
|
1365
|
+
}
|
|
1366
|
+
getMarginUSDCRequiredForTrade(targetMarketIndex, baseSize, estEntryPrice) {
|
|
1367
|
+
return (0, margin_1.calculateMarginUSDCRequiredForTrade)(this.driftClient, targetMarketIndex, baseSize, this.getUserAccount().maxMarginRatio, undefined, estEntryPrice);
|
|
1368
|
+
}
|
|
1369
|
+
getCollateralDepositRequiredForTrade(targetMarketIndex, baseSize, collateralIndex) {
|
|
1370
|
+
return (0, margin_1.calculateCollateralDepositRequiredForTrade)(this.driftClient, targetMarketIndex, baseSize, collateralIndex, this.getUserAccount().maxMarginRatio, false // assume user cant be high leverage if they havent created user account ?
|
|
1371
|
+
);
|
|
1372
|
+
}
|
|
1373
|
+
/**
|
|
1374
|
+
* Get the maximum trade size for a given market, taking into account the user's current leverage, positions, collateral, etc.
|
|
1375
|
+
*
|
|
1376
|
+
* To Calculate Max Quote Available:
|
|
1377
|
+
*
|
|
1378
|
+
* Case 1: SameSide
|
|
1379
|
+
* => Remaining quote to get to maxLeverage
|
|
1380
|
+
*
|
|
1381
|
+
* Case 2: NOT SameSide && currentLeverage <= maxLeverage
|
|
1382
|
+
* => Current opposite position x2 + remaining to get to maxLeverage
|
|
1383
|
+
*
|
|
1384
|
+
* Case 3: NOT SameSide && currentLeverage > maxLeverage && otherPositions - currentPosition > maxLeverage
|
|
1385
|
+
* => strictly reduce current position size
|
|
1386
|
+
*
|
|
1387
|
+
* Case 4: NOT SameSide && currentLeverage > maxLeverage && otherPositions - currentPosition < maxLeverage
|
|
1388
|
+
* => current position + remaining to get to maxLeverage
|
|
1389
|
+
*
|
|
1390
|
+
* @param targetMarketIndex
|
|
1391
|
+
* @param tradeSide
|
|
1392
|
+
* @param isLp
|
|
1393
|
+
* @returns { tradeSize: BN, oppositeSideTradeSize: BN} : Precision QUOTE_PRECISION
|
|
1394
|
+
*/
|
|
1395
|
+
getMaxTradeSizeUSDCForPerp(targetMarketIndex, tradeSide, isLp = false) {
|
|
1396
|
+
let tradeSize = numericConstants_1.ZERO;
|
|
1397
|
+
let oppositeSideTradeSize = numericConstants_1.ZERO;
|
|
1398
|
+
const currentPosition = this.getPerpPositionWithLPSettle(targetMarketIndex, undefined, true)[0] ||
|
|
1399
|
+
this.getEmptyPosition(targetMarketIndex);
|
|
1400
|
+
const targetSide = (0, types_1.isVariant)(tradeSide, 'short') ? 'short' : 'long';
|
|
1401
|
+
const currentPositionSide = (currentPosition === null || currentPosition === void 0 ? void 0 : currentPosition.baseAssetAmount.isNeg())
|
|
1402
|
+
? 'short'
|
|
1403
|
+
: 'long';
|
|
1404
|
+
const targetingSameSide = !currentPosition
|
|
1405
|
+
? true
|
|
1406
|
+
: targetSide === currentPositionSide;
|
|
1407
|
+
const oracleData = this.getOracleDataForPerpMarket(targetMarketIndex);
|
|
1408
|
+
const marketAccount = this.driftClient.getPerpMarketAccount(targetMarketIndex);
|
|
1409
|
+
const lpBuffer = isLp
|
|
1410
|
+
? oracleData.price
|
|
1411
|
+
.mul(marketAccount.amm.orderStepSize)
|
|
1412
|
+
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
1413
|
+
: numericConstants_1.ZERO;
|
|
1414
|
+
// add any position we have on the opposite side of the current trade, because we can "flip" the size of this position without taking any extra leverage.
|
|
1415
|
+
const oppositeSizeLiabilityValue = targetingSameSide
|
|
1416
|
+
? numericConstants_1.ZERO
|
|
1417
|
+
: (0, _1.calculatePerpLiabilityValue)(currentPosition.baseAssetAmount, oracleData.price, (0, types_1.isVariant)(marketAccount.contractType, 'prediction'));
|
|
1418
|
+
const maxPositionSize = this.getPerpBuyingPower(targetMarketIndex, lpBuffer);
|
|
1419
|
+
if (maxPositionSize.gte(numericConstants_1.ZERO)) {
|
|
1420
|
+
if (oppositeSizeLiabilityValue.eq(numericConstants_1.ZERO)) {
|
|
1421
|
+
// case 1 : Regular trade where current total position less than max, and no opposite position to account for
|
|
1422
|
+
// do nothing
|
|
1423
|
+
tradeSize = maxPositionSize;
|
|
1424
|
+
}
|
|
1425
|
+
else {
|
|
1426
|
+
// case 2 : trade where current total position less than max, but need to account for flipping the current position over to the other side
|
|
1427
|
+
tradeSize = maxPositionSize.add(oppositeSizeLiabilityValue);
|
|
1428
|
+
oppositeSideTradeSize = oppositeSizeLiabilityValue;
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
else {
|
|
1432
|
+
// current leverage is greater than max leverage - can only reduce position size
|
|
1433
|
+
if (!targetingSameSide) {
|
|
1434
|
+
const market = this.driftClient.getPerpMarketAccount(targetMarketIndex);
|
|
1435
|
+
const perpLiabilityValue = (0, _1.calculatePerpLiabilityValue)(currentPosition.baseAssetAmount, oracleData.price, (0, types_1.isVariant)(market.contractType, 'prediction'));
|
|
1436
|
+
const totalCollateral = this.getTotalCollateral();
|
|
1437
|
+
const marginRequirement = this.getInitialMarginRequirement();
|
|
1438
|
+
const marginFreedByClosing = perpLiabilityValue
|
|
1439
|
+
.mul(new _1.BN(market.marginRatioInitial))
|
|
1440
|
+
.div(numericConstants_1.MARGIN_PRECISION);
|
|
1441
|
+
const marginRequirementAfterClosing = marginRequirement.sub(marginFreedByClosing);
|
|
1442
|
+
if (marginRequirementAfterClosing.gt(totalCollateral)) {
|
|
1443
|
+
oppositeSideTradeSize = perpLiabilityValue;
|
|
1444
|
+
}
|
|
1445
|
+
else {
|
|
1446
|
+
const freeCollateralAfterClose = totalCollateral.sub(marginRequirementAfterClosing);
|
|
1447
|
+
const buyingPowerAfterClose = this.getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(targetMarketIndex, freeCollateralAfterClose, numericConstants_1.ZERO);
|
|
1448
|
+
oppositeSideTradeSize = perpLiabilityValue;
|
|
1449
|
+
tradeSize = buyingPowerAfterClose;
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
else {
|
|
1453
|
+
// do nothing if targetting same side
|
|
1454
|
+
tradeSize = maxPositionSize;
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
return { tradeSize, oppositeSideTradeSize };
|
|
1458
|
+
}
|
|
1459
|
+
/**
|
|
1460
|
+
* Get the maximum trade size for a given market, taking into account the user's current leverage, positions, collateral, etc.
|
|
1461
|
+
*
|
|
1462
|
+
* @param targetMarketIndex
|
|
1463
|
+
* @param direction
|
|
1464
|
+
* @param currentQuoteAssetValue
|
|
1465
|
+
* @param currentSpotMarketNetValue
|
|
1466
|
+
* @returns tradeSizeAllowed : Precision QUOTE_PRECISION
|
|
1467
|
+
*/
|
|
1468
|
+
getMaxTradeSizeUSDCForSpot(targetMarketIndex, direction, currentQuoteAssetValue, currentSpotMarketNetValue) {
|
|
1469
|
+
const market = this.driftClient.getSpotMarketAccount(targetMarketIndex);
|
|
1470
|
+
const oraclePrice = this.driftClient.getOracleDataForSpotMarket(targetMarketIndex).price;
|
|
1471
|
+
currentQuoteAssetValue = this.getSpotMarketAssetValue(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
|
|
1472
|
+
currentSpotMarketNetValue =
|
|
1473
|
+
currentSpotMarketNetValue !== null && currentSpotMarketNetValue !== void 0 ? currentSpotMarketNetValue : this.getSpotPositionValue(targetMarketIndex);
|
|
1474
|
+
let freeCollateral = this.getFreeCollateral();
|
|
1475
|
+
const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, oraclePrice, 'Initial', numericConstants_1.ZERO, (0, types_1.isVariant)(direction, 'long')
|
|
1476
|
+
? _1.SpotBalanceType.DEPOSIT
|
|
1477
|
+
: _1.SpotBalanceType.BORROW, this.getUserAccount().maxMarginRatio);
|
|
1478
|
+
let tradeAmount = numericConstants_1.ZERO;
|
|
1479
|
+
if (this.getUserAccount().isMarginTradingEnabled) {
|
|
1480
|
+
// if the user is buying/selling and already short/long, need to account for closing out short/long
|
|
1481
|
+
if ((0, types_1.isVariant)(direction, 'long') && currentSpotMarketNetValue.lt(numericConstants_1.ZERO)) {
|
|
1482
|
+
tradeAmount = currentSpotMarketNetValue.abs();
|
|
1483
|
+
const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, oraclePrice, 'Initial', this.getTokenAmount(targetMarketIndex).abs(), _1.SpotBalanceType.BORROW, this.getUserAccount().maxMarginRatio);
|
|
1484
|
+
freeCollateral = freeCollateral.add(tradeAmount.mul(new _1.BN(marginRatio)).div(numericConstants_1.MARGIN_PRECISION));
|
|
1485
|
+
}
|
|
1486
|
+
else if ((0, types_1.isVariant)(direction, 'short') &&
|
|
1487
|
+
currentSpotMarketNetValue.gt(numericConstants_1.ZERO)) {
|
|
1488
|
+
tradeAmount = currentSpotMarketNetValue;
|
|
1489
|
+
const marginRatio = (0, _1.calculateSpotMarketMarginRatio)(market, oraclePrice, 'Initial', this.getTokenAmount(targetMarketIndex), _1.SpotBalanceType.DEPOSIT, this.getUserAccount().maxMarginRatio);
|
|
1490
|
+
freeCollateral = freeCollateral.add(tradeAmount.mul(new _1.BN(marginRatio)).div(numericConstants_1.MARGIN_PRECISION));
|
|
1491
|
+
}
|
|
1492
|
+
tradeAmount = tradeAmount.add(freeCollateral.mul(numericConstants_1.MARGIN_PRECISION).div(new _1.BN(marginRatio)));
|
|
1493
|
+
}
|
|
1494
|
+
else if ((0, types_1.isVariant)(direction, 'long')) {
|
|
1495
|
+
tradeAmount = _1.BN.min(currentQuoteAssetValue, freeCollateral.mul(numericConstants_1.MARGIN_PRECISION).div(new _1.BN(marginRatio)));
|
|
1496
|
+
}
|
|
1497
|
+
else {
|
|
1498
|
+
tradeAmount = _1.BN.max(numericConstants_1.ZERO, currentSpotMarketNetValue);
|
|
1499
|
+
}
|
|
1500
|
+
return tradeAmount;
|
|
1501
|
+
}
|
|
1502
|
+
/**
|
|
1503
|
+
* Calculates the max amount of token that can be swapped from inMarket to outMarket
|
|
1504
|
+
* Assumes swap happens at oracle price
|
|
1505
|
+
*
|
|
1506
|
+
* @param inMarketIndex
|
|
1507
|
+
* @param outMarketIndex
|
|
1508
|
+
* @param calculateSwap function to similate in to out swa
|
|
1509
|
+
* @param iterationLimit how long to run appromixation before erroring out
|
|
1510
|
+
*/
|
|
1511
|
+
getMaxSwapAmount({ inMarketIndex, outMarketIndex, calculateSwap, iterationLimit = 1000, }) {
|
|
1512
|
+
const inMarket = this.driftClient.getSpotMarketAccount(inMarketIndex);
|
|
1513
|
+
const outMarket = this.driftClient.getSpotMarketAccount(outMarketIndex);
|
|
1514
|
+
const inOraclePriceData = this.getOracleDataForSpotMarket(inMarketIndex);
|
|
1515
|
+
const inOraclePrice = inOraclePriceData.price;
|
|
1516
|
+
const outOraclePriceData = this.getOracleDataForSpotMarket(outMarketIndex);
|
|
1517
|
+
const outOraclePrice = outOraclePriceData.price;
|
|
1518
|
+
const inStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(inOraclePrice);
|
|
1519
|
+
const outStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(outOraclePrice);
|
|
1520
|
+
const inPrecision = new _1.BN(10 ** inMarket.decimals);
|
|
1521
|
+
const outPrecision = new _1.BN(10 ** outMarket.decimals);
|
|
1522
|
+
const inSpotPosition = this.getSpotPosition(inMarketIndex) ||
|
|
1523
|
+
this.getEmptySpotPosition(inMarketIndex);
|
|
1524
|
+
const outSpotPosition = this.getSpotPosition(outMarketIndex) ||
|
|
1525
|
+
this.getEmptySpotPosition(outMarketIndex);
|
|
1526
|
+
const freeCollateral = this.getFreeCollateral();
|
|
1527
|
+
const inContributionInitial = this.calculateSpotPositionFreeCollateralContribution(inSpotPosition, inStrictOraclePrice);
|
|
1528
|
+
const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition, inStrictOraclePrice);
|
|
1529
|
+
const outContributionInitial = this.calculateSpotPositionFreeCollateralContribution(outSpotPosition, outStrictOraclePrice);
|
|
1530
|
+
const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition, outStrictOraclePrice);
|
|
1531
|
+
const initialContribution = inContributionInitial.add(outContributionInitial);
|
|
1532
|
+
const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
|
|
1533
|
+
if (!calculateSwap) {
|
|
1534
|
+
calculateSwap = (inSwap) => {
|
|
1535
|
+
return inSwap
|
|
1536
|
+
.mul(outPrecision)
|
|
1537
|
+
.mul(inOraclePrice)
|
|
1538
|
+
.div(outOraclePrice)
|
|
1539
|
+
.div(inPrecision);
|
|
1540
|
+
};
|
|
1541
|
+
}
|
|
1542
|
+
let inSwap = numericConstants_1.ZERO;
|
|
1543
|
+
let outSwap = numericConstants_1.ZERO;
|
|
1544
|
+
const inTokenAmount = this.getTokenAmount(inMarketIndex);
|
|
1545
|
+
const outTokenAmount = this.getTokenAmount(outMarketIndex);
|
|
1546
|
+
const inAssetWeight = (0, spotBalance_1.calculateAssetWeight)(inTokenAmount, inOraclePriceData.price, inMarket, 'Initial');
|
|
1547
|
+
const outAssetWeight = (0, spotBalance_1.calculateAssetWeight)(outTokenAmount, outOraclePriceData.price, outMarket, 'Initial');
|
|
1548
|
+
const outSaferThanIn =
|
|
1549
|
+
// selling asset to close borrow
|
|
1550
|
+
(inTokenAmount.gt(numericConstants_1.ZERO) && outTokenAmount.lt(numericConstants_1.ZERO)) ||
|
|
1551
|
+
// buying asset with higher initial asset weight
|
|
1552
|
+
inAssetWeight.lt(outAssetWeight);
|
|
1553
|
+
if (freeCollateral.lt(numericConstants_1.PRICE_PRECISION.divn(100))) {
|
|
1554
|
+
if (outSaferThanIn && inTokenAmount.gt(numericConstants_1.ZERO)) {
|
|
1555
|
+
inSwap = inTokenAmount;
|
|
1556
|
+
outSwap = calculateSwap(inSwap);
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
else {
|
|
1560
|
+
let minSwap = numericConstants_1.ZERO;
|
|
1561
|
+
let maxSwap = _1.BN.max(freeCollateral.mul(inPrecision).mul(new _1.BN(100)).div(inOraclePrice), // 100x current free collateral
|
|
1562
|
+
inTokenAmount.abs().mul(new _1.BN(10)) // 10x current position
|
|
1563
|
+
);
|
|
1564
|
+
inSwap = maxSwap.div(numericConstants_1.TWO);
|
|
1565
|
+
const error = freeCollateral.div(new _1.BN(10000));
|
|
1566
|
+
let i = 0;
|
|
1567
|
+
let freeCollateralAfter = freeCollateral;
|
|
1568
|
+
while (freeCollateralAfter.gt(error) || freeCollateralAfter.isNeg()) {
|
|
1569
|
+
outSwap = calculateSwap(inSwap);
|
|
1570
|
+
const inPositionAfter = this.cloneAndUpdateSpotPosition(inSpotPosition, inSwap.neg(), inMarket);
|
|
1571
|
+
const outPositionAfter = this.cloneAndUpdateSpotPosition(outSpotPosition, outSwap, outMarket);
|
|
1572
|
+
const inContributionAfter = this.calculateSpotPositionFreeCollateralContribution(inPositionAfter, inStrictOraclePrice);
|
|
1573
|
+
const outContributionAfter = this.calculateSpotPositionFreeCollateralContribution(outPositionAfter, outStrictOraclePrice);
|
|
1574
|
+
const contributionAfter = inContributionAfter.add(outContributionAfter);
|
|
1575
|
+
const contributionDelta = contributionAfter.sub(initialContribution);
|
|
1576
|
+
freeCollateralAfter = freeCollateral.add(contributionDelta);
|
|
1577
|
+
if (freeCollateralAfter.gt(error)) {
|
|
1578
|
+
minSwap = inSwap;
|
|
1579
|
+
inSwap = minSwap.add(maxSwap).div(numericConstants_1.TWO);
|
|
1580
|
+
}
|
|
1581
|
+
else if (freeCollateralAfter.isNeg()) {
|
|
1582
|
+
maxSwap = inSwap;
|
|
1583
|
+
inSwap = minSwap.add(maxSwap).div(numericConstants_1.TWO);
|
|
1584
|
+
}
|
|
1585
|
+
if (i++ > iterationLimit) {
|
|
1586
|
+
console.log('getMaxSwapAmount iteration limit reached');
|
|
1587
|
+
break;
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
const inPositionAfter = this.cloneAndUpdateSpotPosition(inSpotPosition, inSwap.neg(), inMarket);
|
|
1592
|
+
const outPositionAfter = this.cloneAndUpdateSpotPosition(outSpotPosition, outSwap, outMarket);
|
|
1593
|
+
const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter, inStrictOraclePrice);
|
|
1594
|
+
const { totalAssetValue: outTotalAssetValueAfter, totalLiabilityValue: outTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(outPositionAfter, outStrictOraclePrice);
|
|
1595
|
+
const spotAssetValueDelta = inTotalAssetValueAfter
|
|
1596
|
+
.add(outTotalAssetValueAfter)
|
|
1597
|
+
.sub(inTotalAssetValueInitial)
|
|
1598
|
+
.sub(outTotalAssetValueInitial);
|
|
1599
|
+
const spotLiabilityValueDelta = inTotalLiabilityValueAfter
|
|
1600
|
+
.add(outTotalLiabilityValueAfter)
|
|
1601
|
+
.sub(inTotalLiabilityValueInitial)
|
|
1602
|
+
.sub(outTotalLiabilityValueInitial);
|
|
1603
|
+
const spotAssetValueAfter = spotAssetValue.add(spotAssetValueDelta);
|
|
1604
|
+
const spotLiabilityValueAfter = spotLiabilityValue.add(spotLiabilityValueDelta);
|
|
1605
|
+
const leverage = this.calculateLeverageFromComponents({
|
|
1606
|
+
perpLiabilityValue,
|
|
1607
|
+
perpPnl,
|
|
1608
|
+
spotAssetValue: spotAssetValueAfter,
|
|
1609
|
+
spotLiabilityValue: spotLiabilityValueAfter,
|
|
1610
|
+
});
|
|
1611
|
+
return { inAmount: inSwap, outAmount: outSwap, leverage };
|
|
1612
|
+
}
|
|
1613
|
+
cloneAndUpdateSpotPosition(position, tokenAmount, market) {
|
|
1614
|
+
const clonedPosition = Object.assign({}, position);
|
|
1615
|
+
if (tokenAmount.eq(numericConstants_1.ZERO)) {
|
|
1616
|
+
return clonedPosition;
|
|
1617
|
+
}
|
|
1618
|
+
const preTokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(position.scaledBalance, market, position.balanceType), position.balanceType);
|
|
1619
|
+
if ((0, _1.sigNum)(preTokenAmount).eq((0, _1.sigNum)(tokenAmount))) {
|
|
1620
|
+
const scaledBalanceDelta = (0, _1.getBalance)(tokenAmount.abs(), market, position.balanceType);
|
|
1621
|
+
clonedPosition.scaledBalance =
|
|
1622
|
+
clonedPosition.scaledBalance.add(scaledBalanceDelta);
|
|
1623
|
+
return clonedPosition;
|
|
1624
|
+
}
|
|
1625
|
+
const updateDirection = tokenAmount.isNeg()
|
|
1626
|
+
? _1.SpotBalanceType.BORROW
|
|
1627
|
+
: _1.SpotBalanceType.DEPOSIT;
|
|
1628
|
+
if (tokenAmount.abs().gte(preTokenAmount.abs())) {
|
|
1629
|
+
clonedPosition.scaledBalance = (0, _1.getBalance)(tokenAmount.abs().sub(preTokenAmount.abs()), market, updateDirection);
|
|
1630
|
+
clonedPosition.balanceType = updateDirection;
|
|
1631
|
+
}
|
|
1632
|
+
else {
|
|
1633
|
+
const scaledBalanceDelta = (0, _1.getBalance)(tokenAmount.abs(), market, position.balanceType);
|
|
1634
|
+
clonedPosition.scaledBalance =
|
|
1635
|
+
clonedPosition.scaledBalance.sub(scaledBalanceDelta);
|
|
1636
|
+
}
|
|
1637
|
+
return clonedPosition;
|
|
1638
|
+
}
|
|
1639
|
+
calculateSpotPositionFreeCollateralContribution(spotPosition, strictOraclePrice) {
|
|
1640
|
+
const marginCategory = 'Initial';
|
|
1641
|
+
const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
1642
|
+
const { freeCollateralContribution } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory, this.getUserAccount().maxMarginRatio);
|
|
1643
|
+
return freeCollateralContribution;
|
|
1644
|
+
}
|
|
1645
|
+
calculateSpotPositionLeverageContribution(spotPosition, strictOraclePrice) {
|
|
1646
|
+
let totalAssetValue = numericConstants_1.ZERO;
|
|
1647
|
+
let totalLiabilityValue = numericConstants_1.ZERO;
|
|
1648
|
+
const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
1649
|
+
const { tokenValue, ordersValue } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, 'Initial', this.getUserAccount().maxMarginRatio);
|
|
1650
|
+
if (tokenValue.gte(numericConstants_1.ZERO)) {
|
|
1651
|
+
totalAssetValue = tokenValue;
|
|
1652
|
+
}
|
|
1653
|
+
else {
|
|
1654
|
+
totalLiabilityValue = tokenValue.abs();
|
|
1655
|
+
}
|
|
1656
|
+
if (ordersValue.gt(numericConstants_1.ZERO)) {
|
|
1657
|
+
totalAssetValue = totalAssetValue.add(ordersValue);
|
|
1658
|
+
}
|
|
1659
|
+
else {
|
|
1660
|
+
totalLiabilityValue = totalLiabilityValue.add(ordersValue.abs());
|
|
1661
|
+
}
|
|
1662
|
+
return {
|
|
1663
|
+
totalAssetValue,
|
|
1664
|
+
totalLiabilityValue,
|
|
1665
|
+
};
|
|
1666
|
+
}
|
|
1667
|
+
/**
|
|
1668
|
+
* Estimates what the user leverage will be after swap
|
|
1669
|
+
* @param inMarketIndex
|
|
1670
|
+
* @param outMarketIndex
|
|
1671
|
+
* @param inAmount
|
|
1672
|
+
* @param outAmount
|
|
1673
|
+
*/
|
|
1674
|
+
accountLeverageAfterSwap({ inMarketIndex, outMarketIndex, inAmount, outAmount, }) {
|
|
1675
|
+
const inMarket = this.driftClient.getSpotMarketAccount(inMarketIndex);
|
|
1676
|
+
const outMarket = this.driftClient.getSpotMarketAccount(outMarketIndex);
|
|
1677
|
+
const inOraclePriceData = this.getOracleDataForSpotMarket(inMarketIndex);
|
|
1678
|
+
const inOraclePrice = inOraclePriceData.price;
|
|
1679
|
+
const outOraclePriceData = this.getOracleDataForSpotMarket(outMarketIndex);
|
|
1680
|
+
const outOraclePrice = outOraclePriceData.price;
|
|
1681
|
+
const inStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(inOraclePrice);
|
|
1682
|
+
const outStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(outOraclePrice);
|
|
1683
|
+
const inSpotPosition = this.getSpotPosition(inMarketIndex) ||
|
|
1684
|
+
this.getEmptySpotPosition(inMarketIndex);
|
|
1685
|
+
const outSpotPosition = this.getSpotPosition(outMarketIndex) ||
|
|
1686
|
+
this.getEmptySpotPosition(outMarketIndex);
|
|
1687
|
+
const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition, inStrictOraclePrice);
|
|
1688
|
+
const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition, outStrictOraclePrice);
|
|
1689
|
+
const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
|
|
1690
|
+
const inPositionAfter = this.cloneAndUpdateSpotPosition(inSpotPosition, inAmount.abs().neg(), inMarket);
|
|
1691
|
+
const outPositionAfter = this.cloneAndUpdateSpotPosition(outSpotPosition, outAmount.abs(), outMarket);
|
|
1692
|
+
const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter, inStrictOraclePrice);
|
|
1693
|
+
const { totalAssetValue: outTotalAssetValueAfter, totalLiabilityValue: outTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(outPositionAfter, outStrictOraclePrice);
|
|
1694
|
+
const spotAssetValueDelta = inTotalAssetValueAfter
|
|
1695
|
+
.add(outTotalAssetValueAfter)
|
|
1696
|
+
.sub(inTotalAssetValueInitial)
|
|
1697
|
+
.sub(outTotalAssetValueInitial);
|
|
1698
|
+
const spotLiabilityValueDelta = inTotalLiabilityValueAfter
|
|
1699
|
+
.add(outTotalLiabilityValueAfter)
|
|
1700
|
+
.sub(inTotalLiabilityValueInitial)
|
|
1701
|
+
.sub(outTotalLiabilityValueInitial);
|
|
1702
|
+
const spotAssetValueAfter = spotAssetValue.add(spotAssetValueDelta);
|
|
1703
|
+
const spotLiabilityValueAfter = spotLiabilityValue.add(spotLiabilityValueDelta);
|
|
1704
|
+
return this.calculateLeverageFromComponents({
|
|
1705
|
+
perpLiabilityValue,
|
|
1706
|
+
perpPnl,
|
|
1707
|
+
spotAssetValue: spotAssetValueAfter,
|
|
1708
|
+
spotLiabilityValue: spotLiabilityValueAfter,
|
|
1709
|
+
});
|
|
1710
|
+
}
|
|
1711
|
+
// TODO - should this take the price impact of the trade into account for strict accuracy?
|
|
1712
|
+
/**
|
|
1713
|
+
* Returns the leverage ratio for the account after adding (or subtracting) the given quote size to the given position
|
|
1714
|
+
* @param targetMarketIndex
|
|
1715
|
+
* @param: targetMarketType
|
|
1716
|
+
* @param tradeQuoteAmount
|
|
1717
|
+
* @param tradeSide
|
|
1718
|
+
* @param includeOpenOrders
|
|
1719
|
+
* @returns leverageRatio : Precision TEN_THOUSAND
|
|
1720
|
+
*/
|
|
1721
|
+
accountLeverageRatioAfterTrade(targetMarketIndex, targetMarketType, tradeQuoteAmount, tradeSide, includeOpenOrders = true) {
|
|
1722
|
+
const tradeIsPerp = (0, types_1.isVariant)(targetMarketType, 'perp');
|
|
1723
|
+
if (!tradeIsPerp) {
|
|
1724
|
+
// calculate new asset/liability values for base and quote market to find new account leverage
|
|
1725
|
+
const totalLiabilityValue = this.getTotalLiabilityValue();
|
|
1726
|
+
const totalAssetValue = this.getTotalAssetValue();
|
|
1727
|
+
const spotLiabilityValue = this.getSpotMarketLiabilityValue(undefined, undefined, undefined, includeOpenOrders);
|
|
1728
|
+
const currentQuoteAssetValue = this.getSpotMarketAssetValue(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, undefined, includeOpenOrders);
|
|
1729
|
+
const currentQuoteLiabilityValue = this.getSpotMarketLiabilityValue(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, undefined, undefined, includeOpenOrders);
|
|
1730
|
+
const currentQuoteValue = currentQuoteAssetValue.sub(currentQuoteLiabilityValue);
|
|
1731
|
+
const currentSpotMarketAssetValue = this.getSpotMarketAssetValue(targetMarketIndex, undefined, includeOpenOrders);
|
|
1732
|
+
const currentSpotMarketLiabilityValue = this.getSpotMarketLiabilityValue(targetMarketIndex, undefined, undefined, includeOpenOrders);
|
|
1733
|
+
const currentSpotMarketNetValue = currentSpotMarketAssetValue.sub(currentSpotMarketLiabilityValue);
|
|
1734
|
+
let assetValueToAdd = numericConstants_1.ZERO;
|
|
1735
|
+
let liabilityValueToAdd = numericConstants_1.ZERO;
|
|
1736
|
+
const newQuoteNetValue = tradeSide == _1.PositionDirection.SHORT
|
|
1737
|
+
? currentQuoteValue.add(tradeQuoteAmount)
|
|
1738
|
+
: currentQuoteValue.sub(tradeQuoteAmount);
|
|
1739
|
+
const newQuoteAssetValue = _1.BN.max(newQuoteNetValue, numericConstants_1.ZERO);
|
|
1740
|
+
const newQuoteLiabilityValue = _1.BN.min(newQuoteNetValue, numericConstants_1.ZERO).abs();
|
|
1741
|
+
assetValueToAdd = assetValueToAdd.add(newQuoteAssetValue.sub(currentQuoteAssetValue));
|
|
1742
|
+
liabilityValueToAdd = liabilityValueToAdd.add(newQuoteLiabilityValue.sub(currentQuoteLiabilityValue));
|
|
1743
|
+
const newSpotMarketNetValue = tradeSide == _1.PositionDirection.LONG
|
|
1744
|
+
? currentSpotMarketNetValue.add(tradeQuoteAmount)
|
|
1745
|
+
: currentSpotMarketNetValue.sub(tradeQuoteAmount);
|
|
1746
|
+
const newSpotMarketAssetValue = _1.BN.max(newSpotMarketNetValue, numericConstants_1.ZERO);
|
|
1747
|
+
const newSpotMarketLiabilityValue = _1.BN.min(newSpotMarketNetValue, numericConstants_1.ZERO).abs();
|
|
1748
|
+
assetValueToAdd = assetValueToAdd.add(newSpotMarketAssetValue.sub(currentSpotMarketAssetValue));
|
|
1749
|
+
liabilityValueToAdd = liabilityValueToAdd.add(newSpotMarketLiabilityValue.sub(currentSpotMarketLiabilityValue));
|
|
1750
|
+
const totalAssetValueAfterTrade = totalAssetValue.add(assetValueToAdd);
|
|
1751
|
+
const totalSpotLiabilityValueAfterTrade = spotLiabilityValue.add(liabilityValueToAdd);
|
|
1752
|
+
const totalLiabilityValueAfterTrade = totalLiabilityValue.add(liabilityValueToAdd);
|
|
1753
|
+
const netAssetValueAfterTrade = totalAssetValueAfterTrade.sub(totalSpotLiabilityValueAfterTrade);
|
|
1754
|
+
if (netAssetValueAfterTrade.eq(numericConstants_1.ZERO)) {
|
|
1755
|
+
return numericConstants_1.ZERO;
|
|
1756
|
+
}
|
|
1757
|
+
const newLeverage = totalLiabilityValueAfterTrade
|
|
1758
|
+
.mul(numericConstants_1.TEN_THOUSAND)
|
|
1759
|
+
.div(netAssetValueAfterTrade);
|
|
1760
|
+
return newLeverage;
|
|
1761
|
+
}
|
|
1762
|
+
const currentPosition = this.getPerpPositionWithLPSettle(targetMarketIndex)[0] ||
|
|
1763
|
+
this.getEmptyPosition(targetMarketIndex);
|
|
1764
|
+
const perpMarket = this.driftClient.getPerpMarketAccount(targetMarketIndex);
|
|
1765
|
+
const oracleData = this.getOracleDataForPerpMarket(targetMarketIndex);
|
|
1766
|
+
let {
|
|
1767
|
+
// eslint-disable-next-line prefer-const
|
|
1768
|
+
worstCaseBaseAssetAmount: worstCaseBase, worstCaseLiabilityValue: currentPositionQuoteAmount, } = (0, _1.calculateWorstCasePerpLiabilityValue)(currentPosition, perpMarket, oracleData.price);
|
|
1769
|
+
// current side is short if position base asset amount is negative OR there is no position open but open orders are short
|
|
1770
|
+
const currentSide = currentPosition.baseAssetAmount.isNeg() ||
|
|
1771
|
+
(currentPosition.baseAssetAmount.eq(numericConstants_1.ZERO) && worstCaseBase.isNeg())
|
|
1772
|
+
? _1.PositionDirection.SHORT
|
|
1773
|
+
: _1.PositionDirection.LONG;
|
|
1774
|
+
if (currentSide === _1.PositionDirection.SHORT)
|
|
1775
|
+
currentPositionQuoteAmount = currentPositionQuoteAmount.neg();
|
|
1776
|
+
if (tradeSide === _1.PositionDirection.SHORT)
|
|
1777
|
+
tradeQuoteAmount = tradeQuoteAmount.neg();
|
|
1778
|
+
const currentPerpPositionAfterTrade = currentPositionQuoteAmount
|
|
1779
|
+
.add(tradeQuoteAmount)
|
|
1780
|
+
.abs();
|
|
1781
|
+
const totalPositionAfterTradeExcludingTargetMarket = this.getTotalPerpPositionValueExcludingMarket(targetMarketIndex, undefined, undefined, includeOpenOrders);
|
|
1782
|
+
const totalAssetValue = this.getTotalAssetValue();
|
|
1783
|
+
const totalPerpPositionLiability = currentPerpPositionAfterTrade
|
|
1784
|
+
.add(totalPositionAfterTradeExcludingTargetMarket)
|
|
1785
|
+
.abs();
|
|
1786
|
+
const totalSpotLiability = this.getSpotMarketLiabilityValue(undefined, undefined, undefined, includeOpenOrders);
|
|
1787
|
+
const totalLiabilitiesAfterTrade = totalPerpPositionLiability.add(totalSpotLiability);
|
|
1788
|
+
const netAssetValue = totalAssetValue.sub(totalSpotLiability);
|
|
1789
|
+
if (netAssetValue.eq(numericConstants_1.ZERO)) {
|
|
1790
|
+
return numericConstants_1.ZERO;
|
|
1791
|
+
}
|
|
1792
|
+
const newLeverage = totalLiabilitiesAfterTrade
|
|
1793
|
+
.mul(numericConstants_1.TEN_THOUSAND)
|
|
1794
|
+
.div(netAssetValue);
|
|
1795
|
+
return newLeverage;
|
|
1796
|
+
}
|
|
1797
|
+
getUserFeeTier(marketType, now) {
|
|
1798
|
+
const state = this.driftClient.getStateAccount();
|
|
1799
|
+
let feeTierIndex = 0;
|
|
1800
|
+
if ((0, types_1.isVariant)(marketType, 'perp')) {
|
|
1801
|
+
if (this.isHighLeverageMode()) {
|
|
1802
|
+
return state.perpFeeStructure.feeTiers[0];
|
|
1803
|
+
}
|
|
1804
|
+
const userStatsAccount = this.driftClient
|
|
1805
|
+
.getUserStats()
|
|
1806
|
+
.getAccount();
|
|
1807
|
+
const total30dVolume = (0, _1.getUser30dRollingVolumeEstimate)(userStatsAccount, now);
|
|
1808
|
+
const stakedQuoteAssetAmount = userStatsAccount.ifStakedQuoteAssetAmount;
|
|
1809
|
+
const volumeTiers = [
|
|
1810
|
+
new _1.BN(100000000).mul(numericConstants_1.QUOTE_PRECISION),
|
|
1811
|
+
new _1.BN(50000000).mul(numericConstants_1.QUOTE_PRECISION),
|
|
1812
|
+
new _1.BN(10000000).mul(numericConstants_1.QUOTE_PRECISION),
|
|
1813
|
+
new _1.BN(5000000).mul(numericConstants_1.QUOTE_PRECISION),
|
|
1814
|
+
new _1.BN(1000000).mul(numericConstants_1.QUOTE_PRECISION),
|
|
1815
|
+
];
|
|
1816
|
+
const stakedTiers = [
|
|
1817
|
+
new _1.BN(10000).mul(numericConstants_1.QUOTE_PRECISION),
|
|
1818
|
+
new _1.BN(5000).mul(numericConstants_1.QUOTE_PRECISION),
|
|
1819
|
+
new _1.BN(2000).mul(numericConstants_1.QUOTE_PRECISION),
|
|
1820
|
+
new _1.BN(1000).mul(numericConstants_1.QUOTE_PRECISION),
|
|
1821
|
+
new _1.BN(500).mul(numericConstants_1.QUOTE_PRECISION),
|
|
1822
|
+
];
|
|
1823
|
+
for (let i = 0; i < volumeTiers.length; i++) {
|
|
1824
|
+
if (total30dVolume.gte(volumeTiers[i]) ||
|
|
1825
|
+
stakedQuoteAssetAmount.gte(stakedTiers[i])) {
|
|
1826
|
+
feeTierIndex = 5 - i;
|
|
1827
|
+
break;
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
return state.perpFeeStructure.feeTiers[feeTierIndex];
|
|
1831
|
+
}
|
|
1832
|
+
return state.spotFeeStructure.feeTiers[feeTierIndex];
|
|
1833
|
+
}
|
|
1834
|
+
/**
|
|
1835
|
+
* Calculates how much perp fee will be taken for a given sized trade
|
|
1836
|
+
* @param quoteAmount
|
|
1837
|
+
* @returns feeForQuote : Precision QUOTE_PRECISION
|
|
1838
|
+
*/
|
|
1839
|
+
calculateFeeForQuoteAmount(quoteAmount, marketIndex) {
|
|
1840
|
+
if (marketIndex !== undefined) {
|
|
1841
|
+
const takerFeeMultiplier = this.driftClient.getMarketFees(_1.MarketType.PERP, marketIndex, this).takerFee;
|
|
1842
|
+
const feeAmountNum = _1.BigNum.from(quoteAmount, numericConstants_1.QUOTE_PRECISION_EXP).toNum() *
|
|
1843
|
+
takerFeeMultiplier;
|
|
1844
|
+
return _1.BigNum.fromPrint(feeAmountNum.toString(), numericConstants_1.QUOTE_PRECISION_EXP).val;
|
|
1845
|
+
}
|
|
1846
|
+
else {
|
|
1847
|
+
const feeTier = this.getUserFeeTier(_1.MarketType.PERP);
|
|
1848
|
+
return quoteAmount
|
|
1849
|
+
.mul(new _1.BN(feeTier.feeNumerator))
|
|
1850
|
+
.div(new _1.BN(feeTier.feeDenominator));
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
/**
|
|
1854
|
+
* Calculates a user's max withdrawal amounts for a spot market. If reduceOnly is true,
|
|
1855
|
+
* it will return the max withdrawal amount without opening a liability for the user
|
|
1856
|
+
* @param marketIndex
|
|
1857
|
+
* @returns withdrawalLimit : Precision is the token precision for the chosen SpotMarket
|
|
1858
|
+
*/
|
|
1859
|
+
getWithdrawalLimit(marketIndex, reduceOnly) {
|
|
1860
|
+
const nowTs = new _1.BN(Math.floor(Date.now() / 1000));
|
|
1861
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(marketIndex);
|
|
1862
|
+
// eslint-disable-next-line prefer-const
|
|
1863
|
+
let { borrowLimit, withdrawLimit } = (0, spotBalance_1.calculateWithdrawLimit)(spotMarket, nowTs);
|
|
1864
|
+
const freeCollateral = this.getFreeCollateral();
|
|
1865
|
+
const initialMarginRequirement = this.getInitialMarginRequirement();
|
|
1866
|
+
const oracleData = this.getOracleDataForSpotMarket(marketIndex);
|
|
1867
|
+
const precisionIncrease = numericConstants_1.TEN.pow(new _1.BN(spotMarket.decimals - 6));
|
|
1868
|
+
const { canBypass, depositAmount: userDepositAmount } = this.canBypassWithdrawLimits(marketIndex);
|
|
1869
|
+
if (canBypass) {
|
|
1870
|
+
withdrawLimit = _1.BN.max(withdrawLimit, userDepositAmount);
|
|
1871
|
+
}
|
|
1872
|
+
const assetWeight = (0, spotBalance_1.calculateAssetWeight)(userDepositAmount, oracleData.price, spotMarket, 'Initial');
|
|
1873
|
+
let amountWithdrawable;
|
|
1874
|
+
if (assetWeight.eq(numericConstants_1.ZERO)) {
|
|
1875
|
+
amountWithdrawable = userDepositAmount;
|
|
1876
|
+
}
|
|
1877
|
+
else if (initialMarginRequirement.eq(numericConstants_1.ZERO)) {
|
|
1878
|
+
amountWithdrawable = userDepositAmount;
|
|
1879
|
+
}
|
|
1880
|
+
else {
|
|
1881
|
+
amountWithdrawable = (0, _1.divCeil)((0, _1.divCeil)(freeCollateral.mul(numericConstants_1.MARGIN_PRECISION), assetWeight).mul(numericConstants_1.PRICE_PRECISION), oracleData.price).mul(precisionIncrease);
|
|
1882
|
+
}
|
|
1883
|
+
const maxWithdrawValue = _1.BN.min(_1.BN.min(amountWithdrawable, userDepositAmount), withdrawLimit.abs());
|
|
1884
|
+
if (reduceOnly) {
|
|
1885
|
+
return _1.BN.max(maxWithdrawValue, numericConstants_1.ZERO);
|
|
1886
|
+
}
|
|
1887
|
+
else {
|
|
1888
|
+
const weightedAssetValue = this.getSpotMarketAssetValue(marketIndex, 'Initial', false);
|
|
1889
|
+
const freeCollatAfterWithdraw = userDepositAmount.gt(numericConstants_1.ZERO)
|
|
1890
|
+
? freeCollateral.sub(weightedAssetValue)
|
|
1891
|
+
: freeCollateral;
|
|
1892
|
+
const maxLiabilityAllowed = freeCollatAfterWithdraw
|
|
1893
|
+
.mul(numericConstants_1.MARGIN_PRECISION)
|
|
1894
|
+
.div(new _1.BN(spotMarket.initialLiabilityWeight))
|
|
1895
|
+
.mul(numericConstants_1.PRICE_PRECISION)
|
|
1896
|
+
.div(oracleData.price)
|
|
1897
|
+
.mul(precisionIncrease);
|
|
1898
|
+
const maxBorrowValue = _1.BN.min(maxWithdrawValue.add(maxLiabilityAllowed), borrowLimit.abs());
|
|
1899
|
+
return _1.BN.max(maxBorrowValue, numericConstants_1.ZERO);
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
canBypassWithdrawLimits(marketIndex) {
|
|
1903
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(marketIndex);
|
|
1904
|
+
const maxDepositAmount = spotMarket.withdrawGuardThreshold.div(new _1.BN(10));
|
|
1905
|
+
const position = this.getSpotPosition(marketIndex);
|
|
1906
|
+
const netDeposits = this.getUserAccount().totalDeposits.sub(this.getUserAccount().totalWithdraws);
|
|
1907
|
+
if (!position) {
|
|
1908
|
+
return {
|
|
1909
|
+
canBypass: false,
|
|
1910
|
+
maxDepositAmount,
|
|
1911
|
+
depositAmount: numericConstants_1.ZERO,
|
|
1912
|
+
netDeposits,
|
|
1913
|
+
};
|
|
1914
|
+
}
|
|
1915
|
+
if ((0, types_1.isVariant)(position.balanceType, 'borrow')) {
|
|
1916
|
+
return {
|
|
1917
|
+
canBypass: false,
|
|
1918
|
+
maxDepositAmount,
|
|
1919
|
+
netDeposits,
|
|
1920
|
+
depositAmount: numericConstants_1.ZERO,
|
|
1921
|
+
};
|
|
1922
|
+
}
|
|
1923
|
+
const depositAmount = (0, spotBalance_1.getTokenAmount)(position.scaledBalance, spotMarket, _1.SpotBalanceType.DEPOSIT);
|
|
1924
|
+
if (netDeposits.lt(numericConstants_1.ZERO)) {
|
|
1925
|
+
return {
|
|
1926
|
+
canBypass: false,
|
|
1927
|
+
maxDepositAmount,
|
|
1928
|
+
depositAmount,
|
|
1929
|
+
netDeposits,
|
|
1930
|
+
};
|
|
1931
|
+
}
|
|
1932
|
+
return {
|
|
1933
|
+
canBypass: depositAmount.lt(maxDepositAmount),
|
|
1934
|
+
maxDepositAmount,
|
|
1935
|
+
netDeposits,
|
|
1936
|
+
depositAmount,
|
|
1937
|
+
};
|
|
1938
|
+
}
|
|
1939
|
+
canMakeIdle(slot) {
|
|
1940
|
+
const userAccount = this.getUserAccount();
|
|
1941
|
+
if (userAccount.idle) {
|
|
1942
|
+
return false;
|
|
1943
|
+
}
|
|
1944
|
+
const { totalAssetValue, totalLiabilityValue } = this.getSpotMarketAssetAndLiabilityValue();
|
|
1945
|
+
const equity = totalAssetValue.sub(totalLiabilityValue);
|
|
1946
|
+
let slotsBeforeIdle;
|
|
1947
|
+
if (equity.lt(numericConstants_1.QUOTE_PRECISION.muln(1000))) {
|
|
1948
|
+
slotsBeforeIdle = new _1.BN(9000); // 1 hour
|
|
1949
|
+
}
|
|
1950
|
+
else {
|
|
1951
|
+
slotsBeforeIdle = new _1.BN(1512000); // 1 week
|
|
1952
|
+
}
|
|
1953
|
+
const userLastActiveSlot = userAccount.lastActiveSlot;
|
|
1954
|
+
const slotsSinceLastActive = slot.sub(userLastActiveSlot);
|
|
1955
|
+
if (slotsSinceLastActive.lt(slotsBeforeIdle)) {
|
|
1956
|
+
return false;
|
|
1957
|
+
}
|
|
1958
|
+
if (this.isBeingLiquidated()) {
|
|
1959
|
+
return false;
|
|
1960
|
+
}
|
|
1961
|
+
for (const perpPosition of userAccount.perpPositions) {
|
|
1962
|
+
if (!(0, position_1.positionIsAvailable)(perpPosition)) {
|
|
1963
|
+
return false;
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
1967
|
+
if ((0, types_1.isVariant)(spotPosition.balanceType, 'borrow') &&
|
|
1968
|
+
spotPosition.scaledBalance.gt(numericConstants_1.ZERO)) {
|
|
1969
|
+
return false;
|
|
1970
|
+
}
|
|
1971
|
+
if (spotPosition.openOrders !== 0) {
|
|
1972
|
+
return false;
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
for (const order of userAccount.orders) {
|
|
1976
|
+
if (!(0, types_1.isVariant)(order.status, 'init')) {
|
|
1977
|
+
return false;
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
return true;
|
|
1981
|
+
}
|
|
1982
|
+
getSafestTiers() {
|
|
1983
|
+
let safestPerpTier = 4;
|
|
1984
|
+
let safestSpotTier = 4;
|
|
1985
|
+
for (const perpPosition of this.getActivePerpPositions()) {
|
|
1986
|
+
safestPerpTier = Math.min(safestPerpTier, (0, tiers_1.getPerpMarketTierNumber)(this.driftClient.getPerpMarketAccount(perpPosition.marketIndex)));
|
|
1987
|
+
}
|
|
1988
|
+
for (const spotPosition of this.getActiveSpotPositions()) {
|
|
1989
|
+
if ((0, types_1.isVariant)(spotPosition.balanceType, 'deposit')) {
|
|
1990
|
+
continue;
|
|
1991
|
+
}
|
|
1992
|
+
safestSpotTier = Math.min(safestSpotTier, (0, tiers_1.getSpotMarketTierNumber)(this.driftClient.getSpotMarketAccount(spotPosition.marketIndex)));
|
|
1993
|
+
}
|
|
1994
|
+
return {
|
|
1995
|
+
perpTier: safestPerpTier,
|
|
1996
|
+
spotTier: safestSpotTier,
|
|
1997
|
+
};
|
|
1998
|
+
}
|
|
1999
|
+
getPerpPositionHealth({ marginCategory, perpPosition, oraclePriceData, quoteOraclePriceData, }) {
|
|
2000
|
+
const settledLpPosition = this.getPerpPositionWithLPSettle(perpPosition.marketIndex, perpPosition)[0];
|
|
2001
|
+
const perpMarket = this.driftClient.getPerpMarketAccount(perpPosition.marketIndex);
|
|
2002
|
+
const _oraclePriceData = oraclePriceData ||
|
|
2003
|
+
this.driftClient.getOracleDataForPerpMarket(perpMarket.marketIndex);
|
|
2004
|
+
const oraclePrice = _oraclePriceData.price;
|
|
2005
|
+
const { worstCaseBaseAssetAmount: worstCaseBaseAmount, worstCaseLiabilityValue, } = (0, _1.calculateWorstCasePerpLiabilityValue)(settledLpPosition, perpMarket, oraclePrice);
|
|
2006
|
+
const marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(perpMarket, worstCaseBaseAmount.abs(), marginCategory, this.getUserAccount().maxMarginRatio, this.isHighLeverageMode()));
|
|
2007
|
+
const _quoteOraclePriceData = quoteOraclePriceData ||
|
|
2008
|
+
this.driftClient.getOracleDataForSpotMarket(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
|
|
2009
|
+
let marginRequirement = worstCaseLiabilityValue
|
|
2010
|
+
.mul(_quoteOraclePriceData.price)
|
|
2011
|
+
.div(numericConstants_1.PRICE_PRECISION)
|
|
2012
|
+
.mul(marginRatio)
|
|
2013
|
+
.div(numericConstants_1.MARGIN_PRECISION);
|
|
2014
|
+
marginRequirement = marginRequirement.add(new _1.BN(perpPosition.openOrders).mul(numericConstants_1.OPEN_ORDER_MARGIN_REQUIREMENT));
|
|
2015
|
+
if (perpPosition.lpShares.gt(numericConstants_1.ZERO)) {
|
|
2016
|
+
marginRequirement = marginRequirement.add(_1.BN.max(numericConstants_1.QUOTE_PRECISION, oraclePrice
|
|
2017
|
+
.mul(perpMarket.amm.orderStepSize)
|
|
2018
|
+
.mul(numericConstants_1.QUOTE_PRECISION)
|
|
2019
|
+
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
2020
|
+
.div(numericConstants_1.PRICE_PRECISION)));
|
|
2021
|
+
}
|
|
2022
|
+
return {
|
|
2023
|
+
marketIndex: perpMarket.marketIndex,
|
|
2024
|
+
size: worstCaseBaseAmount,
|
|
2025
|
+
value: worstCaseLiabilityValue,
|
|
2026
|
+
weight: marginRatio,
|
|
2027
|
+
weightedValue: marginRequirement,
|
|
2028
|
+
};
|
|
2029
|
+
}
|
|
2030
|
+
getHealthComponents({ marginCategory, }) {
|
|
2031
|
+
const healthComponents = {
|
|
2032
|
+
deposits: [],
|
|
2033
|
+
borrows: [],
|
|
2034
|
+
perpPositions: [],
|
|
2035
|
+
perpPnl: [],
|
|
2036
|
+
};
|
|
2037
|
+
for (const perpPosition of this.getActivePerpPositions()) {
|
|
2038
|
+
const perpMarket = this.driftClient.getPerpMarketAccount(perpPosition.marketIndex);
|
|
2039
|
+
const oraclePriceData = this.driftClient.getOracleDataForPerpMarket(perpMarket.marketIndex);
|
|
2040
|
+
const quoteOraclePriceData = this.driftClient.getOracleDataForSpotMarket(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
|
|
2041
|
+
healthComponents.perpPositions.push(this.getPerpPositionHealth({
|
|
2042
|
+
marginCategory,
|
|
2043
|
+
perpPosition,
|
|
2044
|
+
oraclePriceData,
|
|
2045
|
+
quoteOraclePriceData,
|
|
2046
|
+
}));
|
|
2047
|
+
const quoteSpotMarket = this.driftClient.getSpotMarketAccount(perpMarket.quoteSpotMarketIndex);
|
|
2048
|
+
const settledPerpPosition = this.getPerpPositionWithLPSettle(perpPosition.marketIndex, perpPosition)[0];
|
|
2049
|
+
const positionUnrealizedPnl = (0, _1.calculatePositionPNL)(perpMarket, settledPerpPosition, true, oraclePriceData);
|
|
2050
|
+
let pnlWeight;
|
|
2051
|
+
if (positionUnrealizedPnl.gt(numericConstants_1.ZERO)) {
|
|
2052
|
+
pnlWeight = (0, _1.calculateUnrealizedAssetWeight)(perpMarket, quoteSpotMarket, positionUnrealizedPnl, marginCategory, oraclePriceData);
|
|
2053
|
+
}
|
|
2054
|
+
else {
|
|
2055
|
+
pnlWeight = numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION;
|
|
2056
|
+
}
|
|
2057
|
+
const pnlValue = positionUnrealizedPnl
|
|
2058
|
+
.mul(quoteOraclePriceData.price)
|
|
2059
|
+
.div(numericConstants_1.PRICE_PRECISION);
|
|
2060
|
+
const wegithedPnlValue = pnlValue
|
|
2061
|
+
.mul(pnlWeight)
|
|
2062
|
+
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
2063
|
+
healthComponents.perpPnl.push({
|
|
2064
|
+
marketIndex: perpMarket.marketIndex,
|
|
2065
|
+
size: positionUnrealizedPnl,
|
|
2066
|
+
value: pnlValue,
|
|
2067
|
+
weight: pnlWeight,
|
|
2068
|
+
weightedValue: wegithedPnlValue,
|
|
2069
|
+
});
|
|
2070
|
+
}
|
|
2071
|
+
let netQuoteValue = numericConstants_1.ZERO;
|
|
2072
|
+
for (const spotPosition of this.getActiveSpotPositions()) {
|
|
2073
|
+
const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
2074
|
+
const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
|
|
2075
|
+
const strictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(oraclePriceData.price);
|
|
2076
|
+
if (spotPosition.marketIndex === numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
|
|
2077
|
+
const tokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
|
|
2078
|
+
netQuoteValue = netQuoteValue.add(tokenAmount);
|
|
2079
|
+
continue;
|
|
2080
|
+
}
|
|
2081
|
+
const { tokenAmount: worstCaseTokenAmount, tokenValue: tokenValue, weight, weightedTokenValue: weightedTokenValue, ordersValue: ordersValue, } = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory, this.getUserAccount().maxMarginRatio);
|
|
2082
|
+
netQuoteValue = netQuoteValue.add(ordersValue);
|
|
2083
|
+
const baseAssetValue = tokenValue.abs();
|
|
2084
|
+
const weightedValue = weightedTokenValue.abs();
|
|
2085
|
+
if (weightedTokenValue.lt(numericConstants_1.ZERO)) {
|
|
2086
|
+
healthComponents.borrows.push({
|
|
2087
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
2088
|
+
size: worstCaseTokenAmount,
|
|
2089
|
+
value: baseAssetValue,
|
|
2090
|
+
weight: weight,
|
|
2091
|
+
weightedValue: weightedValue,
|
|
2092
|
+
});
|
|
2093
|
+
}
|
|
2094
|
+
else {
|
|
2095
|
+
healthComponents.deposits.push({
|
|
2096
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
2097
|
+
size: worstCaseTokenAmount,
|
|
2098
|
+
value: baseAssetValue,
|
|
2099
|
+
weight: weight,
|
|
2100
|
+
weightedValue: weightedValue,
|
|
2101
|
+
});
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
if (!netQuoteValue.eq(numericConstants_1.ZERO)) {
|
|
2105
|
+
const spotMarketAccount = this.driftClient.getQuoteSpotMarketAccount();
|
|
2106
|
+
const oraclePriceData = this.getOracleDataForSpotMarket(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
|
|
2107
|
+
const baseAssetValue = (0, _1.getTokenValue)(netQuoteValue, spotMarketAccount.decimals, oraclePriceData);
|
|
2108
|
+
const { weight, weightedTokenValue } = (0, spotPosition_1.calculateWeightedTokenValue)(netQuoteValue, baseAssetValue, oraclePriceData.price, spotMarketAccount, marginCategory, this.getUserAccount().maxMarginRatio);
|
|
2109
|
+
if (netQuoteValue.lt(numericConstants_1.ZERO)) {
|
|
2110
|
+
healthComponents.borrows.push({
|
|
2111
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
2112
|
+
size: netQuoteValue,
|
|
2113
|
+
value: baseAssetValue.abs(),
|
|
2114
|
+
weight: weight,
|
|
2115
|
+
weightedValue: weightedTokenValue.abs(),
|
|
2116
|
+
});
|
|
2117
|
+
}
|
|
2118
|
+
else {
|
|
2119
|
+
healthComponents.deposits.push({
|
|
2120
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
2121
|
+
size: netQuoteValue,
|
|
2122
|
+
value: baseAssetValue,
|
|
2123
|
+
weight: weight,
|
|
2124
|
+
weightedValue: weightedTokenValue,
|
|
2125
|
+
});
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
return healthComponents;
|
|
2129
|
+
}
|
|
2130
|
+
/**
|
|
2131
|
+
* Get the total position value, excluding any position coming from the given target market
|
|
2132
|
+
* @param marketToIgnore
|
|
2133
|
+
* @returns positionValue : Precision QUOTE_PRECISION
|
|
2134
|
+
*/
|
|
2135
|
+
getTotalPerpPositionValueExcludingMarket(marketToIgnore, marginCategory, liquidationBuffer, includeOpenOrders) {
|
|
2136
|
+
const currentPerpPosition = this.getPerpPositionWithLPSettle(marketToIgnore, undefined, !!marginCategory)[0] || this.getEmptyPosition(marketToIgnore);
|
|
2137
|
+
const oracleData = this.getOracleDataForPerpMarket(marketToIgnore);
|
|
2138
|
+
let currentPerpPositionValueUSDC = numericConstants_1.ZERO;
|
|
2139
|
+
if (currentPerpPosition) {
|
|
2140
|
+
currentPerpPositionValueUSDC = this.getPerpLiabilityValue(marketToIgnore, oracleData, includeOpenOrders);
|
|
2141
|
+
}
|
|
2142
|
+
return this.getTotalPerpPositionLiability(marginCategory, liquidationBuffer, includeOpenOrders).sub(currentPerpPositionValueUSDC);
|
|
2143
|
+
}
|
|
2144
|
+
getOracleDataForPerpMarket(marketIndex) {
|
|
2145
|
+
return this.driftClient.getOracleDataForPerpMarket(marketIndex);
|
|
2146
|
+
}
|
|
2147
|
+
getOracleDataForSpotMarket(marketIndex) {
|
|
2148
|
+
return this.driftClient.getOracleDataForSpotMarket(marketIndex);
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
exports.User = User;
|