@velocity-exchange/sdk 0.6.1 → 0.8.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 (82) hide show
  1. package/lib/browser/adminClient.d.ts +24 -4
  2. package/lib/browser/adminClient.js +62 -12
  3. package/lib/browser/blockhashSubscriber/BlockhashSubscriber.d.ts +19 -15
  4. package/lib/browser/blockhashSubscriber/BlockhashSubscriber.js +31 -22
  5. package/lib/browser/constants/numericConstants.d.ts +2 -0
  6. package/lib/browser/constants/numericConstants.js +3 -1
  7. package/lib/browser/core/VelocityCore.d.ts +2 -0
  8. package/lib/browser/core/VelocityCore.js +1 -0
  9. package/lib/browser/core/instructions/trigger.d.ts +4 -0
  10. package/lib/browser/core/instructions/trigger.js +4 -0
  11. package/lib/browser/idl/velocity.d.ts +223 -33
  12. package/lib/browser/idl/velocity.json +224 -34
  13. package/lib/browser/math/amm.d.ts +8 -8
  14. package/lib/browser/math/funding.d.ts +2 -2
  15. package/lib/browser/math/liquidation.d.ts +37 -2
  16. package/lib/browser/math/liquidation.js +44 -3
  17. package/lib/browser/math/market.d.ts +5 -4
  18. package/lib/browser/math/market.js +21 -14
  19. package/lib/browser/math/oracles.d.ts +3 -3
  20. package/lib/browser/math/orders.d.ts +1 -1
  21. package/lib/browser/math/spotBalance.d.ts +13 -0
  22. package/lib/browser/math/spotBalance.js +43 -2
  23. package/lib/browser/testClient.js +12 -1
  24. package/lib/browser/tx/txHandler.d.ts +7 -1
  25. package/lib/browser/tx/txHandler.js +7 -3
  26. package/lib/browser/types.d.ts +9 -0
  27. package/lib/browser/user.d.ts +2 -2
  28. package/lib/browser/userMap/userMap.d.ts +1 -0
  29. package/lib/browser/userMap/userMap.js +3 -7
  30. package/lib/browser/velocityClient.d.ts +32 -20
  31. package/lib/browser/velocityClient.js +48 -23
  32. package/lib/node/adminClient.d.ts +24 -4
  33. package/lib/node/adminClient.d.ts.map +1 -1
  34. package/lib/node/adminClient.js +62 -12
  35. package/lib/node/blockhashSubscriber/BlockhashSubscriber.d.ts +19 -15
  36. package/lib/node/blockhashSubscriber/BlockhashSubscriber.d.ts.map +1 -1
  37. package/lib/node/blockhashSubscriber/BlockhashSubscriber.js +31 -22
  38. package/lib/node/constants/numericConstants.d.ts +2 -0
  39. package/lib/node/constants/numericConstants.d.ts.map +1 -1
  40. package/lib/node/constants/numericConstants.js +3 -1
  41. package/lib/node/core/VelocityCore.d.ts +2 -0
  42. package/lib/node/core/VelocityCore.d.ts.map +1 -1
  43. package/lib/node/core/VelocityCore.js +1 -0
  44. package/lib/node/core/instructions/trigger.d.ts +4 -0
  45. package/lib/node/core/instructions/trigger.d.ts.map +1 -1
  46. package/lib/node/core/instructions/trigger.js +4 -0
  47. package/lib/node/idl/velocity.d.ts +223 -33
  48. package/lib/node/idl/velocity.d.ts.map +1 -1
  49. package/lib/node/idl/velocity.json +224 -34
  50. package/lib/node/math/amm.d.ts +8 -8
  51. package/lib/node/math/amm.d.ts.map +1 -1
  52. package/lib/node/math/funding.d.ts +2 -2
  53. package/lib/node/math/funding.d.ts.map +1 -1
  54. package/lib/node/math/liquidation.d.ts +37 -2
  55. package/lib/node/math/liquidation.d.ts.map +1 -1
  56. package/lib/node/math/liquidation.js +44 -3
  57. package/lib/node/math/market.d.ts +5 -4
  58. package/lib/node/math/market.d.ts.map +1 -1
  59. package/lib/node/math/market.js +21 -14
  60. package/lib/node/math/oracles.d.ts +3 -3
  61. package/lib/node/math/oracles.d.ts.map +1 -1
  62. package/lib/node/math/orders.d.ts +1 -1
  63. package/lib/node/math/orders.d.ts.map +1 -1
  64. package/lib/node/math/spotBalance.d.ts +13 -0
  65. package/lib/node/math/spotBalance.d.ts.map +1 -1
  66. package/lib/node/math/spotBalance.js +43 -2
  67. package/lib/node/testClient.d.ts.map +1 -1
  68. package/lib/node/testClient.js +12 -1
  69. package/lib/node/tx/txHandler.d.ts +7 -1
  70. package/lib/node/tx/txHandler.d.ts.map +1 -1
  71. package/lib/node/tx/txHandler.js +7 -3
  72. package/lib/node/types.d.ts +9 -0
  73. package/lib/node/types.d.ts.map +1 -1
  74. package/lib/node/user.d.ts +2 -2
  75. package/lib/node/user.d.ts.map +1 -1
  76. package/lib/node/userMap/userMap.d.ts +1 -0
  77. package/lib/node/userMap/userMap.d.ts.map +1 -1
  78. package/lib/node/userMap/userMap.js +3 -7
  79. package/lib/node/velocityClient.d.ts +32 -20
  80. package/lib/node/velocityClient.d.ts.map +1 -1
  81. package/lib/node/velocityClient.js +48 -23
  82. 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).
