@velocity-exchange/sdk 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/lib/browser/adminClient.d.ts +35 -12
  2. package/lib/browser/adminClient.js +75 -22
  3. package/lib/browser/core/VelocityCore.d.ts +2 -0
  4. package/lib/browser/core/VelocityCore.js +1 -0
  5. package/lib/browser/core/instructions/trigger.d.ts +4 -0
  6. package/lib/browser/core/instructions/trigger.js +4 -0
  7. package/lib/browser/decode/user.js +3 -1
  8. package/lib/browser/equityFloorManager.d.ts +150 -0
  9. package/lib/browser/equityFloorManager.js +279 -0
  10. package/lib/browser/idl/velocity.d.ts +307 -43
  11. package/lib/browser/idl/velocity.json +308 -44
  12. package/lib/browser/index.d.ts +2 -0
  13. package/lib/browser/index.js +2 -0
  14. package/lib/browser/jupiter/jupiterClient.js +24 -3
  15. package/lib/browser/math/liquidation.d.ts +37 -2
  16. package/lib/browser/math/liquidation.js +44 -3
  17. package/lib/browser/math/margin.d.ts +26 -0
  18. package/lib/browser/math/margin.js +41 -1
  19. package/lib/browser/math/spotBalance.d.ts +13 -0
  20. package/lib/browser/math/spotBalance.js +43 -2
  21. package/lib/browser/swap/UnifiedSwapClient.js +17 -3
  22. package/lib/browser/titan/titanClient.d.ts +6 -0
  23. package/lib/browser/titan/titanClient.js +44 -13
  24. package/lib/browser/types.d.ts +15 -2
  25. package/lib/browser/types.js +2 -0
  26. package/lib/browser/user.d.ts +38 -11
  27. package/lib/browser/user.js +84 -33
  28. package/lib/browser/velocityClient.d.ts +37 -24
  29. package/lib/browser/velocityClient.js +56 -35
  30. package/lib/node/adminClient.d.ts +35 -12
  31. package/lib/node/adminClient.d.ts.map +1 -1
  32. package/lib/node/adminClient.js +75 -22
  33. package/lib/node/core/VelocityCore.d.ts +2 -0
  34. package/lib/node/core/VelocityCore.d.ts.map +1 -1
  35. package/lib/node/core/VelocityCore.js +1 -0
  36. package/lib/node/core/instructions/trigger.d.ts +4 -0
  37. package/lib/node/core/instructions/trigger.d.ts.map +1 -1
  38. package/lib/node/core/instructions/trigger.js +4 -0
  39. package/lib/node/decode/user.d.ts.map +1 -1
  40. package/lib/node/decode/user.js +3 -1
  41. package/lib/node/equityFloorManager.d.ts +151 -0
  42. package/lib/node/equityFloorManager.d.ts.map +1 -0
  43. package/lib/node/equityFloorManager.js +279 -0
  44. package/lib/node/idl/velocity.d.ts +307 -43
  45. package/lib/node/idl/velocity.d.ts.map +1 -1
  46. package/lib/node/idl/velocity.json +308 -44
  47. package/lib/node/index.d.ts +2 -0
  48. package/lib/node/index.d.ts.map +1 -1
  49. package/lib/node/index.js +2 -0
  50. package/lib/node/jupiter/jupiterClient.d.ts.map +1 -1
  51. package/lib/node/jupiter/jupiterClient.js +24 -3
  52. package/lib/node/math/liquidation.d.ts +37 -2
  53. package/lib/node/math/liquidation.d.ts.map +1 -1
  54. package/lib/node/math/liquidation.js +44 -3
  55. package/lib/node/math/margin.d.ts +26 -0
  56. package/lib/node/math/margin.d.ts.map +1 -1
  57. package/lib/node/math/margin.js +41 -1
  58. package/lib/node/math/spotBalance.d.ts +13 -0
  59. package/lib/node/math/spotBalance.d.ts.map +1 -1
  60. package/lib/node/math/spotBalance.js +43 -2
  61. package/lib/node/swap/UnifiedSwapClient.d.ts.map +1 -1
  62. package/lib/node/swap/UnifiedSwapClient.js +17 -3
  63. package/lib/node/titan/titanClient.d.ts +6 -0
  64. package/lib/node/titan/titanClient.d.ts.map +1 -1
  65. package/lib/node/titan/titanClient.js +44 -13
  66. package/lib/node/types.d.ts +15 -2
  67. package/lib/node/types.d.ts.map +1 -1
  68. package/lib/node/types.js +2 -0
  69. package/lib/node/user.d.ts +38 -11
  70. package/lib/node/user.d.ts.map +1 -1
  71. package/lib/node/user.js +84 -33
  72. package/lib/node/velocityClient.d.ts +37 -24
  73. package/lib/node/velocityClient.d.ts.map +1 -1
  74. package/lib/node/velocityClient.js +56 -35
  75. package/package.json +1 -1
