@velocity-exchange/sdk 0.4.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/lib/browser/adminClient.d.ts +52 -0
- package/lib/browser/adminClient.js +97 -0
- package/lib/browser/config.js +6 -7
- package/lib/browser/constants/numericConstants.d.ts +1 -1
- package/lib/browser/constants/numericConstants.js +1 -1
- package/lib/browser/decode/user.js +5 -1
- package/lib/browser/idl/velocity.d.ts +191 -15
- package/lib/browser/idl/velocity.json +192 -16
- package/lib/browser/orderSubscriber/OrderSubscriber.d.ts +1 -0
- package/lib/browser/orderSubscriber/OrderSubscriber.js +10 -4
- package/lib/browser/pyth/pythLazerSubscriber.js +37 -27
- package/lib/browser/types.d.ts +6 -0
- package/lib/browser/user.d.ts +20 -3
- package/lib/browser/user.js +52 -4
- package/lib/browser/velocityClient.d.ts +46 -10
- package/lib/browser/velocityClient.js +107 -35
- package/lib/node/adminClient.d.ts +52 -0
- package/lib/node/adminClient.d.ts.map +1 -1
- package/lib/node/adminClient.js +97 -0
- package/lib/node/config.d.ts.map +1 -1
- package/lib/node/config.js +6 -7
- package/lib/node/constants/numericConstants.d.ts +1 -1
- package/lib/node/constants/numericConstants.d.ts.map +1 -1
- package/lib/node/constants/numericConstants.js +1 -1
- package/lib/node/decode/user.d.ts.map +1 -1
- package/lib/node/decode/user.js +5 -1
- package/lib/node/idl/velocity.d.ts +191 -15
- package/lib/node/idl/velocity.d.ts.map +1 -1
- package/lib/node/idl/velocity.json +192 -16
- package/lib/node/orderSubscriber/OrderSubscriber.d.ts +1 -0
- package/lib/node/orderSubscriber/OrderSubscriber.d.ts.map +1 -1
- package/lib/node/orderSubscriber/OrderSubscriber.js +10 -4
- package/lib/node/pyth/pythLazerSubscriber.d.ts.map +1 -1
- package/lib/node/pyth/pythLazerSubscriber.js +37 -27
- package/lib/node/types.d.ts +6 -0
- package/lib/node/types.d.ts.map +1 -1
- package/lib/node/user.d.ts +20 -3
- package/lib/node/user.d.ts.map +1 -1
- package/lib/node/user.js +52 -4
- package/lib/node/velocityClient.d.ts +46 -10
- package/lib/node/velocityClient.d.ts.map +1 -1
- package/lib/node/velocityClient.js +107 -35
- package/package.json +7 -3
- package/.prettierignore +0 -1
- package/CHANGELOG.md +0 -132
- package/build-browser.js +0 -58
- package/bunfig.toml +0 -3
- package/esbuild-shims.js +0 -12
- package/scripts/deposit-isolated-positions.ts +0 -110
- package/scripts/find-flagged-users.ts +0 -213
- package/scripts/grpc-client-test-comparison.ts +0 -372
- package/scripts/grpc-multiuser-client-test-comparison.ts +0 -158
- package/scripts/postbuild.js +0 -95
- package/scripts/single-grpc-client-test.ts +0 -284
- package/scripts/withdraw-isolated-positions.ts +0 -174
- package/src/accounts/README_WebSocketAccountSubscriberV2.md +0 -95
- package/src/accounts/README_WebSocketProgramAccountSubscriberV2.md +0 -135
- package/src/accounts/basicUserAccountSubscriber.ts +0 -79
- package/src/accounts/basicUserStatsAccountSubscriber.ts +0 -87
- package/src/accounts/bulkAccountLoader.ts +0 -358
- package/src/accounts/bulkUserStatsSubscription.ts +0 -40
- package/src/accounts/bulkUserSubscription.ts +0 -39
- package/src/accounts/customizedCadenceBulkAccountLoader.ts +0 -250
- package/src/accounts/fetch.ts +0 -200
- package/src/accounts/grpcAccountSubscriber.ts +0 -225
- package/src/accounts/grpcInsuranceFundStakeAccountSubscriber.ts +0 -73
- package/src/accounts/grpcMultiAccountSubscriber.ts +0 -566
- package/src/accounts/grpcMultiUserAccountSubscriber.ts +0 -328
- package/src/accounts/grpcProgramAccountSubscriber.ts +0 -264
- package/src/accounts/grpcUserAccountSubscriber.ts +0 -63
- package/src/accounts/grpcUserStatsAccountSubscriber.ts +0 -65
- package/src/accounts/grpcVelocityClientAccountSubscriber.ts +0 -257
- package/src/accounts/grpcVelocityClientAccountSubscriberV2.ts +0 -941
- package/src/accounts/laserProgramAccountSubscriber.ts +0 -266
- package/src/accounts/oneShotUserAccountSubscriber.ts +0 -88
- package/src/accounts/oneShotUserStatsAccountSubscriber.ts +0 -94
- package/src/accounts/pollingInsuranceFundStakeAccountSubscriber.ts +0 -223
- package/src/accounts/pollingOracleAccountSubscriber.ts +0 -151
- package/src/accounts/pollingTokenAccountSubscriber.ts +0 -147
- package/src/accounts/pollingUserAccountSubscriber.ts +0 -198
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +0 -180
- package/src/accounts/pollingVelocityClientAccountSubscriber.ts +0 -774
- package/src/accounts/testBulkAccountLoader.ts +0 -59
- package/src/accounts/types.ts +0 -428
- package/src/accounts/utils.ts +0 -90
- package/src/accounts/webSocketAccountSubscriber.ts +0 -304
- package/src/accounts/webSocketAccountSubscriberV2.ts +0 -536
- package/src/accounts/webSocketInsuranceFundStakeAccountSubscriber.ts +0 -171
- package/src/accounts/webSocketProgramAccountSubscriber.ts +0 -244
- package/src/accounts/webSocketProgramAccountSubscriberV2.ts +0 -1048
- package/src/accounts/webSocketProgramAccountsSubscriberV2.ts +0 -1042
- package/src/accounts/webSocketUserAccountSubscriber.ts +0 -139
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +0 -131
- package/src/accounts/webSocketVelocityClientAccountSubscriber.ts +0 -865
- package/src/accounts/webSocketVelocityClientAccountSubscriberV2.ts +0 -897
- package/src/accounts/websocketProgramUserAccountSubscriber.ts +0 -127
- package/src/addresses/marketAddresses.ts +0 -28
- package/src/addresses/pda.ts +0 -620
- package/src/adminClient.ts +0 -8136
- package/src/assert/assert.ts +0 -5
- package/src/auctionSubscriber/auctionSubscriber.ts +0 -86
- package/src/auctionSubscriber/auctionSubscriberGrpc.ts +0 -99
- package/src/auctionSubscriber/index.ts +0 -9
- package/src/auctionSubscriber/types.ts +0 -30
- package/src/bankrun/bankrunConnection.ts +0 -630
- package/src/blockhashSubscriber/BlockhashSubscriber.ts +0 -160
- package/src/blockhashSubscriber/index.ts +0 -6
- package/src/blockhashSubscriber/types.ts +0 -13
- package/src/clock/clockSubscriber.ts +0 -146
- package/src/config.ts +0 -312
- package/src/constants/index.ts +0 -9
- package/src/constants/numericConstants.ts +0 -194
- package/src/constants/perpMarkets.ts +0 -127
- package/src/constants/spotMarkets.ts +0 -104
- package/src/constants/txConstants.ts +0 -2
- package/src/constituentMap/constituentMap.ts +0 -305
- package/src/constituentMap/pollingConstituentAccountSubscriber.ts +0 -99
- package/src/constituentMap/webSocketConstituentAccountSubscriber.ts +0 -121
- package/src/core/VelocityCore.ts +0 -606
- package/src/core/index.ts +0 -12
- package/src/core/instructions/deposit.ts +0 -64
- package/src/core/instructions/fill.ts +0 -51
- package/src/core/instructions/funding.ts +0 -33
- package/src/core/instructions/liquidation.ts +0 -55
- package/src/core/instructions/orders.ts +0 -84
- package/src/core/instructions/perpOrders.ts +0 -312
- package/src/core/instructions/settlement.ts +0 -40
- package/src/core/instructions/trigger.ts +0 -41
- package/src/core/instructions/withdraw.ts +0 -65
- package/src/core/remainingAccounts.ts +0 -320
- package/src/core/signedMsg.ts +0 -109
- package/src/decode/customCoder.ts +0 -148
- package/src/decode/user.ts +0 -401
- package/src/dlob/DLOB.ts +0 -2793
- package/src/dlob/DLOBNode.ts +0 -305
- package/src/dlob/DLOBSubscriber.ts +0 -269
- package/src/dlob/NodeList.ts +0 -244
- package/src/dlob/orderBookLevels.ts +0 -695
- package/src/dlob/types.ts +0 -37
- package/src/events/eventList.ts +0 -114
- package/src/events/eventSubscriber.ts +0 -521
- package/src/events/eventsServerLogProvider.ts +0 -189
- package/src/events/fetchLogs.ts +0 -219
- package/src/events/parse.ts +0 -271
- package/src/events/pollingLogProvider.ts +0 -113
- package/src/events/sort.ts +0 -51
- package/src/events/txEventCache.ts +0 -92
- package/src/events/types.ts +0 -337
- package/src/events/webSocketLogProvider.ts +0 -152
- package/src/factory/bigNum.ts +0 -709
- package/src/factory/oracleClient.ts +0 -73
- package/src/idl/pyth.json +0 -142
- package/src/idl/pyth.ts +0 -97
- package/src/idl/pyth_solana_receiver.json +0 -628
- package/src/idl/token_faucet.json +0 -229
- package/src/idl/token_faucet.ts +0 -197
- package/src/idl/velocity.json +0 -23974
- package/src/idl/velocity.ts +0 -23980
- package/src/index.ts +0 -150
- package/src/indicative-quotes/indicativeQuotesSender.ts +0 -233
- package/src/isomorphic/README.md +0 -19
- package/src/isomorphic/anchor.browser.ts +0 -44
- package/src/isomorphic/anchor.node.ts +0 -1
- package/src/isomorphic/anchor.ts +0 -1
- package/src/isomorphic/anchor29.browser.ts +0 -24
- package/src/isomorphic/anchor29.node.ts +0 -1
- package/src/isomorphic/anchor29.ts +0 -1
- package/src/isomorphic/grpc.browser.ts +0 -4
- package/src/isomorphic/grpc.node.ts +0 -130
- package/src/isomorphic/grpc.ts +0 -1
- package/src/jupiter/jupiterClient.ts +0 -502
- package/src/keypair.ts +0 -32
- package/src/margin/README.md +0 -138
- package/src/marginCalculation.ts +0 -407
- package/src/marinade/idl/idl.json +0 -1962
- package/src/marinade/index.ts +0 -73
- package/src/marinade/types.ts +0 -3925
- package/src/math/amm.ts +0 -1758
- package/src/math/auction.ts +0 -480
- package/src/math/bankruptcy.ts +0 -138
- package/src/math/builder.ts +0 -130
- package/src/math/conversion.ts +0 -45
- package/src/math/exchangeStatus.ts +0 -261
- package/src/math/funding.ts +0 -498
- package/src/math/insurance.ts +0 -171
- package/src/math/liquidation.ts +0 -433
- package/src/math/margin.ts +0 -327
- package/src/math/market.ts +0 -487
- package/src/math/oracles.ts +0 -477
- package/src/math/orders.ts +0 -500
- package/src/math/position.ts +0 -381
- package/src/math/repeg.ts +0 -223
- package/src/math/spotBalance.ts +0 -996
- package/src/math/spotMarket.ts +0 -115
- package/src/math/spotPosition.ts +0 -263
- package/src/math/state.ts +0 -71
- package/src/math/superStake.ts +0 -602
- package/src/math/tiers.ts +0 -73
- package/src/math/trade.ts +0 -879
- package/src/math/utils.ts +0 -183
- package/src/memcmp.ts +0 -279
- package/src/oracles/oracleClientCache.ts +0 -41
- package/src/oracles/oracleId.ts +0 -99
- package/src/oracles/prelaunchOracleClient.ts +0 -63
- package/src/oracles/pythClient.ts +0 -125
- package/src/oracles/pythLazerClient.ts +0 -141
- package/src/oracles/quoteAssetOracleClient.ts +0 -43
- package/src/oracles/strictOraclePrice.ts +0 -40
- package/src/oracles/types.ts +0 -82
- package/src/oracles/utils.ts +0 -45
- package/src/orderParams.ts +0 -117
- package/src/orderSubscriber/OrderSubscriber.ts +0 -378
- package/src/orderSubscriber/PollingSubscription.ts +0 -50
- package/src/orderSubscriber/WebsocketSubscription.ts +0 -137
- package/src/orderSubscriber/grpcSubscription.ts +0 -155
- package/src/orderSubscriber/index.ts +0 -7
- package/src/orderSubscriber/types.ts +0 -64
- package/src/priorityFee/averageOverSlotsStrategy.ts +0 -17
- package/src/priorityFee/averageStrategy.ts +0 -13
- package/src/priorityFee/ewmaStrategy.ts +0 -51
- package/src/priorityFee/heliusPriorityFeeMethod.ts +0 -68
- package/src/priorityFee/index.ts +0 -16
- package/src/priorityFee/maxOverSlotsStrategy.ts +0 -18
- package/src/priorityFee/maxStrategy.ts +0 -8
- package/src/priorityFee/priorityFeeSubscriber.ts +0 -328
- package/src/priorityFee/priorityFeeSubscriberMap.ts +0 -134
- package/src/priorityFee/solanaPriorityFeeMethod.ts +0 -46
- package/src/priorityFee/types.ts +0 -82
- package/src/priorityFee/velocityPriorityFeeMethod.ts +0 -53
- package/src/pyth/constants.ts +0 -9
- package/src/pyth/index.ts +0 -15
- package/src/pyth/pythLazerSubscriber.ts +0 -365
- package/src/pyth/types.ts +0 -4451
- package/src/pyth/utils.ts +0 -13
- package/src/slot/SlotSubscriber.ts +0 -126
- package/src/slot/SlothashSubscriber.ts +0 -163
- package/src/swap/UnifiedSwapClient.ts +0 -315
- package/src/swift/grpcSignedMsgUserAccountSubscriber.ts +0 -81
- package/src/swift/index.ts +0 -10
- package/src/swift/signedMsgUserAccountSubscriber.ts +0 -251
- package/src/swift/swiftOrderSubscriber.ts +0 -351
- package/src/testClient.ts +0 -42
- package/src/titan/titanClient.ts +0 -438
- package/src/token/index.ts +0 -13
- package/src/tokenFaucet.ts +0 -296
- package/src/tx/baseTxSender.ts +0 -651
- package/src/tx/blockhashFetcher/baseBlockhashFetcher.ts +0 -31
- package/src/tx/blockhashFetcher/cachedBlockhashFetcher.ts +0 -105
- package/src/tx/blockhashFetcher/types.ts +0 -9
- package/src/tx/fastSingleTxSender.ts +0 -200
- package/src/tx/forwardOnlyTxSender.ts +0 -193
- package/src/tx/priorityFeeCalculator.ts +0 -117
- package/src/tx/reportTransactionError.ts +0 -176
- package/src/tx/retryTxSender.ts +0 -177
- package/src/tx/txHandler.ts +0 -1009
- package/src/tx/txParamProcessor.ts +0 -225
- package/src/tx/types.ts +0 -117
- package/src/tx/utils.ts +0 -133
- package/src/tx/whileValidTxSender.ts +0 -377
- package/src/types.ts +0 -2575
- package/src/user.ts +0 -5316
- package/src/userConfig.ts +0 -38
- package/src/userMap/PollingSubscription.ts +0 -61
- package/src/userMap/WebsocketSubscription.ts +0 -93
- package/src/userMap/grpcSubscription.ts +0 -93
- package/src/userMap/referrerMap.ts +0 -360
- package/src/userMap/revenueShareEscrowMap.ts +0 -342
- package/src/userMap/userMap.ts +0 -784
- package/src/userMap/userMapConfig.ts +0 -82
- package/src/userMap/userStatsMap.ts +0 -393
- package/src/userName.ts +0 -37
- package/src/userStats.ts +0 -159
- package/src/userStatsConfig.ts +0 -35
- package/src/util/TransactionConfirmationManager.ts +0 -333
- package/src/util/chainClock.ts +0 -65
- package/src/util/computeUnits.ts +0 -101
- package/src/util/digest.ts +0 -33
- package/src/util/ed25519Utils.ts +0 -95
- package/src/util/promiseTimeout.ts +0 -23
- package/src/velocityClient.ts +0 -14802
- package/src/velocityClientConfig.ts +0 -119
- package/src/wallet.ts +0 -91
- package/tests/VelocityCore/builder_escrow.test.ts +0 -121
- package/tests/VelocityCore/decode.test.ts +0 -16
- package/tests/VelocityCore/fill_trigger.test.ts +0 -73
- package/tests/VelocityCore/instructions.test.ts +0 -46
- package/tests/VelocityCore/pdas.test.ts +0 -30
- package/tests/VelocityCore/perp_orders.test.ts +0 -205
- package/tests/VelocityCore/remainingAccounts.test.ts +0 -72
- package/tests/VelocityCore/settlement_liquidation.test.ts +0 -69
- package/tests/accounts/customizedCadenceBulkAccountLoader.test.ts +0 -211
- package/tests/amm/test.ts +0 -2402
- package/tests/auctions/test.ts +0 -81
- package/tests/bn/test.ts +0 -355
- package/tests/builder/builderFee.test.ts +0 -42
- package/tests/ci/verifyConstants.ts +0 -393
- package/tests/decode/test.ts +0 -262
- package/tests/decode/userAccountBufferStrings.ts +0 -102
- package/tests/dlob/helpers.ts +0 -748
- package/tests/dlob/test.ts +0 -6969
- package/tests/dlob/tickSizeStandardization.ts +0 -545
- package/tests/events/parseLogsForCuUsage.ts +0 -139
- package/tests/exchangeStatus/test.ts +0 -45
- package/tests/insurance/test.ts +0 -40
- package/tests/liquidation/test.ts +0 -125
- package/tests/oracles/mmOracleGate.test.ts +0 -379
- package/tests/oracles/pythPegSnap.test.ts +0 -76
- package/tests/sdkParity/enumParity.test.ts +0 -84
- package/tests/sdkParity/marginCategoryFill.test.ts +0 -143
- package/tests/sdkParity/memcmpOffsets.test.ts +0 -139
- package/tests/spot/test.ts +0 -281
- package/tests/tx/TransactionConfirmationManager.test.ts +0 -312
- package/tests/tx/cachedBlockhashFetcher.test.ts +0 -96
- package/tests/tx/priorityFeeCalculator.ts +0 -77
- package/tests/tx/priorityFeeStrategy.ts +0 -95
- package/tests/user/bankruptcy.ts +0 -165
- package/tests/user/feeAndWithdrawLimits.ts +0 -284
- package/tests/user/getMarginCalculation.ts +0 -586
- package/tests/user/helpers.ts +0 -184
- package/tests/user/liquidations.ts +0 -129
- package/tests/user/marginCalculations.test.ts +0 -321
- package/tests/user/test.ts +0 -833
- package/tsconfig.browser.json +0 -18
- package/tsconfig.json +0 -36
package/src/math/position.ts
DELETED
|
@@ -1,381 +0,0 @@
|
|
|
1
|
-
import { BN } from '../isomorphic/anchor';
|
|
2
|
-
import {
|
|
3
|
-
AMM_RESERVE_PRECISION,
|
|
4
|
-
AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO,
|
|
5
|
-
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
6
|
-
FUNDING_RATE_BUFFER_PRECISION,
|
|
7
|
-
PRICE_PRECISION,
|
|
8
|
-
ONE,
|
|
9
|
-
ZERO,
|
|
10
|
-
} from '../constants/numericConstants';
|
|
11
|
-
import { MMOraclePriceData, OraclePriceData } from '../oracles/types';
|
|
12
|
-
import {
|
|
13
|
-
PerpMarketAccount,
|
|
14
|
-
PositionDirection,
|
|
15
|
-
PerpPosition,
|
|
16
|
-
SpotMarketAccount,
|
|
17
|
-
PositionFlag,
|
|
18
|
-
} from '../types';
|
|
19
|
-
import {
|
|
20
|
-
calculateUpdatedAMM,
|
|
21
|
-
calculateUpdatedAMMSpreadReserves,
|
|
22
|
-
calculateAmmReservesAfterSwap,
|
|
23
|
-
getSwapDirection,
|
|
24
|
-
} from './amm';
|
|
25
|
-
import { calculateBaseAssetValueWithOracle } from './margin';
|
|
26
|
-
import { calculateNetUserPnlImbalance } from './market';
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Simulates fully closing `userPosition` against the AMM (optionally through its bid/ask
|
|
30
|
-
* spread reserves) and returns the resulting quote value — i.e. the market value of closing
|
|
31
|
-
* the entire position right now, distinct from `calculateBaseAssetValueWithOracle`'s
|
|
32
|
-
* mark-to-oracle valuation used for margin.
|
|
33
|
-
* @param market Perp market whose AMM is used to price the close.
|
|
34
|
-
* @param userPosition Position to value; returns zero if flat (`baseAssetAmount == 0`).
|
|
35
|
-
* @param mmOraclePriceData MM oracle price data used to re-peg/update the AMM before pricing (unless `skipUpdate`).
|
|
36
|
-
* @param useSpread If true (default) and the market has a nonzero base spread, price through the bid/ask spread reserves on the closing side rather than the raw AMM reserves.
|
|
37
|
-
* @param skipUpdate If true, price against `market.amm` as-is without applying `calculateUpdatedAMM`/spread-reserve updates first (default false).
|
|
38
|
-
* @param latestSlot Current slot, forwarded to the spread-reserve update for reference-price-offset smoothing.
|
|
39
|
-
* @returns Value of fully closing the position, QUOTE_PRECISION (1e6).
|
|
40
|
-
*/
|
|
41
|
-
export function calculateBaseAssetValue(
|
|
42
|
-
market: PerpMarketAccount,
|
|
43
|
-
userPosition: PerpPosition,
|
|
44
|
-
mmOraclePriceData: MMOraclePriceData,
|
|
45
|
-
useSpread = true,
|
|
46
|
-
skipUpdate = false,
|
|
47
|
-
latestSlot?: BN
|
|
48
|
-
): BN {
|
|
49
|
-
if (userPosition.baseAssetAmount.eq(ZERO)) {
|
|
50
|
-
return ZERO;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const directionToClose = findDirectionToClose(userPosition);
|
|
54
|
-
let prepegAmm: Parameters<typeof calculateAmmReservesAfterSwap>[0];
|
|
55
|
-
|
|
56
|
-
if (!skipUpdate) {
|
|
57
|
-
if (market.amm.baseSpread > 0 && useSpread) {
|
|
58
|
-
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } =
|
|
59
|
-
calculateUpdatedAMMSpreadReserves(
|
|
60
|
-
market.amm,
|
|
61
|
-
market.marketStats,
|
|
62
|
-
directionToClose,
|
|
63
|
-
mmOraclePriceData,
|
|
64
|
-
latestSlot
|
|
65
|
-
);
|
|
66
|
-
prepegAmm = {
|
|
67
|
-
baseAssetReserve,
|
|
68
|
-
quoteAssetReserve,
|
|
69
|
-
sqrtK: sqrtK,
|
|
70
|
-
pegMultiplier: newPeg,
|
|
71
|
-
};
|
|
72
|
-
} else {
|
|
73
|
-
prepegAmm = calculateUpdatedAMM(market.amm, mmOraclePriceData);
|
|
74
|
-
}
|
|
75
|
-
} else {
|
|
76
|
-
prepegAmm = market.amm;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const [newQuoteAssetReserve, _] = calculateAmmReservesAfterSwap(
|
|
80
|
-
prepegAmm,
|
|
81
|
-
'base',
|
|
82
|
-
userPosition.baseAssetAmount.abs(),
|
|
83
|
-
getSwapDirection('base', directionToClose)
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
switch (directionToClose) {
|
|
87
|
-
case PositionDirection.SHORT:
|
|
88
|
-
return prepegAmm.quoteAssetReserve
|
|
89
|
-
.sub(newQuoteAssetReserve)
|
|
90
|
-
.mul(prepegAmm.pegMultiplier)
|
|
91
|
-
.div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
|
|
92
|
-
|
|
93
|
-
case PositionDirection.LONG:
|
|
94
|
-
return newQuoteAssetReserve
|
|
95
|
-
.sub(prepegAmm.quoteAssetReserve)
|
|
96
|
-
.mul(prepegAmm.pegMultiplier)
|
|
97
|
-
.div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO)
|
|
98
|
-
.add(ONE);
|
|
99
|
-
|
|
100
|
-
default:
|
|
101
|
-
throw new Error('Invalid position direction to close');
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Calculates a position's unrealized pnl, marked to the oracle price (via
|
|
107
|
-
* `calculateBaseAssetValueWithOracle`) rather than the AMM close price. For a flat position
|
|
108
|
-
* this is simply `quoteAssetAmount` (any residual realized/settled pnl still on the position).
|
|
109
|
-
* @param market Perp market the position belongs to.
|
|
110
|
-
* @param perpPosition Position to value.
|
|
111
|
-
* @param withFunding If true, adds unsettled funding pnl (`calculateUnsettledFundingPnl`) to the result (default false).
|
|
112
|
-
* @param oraclePriceData Must provide `price`, PRICE_PRECISION (1e6); used unless the market is in `settlement` status (which uses `market.expiryPrice` internally).
|
|
113
|
-
* @returns Unrealized pnl, QUOTE_PRECISION (1e6, signed).
|
|
114
|
-
*/
|
|
115
|
-
export function calculatePositionPNL(
|
|
116
|
-
market: PerpMarketAccount,
|
|
117
|
-
perpPosition: PerpPosition,
|
|
118
|
-
withFunding = false,
|
|
119
|
-
oraclePriceData: Pick<OraclePriceData, 'price'>
|
|
120
|
-
): BN {
|
|
121
|
-
if (perpPosition.baseAssetAmount.eq(ZERO)) {
|
|
122
|
-
return perpPosition.quoteAssetAmount;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const baseAssetValue = calculateBaseAssetValueWithOracle(
|
|
126
|
-
market,
|
|
127
|
-
perpPosition,
|
|
128
|
-
oraclePriceData
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
const baseAssetValueSign = perpPosition.baseAssetAmount.isNeg()
|
|
132
|
-
? new BN(-1)
|
|
133
|
-
: new BN(1);
|
|
134
|
-
let pnl = baseAssetValue
|
|
135
|
-
.mul(baseAssetValueSign)
|
|
136
|
-
.add(perpPosition.quoteAssetAmount);
|
|
137
|
-
|
|
138
|
-
if (withFunding) {
|
|
139
|
-
const fundingRatePnL = calculateUnsettledFundingPnl(market, perpPosition);
|
|
140
|
-
pnl = pnl.add(fundingRatePnL);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return pnl;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Caps a position's unrealized pnl (incl. funding) to the amount actually settleable via
|
|
148
|
-
* `settle_pnl`, mirroring `PerpPosition::get_claimable_pnl` in
|
|
149
|
-
* `programs/velocity/src/state/user.rs`. Positive pnl can only be settled up to whichever is
|
|
150
|
-
* larger: pnl already realized by reducing the position (`quoteAssetAmount -
|
|
151
|
-
* quoteEntryAmount`, floored at zero) plus any pnl-pool surplus over the market's net user
|
|
152
|
-
* pnl (`calculateNetUserPnlImbalance`, negated and floored at zero). Negative pnl passes
|
|
153
|
-
* through uncapped — this function does not itself gate on margin requirements (the program
|
|
154
|
-
* separately blocks settling negative pnl for a user who wouldn't meet maintenance margin
|
|
155
|
-
* afterward).
|
|
156
|
-
* @param market Perp market the position belongs to.
|
|
157
|
-
* @param spotMarket Quote spot market, used to size the pnl pool via `calculateNetUserPnlImbalance`.
|
|
158
|
-
* @param perpPosition Position to evaluate.
|
|
159
|
-
* @param oraclePriceData Must provide `price`, PRICE_PRECISION (1e6).
|
|
160
|
-
* @returns Settleable pnl, QUOTE_PRECISION (1e6, signed) — equal to unrealized pnl if negative or uncapped, otherwise capped.
|
|
161
|
-
*/
|
|
162
|
-
export function calculateClaimablePnl(
|
|
163
|
-
market: PerpMarketAccount,
|
|
164
|
-
spotMarket: SpotMarketAccount,
|
|
165
|
-
perpPosition: PerpPosition,
|
|
166
|
-
oraclePriceData: Pick<OraclePriceData, 'price'>
|
|
167
|
-
): BN {
|
|
168
|
-
const unrealizedPnl = calculatePositionPNL(
|
|
169
|
-
market,
|
|
170
|
-
perpPosition,
|
|
171
|
-
true,
|
|
172
|
-
oraclePriceData
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
let unsettledPnl = unrealizedPnl;
|
|
176
|
-
if (unrealizedPnl.gt(ZERO)) {
|
|
177
|
-
const excessPnlPool = BN.max(
|
|
178
|
-
ZERO,
|
|
179
|
-
calculateNetUserPnlImbalance(market, spotMarket, oraclePriceData).mul(
|
|
180
|
-
new BN(-1)
|
|
181
|
-
)
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
const maxPositivePnl = BN.max(
|
|
185
|
-
perpPosition.quoteAssetAmount.sub(perpPosition.quoteEntryAmount),
|
|
186
|
-
ZERO
|
|
187
|
-
).add(excessPnlPool);
|
|
188
|
-
|
|
189
|
-
unsettledPnl = BN.min(maxPositivePnl, unrealizedPnl);
|
|
190
|
-
}
|
|
191
|
-
return unsettledPnl;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Returns the cumulative fees-plus-funding component of a position's pnl (i.e. the part of
|
|
196
|
-
* pnl not explained by price movement): settled funding/fees so far
|
|
197
|
-
* (`quoteBreakEvenAmount - quoteEntryAmount`) plus, optionally, unsettled funding accrued
|
|
198
|
-
* since the last funding settlement.
|
|
199
|
-
* @param market Perp market the position belongs to.
|
|
200
|
-
* @param perpPosition Position to evaluate.
|
|
201
|
-
* @param includeUnsettled If true (default), adds `calculateUnsettledFundingPnl` to the result.
|
|
202
|
-
* @returns Fees + funding pnl, QUOTE_PRECISION (1e6, signed).
|
|
203
|
-
*/
|
|
204
|
-
export function calculateFeesAndFundingPnl(
|
|
205
|
-
market: PerpMarketAccount,
|
|
206
|
-
perpPosition: PerpPosition,
|
|
207
|
-
includeUnsettled = true
|
|
208
|
-
): BN {
|
|
209
|
-
const settledFundingAndFeesPnl = perpPosition.quoteBreakEvenAmount.sub(
|
|
210
|
-
perpPosition.quoteEntryAmount
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
if (!includeUnsettled) {
|
|
214
|
-
return settledFundingAndFeesPnl;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const unsettledFundingPnl = calculateUnsettledFundingPnl(
|
|
218
|
-
market,
|
|
219
|
-
perpPosition
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
return settledFundingAndFeesPnl.add(unsettledFundingPnl);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Returns unsettled funding pnl accrued on the position since its last funding settlement:
|
|
227
|
-
* the delta between the market's current cumulative funding rate (long or short side,
|
|
228
|
-
* selected by position direction) and the position's `lastCumulativeFundingRate`, applied to
|
|
229
|
-
* `baseAssetAmount`. Zero for a flat position.
|
|
230
|
-
*
|
|
231
|
-
* To calculate all fees and funding pnl including settled, use `calculateFeesAndFundingPnl`.
|
|
232
|
-
*
|
|
233
|
-
* @param market Perp market the position belongs to; uses `cumulativeFundingRateLong`/`cumulativeFundingRateShort`.
|
|
234
|
-
* @param perpPosition Position to evaluate.
|
|
235
|
-
* @returns Unsettled funding pnl, QUOTE_PRECISION (1e6, signed).
|
|
236
|
-
*/
|
|
237
|
-
export function calculateUnsettledFundingPnl(
|
|
238
|
-
market: PerpMarketAccount,
|
|
239
|
-
perpPosition: PerpPosition
|
|
240
|
-
): BN {
|
|
241
|
-
if (perpPosition.baseAssetAmount.eq(ZERO)) {
|
|
242
|
-
return ZERO;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
let ammCumulativeFundingRate: BN;
|
|
246
|
-
if (perpPosition.baseAssetAmount.gt(ZERO)) {
|
|
247
|
-
ammCumulativeFundingRate = market.cumulativeFundingRateLong;
|
|
248
|
-
} else {
|
|
249
|
-
ammCumulativeFundingRate = market.cumulativeFundingRateShort;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const perPositionFundingRate = ammCumulativeFundingRate
|
|
253
|
-
.sub(perpPosition.lastCumulativeFundingRate)
|
|
254
|
-
.mul(perpPosition.baseAssetAmount)
|
|
255
|
-
.div(AMM_RESERVE_PRECISION)
|
|
256
|
-
.div(FUNDING_RATE_BUFFER_PRECISION)
|
|
257
|
-
.mul(new BN(-1));
|
|
258
|
-
|
|
259
|
-
return perPositionFundingRate;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* True if a `PerpPosition` slot is free to be reused for a different market, mirroring
|
|
264
|
-
* `PerpPosition::is_available` in `programs/velocity/src/state/user.rs`: no open base
|
|
265
|
-
* position, no open orders, no unsettled quote pnl, no isolated-margin collateral parked in
|
|
266
|
-
* it (`isolatedPositionScaledBalance == 0`), and not currently mid-liquidation/bankruptcy.
|
|
267
|
-
* An isolated position with collateral still deposited is never "available" even if flat,
|
|
268
|
-
* since that collateral must be withdrawn first.
|
|
269
|
-
* @param position Position slot to check.
|
|
270
|
-
* @returns `true` if the slot can be assigned to a new market.
|
|
271
|
-
*/
|
|
272
|
-
export function positionIsAvailable(position: PerpPosition): boolean {
|
|
273
|
-
return (
|
|
274
|
-
position.baseAssetAmount.eq(ZERO) &&
|
|
275
|
-
position.openOrders === 0 &&
|
|
276
|
-
position.quoteAssetAmount.eq(ZERO) &&
|
|
277
|
-
position.isolatedPositionScaledBalance.eq(ZERO) &&
|
|
278
|
-
!positionIsBeingLiquidated(position)
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/** True if `position.positionFlag` has the `BeingLiquidated` or `Bankruptcy` bit set. */
|
|
283
|
-
export function positionIsBeingLiquidated(position: PerpPosition): boolean {
|
|
284
|
-
return (
|
|
285
|
-
(position.positionFlag &
|
|
286
|
-
(PositionFlag.BeingLiquidated | PositionFlag.Bankruptcy)) >
|
|
287
|
-
0
|
|
288
|
-
);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* Price at which closing the position realizes zero further pnl, i.e. entry price adjusted
|
|
293
|
-
* for fees and funding paid/received so far (`quoteBreakEvenAmount / baseAssetAmount`).
|
|
294
|
-
* @param userPosition Position to evaluate.
|
|
295
|
-
* @returns Break-even price (always non-negative), PRICE_PRECISION (1e6). Zero if flat.
|
|
296
|
-
*/
|
|
297
|
-
export function calculateBreakEvenPrice(userPosition: PerpPosition): BN {
|
|
298
|
-
if (userPosition.baseAssetAmount.eq(ZERO)) {
|
|
299
|
-
return ZERO;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
return userPosition.quoteBreakEvenAmount
|
|
303
|
-
.mul(PRICE_PRECISION)
|
|
304
|
-
.mul(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
305
|
-
.div(userPosition.baseAssetAmount)
|
|
306
|
-
.abs();
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
/**
|
|
310
|
-
* Average entry price of the position, before fees/funding (`quoteEntryAmount / baseAssetAmount`).
|
|
311
|
-
* @param userPosition Position to evaluate.
|
|
312
|
-
* @returns Average entry price (always non-negative), PRICE_PRECISION (1e6). Zero if flat.
|
|
313
|
-
*/
|
|
314
|
-
export function calculateEntryPrice(userPosition: PerpPosition): BN {
|
|
315
|
-
if (userPosition.baseAssetAmount.eq(ZERO)) {
|
|
316
|
-
return ZERO;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
return userPosition.quoteEntryAmount
|
|
320
|
-
.mul(PRICE_PRECISION)
|
|
321
|
-
.mul(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
322
|
-
.div(userPosition.baseAssetAmount)
|
|
323
|
-
.abs();
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Cost basis of the position (`quoteAssetAmount / baseAssetAmount`, optionally including
|
|
328
|
-
* realized settled pnl), i.e. the current quote value backing the position expressed per
|
|
329
|
-
* unit of base — this differs from `calculateEntryPrice` whenever the position has
|
|
330
|
-
* accumulated settled pnl or fees since it was opened.
|
|
331
|
-
* @param userPosition Position to evaluate.
|
|
332
|
-
* @param includeSettledPnl If true, folds `userPosition.settledPnl` into the quote amount before dividing (default false).
|
|
333
|
-
* @returns Cost basis (always non-negative), PRICE_PRECISION (1e6). Zero if flat.
|
|
334
|
-
*/
|
|
335
|
-
export function calculateCostBasis(
|
|
336
|
-
userPosition: PerpPosition,
|
|
337
|
-
includeSettledPnl = false
|
|
338
|
-
): BN {
|
|
339
|
-
if (userPosition.baseAssetAmount.eq(ZERO)) {
|
|
340
|
-
return ZERO;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
return userPosition.quoteAssetAmount
|
|
344
|
-
.add(includeSettledPnl ? userPosition.settledPnl : ZERO)
|
|
345
|
-
.mul(PRICE_PRECISION)
|
|
346
|
-
.mul(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
347
|
-
.div(userPosition.baseAssetAmount)
|
|
348
|
-
.abs();
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/** Direction of the trade that would fully close `userPosition`: `SHORT` for a long position (base > 0), `LONG` otherwise (including flat). */
|
|
352
|
-
export function findDirectionToClose(
|
|
353
|
-
userPosition: PerpPosition
|
|
354
|
-
): PositionDirection {
|
|
355
|
-
return userPosition.baseAssetAmount.gt(ZERO)
|
|
356
|
-
? PositionDirection.SHORT
|
|
357
|
-
: PositionDirection.LONG;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/** The position's own directional exposure: `LONG` if `baseAssetAmount >= 0` (including flat), `SHORT` if negative. */
|
|
361
|
-
export function positionCurrentDirection(
|
|
362
|
-
userPosition: PerpPosition
|
|
363
|
-
): PositionDirection {
|
|
364
|
-
return userPosition.baseAssetAmount.gte(ZERO)
|
|
365
|
-
? PositionDirection.LONG
|
|
366
|
-
: PositionDirection.SHORT;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
/** True if the position has no open base exposure and no open orders (a coarser check than `positionIsAvailable` — does not check quote pnl, isolated collateral, or liquidation flags). */
|
|
370
|
-
export function isEmptyPosition(userPosition: PerpPosition): boolean {
|
|
371
|
-
return userPosition.baseAssetAmount.eq(ZERO) && userPosition.openOrders === 0;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
/** True if the position has any open orders, resting bids, or resting asks, mirroring `PerpPosition::has_open_order` in `programs/velocity/src/state/user.rs`. */
|
|
375
|
-
export function hasOpenOrders(position: PerpPosition): boolean {
|
|
376
|
-
return (
|
|
377
|
-
position.openOrders != 0 ||
|
|
378
|
-
!position.openBids.eq(ZERO) ||
|
|
379
|
-
!position.openAsks.eq(ZERO)
|
|
380
|
-
);
|
|
381
|
-
}
|
package/src/math/repeg.ts
DELETED
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { BN } from '../isomorphic/anchor';
|
|
2
|
-
import { assert } from '../assert/assert';
|
|
3
|
-
import {
|
|
4
|
-
PRICE_PRECISION,
|
|
5
|
-
AMM_RESERVE_PRECISION,
|
|
6
|
-
PEG_PRECISION,
|
|
7
|
-
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
8
|
-
PRICE_DIV_PEG,
|
|
9
|
-
QUOTE_PRECISION,
|
|
10
|
-
ZERO,
|
|
11
|
-
ONE,
|
|
12
|
-
PERCENTAGE_PRECISION,
|
|
13
|
-
} from '../constants/numericConstants';
|
|
14
|
-
import { AMM } from '../types';
|
|
15
|
-
/**
|
|
16
|
-
* Closed-form estimate of the quote-denominated cost of scaling the AMM's `sqrtK`
|
|
17
|
-
* (liquidity depth) by `numerator / denomenator` while holding `pegMultiplier` fixed.
|
|
18
|
-
* Used by `calculateNewAmm` as the cheap-to-compute stand-in for the program's K-shrink
|
|
19
|
-
* step (`adjust_k_cost_and_update` in `vlp/amm/quoter.rs`, which shrinks `sqrtK` by 0.1%
|
|
20
|
-
* — i.e. `numerator`/`denomenator` = 999/1000 — when a straight repeg to the oracle price
|
|
21
|
-
* would exceed the AMM's affordability budget). A positive result is a cost the AMM must
|
|
22
|
-
* fund from `totalFeeMinusDistributions`; shrinking K (denomenator > numerator) typically
|
|
23
|
-
* yields a negative cost (a rebate) since it reduces the AMM's net unrealized exposure.
|
|
24
|
-
* @param amm AMM state (uses `baseAssetReserve`, `quoteAssetReserve`, `baseAssetAmountWithAmm`, `pegMultiplier`).
|
|
25
|
-
* @param numerator Numerator of the K scale factor (e.g. 999).
|
|
26
|
-
* @param denomenator Denominator of the K scale factor (e.g. 1000).
|
|
27
|
-
* @returns Cost of the K adjustment, QUOTE_PRECISION (1e6).
|
|
28
|
-
*/
|
|
29
|
-
export function calculateAdjustKCost(
|
|
30
|
-
amm: AMM,
|
|
31
|
-
numerator: BN,
|
|
32
|
-
denomenator: BN
|
|
33
|
-
): BN {
|
|
34
|
-
// const k = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
35
|
-
const x = amm.baseAssetReserve;
|
|
36
|
-
const y = amm.quoteAssetReserve;
|
|
37
|
-
|
|
38
|
-
const d = amm.baseAssetAmountWithAmm;
|
|
39
|
-
const Q = amm.pegMultiplier;
|
|
40
|
-
|
|
41
|
-
const quoteScale = y.mul(d).mul(Q); //.div(AMM_RESERVE_PRECISION);
|
|
42
|
-
|
|
43
|
-
const p = numerator.mul(PRICE_PRECISION).div(denomenator);
|
|
44
|
-
|
|
45
|
-
const cost = quoteScale
|
|
46
|
-
.mul(PERCENTAGE_PRECISION)
|
|
47
|
-
.mul(PERCENTAGE_PRECISION)
|
|
48
|
-
.div(x.add(d))
|
|
49
|
-
.sub(
|
|
50
|
-
quoteScale
|
|
51
|
-
.mul(p)
|
|
52
|
-
.mul(PERCENTAGE_PRECISION)
|
|
53
|
-
.mul(PERCENTAGE_PRECISION)
|
|
54
|
-
.div(PRICE_PRECISION)
|
|
55
|
-
.div(x.mul(p).div(PRICE_PRECISION).add(d))
|
|
56
|
-
)
|
|
57
|
-
.div(PERCENTAGE_PRECISION)
|
|
58
|
-
.div(PERCENTAGE_PRECISION)
|
|
59
|
-
.div(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
60
|
-
.div(PEG_PRECISION);
|
|
61
|
-
|
|
62
|
-
return cost.mul(new BN(-1));
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// /**
|
|
66
|
-
// * Helper function calculating adjust k cost
|
|
67
|
-
// * @param amm
|
|
68
|
-
// * @param numerator
|
|
69
|
-
// * @param denomenator
|
|
70
|
-
// * @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
71
|
-
// */
|
|
72
|
-
// export function calculateAdjustKCost2(
|
|
73
|
-
// amm: AMM,
|
|
74
|
-
// numerator: BN,
|
|
75
|
-
// denomenator: BN
|
|
76
|
-
// ): BN {
|
|
77
|
-
// // const k = market.amm.sqrtK.mul(market.amm.sqrtK);
|
|
78
|
-
// const directionToClose = amm.baseAssetAmountWithAmm.gt(ZERO)
|
|
79
|
-
// ? PositionDirection.SHORT
|
|
80
|
-
// : PositionDirection.LONG;
|
|
81
|
-
|
|
82
|
-
// const [newQuoteAssetReserve, _newBaseAssetReserve] =
|
|
83
|
-
// calculateAmmReservesAfterSwap(
|
|
84
|
-
// amm,
|
|
85
|
-
// 'base',
|
|
86
|
-
// amm.baseAssetAmountWithAmm.abs(),
|
|
87
|
-
// getSwapDirection('base', directionToClose)
|
|
88
|
-
// );
|
|
89
|
-
// }
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Calculates the quote-denominated cost of moving the AMM's `pegMultiplier` to `newPeg`,
|
|
93
|
-
* mirroring `calculate_repeg_cost` in `vlp/amm/math/repeg.rs`: `(quoteAssetReserve -
|
|
94
|
-
* terminalQuoteAssetReserve) * (newPeg - pegMultiplier) / AMM_TO_QUOTE_PRECISION_RATIO`.
|
|
95
|
-
* The sign follows the AMM's inventory skew (`quoteAssetReserve - terminalQuoteAssetReserve`)
|
|
96
|
-
* — repegging in the direction that favors the AMM's current net position is free or a
|
|
97
|
-
* rebate; repegging against it costs `totalFeeMinusDistributions`. Zero when the AMM carries
|
|
98
|
-
* no net inventory (`quoteAssetReserve == terminalQuoteAssetReserve`).
|
|
99
|
-
* @param amm AMM state (uses `quoteAssetReserve`, `terminalQuoteAssetReserve`, `pegMultiplier`).
|
|
100
|
-
* @param newPeg Candidate peg multiplier, PEG_PRECISION (1e6).
|
|
101
|
-
* @returns Signed cost of the repeg, QUOTE_PRECISION (1e6).
|
|
102
|
-
*/
|
|
103
|
-
export function calculateRepegCost(amm: AMM, newPeg: BN): BN {
|
|
104
|
-
const dqar = amm.quoteAssetReserve.sub(amm.terminalQuoteAssetReserve);
|
|
105
|
-
const cost = dqar
|
|
106
|
-
.mul(newPeg.sub(amm.pegMultiplier))
|
|
107
|
-
.div(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
108
|
-
.div(PEG_PRECISION);
|
|
109
|
-
return cost;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Solves for a `sqrtK` scale factor `numerator / denominator` such that repegging the AMM
|
|
114
|
-
* to price-neutral (holding the terminal/reserve price relationship implied by the current
|
|
115
|
-
* inventory) costs exactly `budget`. Used as the closed-form companion to
|
|
116
|
-
* `calculateAdjustKCost` (same K-shrink mechanism as the program's `adjust_k_cost_and_update`)
|
|
117
|
-
* when solving for "how much must K move to spend exactly this much." Falls back to a fixed
|
|
118
|
-
* `[10000, 1]` (10000x factor) if the budget is negative (protocol spending to increase K) and the
|
|
119
|
-
* solution would be numerically unstable.
|
|
120
|
-
* @param x AMM `baseAssetReserve`, AMM_RESERVE_PRECISION (1e9).
|
|
121
|
-
* @param y AMM `quoteAssetReserve`, AMM_RESERVE_PRECISION (1e9).
|
|
122
|
-
* @param budget Quote budget available to spend on the K adjustment, QUOTE_PRECISION (1e6).
|
|
123
|
-
* @param Q AMM `pegMultiplier`, PEG_PRECISION (1e6).
|
|
124
|
-
* @param d AMM `baseAssetAmountWithAmm` (net AMM inventory), AMM_RESERVE_PRECISION (1e9).
|
|
125
|
-
* @returns `[numerator, denominator]` scale factor to apply to `sqrtK`/`baseAssetReserve`.
|
|
126
|
-
*/
|
|
127
|
-
export function calculateBudgetedKBN(
|
|
128
|
-
x: BN,
|
|
129
|
-
y: BN,
|
|
130
|
-
budget: BN,
|
|
131
|
-
Q: BN,
|
|
132
|
-
d: BN
|
|
133
|
-
): [BN, BN] {
|
|
134
|
-
assert(Q.gt(new BN(0)));
|
|
135
|
-
const C = budget.mul(new BN(-1));
|
|
136
|
-
|
|
137
|
-
let dSign = new BN(1);
|
|
138
|
-
if (d.lt(new BN(0))) {
|
|
139
|
-
dSign = new BN(-1);
|
|
140
|
-
}
|
|
141
|
-
const pegged_y_d_d = y
|
|
142
|
-
.mul(d)
|
|
143
|
-
.mul(d)
|
|
144
|
-
.mul(Q)
|
|
145
|
-
.div(AMM_RESERVE_PRECISION)
|
|
146
|
-
.div(AMM_RESERVE_PRECISION)
|
|
147
|
-
.div(PEG_PRECISION);
|
|
148
|
-
|
|
149
|
-
const numer1 = pegged_y_d_d;
|
|
150
|
-
const numer2 = C.mul(d)
|
|
151
|
-
.div(QUOTE_PRECISION)
|
|
152
|
-
.mul(x.add(d))
|
|
153
|
-
.div(AMM_RESERVE_PRECISION)
|
|
154
|
-
.mul(dSign);
|
|
155
|
-
|
|
156
|
-
const denom1 = C.mul(x)
|
|
157
|
-
.mul(x.add(d))
|
|
158
|
-
.div(AMM_RESERVE_PRECISION)
|
|
159
|
-
.div(QUOTE_PRECISION);
|
|
160
|
-
const denom2 = pegged_y_d_d;
|
|
161
|
-
|
|
162
|
-
// protocol is spending to increase k
|
|
163
|
-
if (C.lt(ZERO)) {
|
|
164
|
-
// thus denom1 is negative and solution is unstable
|
|
165
|
-
if (denom1.abs().gt(denom2.abs())) {
|
|
166
|
-
console.log('denom1 > denom2', denom1.toString(), denom2.toString());
|
|
167
|
-
console.log('budget cost exceeds stable K solution');
|
|
168
|
-
return [new BN(10000), new BN(1)];
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const numerator = numer1.sub(numer2).div(AMM_TO_QUOTE_PRECISION_RATIO);
|
|
173
|
-
const denominator = denom1.add(denom2).div(AMM_TO_QUOTE_PRECISION_RATIO);
|
|
174
|
-
|
|
175
|
-
return [numerator, denominator];
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Calculates the largest peg move affordable within `budget`, capped so it never overshoots
|
|
180
|
-
* `targetPrice`'s implied peg. Mirrors the "use full budget peg" branch of `adjust_amm` in
|
|
181
|
-
* `vlp/amm/math/repeg.rs`: computes a per-peg-unit cost from the AMM's inventory skew, then
|
|
182
|
-
* returns `targetPeg` directly whenever moving toward it is free or revenue-generating
|
|
183
|
-
* (`useTargetPeg`), otherwise walks the peg by `budget / perPegCost` and floors it at 1.
|
|
184
|
-
* @param amm AMM state (uses `quoteAssetReserve`, `terminalQuoteAssetReserve`, `baseAssetReserve`, `pegMultiplier`).
|
|
185
|
-
* @param budget Quote budget available to spend on the repeg, QUOTE_PRECISION (1e6).
|
|
186
|
-
* @param targetPrice Oracle-implied target price driving the optimal peg, PRICE_PRECISION (1e6).
|
|
187
|
-
* @returns New peg multiplier, PEG_PRECISION (1e6), never below 1.
|
|
188
|
-
*/
|
|
189
|
-
export function calculateBudgetedPeg(
|
|
190
|
-
amm: AMM,
|
|
191
|
-
budget: BN,
|
|
192
|
-
targetPrice: BN
|
|
193
|
-
): BN {
|
|
194
|
-
let perPegCost = amm.quoteAssetReserve
|
|
195
|
-
.sub(amm.terminalQuoteAssetReserve)
|
|
196
|
-
.div(AMM_RESERVE_PRECISION.div(PRICE_PRECISION));
|
|
197
|
-
|
|
198
|
-
if (perPegCost.gt(ZERO)) {
|
|
199
|
-
perPegCost = perPegCost.add(ONE);
|
|
200
|
-
} else if (perPegCost.lt(ZERO)) {
|
|
201
|
-
perPegCost = perPegCost.sub(ONE);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const targetPeg = targetPrice
|
|
205
|
-
.mul(amm.baseAssetReserve)
|
|
206
|
-
.div(amm.quoteAssetReserve)
|
|
207
|
-
.div(PRICE_DIV_PEG);
|
|
208
|
-
|
|
209
|
-
const pegChangeDirection = targetPeg.sub(amm.pegMultiplier);
|
|
210
|
-
|
|
211
|
-
const useTargetPeg =
|
|
212
|
-
(perPegCost.lt(ZERO) && pegChangeDirection.gt(ZERO)) ||
|
|
213
|
-
(perPegCost.gt(ZERO) && pegChangeDirection.lt(ZERO));
|
|
214
|
-
|
|
215
|
-
if (perPegCost.eq(ZERO) || useTargetPeg) {
|
|
216
|
-
return targetPeg;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const budgetDeltaPeg = budget.mul(PEG_PRECISION).div(perPegCost);
|
|
220
|
-
const newPeg = BN.max(ONE, amm.pegMultiplier.add(budgetDeltaPeg));
|
|
221
|
-
|
|
222
|
-
return newPeg;
|
|
223
|
-
}
|