@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/orders.ts
DELETED
|
@@ -1,500 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isOneOfVariant,
|
|
3
|
-
isVariant,
|
|
4
|
-
PerpMarketAccount,
|
|
5
|
-
AMM,
|
|
6
|
-
MarketStats,
|
|
7
|
-
Order,
|
|
8
|
-
PositionDirection,
|
|
9
|
-
MarketTypeStr,
|
|
10
|
-
OrderBitFlag,
|
|
11
|
-
StateAccount,
|
|
12
|
-
} from '../types';
|
|
13
|
-
import {
|
|
14
|
-
ZERO,
|
|
15
|
-
ONE,
|
|
16
|
-
SPOT_MARKET_IMF_PRECISION,
|
|
17
|
-
MARGIN_PRECISION,
|
|
18
|
-
} from '../constants/numericConstants';
|
|
19
|
-
import { BN } from '../isomorphic/anchor';
|
|
20
|
-
import { MMOraclePriceData, OraclePriceData } from '../oracles/types';
|
|
21
|
-
import {
|
|
22
|
-
getAuctionPrice,
|
|
23
|
-
isAuctionComplete,
|
|
24
|
-
isFallbackAvailableLiquiditySource,
|
|
25
|
-
} from './auction';
|
|
26
|
-
import {
|
|
27
|
-
calculateMaxBaseAssetAmountFillable,
|
|
28
|
-
calculateMaxBaseAssetAmountToTrade,
|
|
29
|
-
calculateUpdatedAMM,
|
|
30
|
-
} from './amm';
|
|
31
|
-
import { calculateSizePremiumLiabilityWeight } from './margin';
|
|
32
|
-
|
|
33
|
-
/** Rounds `baseAssetAmount` down to the nearest multiple of `stepSize` (always truncates toward zero — never rounds up), matching the on-chain order/fill step-size standardization. @param baseAssetAmount Amount to round, BASE_PRECISION (1e9). @param stepSize Market's order step size, BASE_PRECISION (1e9). @returns Amount rounded down to a `stepSize` multiple, BASE_PRECISION (1e9). */
|
|
34
|
-
export function standardizeBaseAssetAmount(
|
|
35
|
-
baseAssetAmount: BN,
|
|
36
|
-
stepSize: BN
|
|
37
|
-
): BN {
|
|
38
|
-
const remainder = baseAssetAmount.mod(stepSize);
|
|
39
|
-
return baseAssetAmount.sub(remainder);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Rounds `price` to a multiple of `tickSize`, rounding in the direction that's conservative
|
|
44
|
-
* for the order's side: down for a long (never overpay past the tick) and up for a short
|
|
45
|
-
* (never undersell past the tick). Used across auction pricing and limit-price derivation so
|
|
46
|
-
* every price the SDK produces already lines up with the market's `orderTickSize` before it
|
|
47
|
-
* reaches the program, avoiding the on-chain tick-size rejection this standardization fix
|
|
48
|
-
* addresses. A `tickSize <= 0` (unset/no constraint) or `price == 0` passes through
|
|
49
|
-
* unchanged.
|
|
50
|
-
* @param price Price to standardize, PRICE_PRECISION (1e6).
|
|
51
|
-
* @param tickSize Market's order tick size, PRICE_PRECISION (1e6). Non-positive means "no tick constraint."
|
|
52
|
-
* @param direction Order side; determines rounding direction.
|
|
53
|
-
* @returns `price` rounded to the nearest tick in the conservative direction, PRICE_PRECISION (1e6).
|
|
54
|
-
*/
|
|
55
|
-
export function standardizePrice(
|
|
56
|
-
price: BN,
|
|
57
|
-
tickSize: BN,
|
|
58
|
-
direction: PositionDirection
|
|
59
|
-
): BN {
|
|
60
|
-
if (price.eq(ZERO)) {
|
|
61
|
-
return price;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// A non-positive tick size means "no tick constraint" (e.g. unset markets);
|
|
65
|
-
// on-chain markets always have tick_size >= 1, but guard against a zero
|
|
66
|
-
// divisor rather than throwing.
|
|
67
|
-
if (tickSize.lte(ZERO)) {
|
|
68
|
-
return price;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const remainder = price.mod(tickSize);
|
|
72
|
-
if (remainder.eq(ZERO)) {
|
|
73
|
-
return price;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (isVariant(direction, 'long')) {
|
|
77
|
-
return price.sub(remainder);
|
|
78
|
-
} else {
|
|
79
|
-
return price.add(tickSize).sub(remainder);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Resolves an order's effective limit price at the current slot, standardized to
|
|
85
|
-
* `tickSize`: the in-progress auction price while the auction hasn't completed, the
|
|
86
|
-
* oracle-offset price for oracle-pegged orders, the order's fixed `price` if set, or
|
|
87
|
-
* `fallbackPrice` (also standardized) for a market order with no price/offset/auction.
|
|
88
|
-
* @param order Order to price.
|
|
89
|
-
* @param oraclePriceData Oracle price source — use `MMOraclePriceData` for perp orders, `OraclePriceData` for spot.
|
|
90
|
-
* @param slot Current slot, used to evaluate auction progress.
|
|
91
|
-
* @param fallbackPrice Price to return for a market order with no auction/offset/fixed price (e.g. a mark or oracle price), PRICE_PRECISION (1e6).
|
|
92
|
-
* @param tickSize Market's order tick size, PRICE_PRECISION (1e6). Defaults to `ONE` (no effective standardization).
|
|
93
|
-
* @returns Limit price, PRICE_PRECISION (1e6); `undefined` if the order has no resolvable price and no `fallbackPrice` was given.
|
|
94
|
-
*/
|
|
95
|
-
export function getLimitPrice<T extends MarketTypeStr>(
|
|
96
|
-
order: Order,
|
|
97
|
-
oraclePriceData: T extends 'spot' ? OraclePriceData : MMOraclePriceData,
|
|
98
|
-
slot: number,
|
|
99
|
-
fallbackPrice?: BN,
|
|
100
|
-
tickSize: BN = ONE
|
|
101
|
-
): BN | undefined {
|
|
102
|
-
if (hasAuctionPrice(order, slot)) {
|
|
103
|
-
return getAuctionPrice(order, slot, oraclePriceData.price, tickSize);
|
|
104
|
-
} else if (!order.oraclePriceOffset.eq(ZERO)) {
|
|
105
|
-
const limitPrice = BN.max(
|
|
106
|
-
oraclePriceData.price.add(order.oraclePriceOffset),
|
|
107
|
-
tickSize
|
|
108
|
-
);
|
|
109
|
-
return standardizePrice(limitPrice, tickSize, order.direction);
|
|
110
|
-
} else if (order.price.eq(ZERO)) {
|
|
111
|
-
return fallbackPrice === undefined
|
|
112
|
-
? undefined
|
|
113
|
-
: standardizePrice(fallbackPrice, tickSize, order.direction);
|
|
114
|
-
} else {
|
|
115
|
-
return order.price;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/** True if the order has any way to resolve a limit price right now: a fixed `price`, a nonzero oracle offset, or an auction still in progress. */
|
|
120
|
-
export function hasLimitPrice(order: Order, slot: number): boolean {
|
|
121
|
-
return (
|
|
122
|
-
order.price.gt(ZERO) ||
|
|
123
|
-
!order.oraclePriceOffset.eq(ZERO) ||
|
|
124
|
-
!isAuctionComplete(order, slot)
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/** True if the order still has an active (incomplete) auction with a nonzero start or end price. */
|
|
129
|
-
export function hasAuctionPrice(order: Order, slot: number): boolean {
|
|
130
|
-
return (
|
|
131
|
-
!isAuctionComplete(order, slot) &&
|
|
132
|
-
(!order.auctionStartPrice.eq(ZERO) || !order.auctionEndPrice.eq(ZERO))
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* True if the AMM is currently a fillable liquidity source for `order` — either it's
|
|
138
|
-
* expired (always fillable to clean up), or the AMM has fillable size at the order's limit
|
|
139
|
-
* price AND is an allowed liquidity source right now (`isFallbackAvailableLiquiditySource`,
|
|
140
|
-
* which gates on oracle validity and low-risk-for-AMM classification).
|
|
141
|
-
* @param order Order to check.
|
|
142
|
-
* @param market Perp market the order is on.
|
|
143
|
-
* @param mmOraclePriceData Current MM oracle price data.
|
|
144
|
-
* @param slot Current slot.
|
|
145
|
-
* @param ts Current unix timestamp (seconds), used for expiry.
|
|
146
|
-
* @param state Global state, providing oracle guard rails and paused-operations flags.
|
|
147
|
-
* @returns `true` if the AMM may currently fill this order.
|
|
148
|
-
*/
|
|
149
|
-
export function isFillableByVAMM(
|
|
150
|
-
order: Order,
|
|
151
|
-
market: PerpMarketAccount,
|
|
152
|
-
mmOraclePriceData: MMOraclePriceData,
|
|
153
|
-
slot: number,
|
|
154
|
-
ts: number,
|
|
155
|
-
state: StateAccount
|
|
156
|
-
): boolean {
|
|
157
|
-
return (
|
|
158
|
-
(isFallbackAvailableLiquiditySource(
|
|
159
|
-
order,
|
|
160
|
-
mmOraclePriceData,
|
|
161
|
-
slot,
|
|
162
|
-
state,
|
|
163
|
-
market
|
|
164
|
-
) &&
|
|
165
|
-
calculateBaseAssetAmountForAmmToFulfill(
|
|
166
|
-
order,
|
|
167
|
-
market,
|
|
168
|
-
mmOraclePriceData,
|
|
169
|
-
slot
|
|
170
|
-
).gt(ZERO)) ||
|
|
171
|
-
isOrderExpired(order, ts)
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* True if filling `order` against the AMM is considered low-risk even when the MM oracle
|
|
177
|
-
* isn't fully valid, approximating `Order::is_low_risk_for_amm` in
|
|
178
|
-
* `programs/velocity/src/state/user.rs`. Always false for spot orders. True when the order
|
|
179
|
-
* was placed at or before the MM oracle's slot (so it can't be exploiting oracle staleness),
|
|
180
|
-
* during liquidation, or when the order carries the `SafeTriggerOrder` bit flag.
|
|
181
|
-
* @param order Order to check.
|
|
182
|
-
* @param mmOraclePriceData Current MM oracle price data, used for its `slot`.
|
|
183
|
-
* @param isLiquidation Whether the fill is part of a liquidation (always low-risk if so).
|
|
184
|
-
* @returns `true` if the order is low-risk for an AMM fill under a degraded oracle.
|
|
185
|
-
*/
|
|
186
|
-
export function isLowRiskForAmm(
|
|
187
|
-
order: Order,
|
|
188
|
-
mmOraclePriceData: MMOraclePriceData,
|
|
189
|
-
isLiquidation?: boolean
|
|
190
|
-
): boolean {
|
|
191
|
-
if (isVariant(order.marketType, 'spot')) {
|
|
192
|
-
return false;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const orderOlderThanOracleDelay = new BN(order.slot).lte(
|
|
196
|
-
mmOraclePriceData.slot
|
|
197
|
-
);
|
|
198
|
-
|
|
199
|
-
return (
|
|
200
|
-
orderOlderThanOracleDelay ||
|
|
201
|
-
isLiquidation ||
|
|
202
|
-
(order.bitFlags & OrderBitFlag.SafeTriggerOrder) !== 0
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Calculates how much of `order` the AMM can currently fill, capped by both the order's
|
|
208
|
-
* limit price (via `calculateBaseAssetAmountToFillUpToLimitPrice`, standardized to
|
|
209
|
-
* `market.orderTickSize`) and the AMM's own max fillable size
|
|
210
|
-
* (`calculateMaxBaseAssetAmountFillable`). Returns zero for a not-yet-triggered
|
|
211
|
-
* trigger order. Prices against `calculateUpdatedAMM` (i.e. the repegged/curve-updated AMM
|
|
212
|
-
* state), not the raw stored reserves.
|
|
213
|
-
* @param order Order to evaluate.
|
|
214
|
-
* @param market Perp market the order is on.
|
|
215
|
-
* @param mmOraclePriceData Current MM oracle price data.
|
|
216
|
-
* @param slot Current slot.
|
|
217
|
-
* @returns Fillable base asset amount, BASE_PRECISION (1e9).
|
|
218
|
-
*/
|
|
219
|
-
export function calculateBaseAssetAmountForAmmToFulfill(
|
|
220
|
-
order: Order,
|
|
221
|
-
market: PerpMarketAccount,
|
|
222
|
-
mmOraclePriceData: MMOraclePriceData,
|
|
223
|
-
slot: number
|
|
224
|
-
): BN {
|
|
225
|
-
if (mustBeTriggered(order) && !isTriggered(order)) {
|
|
226
|
-
return ZERO;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const limitPrice = getLimitPrice(
|
|
230
|
-
order,
|
|
231
|
-
mmOraclePriceData,
|
|
232
|
-
slot,
|
|
233
|
-
undefined,
|
|
234
|
-
market.orderTickSize
|
|
235
|
-
);
|
|
236
|
-
let baseAssetAmount;
|
|
237
|
-
|
|
238
|
-
const updatedAMM = calculateUpdatedAMM(market.amm, mmOraclePriceData);
|
|
239
|
-
if (limitPrice !== undefined) {
|
|
240
|
-
baseAssetAmount = calculateBaseAssetAmountToFillUpToLimitPrice(
|
|
241
|
-
order,
|
|
242
|
-
updatedAMM,
|
|
243
|
-
market.marketStats,
|
|
244
|
-
market.orderStepSize,
|
|
245
|
-
market.orderTickSize,
|
|
246
|
-
limitPrice,
|
|
247
|
-
mmOraclePriceData
|
|
248
|
-
);
|
|
249
|
-
} else {
|
|
250
|
-
baseAssetAmount = order.baseAssetAmount.sub(order.baseAssetAmountFilled);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
const maxBaseAssetAmount = calculateMaxBaseAssetAmountFillable(
|
|
254
|
-
updatedAMM,
|
|
255
|
-
market.orderStepSize,
|
|
256
|
-
order.direction
|
|
257
|
-
);
|
|
258
|
-
|
|
259
|
-
return BN.min(maxBaseAssetAmount, baseAssetAmount);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Calculates how much base asset the AMM can trade against `order` without crossing its
|
|
264
|
-
* limit price, adjusting the limit by one tick in the order's favor (so the AMM never fills
|
|
265
|
-
* exactly at the boundary) before asking `calculateMaxBaseAssetAmountToTrade` how much
|
|
266
|
-
* inventory the AMM has at that price. Returns zero if the AMM would only trade in the
|
|
267
|
-
* opposite direction from the order. Caps the result at the order's unfilled remainder.
|
|
268
|
-
* @param order Order being filled.
|
|
269
|
-
* @param amm AMM state to trade against.
|
|
270
|
-
* @param marketStats Market stats needed to compute spread reserves.
|
|
271
|
-
* @param orderStepSize Market's order step size, BASE_PRECISION (1e9), used to standardize the result.
|
|
272
|
-
* @param orderTickSize Market's order tick size, PRICE_PRECISION (1e6), used to adjust the limit price by one tick.
|
|
273
|
-
* @param limitPrice Order's limit price, PRICE_PRECISION (1e6).
|
|
274
|
-
* @param mmOraclePriceData Current MM oracle price data.
|
|
275
|
-
* @returns Fillable base asset amount up to the limit price, BASE_PRECISION (1e9).
|
|
276
|
-
*/
|
|
277
|
-
export function calculateBaseAssetAmountToFillUpToLimitPrice(
|
|
278
|
-
order: Order,
|
|
279
|
-
amm: AMM,
|
|
280
|
-
marketStats: MarketStats,
|
|
281
|
-
orderStepSize: BN,
|
|
282
|
-
orderTickSize: BN,
|
|
283
|
-
limitPrice: BN,
|
|
284
|
-
mmOraclePriceData: MMOraclePriceData
|
|
285
|
-
): BN {
|
|
286
|
-
const adjustedLimitPrice = isVariant(order.direction, 'long')
|
|
287
|
-
? limitPrice.sub(orderTickSize)
|
|
288
|
-
: limitPrice.add(orderTickSize);
|
|
289
|
-
|
|
290
|
-
const [maxAmountToTrade, direction] = calculateMaxBaseAssetAmountToTrade(
|
|
291
|
-
amm,
|
|
292
|
-
marketStats,
|
|
293
|
-
adjustedLimitPrice,
|
|
294
|
-
order.direction,
|
|
295
|
-
mmOraclePriceData
|
|
296
|
-
);
|
|
297
|
-
|
|
298
|
-
const baseAssetAmount = standardizeBaseAssetAmount(
|
|
299
|
-
maxAmountToTrade,
|
|
300
|
-
orderStepSize
|
|
301
|
-
);
|
|
302
|
-
|
|
303
|
-
// Check that directions are the same
|
|
304
|
-
const sameDirection = isSameDirection(direction, order.direction);
|
|
305
|
-
if (!sameDirection) {
|
|
306
|
-
return ZERO;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const baseAssetAmountUnfilled = order.baseAssetAmount.sub(
|
|
310
|
-
order.baseAssetAmountFilled
|
|
311
|
-
);
|
|
312
|
-
return baseAssetAmount.gt(baseAssetAmountUnfilled)
|
|
313
|
-
? baseAssetAmountUnfilled
|
|
314
|
-
: baseAssetAmount;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
function isSameDirection(
|
|
318
|
-
firstDirection: PositionDirection,
|
|
319
|
-
secondDirection: PositionDirection
|
|
320
|
-
): boolean {
|
|
321
|
-
return (
|
|
322
|
-
(isVariant(firstDirection, 'long') && isVariant(secondDirection, 'long')) ||
|
|
323
|
-
(isVariant(firstDirection, 'short') && isVariant(secondDirection, 'short'))
|
|
324
|
-
);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* True if `order.maxTs` has passed as of `ts`. Never true for trigger orders, non-`open`
|
|
329
|
-
* orders, or orders with no expiry (`maxTs == 0`).
|
|
330
|
-
* @param order Order to check.
|
|
331
|
-
* @param ts Current unix timestamp (seconds).
|
|
332
|
-
* @param enforceBuffer If true, extends `maxTs` by `bufferSeconds` before comparing, but only for limit orders (default false) — gives resting limit orders a grace period before being treated as expired.
|
|
333
|
-
* @param bufferSeconds Grace period in seconds applied when `enforceBuffer` is true (default 15).
|
|
334
|
-
* @returns `true` if the order has expired.
|
|
335
|
-
*/
|
|
336
|
-
export function isOrderExpired(
|
|
337
|
-
order: Order,
|
|
338
|
-
ts: number,
|
|
339
|
-
enforceBuffer = false,
|
|
340
|
-
bufferSeconds = 15
|
|
341
|
-
): boolean {
|
|
342
|
-
if (
|
|
343
|
-
mustBeTriggered(order) ||
|
|
344
|
-
!isVariant(order.status, 'open') ||
|
|
345
|
-
order.maxTs.eq(ZERO)
|
|
346
|
-
) {
|
|
347
|
-
return false;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
let maxTs;
|
|
351
|
-
if (enforceBuffer && isLimitOrder(order)) {
|
|
352
|
-
maxTs = order.maxTs.addn(bufferSeconds);
|
|
353
|
-
} else {
|
|
354
|
-
maxTs = order.maxTs;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
return new BN(ts).gt(maxTs);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/** True if `order.orderType` is `market`, `triggerMarket`, or `oracle`. */
|
|
361
|
-
export function isMarketOrder(order: Order): boolean {
|
|
362
|
-
return isOneOfVariant(order.orderType, ['market', 'triggerMarket', 'oracle']);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
/** True if `order.orderType` is `limit` or `triggerLimit`. */
|
|
366
|
-
export function isLimitOrder(order: Order): boolean {
|
|
367
|
-
return isOneOfVariant(order.orderType, ['limit', 'triggerLimit']);
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
/** True if the order requires a trigger condition to fire before it becomes fillable (`triggerMarket`/`triggerLimit`). */
|
|
371
|
-
export function mustBeTriggered(order: Order): boolean {
|
|
372
|
-
return isOneOfVariant(order.orderType, ['triggerMarket', 'triggerLimit']);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
/** True if a trigger order's condition has already fired (`triggeredAbove`/`triggeredBelow`). */
|
|
376
|
-
export function isTriggered(order: Order): boolean {
|
|
377
|
-
return isOneOfVariant(order.triggerCondition, [
|
|
378
|
-
'triggeredAbove',
|
|
379
|
-
'triggeredBelow',
|
|
380
|
-
]);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/** True if a limit order currently rests on the book — i.e. it's `postOnly`, or its auction (if any) has completed. Always false for non-limit orders. */
|
|
384
|
-
export function isRestingLimitOrder(order: Order, slot: number): boolean {
|
|
385
|
-
if (!isLimitOrder(order)) {
|
|
386
|
-
return false;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
return order.postOnly || isAuctionComplete(order, slot);
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
/** True if the order was submitted via the signed-message (swift/off-chain relay) path (`OrderBitFlag.SignedMessage`). */
|
|
393
|
-
export function isSignedMsgOrder(order: Order): boolean {
|
|
394
|
-
return (order.bitFlags & OrderBitFlag.SignedMessage) !== 0;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
/** True if the order carries a builder-fee attribution (`OrderBitFlag.HasBuilder`) — the associated builder is entitled to a fee cut on fill. */
|
|
398
|
-
export function hasBuilder(order: Order): boolean {
|
|
399
|
-
return (order.bitFlags & OrderBitFlag.HasBuilder) !== 0;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* Resolves the effective base asset amount for a reduce-only order: caps it so the order
|
|
404
|
-
* can't flip the position through zero (a reduce-only long can close at most the existing
|
|
405
|
-
* short, and vice versa). Non-reduce-only orders pass through `order.baseAssetAmount`
|
|
406
|
-
* unchanged.
|
|
407
|
-
* @param order Order to resolve.
|
|
408
|
-
* @param existingBaseAssetAmount Current position size before this order fills, BASE_PRECISION (1e9, signed).
|
|
409
|
-
* @returns Effective base asset amount, BASE_PRECISION (1e9).
|
|
410
|
-
*/
|
|
411
|
-
export function calculateOrderBaseAssetAmount(
|
|
412
|
-
order: Order,
|
|
413
|
-
existingBaseAssetAmount: BN
|
|
414
|
-
): BN {
|
|
415
|
-
if (!order.reduceOnly) {
|
|
416
|
-
return order.baseAssetAmount;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
if (isVariant(order.direction, 'long')) {
|
|
420
|
-
return BN.min(
|
|
421
|
-
BN.min(existingBaseAssetAmount, ZERO).abs(),
|
|
422
|
-
order.baseAssetAmount
|
|
423
|
-
);
|
|
424
|
-
} else {
|
|
425
|
-
return BN.min(BN.max(existingBaseAssetAmount, ZERO), order.baseAssetAmount);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
// ---------- inverse ----------
|
|
430
|
-
/**
|
|
431
|
-
* Inverts `calculateSizePremiumLiabilityWeight` via binary search: given a target margin ratio
|
|
432
|
-
* (liability weight), finds the largest position `size` whose size-premium-adjusted liability
|
|
433
|
-
* weight is still `<= target`. Used to size down an order/position to stay under a margin-ratio
|
|
434
|
-
* target as size grows (the on-chain weight increases with `sqrt(size)` via `imfFactor`).
|
|
435
|
-
* @param target Target (max acceptable) liability weight, MARGIN_PRECISION (1e4).
|
|
436
|
-
* @param imfFactor Market's initial-margin-fraction scaling factor, SPOT_MARKET_IMF_PRECISION-scaled.
|
|
437
|
-
* @param liabilityWeight Market's base (zero-size) liability weight, MARGIN_PRECISION (1e4).
|
|
438
|
-
* @param market Perp market providing `maxOpenInterest` as a final cap on the result.
|
|
439
|
-
* @returns Max size, AMM_RESERVE_PRECISION (1e9), capped at `market.maxOpenInterest` (a zero `maxOpenInterest` means uncapped, per on-chain convention); `null` if `target < liabilityWeight` (impossible) or `imfFactor` is zero (weight is size-invariant, so no size bounds it).
|
|
440
|
-
*/
|
|
441
|
-
export function maxSizeForTargetLiabilityWeightBN(
|
|
442
|
-
target: BN,
|
|
443
|
-
imfFactor: BN,
|
|
444
|
-
liabilityWeight: BN,
|
|
445
|
-
market: PerpMarketAccount
|
|
446
|
-
): BN | null {
|
|
447
|
-
if (target.lt(liabilityWeight)) return null;
|
|
448
|
-
if (imfFactor.isZero()) return null;
|
|
449
|
-
|
|
450
|
-
const base = liabilityWeight.muln(4).divn(5);
|
|
451
|
-
|
|
452
|
-
const denom = new BN(100_000)
|
|
453
|
-
.mul(SPOT_MARKET_IMF_PRECISION)
|
|
454
|
-
.div(MARGIN_PRECISION);
|
|
455
|
-
if (denom.isZero())
|
|
456
|
-
throw new Error('denom=0: bad precision/spotImfPrecision');
|
|
457
|
-
|
|
458
|
-
const allowedInc = target.gt(base) ? target.sub(base) : ZERO;
|
|
459
|
-
|
|
460
|
-
const maxSqrt = allowedInc.mul(denom).div(imfFactor);
|
|
461
|
-
|
|
462
|
-
if (maxSqrt.lte(ZERO)) {
|
|
463
|
-
const fitsZero = calculateSizePremiumLiabilityWeight(
|
|
464
|
-
ZERO,
|
|
465
|
-
imfFactor,
|
|
466
|
-
liabilityWeight,
|
|
467
|
-
MARGIN_PRECISION
|
|
468
|
-
).lte(target);
|
|
469
|
-
return fitsZero ? ZERO : null;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
let hi = maxSqrt.mul(maxSqrt).sub(ONE).divn(10);
|
|
473
|
-
if (hi.isNeg()) hi = ZERO;
|
|
474
|
-
|
|
475
|
-
let lo = ZERO;
|
|
476
|
-
while (lo.lt(hi)) {
|
|
477
|
-
const mid = lo.add(hi).add(ONE).divn(2); // upper mid to prevent infinite loop
|
|
478
|
-
if (
|
|
479
|
-
calculateSizePremiumLiabilityWeight(
|
|
480
|
-
mid,
|
|
481
|
-
imfFactor,
|
|
482
|
-
liabilityWeight,
|
|
483
|
-
MARGIN_PRECISION
|
|
484
|
-
).lte(target)
|
|
485
|
-
) {
|
|
486
|
-
lo = mid;
|
|
487
|
-
} else {
|
|
488
|
-
hi = mid.sub(ONE);
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// cap at max OI. A maxOpenInterest of 0 means no configured cap (unlimited),
|
|
493
|
-
// matching the on-chain convention — do not treat it as a hard cap of 0.
|
|
494
|
-
const maxOpenInterest = market.maxOpenInterest;
|
|
495
|
-
if (!maxOpenInterest.isZero() && lo.gt(maxOpenInterest)) {
|
|
496
|
-
return maxOpenInterest;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
return lo;
|
|
500
|
-
}
|