package/lib/node/user.js CHANGED
@@ -724,12 +724,10 @@ class User {
724
724
  * @param marginCategory `'Initial'` or `'Maintenance'` asset/liability weights; omit for unweighted (100%) values.
725
725
  * @param liquidationBuffer Optional buffer (MARGIN_PRECISION, 1e4) added to the liability weight side.
726
726
  * @param includeOpenOrders If false, ignores open bids/asks and only counts the current balance (faster, less conservative).
727
- * @param strict Use the worse of live oracle price vs 5-minute TWAP. Defaults to false.
728
- * @param now Unix timestamp (seconds) used for TWAP staleness when `strict` is set; defaults to current time.
727
+ * @param strict Use the worse of live oracle price vs the market's stored 5-minute TWAP. Defaults to false.
729
728
  * @returns `{ totalAssetValue, totalLiabilityValue }`, both QUOTE_PRECISION (1e6) and non-negative.
730
729
  */
731
- getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict = false, now) {
732
- now = now || new anchor_1.BN(new Date().getTime() / 1000);
730
+ getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict = false) {
733
731
  let netQuoteValue = numericConstants_1.ZERO;
734
732
  let totalAssetValue = numericConstants_1.ZERO;
735
733
  let totalLiabilityValue = numericConstants_1.ZERO;
@@ -744,11 +742,11 @@ class User {
744
742
  }
745
743
  const spotMarketAccount = this.velocityClient.getSpotMarketAccountOrThrow(spotPosition.marketIndex);
746
744
  const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
747
- let twap5min;
748
- if (strict) {
749
- twap5min = (0, oracles_1.calculateLiveOracleTwap)(spotMarketAccount.historicalOracleData, oraclePriceData, now, numericConstants_1.FIVE_MINUTE // 5MIN
750
- );
751
- }
745
+ // mirrors margin.rs: strict mode prices against the market's *stored*
746
+ // 5min TWAP, not a live-projected one
747
+ const twap5min = strict
748
+ ? spotMarketAccount.historicalOracleData.lastOraclePriceTwap5Min
749
+ : undefined;
752
750
  const strictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(oraclePriceData.price, twap5min);
753
751
  if (spotPosition.marketIndex === numericConstants_1.QUOTE_SPOT_MARKET_INDEX &&
754
752
  countForQuote) {
@@ -813,8 +811,8 @@ class User {
813
811
  return { totalAssetValue, totalLiabilityValue };
814
812
  }
815
813
  /** Convenience wrapper around `getSpotMarketAssetAndLiabilityValue` returning only `totalLiabilityValue`. See that method for parameter semantics. Returns QUOTE_PRECISION (1e6). */
816
- getSpotMarketLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict = false, now) {
817
- const { totalLiabilityValue } = this.getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict, now);
814
+ getSpotMarketLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict = false) {
815
+ const { totalLiabilityValue } = this.getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict);
818
816
  return totalLiabilityValue;
819
817
  }
820
818
  /** Thin wrapper around the `math/spotBalance` `getSpotLiabilityValue` helper that supplies the user's `maxMarginRatio`. Returns QUOTE_PRECISION (1e6), negative. */
@@ -822,8 +820,8 @@ class User {
822
820
  return (0, spotBalance_2.getSpotLiabilityValue)(tokenAmount, strictOraclePrice, spotMarketAccount, this.getUserAccountOrThrow().maxMarginRatio, marginCategory, liquidationBuffer);
823
821
  }
824
822
  /** Convenience wrapper around `getSpotMarketAssetAndLiabilityValue` returning only `totalAssetValue`. See that method for parameter semantics. Returns QUOTE_PRECISION (1e6), non-negative. */