@@ -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
  },
@@ -1,12 +1,14 @@
1
1
  import { BlockhashWithExpiryBlockHeight, Context } from '@solana/web3.js';
2
2
  import { BlockhashSubscriberConfig } from './types';
3
3
  /**
4
- * BlockhashSubscriber — polls `getLatestBlockhashAndContext`/`getBlockHeight`
5
- * on a fixed interval and caches a short history of recent blockhashes, so
6
- * callers can grab a recent blockhash for transaction building without an
7
- * RPC round-trip per transaction. Nothing is populated until `subscribe()`
8
- * (or a manual `updateBlockhash()`) has completed at least once all getters
9
- * return `undefined`/empty before then.
4
+ * BlockhashSubscriber — polls `getLatestBlockhashAndContext` on a fixed
5
+ * interval and caches a short history of recent blockhashes, so callers can
6
+ * grab a recent blockhash for transaction building without an RPC round-trip
7
+ * per transaction. The current block height is derived from the same response
8
+ * (`lastValidBlockHeight - 150`), so no paired `getBlockHeight` call is made.
9
+ * Nothing is populated until `subscribe()` (or a manual `updateBlockhash()`)
10
+ * has completed at least once — all getters return `undefined`/empty before
11
+ * then.
10
12
  */
11
13
  export declare class BlockhashSubscriber {
12
14
  private connection;
@@ -28,9 +30,9 @@ export declare class BlockhashSubscriber {
28
30
  * @returns The block height as of the most recent successful poll, or
29
31
  * `undefined` if `subscribe()`/`updateBlockhash()` has not yet completed
30
32
  * successfully at least once (including if every poll so far has errored).
31
- * This value is a `getBlockHeight` snapshot taken alongside the latest
32
- * blockhash fetch — it is not guaranteed to be perfectly in sync with the
33
- * blockhash slot, only "recent as of the last poll".
33
+ * This value is derived from the latest blockhash fetch
34
+ * (`lastValidBlockHeight - 150`) — it is not guaranteed to be perfectly in
35
+ * sync with the blockhash slot, only "recent as of the last poll".
34
36
  */
35
37
  getLatestBlockHeight(): number | undefined;
36
38
  /** @returns The RPC `Context` (including `slot`) captured with the most recent successful blockhash poll, or `undefined` before the first successful poll. */
@@ -45,12 +47,14 @@ export declare class BlockhashSubscriber {
45
47
  /** Drops cached blockhashes whose `lastValidBlockHeight` is at or below `latestBlockHeight` (i.e. already expired for transaction signing). Called automatically after every `updateBlockhash`. No-ops if `latestBlockHeight` hasn't been set yet. */
46
48
  pruneBlockhashes(): void;
47
49
  /**
48
- * Fetches the latest blockhash and block height in parallel and appends
49
- * the blockhash to the cache (skipped if it's identical to the
50
- * most-recently-cached one), then prunes expired entries. Errors (e.g. RPC
51
- * failure) are caught and logged, not thrown — on error, `latestBlockHeight`
52
- * is left at its previous value, but `pruneBlockhashes()` still runs in a
53
- * `finally` block and may evict entries that expired in the meantime.
50
+ * Fetches the latest blockhash and appends it to the cache (skipped if it's
51
+ * identical to the most-recently-cached one), then prunes expired entries.
52
+ * The current block height is derived from the same response
53
+ * (`lastValidBlockHeight - 150`) rather than a paired `getBlockHeight` call.
54
+ * Errors (e.g. RPC failure) are caught and logged, not thrown on error,
55
+ * `latestBlockHeight` is left at its previous value, but `pruneBlockhashes()`
56
+ * still runs in a `finally` block and may evict entries that expired in the
57
+ * meantime.
54
58
  */
55
59
  updateBlockhash(): Promise<void>;
56
60
  /** Performs an immediate `updateBlockhash()` and then starts polling on `updateIntervalMs`. Idempotent — a second call while already subscribed is a no-op. */
@@ -3,12 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BlockhashSubscriber = void 0;
4
4
  const web3_js_1 = require("@solana/web3.js");
5
5
  /**
6
- * BlockhashSubscriber polls `getLatestBlockhashAndContext`/`getBlockHeight`
7
- * on a fixed interval and caches a short history of recent blockhashes, so
8
- * callers can grab a recent blockhash for transaction building without an
9
- * RPC round-trip per transaction. Nothing is populated until `subscribe()`
10
- * (or a manual `updateBlockhash()`) has completed at least once — all getters
11
- * return `undefined`/empty before then.
6
+ * A blockhash is valid for signing until 150 blocks after the block it was
7
+ * fetched from, so `getLatestBlockhash`'s `lastValidBlockHeight` is exactly
8
+ * `(block height of that blockhash) + 150`. Subtracting this offset recovers
9
+ * the current block height without a second RPC call.
10
+ */
11
+ const BLOCKHASH_VALIDITY_BLOCKS = 150;
12
+ /**
13
+ * BlockhashSubscriber — polls `getLatestBlockhashAndContext` on a fixed
14
+ * interval and caches a short history of recent blockhashes, so callers can
15
+ * grab a recent blockhash for transaction building without an RPC round-trip
16
+ * per transaction. The current block height is derived from the same response
17
+ * (`lastValidBlockHeight - 150`), so no paired `getBlockHeight` call is made.
18
+ * Nothing is populated until `subscribe()` (or a manual `updateBlockhash()`)
19
+ * has completed at least once — all getters return `undefined`/empty before
20
+ * then.
12
21
  */
13
22
  class BlockhashSubscriber {
14
23
  /**
@@ -34,9 +43,9 @@ class BlockhashSubscriber {
34
43
  * @returns The block height as of the most recent successful poll, or
35
44
  * `undefined` if `subscribe()`/`updateBlockhash()` has not yet completed
36
45
  * successfully at least once (including if every poll so far has errored).
37
- * This value is a `getBlockHeight` snapshot taken alongside the latest
38
- * blockhash fetch — it is not guaranteed to be perfectly in sync with the
39
- * blockhash slot, only "recent as of the last poll".
46
+ * This value is derived from the latest blockhash fetch
47
+ * (`lastValidBlockHeight - 150`) — it is not guaranteed to be perfectly in
48
+ * sync with the blockhash slot, only "recent as of the last poll".
40
49
  */
41
50
  getLatestBlockHeight() {
42
51
  return this.latestBlockHeight;
@@ -69,22 +78,22 @@ class BlockhashSubscriber {
69
78
  }
70
79
  }
71
80
  /**
72
- * Fetches the latest blockhash and block height in parallel and appends
73
- * the blockhash to the cache (skipped if it's identical to the
74
- * most-recently-cached one), then prunes expired entries. Errors (e.g. RPC
75
- * failure) are caught and logged, not thrown — on error, `latestBlockHeight`
76
- * is left at its previous value, but `pruneBlockhashes()` still runs in a
77
- * `finally` block and may evict entries that expired in the meantime.
81
+ * Fetches the latest blockhash and appends it to the cache (skipped if it's
82
+ * identical to the most-recently-cached one), then prunes expired entries.
83
+ * The current block height is derived from the same response
84
+ * (`lastValidBlockHeight - 150`) rather than a paired `getBlockHeight` call.
85
+ * Errors (e.g. RPC failure) are caught and logged, not thrown on error,
86
+ * `latestBlockHeight` is left at its previous value, but `pruneBlockhashes()`
87
+ * still runs in a `finally` block and may evict entries that expired in the
88
+ * meantime.
78
89
  */
79
90
  async updateBlockhash() {
80
91
  try {
81
- const [resp, lastConfirmedBlockHeight] = await Promise.all([
82
- this.connection.getLatestBlockhashAndContext({
83
- commitment: this.commitment,
84
- }),
85
- this.connection.getBlockHeight({ commitment: this.commitment }),
86
- ]);
87
- this.latestBlockHeight = lastConfirmedBlockHeight;
92
+ const resp = await this.connection.getLatestBlockhashAndContext({
93
+ commitment: this.commitment,
94
+ });
95
+ this.latestBlockHeight =
96
+ resp.value.lastValidBlockHeight - BLOCKHASH_VALIDITY_BLOCKS;
88
97
  this.latestBlockHeightContext = resp.context;
89
98
  // avoid caching duplicate blockhashes
90
99
  if (this.blockhashes.length > 0) {
@@ -102,6 +102,8 @@ export declare const FUNDING_RATE_CLAMP_DENOMINATOR: BN;
102
102
  export declare const PRICE_TIMES_AMM_TO_QUOTE_PRECISION_RATIO: BN;
103
103
  /** 300 seconds. */
104
104
  export declare const FIVE_MINUTE: BN;
105
+ /** Max age of the last fill before the trigger price's last-fill leg is treated as absent (oracle price substitutes). */
106
+ export declare const TRIGGER_PRICE_LAST_FILL_MAX_AGE: BN;
105
107
  /** 3600 seconds. */
106
108
  export declare const ONE_HOUR: BN;
107
109
  /** 31,536,000 seconds (365 days). */
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MARGIN_PRECISION = exports.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO = exports.PRICE_TO_QUOTE_PRECISION = exports.PRICE_DIV_PEG = exports.AMM_TO_QUOTE_PRECISION_RATIO = exports.BASE_PRECISION_EXP = exports.BASE_PRECISION = exports.AMM_RESERVE_PRECISION = exports.PEG_PRECISION = exports.FUNDING_RATE_BUFFER_PRECISION = exports.FUNDING_RATE_PRECISION = exports.PRICE_PRECISION = exports.QUOTE_PRECISION = exports.LIQUIDATION_FEE_PRECISION = exports.SPOT_MARKET_IMF_PRECISION = exports.SPOT_MARKET_IMF_PRECISION_EXP = exports.SPOT_MARKET_BALANCE_PRECISION = exports.SPOT_MARKET_BALANCE_PRECISION_EXP = exports.SPOT_MARKET_WEIGHT_PRECISION = exports.SPOT_MARKET_UTILIZATION_PRECISION = exports.SPOT_MARKET_UTILIZATION_PRECISION_EXP = exports.SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION = exports.SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION_EXP = exports.SPOT_MARKET_RATE_PRECISION = exports.SPOT_MARKET_RATE_PRECISION_EXP = exports.AMM_RESERVE_PRECISION_EXP = exports.PEG_PRECISION_EXP = exports.FUNDING_RATE_PRECISION_EXP = exports.PRICE_PRECISION_EXP = exports.FUNDING_RATE_BUFFER_PRECISION_EXP = exports.QUOTE_PRECISION_EXP = exports.CONCENTRATION_PRECISION = exports.PERCENTAGE_PRECISION = exports.PERCENTAGE_PRECISION_EXP = exports.MAX_LEVERAGE_ORDER_SIZE = exports.MAX_LEVERAGE = exports.TEN_MILLION = exports.BN_MAX = exports.TEN_THOUSAND = exports.TEN = exports.NINE = exports.EIGHT = exports.SEVEN = exports.SIX = exports.FIVE = exports.FOUR = exports.THREE = exports.TWO = exports.ONE = exports.ZERO = void 0;
4
- exports.MIN_I64 = exports.MAX_I64 = exports.GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE = exports.MAX_POSITIVE_UPNL_FOR_INITIAL_MARGIN = exports.DUST_POSITION_SIZE = exports.SLOT_TIME_ESTIMATE_MS = exports.IDLE_TIME_SLOTS = exports.ACCOUNT_AGE_DELETION_CUTOFF_SECONDS = exports.DEFAULT_REVENUE_SINCE_LAST_FUNDING_SPREAD_RETREAT = exports.OPEN_ORDER_MARGIN_REQUIREMENT = exports.LAMPORTS_EXP = exports.LAMPORTS_PRECISION = exports.QUOTE_SPOT_MARKET_INDEX = exports.ONE_YEAR = exports.ONE_HOUR = exports.FIVE_MINUTE = exports.PRICE_TIMES_AMM_TO_QUOTE_PRECISION_RATIO = exports.FUNDING_RATE_CLAMP_DENOMINATOR = exports.FUNDING_RATE_OFFSET_PERCENTAGE = exports.FUNDING_RATE_OFFSET_DENOMINATOR = exports.LIQUIDATION_PCT_PRECISION = exports.BID_ASK_SPREAD_PRECISION = exports.BPS_PRECISION = void 0;
4
+ exports.MIN_I64 = exports.MAX_I64 = exports.GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE = exports.MAX_POSITIVE_UPNL_FOR_INITIAL_MARGIN = exports.DUST_POSITION_SIZE = exports.SLOT_TIME_ESTIMATE_MS = exports.IDLE_TIME_SLOTS = exports.ACCOUNT_AGE_DELETION_CUTOFF_SECONDS = exports.DEFAULT_REVENUE_SINCE_LAST_FUNDING_SPREAD_RETREAT = exports.OPEN_ORDER_MARGIN_REQUIREMENT = exports.LAMPORTS_EXP = exports.LAMPORTS_PRECISION = exports.QUOTE_SPOT_MARKET_INDEX = exports.ONE_YEAR = exports.ONE_HOUR = exports.TRIGGER_PRICE_LAST_FILL_MAX_AGE = exports.FIVE_MINUTE = exports.PRICE_TIMES_AMM_TO_QUOTE_PRECISION_RATIO = exports.FUNDING_RATE_CLAMP_DENOMINATOR = exports.FUNDING_RATE_OFFSET_PERCENTAGE = exports.FUNDING_RATE_OFFSET_DENOMINATOR = exports.LIQUIDATION_PCT_PRECISION = exports.BID_ASK_SPREAD_PRECISION = exports.BPS_PRECISION = void 0;
5
5
  const web3_js_1 = require("@solana/web3.js");
6
6
  const anchor_1 = require("../isomorphic/anchor");
7
7
  /** Precision constants used throughout the SDK. Each mirrors an on-chain fixed-point scale — a raw `BN` amount at that precision represents `amount / 10^exponent` in human units (e.g. `PRICE_PRECISION` = 1e6, so a raw price of `1_500_000` is `$1.50`). Values must stay numerically identical to the Rust program's `math::constants` — a mismatch here silently mis-scales every derived SDK computation. */
@@ -107,6 +107,8 @@ exports.FUNDING_RATE_CLAMP_DENOMINATOR = new anchor_1.BN(2000);
107
107
  exports.PRICE_TIMES_AMM_TO_QUOTE_PRECISION_RATIO = exports.PRICE_PRECISION.mul(exports.AMM_TO_QUOTE_PRECISION_RATIO);
108
108
  /** 300 seconds. */
109
109
  exports.FIVE_MINUTE = new anchor_1.BN(60 * 5);
110
+ /** Max age of the last fill before the trigger price's last-fill leg is treated as absent (oracle price substitutes). */
111
+ exports.TRIGGER_PRICE_LAST_FILL_MAX_AGE = exports.FIVE_MINUTE;
110
112
  /** 3600 seconds. */
111
113
  exports.ONE_HOUR = new anchor_1.BN(60 * 60);
112
114
  /** 31,536,000 seconds (365 days). */
@@ -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,