@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
@@ -894,9 +894,13 @@ export declare class AdminClient extends VelocityClient {
894
894
  * `updateWithdrawGuardThreshold` — in particular, the `oracle` param must equal
895
895
  * `spotMarket.oracle` (enforced by the `has_one` constraint) and is auto-resolved when
896
896
  * omitted. Throws if the spot market account can't be found when not subscribed.
897
+ * @param admin - Overrides the `admin` signer account. The instruction is warm-gated
898
+ * on-chain, so pass the key that will actually sign at execution — e.g. a Squads warm-admin
899
+ * vault PDA when the ix is wrapped in a multisig proposal. Defaults to `state.coldAdmin`
900
+ * (or the wallet if not subscribed).
897
901
  * @returns The unsigned `updateWithdrawGuardThreshold` instruction.
898
902
  */
899
- getUpdateWithdrawGuardThresholdIx(spotMarketIndex: number, withdrawGuardThreshold: BN, oracle?: PublicKey): Promise<TransactionInstruction>;
903
+ getUpdateWithdrawGuardThresholdIx(spotMarketIndex: number, withdrawGuardThreshold: BN, oracle?: PublicKey, admin?: PublicKey): Promise<TransactionInstruction>;
900
904
  /**
901
905
  * Sets a spot market's lending-gain carveouts: the share of deposit interest routed to the
902
906
  * insurance fund (`ifFeeFactor`) and to the withdrawable protocol fee pool
@@ -913,9 +917,13 @@ export declare class AdminClient extends VelocityClient {
913
917
  /**
914
918
  * Builds the `updateSpotMarketIfFactor` instruction without sending it. See
915
919
  * `updateSpotMarketIfFactor` for units and validation.
920
+ * @param admin - Overrides the `admin` signer account. The instruction is warm-gated
921
+ * on-chain, so pass the key that will actually sign at execution — e.g. a Squads warm-admin
922
+ * vault PDA when the ix is wrapped in a multisig proposal. Defaults to `state.coldAdmin`
923
+ * (or the wallet if not subscribed).
916
924
  * @returns The unsigned `updateSpotMarketIfFactor` instruction.
917
925
  */
918
- getUpdateSpotMarketIfFactorIx(spotMarketIndex: number, ifFeeFactor: number, protocolFeeFactor: number): Promise<TransactionInstruction>;
926
+ getUpdateSpotMarketIfFactorIx(spotMarketIndex: number, ifFeeFactor: number, protocolFeeFactor: number, admin?: PublicKey): Promise<TransactionInstruction>;
919
927
  /**
920
928
  * Sets how often a spot market's revenue pool may be settled to the insurance fund.
921
929
  * Requires warm admin (`check_warm`).
@@ -943,6 +951,10 @@ export declare class AdminClient extends VelocityClient {
943
951
  * @returns The unsigned `updateSpotMarketMaxTokenDeposits` instruction.
944
952
  */
945
953
  getUpdateSpotMarketMaxTokenDepositsIx(spotMarketIndex: number, maxTokenDeposits: BN): Promise<TransactionInstruction>;
954
+ updateSpotMarketWithdrawCircuitBreaker(spotMarketIndex: number, withdrawCircuitBreakerBps: number): Promise<TransactionSignature>;
955
+ getUpdateSpotMarketWithdrawCircuitBreakerIx(spotMarketIndex: number, withdrawCircuitBreakerBps: number): Promise<TransactionInstruction>;
956
+ updateSpotMarketDepositCap(spotMarketIndex: number, depositGuardThreshold: BN, maxDepositBpsPerDay: number): Promise<TransactionSignature>;
957
+ getUpdateSpotMarketDepositCapIx(spotMarketIndex: number, depositGuardThreshold: BN, maxDepositBpsPerDay: number): Promise<TransactionInstruction>;
946
958
  /**
947
959
  * Caps a spot market's total borrows as a fraction of its `maxTokenDeposits`, rather than
948
960
  * an absolute token amount. Requires warm admin (`check_warm`). On-chain, the effective cap
@@ -971,9 +983,13 @@ export declare class AdminClient extends VelocityClient {
971
983
  /**
972
984
  * Builds the `updateSpotMarketScaleInitialAssetWeightStart` instruction without sending it.
973
985
  * See `updateSpotMarketScaleInitialAssetWeightStart`.
986
+ * @param admin - Overrides the `admin` signer account. The instruction is warm-gated
987
+ * on-chain, so pass the key that will actually sign at execution — e.g. a Squads warm-admin
988
+ * vault PDA when the ix is wrapped in a multisig proposal. Defaults to `state.coldAdmin`
989
+ * (or the wallet if not subscribed).
974
990
  * @returns The unsigned `updateSpotMarketScaleInitialAssetWeightStart` instruction.
975
991
  */
976
- getUpdateSpotMarketScaleInitialAssetWeightStartIx(spotMarketIndex: number, scaleInitialAssetWeightStart: BN): Promise<TransactionInstruction>;
992
+ getUpdateSpotMarketScaleInitialAssetWeightStartIx(spotMarketIndex: number, scaleInitialAssetWeightStart: BN, admin?: PublicKey): Promise<TransactionInstruction>;
977
993
  /**
978
994
  * Sets how long an insurance-fund staker's unstake request must sit in escrow before it can
979
995
  * be completed for a given spot market. Requires warm admin (`check_warm`).
@@ -1258,9 +1274,13 @@ export declare class AdminClient extends VelocityClient {
1258
1274
  /**
1259
1275
  * Builds the `updateSpotMarketStatus` instruction without sending it. See
1260
1276
  * `updateSpotMarketStatus`.
1277
+ * @param admin - Overrides the `admin` signer account. The instruction is warm-gated
1278
+ * on-chain, so pass the key that will actually sign at execution — e.g. a Squads warm-admin
1279
+ * vault PDA when the ix is wrapped in a multisig proposal. Defaults to `state.coldAdmin`
1280
+ * (or the wallet if not subscribed).
1261
1281
  * @returns The unsigned `updateSpotMarketStatus` instruction.
1262
1282
  */
1263
- getUpdateSpotMarketStatusIx(spotMarketIndex: number, marketStatus: MarketStatus): Promise<TransactionInstruction>;
1283
+ getUpdateSpotMarketStatusIx(spotMarketIndex: number, marketStatus: MarketStatus, admin?: PublicKey): Promise<TransactionInstruction>;
1264
1284
  /**
1265
1285
  * Sets a spot market's operation pause bitmask (`SpotOperation`: `UpdateCumulativeInterest`
1266
1286
  * 0b00001, `Fill` 0b00010, `Deposit` 0b00100, `Withdraw` 0b01000, `Liquidation` 0b10000).
@@ -2480,24 +2500,27 @@ export declare class AdminClient extends VelocityClient {
2480
2500
  */
2481
2501
  getUpdateSpecialUserStatusIx(userAccountPublicKey: PublicKey, status: number): Promise<TransactionInstruction>;
2482
2502
  /**
2483
- * Sets a `User` account's `equityFloor`: the minimum cross-margin total
2484
- * collateral (QUOTE_PRECISION) the account must keep. Below the floor the
2485
- * program rejects risk-increasing order placement and fills, withdrawals,
2486
- * and deposit/position transfers out of the account; reduce-only activity
2487
- * stays allowed. Requires warm admin (`check_warm`); the account's
2488
- * authority and delegate cannot change it. Pass `0` to disable.
2503
+ * Sets a `User` account's `equityFloor` and `equityFloorBuffer`. The floor
2504
+ * is the minimum cross-margin total collateral (QUOTE_PRECISION) below
2505
+ * which the permissionless breaker can trip; risk-increasing order
2506
+ * placement and fills, withdrawals, and deposit/position transfers out of
2507
+ * the account must clear `floor + buffer` (`EquityBelowFloor` otherwise);
2508
+ * reduce-only activity stays allowed. Requires warm admin (`check_warm`);
2509
+ * the account's authority and delegate cannot change either value. Pass
2510
+ * `0` as the floor to disable both checks.
2489
2511
  * @param userAccountPublicKey - `User` PDA to update.
2490
2512
  * @param equityFloor - New floor, QUOTE_PRECISION; `0` disables.
2513
+ * @param equityFloorBuffer - New buffer, QUOTE_PRECISION; no effect while the floor is 0.
2491
2514
  * @param txParams - Optional transaction-building overrides.
2492
2515
  * @returns Transaction signature.
2493
2516
  */
2494
- updateUserEquityFloor(userAccountPublicKey: PublicKey, equityFloor: BN, txParams?: TxParams): Promise<TransactionSignature>;
2517
+ updateUserEquityFloor(userAccountPublicKey: PublicKey, equityFloor: BN, equityFloorBuffer: BN, txParams?: TxParams): Promise<TransactionSignature>;
2495
2518
  /**
2496
2519
  * Builds the `updateUserEquityFloor` instruction without sending it. See
2497
2520
  * `updateUserEquityFloor`.
2498
2521
  * @returns The unsigned `updateUserEquityFloor` instruction.
2499
2522
  */
2500
- getUpdateUserEquityFloorIx(userAccountPublicKey: PublicKey, equityFloor: BN): Promise<TransactionInstruction>;
2523
+ getUpdateUserEquityFloorIx(userAccountPublicKey: PublicKey, equityFloor: BN, equityFloorBuffer: BN): Promise<TransactionInstruction>;
2501
2524
  /**
2502
2525
  * Clears the authority-wide equity floor breaker set by the permissionless
2503
2526
  * `tripEquityFloorBreaker` keeper instruction, unfreezing all of the
@@ -1767,9 +1767,13 @@ class AdminClient extends velocityClient_1.VelocityClient {
1767
1767
  * `updateWithdrawGuardThreshold` — in particular, the `oracle` param must equal
1768
1768
  * `spotMarket.oracle` (enforced by the `has_one` constraint) and is auto-resolved when
1769
1769
  * omitted. Throws if the spot market account can't be found when not subscribed.
1770
+ * @param admin - Overrides the `admin` signer account. The instruction is warm-gated
1771
+ * on-chain, so pass the key that will actually sign at execution — e.g. a Squads warm-admin
1772
+ * vault PDA when the ix is wrapped in a multisig proposal. Defaults to `state.coldAdmin`
1773
+ * (or the wallet if not subscribed).
1770
1774
  * @returns The unsigned `updateWithdrawGuardThreshold` instruction.
1771
1775
  */
1772
- async getUpdateWithdrawGuardThresholdIx(spotMarketIndex, withdrawGuardThreshold, oracle) {
1776
+ async getUpdateWithdrawGuardThresholdIx(spotMarketIndex, withdrawGuardThreshold, oracle, admin) {
1773
1777
  const spotMarketPublicKey = await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, spotMarketIndex);
1774
1778
  if (!oracle) {
1775
1779
  const cachedSpotMarket = this.isSubscribed
@@ -1789,9 +1793,9 @@ class AdminClient extends velocityClient_1.VelocityClient {
1789
1793
  }
1790
1794
  return await this.program.instruction.updateWithdrawGuardThreshold(withdrawGuardThreshold, {
1791
1795
  accounts: {
1792
- admin: this.isSubscribed
1796
+ admin: admin !== null && admin !== void 0 ? admin : (this.isSubscribed
1793
1797
  ? this.getStateAccount().coldAdmin
1794
- : this.wallet.publicKey,
1798
+ : this.wallet.publicKey),
1795
1799
  state: await this.getStatePublicKey(),
1796
1800
  spotMarket: spotMarketPublicKey,
1797
1801
  oracle,
@@ -1819,14 +1823,18 @@ class AdminClient extends velocityClient_1.VelocityClient {
1819
1823
  /**
1820
1824
  * Builds the `updateSpotMarketIfFactor` instruction without sending it. See
1821
1825
  * `updateSpotMarketIfFactor` for units and validation.
1826
+ * @param admin - Overrides the `admin` signer account. The instruction is warm-gated
1827
+ * on-chain, so pass the key that will actually sign at execution — e.g. a Squads warm-admin
1828
+ * vault PDA when the ix is wrapped in a multisig proposal. Defaults to `state.coldAdmin`
1829
+ * (or the wallet if not subscribed).
1822
1830
  * @returns The unsigned `updateSpotMarketIfFactor` instruction.
1823
1831
  */
1824
- async getUpdateSpotMarketIfFactorIx(spotMarketIndex, ifFeeFactor, protocolFeeFactor) {
1832
+ async getUpdateSpotMarketIfFactorIx(spotMarketIndex, ifFeeFactor, protocolFeeFactor, admin) {
1825
1833
  return await this.program.instruction.updateSpotMarketIfFactor(spotMarketIndex, ifFeeFactor, protocolFeeFactor, {
1826
1834
  accounts: {
1827
- admin: this.isSubscribed
1835
+ admin: admin !== null && admin !== void 0 ? admin : (this.isSubscribed
1828
1836
  ? this.getStateAccount().coldAdmin
1829
- : this.wallet.publicKey,
1837
+ : this.wallet.publicKey),
1830
1838
  state: await this.getStatePublicKey(),
1831
1839
  spotMarket: await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, spotMarketIndex),
1832
1840
  },
@@ -1889,6 +1897,40 @@ class AdminClient extends velocityClient_1.VelocityClient {
1889
1897
  },
1890
1898
  });
1891
1899
  }
1900
+ async updateSpotMarketWithdrawCircuitBreaker(spotMarketIndex, withdrawCircuitBreakerBps) {
1901
+ const ix = await this.getUpdateSpotMarketWithdrawCircuitBreakerIx(spotMarketIndex, withdrawCircuitBreakerBps);
1902
+ const tx = await this.buildTransaction(ix);
1903
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
1904
+ return txSig;
1905
+ }
1906
+ async getUpdateSpotMarketWithdrawCircuitBreakerIx(spotMarketIndex, withdrawCircuitBreakerBps) {
1907
+ return this.program.instruction.updateSpotMarketWithdrawCircuitBreaker(withdrawCircuitBreakerBps, {
1908
+ accounts: {
1909
+ admin: this.isSubscribed
1910
+ ? this.getStateAccount().coldAdmin
1911
+ : this.wallet.publicKey,
1912
+ state: await this.getStatePublicKey(),
1913
+ spotMarket: await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, spotMarketIndex),
1914
+ },
1915
+ });
1916
+ }
1917
+ async updateSpotMarketDepositCap(spotMarketIndex, depositGuardThreshold, maxDepositBpsPerDay) {
1918
+ const ix = await this.getUpdateSpotMarketDepositCapIx(spotMarketIndex, depositGuardThreshold, maxDepositBpsPerDay);
1919
+ const tx = await this.buildTransaction(ix);
1920
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
1921
+ return txSig;
1922
+ }
1923
+ async getUpdateSpotMarketDepositCapIx(spotMarketIndex, depositGuardThreshold, maxDepositBpsPerDay) {
1924
+ return this.program.instruction.updateSpotMarketDepositCap(depositGuardThreshold, maxDepositBpsPerDay, {
1925
+ accounts: {
1926
+ admin: this.isSubscribed
1927
+ ? this.getStateAccount().coldAdmin
1928
+ : this.wallet.publicKey,
1929
+ state: await this.getStatePublicKey(),
1930
+ spotMarket: await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, spotMarketIndex),
1931
+ },
1932
+ });
1933
+ }
1892
1934
  /**
1893
1935
  * Caps a spot market's total borrows as a fraction of its `maxTokenDeposits`, rather than
1894
1936
  * an absolute token amount. Requires warm admin (`check_warm`). On-chain, the effective cap
@@ -1937,14 +1979,18 @@ class AdminClient extends velocityClient_1.VelocityClient {
1937
1979
  /**
1938
1980
  * Builds the `updateSpotMarketScaleInitialAssetWeightStart` instruction without sending it.
1939
1981
  * See `updateSpotMarketScaleInitialAssetWeightStart`.
1982
+ * @param admin - Overrides the `admin` signer account. The instruction is warm-gated
1983
+ * on-chain, so pass the key that will actually sign at execution — e.g. a Squads warm-admin
1984
+ * vault PDA when the ix is wrapped in a multisig proposal. Defaults to `state.coldAdmin`
1985
+ * (or the wallet if not subscribed).
1940
1986
  * @returns The unsigned `updateSpotMarketScaleInitialAssetWeightStart` instruction.
1941
1987
  */
1942
- async getUpdateSpotMarketScaleInitialAssetWeightStartIx(spotMarketIndex, scaleInitialAssetWeightStart) {
1988
+ async getUpdateSpotMarketScaleInitialAssetWeightStartIx(spotMarketIndex, scaleInitialAssetWeightStart, admin) {
1943
1989
  return this.program.instruction.updateSpotMarketScaleInitialAssetWeightStart(scaleInitialAssetWeightStart, {
1944
1990
  accounts: {
1945
- admin: this.isSubscribed
1991
+ admin: admin !== null && admin !== void 0 ? admin : (this.isSubscribed
1946
1992
  ? this.getStateAccount().coldAdmin
1947
- : this.wallet.publicKey,
1993
+ : this.wallet.publicKey),
1948
1994
  state: await this.getStatePublicKey(),
1949
1995
  spotMarket: await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, spotMarketIndex),
1950
1996
  },
@@ -2492,14 +2538,18 @@ class AdminClient extends velocityClient_1.VelocityClient {
2492
2538
  /**
2493
2539
  * Builds the `updateSpotMarketStatus` instruction without sending it. See
2494
2540
  * `updateSpotMarketStatus`.
2541
+ * @param admin - Overrides the `admin` signer account. The instruction is warm-gated
2542
+ * on-chain, so pass the key that will actually sign at execution — e.g. a Squads warm-admin
2543
+ * vault PDA when the ix is wrapped in a multisig proposal. Defaults to `state.coldAdmin`
2544
+ * (or the wallet if not subscribed).
2495
2545
  * @returns The unsigned `updateSpotMarketStatus` instruction.
2496
2546
  */
2497
- async getUpdateSpotMarketStatusIx(spotMarketIndex, marketStatus) {
2547
+ async getUpdateSpotMarketStatusIx(spotMarketIndex, marketStatus, admin) {
2498
2548
  return await this.program.instruction.updateSpotMarketStatus(marketStatus, {
2499
2549
  accounts: {
2500
- admin: this.isSubscribed
2550
+ admin: admin !== null && admin !== void 0 ? admin : (this.isSubscribed
2501
2551
  ? this.getStateAccount().coldAdmin
2502
- : this.wallet.publicKey,
2552
+ : this.wallet.publicKey),
2503
2553
  state: await this.getStatePublicKey(),
2504
2554
  spotMarket: await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, spotMarketIndex),
2505
2555
  },
@@ -4886,19 +4936,22 @@ class AdminClient extends velocityClient_1.VelocityClient {
4886
4936
  });
4887
4937
  }
4888
4938
  /**
4889
- * Sets a `User` account's `equityFloor`: the minimum cross-margin total
4890
- * collateral (QUOTE_PRECISION) the account must keep. Below the floor the
4891
- * program rejects risk-increasing order placement and fills, withdrawals,
4892
- * and deposit/position transfers out of the account; reduce-only activity
4893
- * stays allowed. Requires warm admin (`check_warm`); the account's
4894
- * authority and delegate cannot change it. Pass `0` to disable.
4939
+ * Sets a `User` account's `equityFloor` and `equityFloorBuffer`. The floor
4940
+ * is the minimum cross-margin total collateral (QUOTE_PRECISION) below
4941
+ * which the permissionless breaker can trip; risk-increasing order
4942
+ * placement and fills, withdrawals, and deposit/position transfers out of
4943
+ * the account must clear `floor + buffer` (`EquityBelowFloor` otherwise);
4944
+ * reduce-only activity stays allowed. Requires warm admin (`check_warm`);
4945
+ * the account's authority and delegate cannot change either value. Pass
4946
+ * `0` as the floor to disable both checks.
4895
4947
  * @param userAccountPublicKey - `User` PDA to update.
4896
4948
  * @param equityFloor - New floor, QUOTE_PRECISION; `0` disables.
4949
+ * @param equityFloorBuffer - New buffer, QUOTE_PRECISION; no effect while the floor is 0.
4897
4950
  * @param txParams - Optional transaction-building overrides.
4898
4951
  * @returns Transaction signature.
4899
4952
  */
4900
- async updateUserEquityFloor(userAccountPublicKey, equityFloor, txParams) {
4901
- const ix = await this.getUpdateUserEquityFloorIx(userAccountPublicKey, equityFloor);
4953
+ async updateUserEquityFloor(userAccountPublicKey, equityFloor, equityFloorBuffer, txParams) {
4954
+ const ix = await this.getUpdateUserEquityFloorIx(userAccountPublicKey, equityFloor, equityFloorBuffer);
4902
4955
  const tx = await this.buildTransaction(ix, txParams);
4903
4956
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
4904
4957
  return txSig;
@@ -4908,8 +4961,8 @@ class AdminClient extends velocityClient_1.VelocityClient {
4908
4961
  * `updateUserEquityFloor`.
4909
4962
  * @returns The unsigned `updateUserEquityFloor` instruction.
4910
4963
  */
4911
- async getUpdateUserEquityFloorIx(userAccountPublicKey, equityFloor) {
4912
- return this.program.instruction.updateUserEquityFloor(equityFloor, {
4964
+ async getUpdateUserEquityFloorIx(userAccountPublicKey, equityFloor, equityFloorBuffer) {
4965
+ return this.program.instruction.updateUserEquityFloor(equityFloor, equityFloorBuffer, {
4913
4966
  accounts: {
4914
4967
  admin: this.useHotWalletAdmin
4915
4968
  ? this.wallet.publicKey
@@ -224,6 +224,7 @@ export declare class VelocityCore {
224
224
  * @param args.state - the global `State` PDA.
225
225
  * @param args.filler - the keeper's `User` account submitting the trigger.
226
226
  * @param args.user - the order owner's `User` account.
227
+ * @param args.userStats - the order owner's `UserStats` account (authority-wide equity breaker).
227
228
  * @param args.authority - signer that must own or be a registered delegate of `filler`.
228
229
  * @param args.remainingAccounts - oracle/market `AccountMeta[]` for the order's market.
229
230
  * @returns the unsigned `triggerOrder` `TransactionInstruction`.
@@ -234,6 +235,7 @@ export declare class VelocityCore {
234
235
  state: PublicKey;
235
236
  filler: PublicKey;
236
237
  user: PublicKey;
238
+ userStats: PublicKey;
237
239
  authority: PublicKey;
238
240
  remainingAccounts: AccountMeta[];
239
241
  }): Promise<TransactionInstruction>;
@@ -202,6 +202,7 @@ class VelocityCore {
202
202
  * @param args.state - the global `State` PDA.
203
203
  * @param args.filler - the keeper's `User` account submitting the trigger.
204
204
  * @param args.user - the order owner's `User` account.
205
+ * @param args.userStats - the order owner's `UserStats` account (authority-wide equity breaker).
205
206
  * @param args.authority - signer that must own or be a registered delegate of `filler`.
206
207
  * @param args.remainingAccounts - oracle/market `AccountMeta[]` for the order's market.
207
208
  * @returns the unsigned `triggerOrder` `TransactionInstruction`.
@@ -11,6 +11,9 @@ import type { VelocityProgram } from '../../config';
11
11
  * @param args.state - the global `State` PDA.
12
12
  * @param args.filler - the keeper's `User` account submitting the trigger.
13
13
  * @param args.user - the order owner's `User` account.
14
+ * @param args.userStats - the order owner's `UserStats` account (checked for the
15
+ * authority-wide equity breaker; a risk-increasing trigger order is cancelled
16
+ * rather than activated while the breaker is tripped).
14
17
  * @param args.authority - signer that must own or be a registered delegate of `filler`.
15
18
  * @param args.remainingAccounts - oracle/market `AccountMeta[]` for the order's market.
16
19
  * @returns the unsigned `triggerOrder` `TransactionInstruction`.
@@ -21,6 +24,7 @@ export declare function buildTriggerOrderInstruction(args: {
21
24
  state: PublicKey;
22
25
  filler: PublicKey;
23
26
  user: PublicKey;
27
+ userStats: PublicKey;
24
28
  authority: PublicKey;
25
29
  remainingAccounts: AccountMeta[];
26
30
  }): Promise<TransactionInstruction>;
@@ -12,6 +12,9 @@ exports.buildTriggerOrderInstruction = void 0;
12
12
  * @param args.state - the global `State` PDA.
13
13
  * @param args.filler - the keeper's `User` account submitting the trigger.
14
14
  * @param args.user - the order owner's `User` account.
15
+ * @param args.userStats - the order owner's `UserStats` account (checked for the
16
+ * authority-wide equity breaker; a risk-increasing trigger order is cancelled
17
+ * rather than activated while the breaker is tripped).
15
18
  * @param args.authority - signer that must own or be a registered delegate of `filler`.
16
19
  * @param args.remainingAccounts - oracle/market `AccountMeta[]` for the order's market.
17
20
  * @returns the unsigned `triggerOrder` `TransactionInstruction`.
@@ -22,6 +25,7 @@ async function buildTriggerOrderInstruction(args) {
22
25
  state: args.state,
23
26
  filler: args.filler,
24
27
  user: args.user,
28
+ userStats: args.userStats,
25
29
  authority: args.authority,
26
30
  },
27
31
  remainingAccounts: args.remainingAccounts,
@@ -336,7 +336,8 @@ function decodeUser(buffer) {
336
336
  offset += 3; // padding
337
337
  const equityFloor = readUnsignedBigInt64LE(buffer, offset);
338
338
  offset += 8;
339
- offset += 8; // padding2
339
+ const equityFloorBuffer = readUnsignedBigInt64LE(buffer, offset);
340
+ offset += 8;
340
341
  return {
341
342
  authority,
342
343
  delegate,
@@ -366,6 +367,7 @@ function decodeUser(buffer) {
366
367
  poolId,
367
368
  specialUserStatus,
368
369
  equityFloor,
370
+ equityFloorBuffer,
369
371
  };
370
372
  }
371
373
  exports.decodeUser = decodeUser;
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Maker-facing abstraction over the per-subaccount equity floor. The on-chain
3
+ * checks are deliberately per-subaccount (each check reads only the one User
4
+ * account already loaded in the hot path), which leaves the burden of placing
5
+ * floor where the equity is on the delegate. This module removes that burden:
6
+ * it treats an authority's subaccounts as one pool, plans quote transfers with
7
+ * the exact floor delta they must carry, computes how much can leave a
8
+ * subaccount, and rebalances the floor split to match where the equity
9
+ * actually sits — so a delegate never has to reason about floor placement to
10
+ * stay clear of the breaker.
11
+ */
12
+ import { PublicKey } from '@solana/web3.js';
13
+ import { TransactionSignature } from '@solana/web3.js';
14
+ import { BN } from './isomorphic/anchor';
15
+ import { EquityFloorLevel } from './math/margin';
16
+ import { VelocityClient } from './velocityClient';
17
+ import { TxParams } from './types';
18
+ /** One subaccount's standing relative to its floor. All BN values QUOTE_PRECISION. */
19
+ export type SubaccountFloorStatus = {
20
+ subAccountId: number;
21
+ /** Cross-margin total collateral, strict (TWAP-bounded) pricing — what the on-chain checks see. */
22
+ equity: BN;
23
+ equityFloor: BN;
24
+ equityFloorBuffer: BN;
25
+ /** `equityFloor + equityFloorBuffer`: what risk-increasing actions must clear. */
26
+ bufferedFloor: BN;
27
+ /** `equity - equityFloor`; negative means the breaker can trip on this subaccount. */
28
+ headroom: BN;
29
+ /** `equity - bufferedFloor`; negative means risk-increasing actions are rejecting. */
30
+ bufferedHeadroom: BN;
31
+ level: EquityFloorLevel;
32
+ };
33
+ /** Authority-wide standing: aggregates plus the per-subaccount breakdown. */
34
+ export type EquityFloorStatus = {
35
+ authority: PublicKey;
36
+ breakerTripped: boolean;
37
+ totalEquity: BN;
38
+ totalFloor: BN;
39
+ totalBuffer: BN;
40
+ /** `totalEquity - (totalFloor + totalBuffer)`: the slack the whole pool has to allocate. */
41
+ totalBufferedHeadroom: BN;
42
+ /** Worst level across subaccounts with a floor set. */
43
+ level: EquityFloorLevel;
44
+ subaccounts: SubaccountFloorStatus[];
45
+ };
46
+ /** A floor-only rebalance step: zero-amount `transferDepositByDelegate` carrying `equityFloorDelta`. */
47
+ export type FloorMove = {
48
+ fromSubAccountId: number;
49
+ toSubAccountId: number;
50
+ equityFloorDelta: BN;
51
+ };
52
+ /** A fully resolved quote transfer ready to submit. */
53
+ export type QuoteTransferPlan = {
54
+ amount: BN;
55
+ marketIndex: number;
56
+ fromSubAccountId: number;
57
+ toSubAccountId: number;
58
+ equityFloorDelta: BN;
59
+ };
60
+ /**
61
+ * Splits `totalFloor` across subaccounts proportionally to their equity,
62
+ * clamped so every allocation is backed (`floor_i <= max(0, equity_i -
63
+ * buffer_i)`), with the clamped remainder water-filled into subaccounts that
64
+ * still have capacity. Entries in `pinned` keep their current floor and
65
+ * receive none of the remainder (used for breached subaccounts, which cannot
66
+ * shed floor on-chain). Returns `null` when no backed allocation exists, i.e.
67
+ * the pool's equity cannot cover `totalFloor` plus buffers.
68
+ */
69
+ export declare function allocateEquityFloors(totalFloor: BN, subaccounts: {
70
+ equity: BN;
71
+ buffer: BN;
72
+ currentFloor: BN;
73
+ }[], pinned?: boolean[]): BN[] | null;
74
+ /**
75
+ * Turns a current → target floor split into concrete moves, greedily matching
76
+ * surpluses against deficits. The moves conserve the floor sum by
77
+ * construction and each one only ever sheds floor from a subaccount whose
78
+ * floor is above its target.
79
+ */
80
+ export declare function planFloorMoves(subAccountIds: number[], current: BN[], target: BN[]): FloorMove[];
81
+ export type EquityFloorManagerConfig = {
82
+ /**
83
+ * Subaccount ids to manage. Defaults to every subaccount of the client's
84
+ * authority currently subscribed on the `VelocityClient`.
85
+ */
86
+ subAccountIds?: number[];
87
+ /**
88
+ * Client-side equity haircut (QUOTE_PRECISION) applied when sizing floor
89
+ * deltas, absorbing the dust by which strict on-chain pricing can differ
90
+ * from the client's. Defaults to 1 quote unit ($1).
91
+ */
92
+ collateralHaircut?: BN;
93
+ };
94
+ /**
95
+ * See the module doc. All reads use the subaccounts already subscribed on the
96
+ * wrapped `VelocityClient` (the delegate's client, whose `authority` is the
97
+ * subaccounts' owner); all writes go through `transferDepositByDelegate`.
98
+ */
99
+ export declare class EquityFloorManager {
100
+ private velocityClient;
101
+ private collateralHaircut;
102
+ private subAccountIds?;
103
+ constructor(velocityClient: VelocityClient, config?: EquityFloorManagerConfig);
104
+ private getManagedUsers;
105
+ private getSubaccountStatus;
106
+ /** Full authority-wide standing: aggregates, worst level, per-subaccount detail. */
107
+ getStatus(): EquityFloorStatus;
108
+ /**
109
+ * The most quote that can leave `subAccountId` to the outside (a
110
+ * withdrawal, which cannot move floor): equity above the buffered floor,
111
+ * less the haircut. Floor constraint only — the withdrawal itself is still
112
+ * subject to margin and borrow limits.
113
+ */
114
+ getMaxWithdrawable(subAccountId: number): BN;
115
+ /**
116
+ * The most quote that can move from one subaccount to another when the
117
+ * transfer carries floor with it. Because floor travels with the funds
118
+ * (capped at the floor the debited side holds, after which its check
119
+ * disables entirely), this is normally the debited side's whole equity —
120
+ * bounded by what the credited side's equity can back. Floor constraint
121
+ * only; margin and borrow limits still apply on top.
122
+ */
123
+ getMaxQuoteTransferable(fromSubAccountId: number, toSubAccountId: number): BN;
124
+ /**
125
+ * Resolves a quote transfer into the exact instruction parameters,
126
+ * padding the auto floor delta by the haircut so on-chain strict pricing
127
+ * dust cannot fail it. The padded delta never exceeds the amount or the
128
+ * debited side's floor, so the credited side stays backed whenever it was
129
+ * before.
130
+ */
131
+ planQuoteTransfer(amount: BN, fromSubAccountId: number, toSubAccountId: number): QuoteTransferPlan;
132
+ /** Plans and submits a quote transfer between two subaccounts in one call. */
133
+ transferQuote(amount: BN, fromSubAccountId: number, toSubAccountId: number, txParams?: TxParams): Promise<TransactionSignature>;
134
+ /**
135
+ * Plans the floor-only moves (zero-amount transfers) that re-split the
136
+ * total floor proportionally to where the equity currently sits, so every
137
+ * subaccount ends with the same relative headroom. Breached subaccounts
138
+ * (below their raw floor) cannot shed floor on-chain, so their floor is
139
+ * pinned in place and the rest is allocated around them. Throws when the
140
+ * pool's equity cannot back the total floor plus buffers — at that point
141
+ * no split works and equity must be deposited (or the admin must lower
142
+ * the floor).
143
+ */
144
+ planFloorRebalance(): FloorMove[];
145
+ /**
146
+ * Executes `planFloorRebalance` serially. Safe to run at any time; a
147
+ * no-op when the split already matches the equity distribution.
148
+ */
149
+ rebalanceFloors(txParams?: TxParams): Promise<TransactionSignature[]>;
150
+ }