825
- getSpotMarketAssetValue(marketIndex, marginCategory, includeOpenOrders, strict = false, now) {
826
- const { totalAssetValue } = this.getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, undefined, includeOpenOrders, strict, now);
823
+ getSpotMarketAssetValue(marketIndex, marginCategory, includeOpenOrders, strict = false) {
824
+ const { totalAssetValue } = this.getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, undefined, includeOpenOrders, strict);
827
825
  return totalAssetValue;
828
826
  }
829
827
  /** Thin wrapper around the `math/spotBalance` `getSpotAssetValue` helper that supplies the user's `maxMarginRatio`. Returns QUOTE_PRECISION (1e6), non-negative. */
@@ -831,8 +829,8 @@ class User {
831
829
  return (0, spotBalance_2.getSpotAssetValue)(tokenAmount, strictOraclePrice, spotMarketAccount, this.getUserAccountOrThrow().maxMarginRatio, marginCategory);
832
830
  }
833
831
  /** Net spot value (`totalAssetValue - totalLiabilityValue`) for a single spot market. See `getSpotMarketAssetAndLiabilityValue` for parameter semantics. Returns QUOTE_PRECISION (1e6), can be negative. */
834
- getSpotPositionValue(marketIndex, marginCategory, includeOpenOrders, strict = false, now) {
835
- const { totalAssetValue, totalLiabilityValue } = this.getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, undefined, includeOpenOrders, strict, now);
832
+ getSpotPositionValue(marketIndex, marginCategory, includeOpenOrders, strict = false) {
833
+ const { totalAssetValue, totalLiabilityValue } = this.getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, undefined, includeOpenOrders, strict);
836
834
  return totalAssetValue.sub(totalLiabilityValue);
837
835
  }
838
836
  /**
@@ -900,9 +898,9 @@ class User {
900
898
  }
901
899
  /**
902
900
  * True when the account has an admin-set `equityFloor` and its cross-margin
903
- * total collateral is below it. While below the floor, the program rejects
904
- * risk-increasing order placement and fills, withdrawals, and transfers out
905
- * of the account (`EquityBelowFloor`); reduce-only activity stays allowed.
901
+ * total collateral is below it. This is the trip threshold of the
902
+ * permissionless `tripEquityFloorBreaker`; action gating happens at
903
+ * `equityFloor + equityFloorBuffer` (see `isBelowBufferedEquityFloor`).
906
904
  * Mirrors `User::is_below_equity_floor` on-chain.
907
905
  * @param strict Use TWAP-bounded oracle pricing, matching the withdraw path. Defaults to false.
908
906
  */
@@ -913,9 +911,37 @@ class User {
913
911
  }
914
912
  return this.getTotalCollateral('Initial', strict).lt(equityFloor);
915
913
  }
914
+ /**
915
+ * The equity required by risk-increasing actions:
916
+ * `equityFloor + equityFloorBuffer` (QUOTE_PRECISION). Mirrors
917
+ * `User::buffered_equity_floor` on-chain. Meaningless while
918
+ * `equityFloor` is 0 (the checks are disabled).
919
+ */
920
+ getBufferedEquityFloor() {
921
+ const userAccount = this.getUserAccountOrThrow();
922
+ return userAccount.equityFloor.add(userAccount.equityFloorBuffer);
923
+ }
924
+ /**
925
+ * True when the account has an admin-set `equityFloor` and its cross-margin
926
+ * total collateral is below `equityFloor + equityFloorBuffer`. While below,
927
+ * the program rejects risk-increasing order placement and fills,
928
+ * withdrawals, and transfers out of the account (`EquityBelowFloor`);
929
+ * reduce-only activity stays allowed. Mirrors
930
+ * `User::is_below_buffered_equity_floor` on-chain.
931
+ * @param strict Use TWAP-bounded oracle pricing, matching the withdraw path. Defaults to false.
932
+ */
933
+ isBelowBufferedEquityFloor(strict = false) {
934
+ const equityFloor = this.getUserAccountOrThrow().equityFloor;
935
+ if (equityFloor.lte(numericConstants_1.ZERO)) {
936
+ return false;
937
+ }
938
+ return this.getTotalCollateral('Initial', strict).lt(this.getBufferedEquityFloor());
939
+ }
916
940
  /**
917
941
  * Cross-margin total collateral in excess of the admin-set `equityFloor`,
918
942
  * floored at zero (QUOTE_PRECISION). Unbounded (`null`) when no floor is set.
943
+ * This is headroom above the trip threshold; headroom above the level
944
+ * risk-increasing actions must clear is `getEquityAboveBufferedFloor`.
919
945
  * @param strict Use TWAP-bounded oracle pricing. Defaults to false.
920
946
  */
921
947
  getEquityAboveFloor(strict = false) {
@@ -925,6 +951,20 @@ class User {
925
951
  }
926
952
  return anchor_1.BN.max(this.getTotalCollateral('Initial', strict).sub(equityFloor), numericConstants_1.ZERO);
927
953
  }
954
+ /**
955
+ * Cross-margin total collateral in excess of `equityFloor +
956
+ * equityFloorBuffer`, floored at zero (QUOTE_PRECISION). Unbounded
957
+ * (`null`) when no floor is set. When this reaches zero, risk-increasing
958
+ * actions start rejecting.
959
+ * @param strict Use TWAP-bounded oracle pricing. Defaults to false.
960
+ */
961
+ getEquityAboveBufferedFloor(strict = false) {
962
+ const equityFloor = this.getUserAccountOrThrow().equityFloor;
963
+ if (equityFloor.lte(numericConstants_1.ZERO)) {
964
+ return null;
965
+ }
966
+ return anchor_1.BN.max(this.getTotalCollateral('Initial', strict).sub(this.getBufferedEquityFloor()), numericConstants_1.ZERO);
967
+ }
928
968
  /**
929
969
  * Builds the liquidation-buffer map to pass into margin calculations while
930
970
  * a liquidation is in progress: `'cross'` is set to the state account's
@@ -1979,7 +2019,7 @@ class User {
1979
2019
  * @param outMarketIndex
1980
2020
  * @param calculateSwap Optional function to simulate the in-to-out conversion (e.g. to model swap fees/slippage); defaults to a 1:1 oracle-price conversion.
1981
2021
  * @param iterationLimit How many binary-search iterations to run before erroring out. Defaults to 1000.
1982
- * @returns `inAmount`/`outAmount` in each market's own token decimals, and the resulting `leverage` (TEN_THOUSAND, 1e4 precision) after the swap.
2022
+ * @returns `inAmount`/`outAmount` in each market's own token decimals, and the resulting `leverage` (TEN_THOUSAND, 1e4 precision) after the swap. Sizing is TWAP-bounded to match the program's margin check; `leverage` is marked at the live oracle price so it stays comparable to `getLeverage()`.
1983
2023
  */
1984
2024
  getMaxSwapAmount({ inMarketIndex, outMarketIndex, calculateSwap, iterationLimit = 1000, }) {
1985
2025
  const inMarket = this.velocityClient.getSpotMarketAccountOrThrow(inMarketIndex);
@@ -1988,8 +2028,14 @@ class User {
1988
2028
  const inOraclePrice = inOraclePriceData.price;
1989
2029
  const outOraclePriceData = this.getOracleDataForSpotMarket(outMarketIndex);
1990
2030
  const outOraclePrice = outOraclePriceData.price;
1991
- const inStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(inOraclePrice);
1992
- const outStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(outOraclePrice);
2031
+ // sizing mirrors handle_end_swap: both legs are priced strictly, against
2032
+ // each market's stored 5min TWAP
2033
+ const inStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(inOraclePrice, inMarket.historicalOracleData.lastOraclePriceTwap5Min);
2034
+ const outStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(outOraclePrice, outMarket.historicalOracleData.lastOraclePriceTwap5Min);
2035
+ // the returned leverage is a delta on top of getLeverageComponents' live-oracle
2036
+ // baseline, so pricing its legs strictly would mix two bases in one figure
2037
+ const inLeveragePrice = new strictOraclePrice_1.StrictOraclePrice(inOraclePrice);
2038
+ const outLeveragePrice = new strictOraclePrice_1.StrictOraclePrice(outOraclePrice);
1993
2039
  const inPrecision = new anchor_1.BN(10 ** inMarket.decimals);
1994
2040
  const outPrecision = new anchor_1.BN(10 ** outMarket.decimals);
1995
2041
  const inSpotPosition = this.getSpotPosition(inMarketIndex) ||
@@ -1998,9 +2044,9 @@ class User {
1998
2044
  this.getEmptySpotPosition(outMarketIndex);
1999
2045
  const freeCollateral = this.getFreeCollateral();
2000
2046
  const inContributionInitial = this.calculateSpotPositionFreeCollateralContribution(inSpotPosition, inStrictOraclePrice);
2001
- const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition, inStrictOraclePrice);
2047
+ const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition, inLeveragePrice);
2002
2048
  const outContributionInitial = this.calculateSpotPositionFreeCollateralContribution(outSpotPosition, outStrictOraclePrice);
2003
- const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition, outStrictOraclePrice);
2049
+ const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition, outLeveragePrice);
2004
2050
  const initialContribution = inContributionInitial.add(outContributionInitial);
2005
2051
  const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
2006
2052
  if (!calculateSwap) {
@@ -2063,8 +2109,8 @@ class User {
2063
2109
  }
2064
2110
  const inPositionAfter = this.cloneAndUpdateSpotPosition(inSpotPosition, inSwap.neg(), inMarket);
2065
2111
  const outPositionAfter = this.cloneAndUpdateSpotPosition(outSpotPosition, outSwap, outMarket);
2066
- const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter, inStrictOraclePrice);
2067
- const { totalAssetValue: outTotalAssetValueAfter, totalLiabilityValue: outTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(outPositionAfter, outStrictOraclePrice);
2112
+ const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter, inLeveragePrice);
2113
+ const { totalAssetValue: outTotalAssetValueAfter, totalLiabilityValue: outTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(outPositionAfter, outLeveragePrice);
2068
2114
  const spotAssetValueDelta = inTotalAssetValueAfter
2069
2115
  .add(outTotalAssetValueAfter)
2070
2116
  .sub(inTotalAssetValueInitial)
@@ -2147,7 +2193,8 @@ class User {
2147
2193
  };
2148
2194
  }
2149
2195
  /**
2150
- * Estimates what the user leverage will be after swap
2196
+ * Estimates what the user leverage will be after swap, marked at the live
2197
+ * oracle price so it stays comparable to `getLeverage()`.
2151
2198
  * @param inMarketIndex Market being sold/paid from.
2152
2199
  * @param outMarketIndex Market being bought/received.
2153
2200
  * @param inAmount Amount removed from `inMarketIndex`, that market's own token decimals.
@@ -2161,19 +2208,21 @@ class User {
2161
2208
  const inOraclePrice = inOraclePriceData.price;
2162
2209
  const outOraclePriceData = this.getOracleDataForSpotMarket(outMarketIndex);
2163
2210
  const outOraclePrice = outOraclePriceData.price;
2164
- const inStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(inOraclePrice);
2165
- const outStrictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(outOraclePrice);
2211
+ // same live-oracle basis as getMaxSwapAmount's leverage legs and as the
2212
+ // getLeverageComponents baseline these deltas are applied to
2213
+ const inLeveragePrice = new strictOraclePrice_1.StrictOraclePrice(inOraclePrice);
2214
+ const outLeveragePrice = new strictOraclePrice_1.StrictOraclePrice(outOraclePrice);
2166
2215
  const inSpotPosition = this.getSpotPosition(inMarketIndex) ||
2167
2216
  this.getEmptySpotPosition(inMarketIndex);
2168
2217
  const outSpotPosition = this.getSpotPosition(outMarketIndex) ||
2169
2218
  this.getEmptySpotPosition(outMarketIndex);
2170
- const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition, inStrictOraclePrice);
2171
- const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition, outStrictOraclePrice);
2219
+ const { totalAssetValue: inTotalAssetValueInitial, totalLiabilityValue: inTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(inSpotPosition, inLeveragePrice);
2220
+ const { totalAssetValue: outTotalAssetValueInitial, totalLiabilityValue: outTotalLiabilityValueInitial, } = this.calculateSpotPositionLeverageContribution(outSpotPosition, outLeveragePrice);
2172
2221
  const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
2173
2222
  const inPositionAfter = this.cloneAndUpdateSpotPosition(inSpotPosition, inAmount.abs().neg(), inMarket);
2174
2223
  const outPositionAfter = this.cloneAndUpdateSpotPosition(outSpotPosition, outAmount.abs(), outMarket);
2175
- const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter, inStrictOraclePrice);
2176
- const { totalAssetValue: outTotalAssetValueAfter, totalLiabilityValue: outTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(outPositionAfter, outStrictOraclePrice);
2224
+ const { totalAssetValue: inTotalAssetValueAfter, totalLiabilityValue: inTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(inPositionAfter, inLeveragePrice);
2225
+ const { totalAssetValue: outTotalAssetValueAfter, totalLiabilityValue: outTotalLiabilityValueAfter, } = this.calculateSpotPositionLeverageContribution(outPositionAfter, outLeveragePrice);
2177
2226
  const spotAssetValueDelta = inTotalAssetValueAfter
2178
2227
  .add(outTotalAssetValueAfter)
2179
2228
  .sub(inTotalAssetValueInitial)
@@ -2921,8 +2970,10 @@ class User {
2921
2970
  skipTokenValue = true;
2922
2971
  }
2923
2972
  const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
2973
+ // mirrors margin.rs: strict mode prices against the market's *stored*
2974
+ // 5min TWAP, not a live-projected one
2924
2975
  const twap5 = strict
2925
- ? (0, oracles_1.calculateLiveOracleTwap)(spotMarket.historicalOracleData, oraclePriceData, new anchor_1.BN(Math.floor(Date.now() / 1000)), numericConstants_1.FIVE_MINUTE)
2976
+ ? spotMarket.historicalOracleData.lastOraclePriceTwap5Min
2926
2977
  : undefined;
2927
2978
  const strictOracle = new strictOraclePrice_1.StrictOraclePrice(oraclePriceData.price, twap5);
2928
2979
  if (isQuote) {
@@ -433,25 +433,24 @@ export declare class VelocityClient {
433
433
  externalWallet?: PublicKey;
434
434
  }): Promise<[PublicKey, TransactionInstruction]>;
435
435
  /**
436
- * Grows an existing `SignedMsgUserOrders` account to hold more order-message slots. The program
437
- * only allows growing, never shrinking.
436
+ * Resizes an existing `SignedMsgUserOrders` account. Growing (adding order-message slots) is
437
+ * permitted for any payer; shrinking is only permitted when the payer is the account's
438
+ * `authority`, because the account is authority-scoped and shared across all of the authority's
439
+ * subaccounts — a shrink evicts replay-protection UUIDs for every subaccount.
438
440
  * @param authority - Authority whose account is resized.
439
- * @param numOrders - New (larger) number of order-message slots.
440
- * @param userSubaccountId - Sub-account id used to derive the `user` account passed to the
441
- * instruction; defaults to `0`.
441
+ * @param numOrders - New number of order-message slots.
442
442
  * @param txParams - Optional compute-unit/priority-fee overrides for the transaction.
443
443
  * @returns The transaction signature.
444
444
  */
445
- resizeSignedMsgUserOrders(authority: PublicKey, numOrders: number, userSubaccountId?: number, txParams?: TxParams): Promise<TransactionSignature>;
445
+ resizeSignedMsgUserOrders(authority: PublicKey, numOrders: number, txParams?: TxParams): Promise<TransactionSignature>;
446
446
  /**
447
447
  * Builds the `resizeSignedMsgUserOrders` instruction. See `resizeSignedMsgUserOrders` for
448
448
  * semantics.
449
449
  * @param authority - Authority whose account is resized.
450
- * @param numOrders - New (larger) number of order-message slots.
451
- * @param userSubaccountId - Sub-account id used to derive the `user` account; defaults to `0`.
450
+ * @param numOrders - New number of order-message slots.
452
451
  * @returns The resize instruction.
453
452
  */
454
- getResizeSignedMsgUserOrdersInstruction(authority: PublicKey, numOrders: number, userSubaccountId?: number): Promise<TransactionInstruction>;
453
+ getResizeSignedMsgUserOrdersInstruction(authority: PublicKey, numOrders: number): Promise<TransactionInstruction>;
455
454
  /**
456
455
  * Initializes `authority`'s `SignedMsgWsDelegates` account, which lists wallets authorized to
457
456
  * co-sign/relay that authority's signed-message ("swift") orders over a websocket connection
@@ -1574,14 +1573,17 @@ export declare class VelocityClient {
1574
1573
  * @param fromSubAccountId - Sub-account id to debit.
1575
1574
  * @param toSubAccountId - Sub-account id to credit.
1576
1575
  * @param equityFloorDelta - Equity floor (QUOTE_PRECISION) to move from the debited to the credited
1577
- * sub-account along with the funds, keeping the sum of floors constant. The debited side must stay
1578
- * at/above its reduced floor and the credited side's collateral (after the transfer lands) must back
1579
- * its increased floor, else the transfer reverts with `InvalidEquityFloorTransfer`. Pass `'auto'`
1576
+ * sub-account along with the funds, keeping the sum of floors constant. The debited side must not
1577
+ * already be below the floor being reduced (a below-floor sub-account cannot shed floor to defuse a
1578
+ * pending equity-breaker trip), must stay at/above its reduced floor plus its `equityFloorBuffer`,
1579
+ * and the credited side's collateral (after the transfer lands) must back its increased floor plus
1580
+ * its own buffer, else the transfer reverts with `InvalidEquityFloorTransfer`. Pass `'auto'`
1580
1581
  * (quote market only) to move the minimal floor needed for the debited side to stay at/above its
1581
- * floor: `max(0, amount - (collateral - floor))`, capped at the debited side's floor. The auto delta
1582
- * never exceeds `amount`, so the credited side stays backed whenever it was before. Client-side
1583
- * pricing can differ slightly from the on-chain strict check at the exact boundary; retry with an
1584
- * explicit padded delta if an `'auto'` transfer reverts. Defaults to zero.
1582
+ * buffered floor: `max(0, amount - max(0, collateral - (floor + buffer)))`, capped at the debited
1583
+ * side's floor (see `calculateEquityFloorAutoDelta`). The auto delta never exceeds `amount`, so the
1584
+ * credited side stays backed whenever it was before. Client-side pricing can differ slightly from
1585
+ * the on-chain strict check at the exact boundary; retry with an explicit padded delta if an
1586
+ * `'auto'` transfer reverts. Defaults to zero.
1585
1587
  * @param txParams - Optional compute-unit/priority-fee overrides for the transaction.
1586
1588
  * @returns The transaction signature.
1587
1589
  * @throws (on-chain) if `allowDelegateTransfer` is not enabled, if the signer is not the delegate on
@@ -3220,7 +3222,8 @@ export declare class VelocityClient {
3220
3222
  * position to the calling liquidator's sub-account at the oracle price (subject to `limitPrice`
3221
3223
  * and the on-chain liquidation fee). Reverts if `userAccountPublicKey` equals the liquidator's
3222
3224
  * own user account. Permissionless — any signer can act as liquidator, taking on the position
3223
- * and its PnL themselves.
3225
+ * and its PnL themselves. Reverts with `EquityBelowFloor` if the liquidator's authority-wide
3226
+ * equity breaker is tripped (a tripped authority is barred from position-acquiring liquidations).
3224
3227
  * @param userAccountPublicKey - Public key of the user account being liquidated.
3225
3228
  * @param userAccount - Decoded user account being liquidated.
3226
3229
  * @param marketIndex - Perp market index of the position to liquidate.
@@ -3272,7 +3275,9 @@ export declare class VelocityClient {
3272
3275
  * debt from the user to the liquidator's own sub-account in exchange for `assetMarketIndex`
3273
3276
  * collateral, when the user is below maintenance margin (or already flagged `beingLiquidated`).
3274
3277
  * Reverts if `userAccountPublicKey` equals the liquidator's own user account. Permissionless —
3275
- * any signer can act as liquidator.
3278
+ * any signer can act as liquidator. Reverts with `EquityBelowFloor` if the liquidator's
3279
+ * authority-wide equity breaker is tripped (a tripped authority is barred from position-acquiring
3280
+ * liquidations).
3276
3281
  * @param userAccountPublicKey - Public key of the user account being liquidated.
3277
3282
  * @param userAccount - Decoded user account being liquidated.
3278
3283
  * @param assetMarketIndex - Spot market index of the collateral the liquidator receives.
@@ -3381,7 +3386,9 @@ export declare class VelocityClient {
3381
3386
  * PnL in `perpMarketIndex`. Only usable once the user's position size in `perpMarketIndex` is
3382
3387
  * zero (the PnL must already be fully unrealized/settled-out, not backed by an open position).
3383
3388
  * Reverts if `userAccountPublicKey` equals the liquidator's own user account. Permissionless —
3384
- * any signer can act as liquidator.
3389
+ * any signer can act as liquidator. Reverts with `EquityBelowFloor` if the liquidator's
3390
+ * authority-wide equity breaker is tripped (a tripped authority is barred from
3391
+ * balance-acquiring liquidations).
3385
3392
  * @param userAccountPublicKey - Public key of the user account being liquidated.
3386
3393
  * @param userAccount - Decoded user account being liquidated.
3387
3394
  * @param perpMarketIndex - Perp market index whose unsettled PnL backs the transfer, QUOTE_PRECISION (1e6).
@@ -3412,7 +3419,9 @@ export declare class VelocityClient {
3412
3419
  * `perpMarketIndex` from the user to the liquidator in exchange for `assetMarketIndex` spot
3413
3420
  * collateral (the inverse of `liquidateBorrowForPerpPnl`). Only usable once the user's position
3414
3421
  * size in `perpMarketIndex` is zero. Reverts if `userAccountPublicKey` equals the liquidator's
3415
- * own user account. Permissionless — any signer can act as liquidator.
3422
+ * own user account. Permissionless — any signer can act as liquidator. Reverts with
3423
+ * `EquityBelowFloor` if the liquidator's authority-wide equity breaker is tripped (a tripped
3424
+ * authority is barred from balance-acquiring liquidations).
3416
3425
  * @param userAccountPublicKey - Public key of the user account being liquidated.
3417
3426
  * @param userAccount - Decoded user account being liquidated.
3418
3427
  * @param perpMarketIndex - Perp market index of the negative unsettled PnL being absorbed.
@@ -3693,8 +3702,10 @@ export declare class VelocityClient {
3693
3702
  }): Promise<TransactionInstruction[]>;
3694
3703
  /**
3695
3704
  * Starts the unstaking cooldown for this wallet's insurance fund stake in `marketIndex`, locking
3696
- * in the number of IF shares corresponding to `amount` at the current share price. The actual
3697
- * withdrawal must be completed with `removeInsuranceFundStake` after
3705
+ * in the number of IF shares corresponding to `amount` at the current share price. Any revenue
3706
+ * already due to the insurance fund is settled first (mirroring `addInsuranceFundStake`), so the
3707
+ * frozen exit value includes the staker's share of it rather than forfeiting it to the remaining
3708
+ * stakers. The actual withdrawal must be completed with `removeInsuranceFundStake` after
3698
3709
  * `spotMarket.insuranceFund.unstakingPeriod` seconds have elapsed; only one request may be
3699
3710
  * in-flight per stake account (`cancelRequestRemoveInsuranceFundStake` to reset). A caller may
3700
3711
  * only act on their own stake account.
@@ -3770,8 +3781,10 @@ export declare class VelocityClient {
3770
3781
  * `pendingAmmProvision` into the AMM's fee pool (both leave `feePoolBufferTarget` behind). Every
3771
3782
  * drain reserves `max(netUserPnl, 0)` so user claims stay backed. This runs inline on every
3772
3783
  * `settlePNL` already — this instruction lets a keeper run it on demand without settling anyone's
3773
- * PnL. Gates the oracle price used to value `netUserPnl` the same way `settlePNL` does (price-band
3774
- * + validity/divergence checks when the market has curve updates enabled).
3784
+ * PnL. Values `netUserPnl` at the market's fixed `expiryPrice` when the market is in `settlement`
3785
+ * status (expired positions settle at that price, not the live oracle, so no live-oracle gate is
3786
+ * applied); otherwise it uses the live oracle price and gates it the same way `settlePNL` does
3787
+ * (price-band + validity/divergence checks when the market has curve updates enabled).
3775
3788
  * @param perpMarketIndex - Perp market index to sweep fees for.
3776
3789
  * @param txParams - Optional compute-unit/priority-fee overrides.
3777
3790
  * @returns The transaction signature.