@velocity-exchange/sdk 0.2.5 → 0.3.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 (61) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +3 -3
  3. package/lib/browser/adminClient.d.ts +3 -1
  4. package/lib/browser/adminClient.js +16 -0
  5. package/lib/browser/idl/velocity.d.ts +50 -1
  6. package/lib/browser/idl/velocity.json +50 -1
  7. package/lib/browser/math/exchangeStatus.d.ts +1 -0
  8. package/lib/browser/math/exchangeStatus.js +8 -1
  9. package/lib/browser/math/orders.d.ts +3 -0
  10. package/lib/browser/math/orders.js +6 -2
  11. package/lib/browser/math/state.js +1 -1
  12. package/lib/browser/memcmp.js +26 -5
  13. package/lib/browser/orderSubscriber/OrderSubscriber.js +11 -2
  14. package/lib/browser/swift/swiftOrderSubscriber.js +2 -2
  15. package/lib/browser/tokenFaucet.d.ts +2 -2
  16. package/lib/browser/tokenFaucet.js +11 -4
  17. package/lib/browser/types.d.ts +5 -0
  18. package/lib/browser/types.js +9 -2
  19. package/lib/browser/velocityClient.d.ts +1 -1
  20. package/lib/browser/velocityClient.js +16 -4
  21. package/lib/node/adminClient.d.ts +3 -1
  22. package/lib/node/adminClient.d.ts.map +1 -1
  23. package/lib/node/adminClient.js +16 -0
  24. package/lib/node/idl/velocity.d.ts +50 -1
  25. package/lib/node/idl/velocity.d.ts.map +1 -1
  26. package/lib/node/idl/velocity.json +50 -1
  27. package/lib/node/math/exchangeStatus.d.ts +1 -0
  28. package/lib/node/math/exchangeStatus.d.ts.map +1 -1
  29. package/lib/node/math/exchangeStatus.js +8 -1
  30. package/lib/node/math/orders.d.ts +3 -0
  31. package/lib/node/math/orders.d.ts.map +1 -1
  32. package/lib/node/math/orders.js +6 -2
  33. package/lib/node/math/state.js +1 -1
  34. package/lib/node/memcmp.d.ts.map +1 -1
  35. package/lib/node/memcmp.js +26 -5
  36. package/lib/node/orderSubscriber/OrderSubscriber.d.ts.map +1 -1
  37. package/lib/node/orderSubscriber/OrderSubscriber.js +11 -2
  38. package/lib/node/swift/swiftOrderSubscriber.js +2 -2
  39. package/lib/node/tokenFaucet.d.ts +2 -2
  40. package/lib/node/tokenFaucet.d.ts.map +1 -1
  41. package/lib/node/tokenFaucet.js +11 -4
  42. package/lib/node/types.d.ts +5 -0
  43. package/lib/node/types.d.ts.map +1 -1
  44. package/lib/node/types.js +9 -2
  45. package/lib/node/velocityClient.d.ts +1 -1
  46. package/lib/node/velocityClient.d.ts.map +1 -1
  47. package/lib/node/velocityClient.js +16 -4
  48. package/package.json +1 -1
  49. package/src/adminClient.ts +28 -0
  50. package/src/idl/velocity.json +50 -1
  51. package/src/idl/velocity.ts +50 -1
  52. package/src/math/exchangeStatus.ts +10 -0
  53. package/src/math/orders.ts +6 -2
  54. package/src/math/state.ts +1 -1
  55. package/src/memcmp.ts +27 -5
  56. package/src/orderSubscriber/OrderSubscriber.ts +18 -2
  57. package/src/swift/swiftOrderSubscriber.ts +2 -2
  58. package/src/tokenFaucet.ts +10 -7
  59. package/src/types.ts +8 -0
  60. package/src/velocityClient.ts +17 -5
  61. package/tests/dlob/helpers.ts +1 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # @velocity-exchange/sdk
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#172](https://github.com/velocity-exchange/velocity-v1/pull/172) [`b7d15b9`](https://github.com/velocity-exchange/velocity-v1/commit/b7d15b970a74d267aeaf20bb644d5344b9aadc61) Thanks [@0xahzam](https://github.com/0xahzam)! - Decouple solvency-repair from the withdraw pause. The `resolve_perp_pnl_deficit`,
8
+ `resolve_perp_bankruptcy`, and `resolve_spot_bankruptcy` instructions are now gated by a
9
+ new `State.solvencyStatus` bitfield instead of `WithdrawPaused`, so user withdrawals can
10
+ be halted while solvency repair keeps running (or repair can be frozen on its own). Adds
11
+ the `SolvencyStatus` enum, `StateAccount.solvencyStatus`, a `solvencyRepairPaused()`
12
+ helper, `AdminClient.updateSolvencyStatus`, and the `exchange set-solvency-status` admin
13
+ CLI command.
14
+
15
+ - [#141](https://github.com/velocity-exchange/velocity-v1/pull/141) [`3f148f8`](https://github.com/velocity-exchange/velocity-v1/commit/3f148f8b477e4176e11e0660adb0e67dd5163d3b) Thanks [@ChewingGlass](https://github.com/ChewingGlass)! - Harden the native fast-path admin handlers. The
16
+ `update_amm_spread_adjustment_native` instruction now requires the program
17
+ `State` account: `getUpdateAmmSpreadAdjustmentNativeIx` is now **async** and
18
+ returns a `Promise<TransactionInstruction>` (it derives and appends the state
19
+ account), and its compute-unit budget was raised to cover the on-chain account
20
+ validation. Direct callers must `await` the builder. Two new program error
21
+ codes are surfaced in the IDL: `InvalidNativeStateAccount` (6355) and
22
+ `InvalidNativePerpMarketAccount` (6356).
23
+
24
+ ### Patch Changes
25
+
26
+ - [#173](https://github.com/velocity-exchange/velocity-v1/pull/173) [`2f6c64d`](https://github.com/velocity-exchange/velocity-v1/commit/2f6c64d54f1146d8e7f9ee4ab556929c6bf8b920) Thanks [@ChesterSim](https://github.com/ChesterSim)! - Fix stale `User` account byte offsets in `memcmp` filters and `OrderSubscriber`.
27
+
28
+ The Velocity `User` account is 4496 bytes, but the memcmp filters and the
29
+ `OrderSubscriber` staleness check still used offsets from the older 4376-byte
30
+ layout. As a result `getUserWithOrderFilter()` matched zero accounts, so any
31
+ consumer that bulk-loads users-with-orders (e.g. the DLOB server's
32
+ `OrderSubscriber.fetch()`) loaded no orders and produced an empty order book
33
+ (vAMM-only L2, empty L3). Offsets for `idle`, `hasOpenOrder`, `hasOpenAuction`,
34
+ `poolId`, and `lastActiveSlot` are corrected to match the on-chain layout.
35
+
36
+ ## 0.2.6
37
+
38
+ ### Patch Changes
39
+
40
+ - [#156](https://github.com/velocity-exchange/velocity-v1/pull/156) [`d3b58ab`](https://github.com/velocity-exchange/velocity-v1/commit/d3b58ab7e3ad33f0e6634ff87e9b150915b3aa13) Thanks [@ChesterSim](https://github.com/ChesterSim)! - Fix account decoder to pass account names as-is instead of capitalizing them. The
41
+ Anchor v1 IDL program constructor already camelCases account names, so the extra
42
+ `capitalize()` call was incorrect and caused decoding failures in the gRPC and
43
+ WebSocket subscribers.
44
+
3
45
  ## 0.2.5
4
46
 
5
47
  ### Patch Changes
package/README.md CHANGED
@@ -26,7 +26,7 @@ _Start here if you're integrating with Velocity!_
26
26
  - Useful concepts and examples when integrating Velocity
27
27
  - Docs for Velocity's "Data API"
28
28
  - [Typescript API docs](https://velocity-exchange.github.io/protocol-v2/sdk/)
29
- - JSDoc automated documentation for the Velocity v2 Typescript SDK
29
+ - JSDoc automated documentation for the Velocity v1 Typescript SDK
30
30
  - [Velocity docs](https://docs.drift.trade/)
31
31
  - Comprehensive universal docs for Velocity
32
32
 
@@ -210,7 +210,7 @@ const main = async () => {
210
210
  provider.wallet.publicKey.toString()
211
211
  );
212
212
 
213
- //// Create a Velocity V2 account by Depositing some USDC ($10,000 in this case)
213
+ //// Create a Velocity V1 account by Depositing some USDC ($10,000 in this case)
214
214
  const depositAmount = new BN(10000).mul(QUOTE_PRECISION);
215
215
  await velocityClient.initializeUserAccountAndDepositCollateral(
216
216
  depositAmount,
@@ -267,7 +267,7 @@ main();
267
267
 
268
268
  ## License
269
269
 
270
- Velocity Protocol v2 is licensed under [Apache 2.0](./LICENSE).
270
+ Velocity Protocol v1 is licensed under [Apache 2.0](./LICENSE).
271
271
 
272
272
  Unless you explicitly state otherwise, any contribution intentionally submitted
273
273
  for inclusion in Velocity SDK by you, as defined in the Apache-2.0 license, shall be
@@ -7,7 +7,7 @@
7
7
  * pause/unpause exchange, and all ~126 admin instruction handlers in `instructions/admin.rs`.
8
8
  */
9
9
  import { AddressLookupTableAccount, Keypair, PublicKey, TransactionInstruction, TransactionSignature } from '@solana/web3.js';
10
- import { FeeStructure, OracleGuardRails, OracleSource, ExchangeStatus, MarketStatus, ContractTier, AssetTier, TxParams, AddAmmConstituentMappingDatum, SwapReduceOnly, InitializeConstituentParams, ConstituentStatus, LPPoolAccount, TransferFeeAndPnlPoolDirection, MarketType } from './types';
10
+ import { FeeStructure, OracleGuardRails, OracleSource, ExchangeStatus, SolvencyStatus, MarketStatus, ContractTier, AssetTier, TxParams, AddAmmConstituentMappingDatum, SwapReduceOnly, InitializeConstituentParams, ConstituentStatus, LPPoolAccount, TransferFeeAndPnlPoolDirection, MarketType } from './types';
11
11
  import { BN } from './isomorphic/anchor';
12
12
  import { VelocityClient } from './velocityClient';
13
13
  import { JupiterClient, QuoteResponse } from './jupiter/jupiterClient';
@@ -182,6 +182,8 @@ export declare class AdminClient extends VelocityClient {
182
182
  getUpdatePerpMarketContractTierIx(perpMarketIndex: number, contractTier: ContractTier): Promise<TransactionInstruction>;
183
183
  updateExchangeStatus(exchangeStatus: ExchangeStatus): Promise<TransactionSignature>;
184
184
  getUpdateExchangeStatusIx(exchangeStatus: ExchangeStatus): Promise<TransactionInstruction>;
185
+ updateSolvencyStatus(solvencyStatus: SolvencyStatus): Promise<TransactionSignature>;
186
+ getUpdateSolvencyStatusIx(solvencyStatus: SolvencyStatus): Promise<TransactionInstruction>;
185
187
  updatePerpAuctionDuration(minDuration: BN | number): Promise<TransactionSignature>;
186
188
  getUpdatePerpAuctionDurationIx(minDuration: BN | number): Promise<TransactionInstruction>;
187
189
  updateSpotAuctionDuration(defaultAuctionDuration: number): Promise<TransactionSignature>;
@@ -1501,6 +1501,22 @@ class AdminClient extends velocityClient_1.VelocityClient {
1501
1501
  },
1502
1502
  });
1503
1503
  }
1504
+ async updateSolvencyStatus(solvencyStatus) {
1505
+ const updateSolvencyStatusIx = await this.getUpdateSolvencyStatusIx(solvencyStatus);
1506
+ const tx = await this.buildTransaction(updateSolvencyStatusIx);
1507
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
1508
+ return txSig;
1509
+ }
1510
+ async getUpdateSolvencyStatusIx(solvencyStatus) {
1511
+ return await this.program.instruction.updateSolvencyStatus(solvencyStatus, {
1512
+ accounts: {
1513
+ admin: this.isSubscribed
1514
+ ? this.getStateAccount().coldAdmin
1515
+ : this.wallet.publicKey,
1516
+ state: await this.getStatePublicKey(),
1517
+ },
1518
+ });
1519
+ }
1504
1520
  async updatePerpAuctionDuration(minDuration) {
1505
1521
  const updatePerpAuctionDurationIx = await this.getUpdatePerpAuctionDurationIx(minDuration);
1506
1522
  const tx = await this.buildTransaction(updatePerpAuctionDurationIx);
@@ -11074,6 +11074,35 @@ export type Velocity = {
11074
11074
  }
11075
11075
  ];
11076
11076
  },
11077
+ {
11078
+ "name": "updateSolvencyStatus";
11079
+ "discriminator": [
11080
+ 81,
11081
+ 136,
11082
+ 15,
11083
+ 6,
11084
+ 24,
11085
+ 165,
11086
+ 44,
11087
+ 133
11088
+ ];
11089
+ "accounts": [
11090
+ {
11091
+ "name": "admin";
11092
+ "signer": true;
11093
+ },
11094
+ {
11095
+ "name": "state";
11096
+ "writable": true;
11097
+ }
11098
+ ];
11099
+ "args": [
11100
+ {
11101
+ "name": "solvencyStatus";
11102
+ "type": "u8";
11103
+ }
11104
+ ];
11105
+ },
11077
11106
  {
11078
11107
  "name": "updateSpecialUserStatus";
11079
11108
  "discriminator": [
@@ -15978,6 +16007,16 @@ export type Velocity = {
15978
16007
  "code": 6354;
15979
16008
  "name": "insufficientProtocolFees";
15980
16009
  "msg": "Insufficient protocol fees available to withdraw";
16010
+ },
16011
+ {
16012
+ "code": 6355;
16013
+ "name": "invalidNativeStateAccount";
16014
+ "msg": "Native dispatch: supplied state account is not the canonical Velocity state PDA";
16015
+ },
16016
+ {
16017
+ "code": 6356;
16018
+ "name": "invalidNativePerpMarketAccount";
16019
+ "msg": "Native dispatch: supplied market account is not a Velocity perp market";
15981
16020
  }
15982
16021
  ];
15983
16022
  "types": [
@@ -23213,6 +23252,16 @@ export type Velocity = {
23213
23252
  "name": "lpPoolFeatureBitFlags";
23214
23253
  "type": "u8";
23215
23254
  },
23255
+ {
23256
+ "name": "solvencyStatus";
23257
+ "docs": [
23258
+ "Bitmask of `SolvencyStatus` flags. Gates internal solvency-repair flows",
23259
+ "(bankruptcy / pnl-deficit resolution) independently of `WithdrawPaused`,",
23260
+ "so user withdrawals can be halted while repair keeps running, or repair",
23261
+ "can be frozen on its own when an oracle is suspect. `0` = repair allowed."
23262
+ ];
23263
+ "type": "u8";
23264
+ },
23216
23265
  {
23217
23266
  "name": "protocolFeeRecipientPerp";
23218
23267
  "docs": [
@@ -23247,7 +23296,7 @@ export type Velocity = {
23247
23296
  "type": {
23248
23297
  "array": [
23249
23298
  "u8",
23250
- 272
23299
+ 271
23251
23300
  ];
23252
23301
  };
23253
23302
  }
@@ -11068,6 +11068,35 @@
11068
11068
  }
11069
11069
  ]
11070
11070
  },
11071
+ {
11072
+ "name": "update_solvency_status",
11073
+ "discriminator": [
11074
+ 81,
11075
+ 136,
11076
+ 15,
11077
+ 6,
11078
+ 24,
11079
+ 165,
11080
+ 44,
11081
+ 133
11082
+ ],
11083
+ "accounts": [
11084
+ {
11085
+ "name": "admin",
11086
+ "signer": true
11087
+ },
11088
+ {
11089
+ "name": "state",
11090
+ "writable": true
11091
+ }
11092
+ ],
11093
+ "args": [
11094
+ {
11095
+ "name": "solvency_status",
11096
+ "type": "u8"
11097
+ }
11098
+ ]
11099
+ },
11071
11100
  {
11072
11101
  "name": "update_special_user_status",
11073
11102
  "discriminator": [
@@ -15972,6 +16001,16 @@
15972
16001
  "code": 6354,
15973
16002
  "name": "InsufficientProtocolFees",
15974
16003
  "msg": "Insufficient protocol fees available to withdraw"
16004
+ },
16005
+ {
16006
+ "code": 6355,
16007
+ "name": "InvalidNativeStateAccount",
16008
+ "msg": "Native dispatch: supplied state account is not the canonical Velocity state PDA"
16009
+ },
16010
+ {
16011
+ "code": 6356,
16012
+ "name": "InvalidNativePerpMarketAccount",
16013
+ "msg": "Native dispatch: supplied market account is not a Velocity perp market"
15975
16014
  }
15976
16015
  ],
15977
16016
  "types": [
@@ -23207,6 +23246,16 @@
23207
23246
  "name": "lp_pool_feature_bit_flags",
23208
23247
  "type": "u8"
23209
23248
  },
23249
+ {
23250
+ "name": "solvency_status",
23251
+ "docs": [
23252
+ "Bitmask of `SolvencyStatus` flags. Gates internal solvency-repair flows",
23253
+ "(bankruptcy / pnl-deficit resolution) independently of `WithdrawPaused`,",
23254
+ "so user withdrawals can be halted while repair keeps running, or repair",
23255
+ "can be frozen on its own when an oracle is suspect. `0` = repair allowed."
23256
+ ],
23257
+ "type": "u8"
23258
+ },
23210
23259
  {
23211
23260
  "name": "protocol_fee_recipient_perp",
23212
23261
  "docs": [
@@ -23241,7 +23290,7 @@
23241
23290
  "type": {
23242
23291
  "array": [
23243
23292
  "u8",
23244
- 272
23293
+ 271
23245
23294
  ]
23246
23295
  }
23247
23296
  }
@@ -1,5 +1,6 @@
1
1
  import { PerpMarketAccount, PerpOperation, SpotMarketAccount, SpotOperation, StateAccount, InsuranceFundOperation, MarketConfigFlag } from '../types';
2
2
  export declare function exchangePaused(state: StateAccount): boolean;
3
+ export declare function solvencyRepairPaused(state: StateAccount): boolean;
3
4
  export declare function fillPaused(state: StateAccount, market: PerpMarketAccount | SpotMarketAccount): boolean;
4
5
  export declare function ammPaused(state: StateAccount, market: PerpMarketAccount | SpotMarketAccount): boolean;
5
6
  export declare function isOperationPaused(pausedOperations: number, operation: PerpOperation | SpotOperation | InsuranceFundOperation): boolean;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isFormulaicKUpdateDisabled = exports.isMarketConfigFlagSet = exports.isAmmDrawdownPause = exports.isOperationPaused = exports.ammPaused = exports.fillPaused = exports.exchangePaused = void 0;
3
+ exports.isFormulaicKUpdateDisabled = exports.isMarketConfigFlagSet = exports.isAmmDrawdownPause = exports.isOperationPaused = exports.ammPaused = exports.fillPaused = exports.solvencyRepairPaused = exports.exchangePaused = void 0;
4
4
  const numericConstants_1 = require("../constants/numericConstants");
5
5
  const types_1 = require("../types");
6
6
  const anchor_1 = require("../isomorphic/anchor");
@@ -8,6 +8,13 @@ function exchangePaused(state) {
8
8
  return state.exchangeStatus !== types_1.ExchangeStatus.ACTIVE;
9
9
  }
10
10
  exports.exchangePaused = exchangePaused;
11
+ // Mirror of the program's `State::solvency_repair_paused`. Gates the resolve
12
+ // bankruptcy / pnl-deficit instructions, independent of WITHDRAW_PAUSED.
13
+ function solvencyRepairPaused(state) {
14
+ return ((state.solvencyStatus & types_1.SolvencyStatus.SOLVENCY_REPAIR_PAUSED) ===
15
+ types_1.SolvencyStatus.SOLVENCY_REPAIR_PAUSED);
16
+ }
17
+ exports.solvencyRepairPaused = solvencyRepairPaused;
11
18
  function fillPaused(state, market) {
12
19
  if ((state.exchangeStatus & types_1.ExchangeStatus.FILL_PAUSED) ===
13
20
  types_1.ExchangeStatus.FILL_PAUSED) {
@@ -26,5 +26,8 @@ export declare function calculateOrderBaseAssetAmount(order: Order, existingBase
26
26
  * Returns:
27
27
  * - BN size (>=0) if bounded
28
28
  * - null if impossible (target < liabilityWeight) OR imfFactor == 0 (unbounded)
29
+ *
30
+ * Note: a market.maxOpenInterest of 0 means "no configured cap" and is treated
31
+ * as unlimited rather than a hard cap of 0.
29
32
  */
30
33
  export declare function maxSizeForTargetLiabilityWeightBN(target: BN, imfFactor: BN, liabilityWeight: BN, market: PerpMarketAccount): BN | null;
@@ -181,6 +181,9 @@ exports.calculateOrderBaseAssetAmount = calculateOrderBaseAssetAmount;
181
181
  * Returns:
182
182
  * - BN size (>=0) if bounded
183
183
  * - null if impossible (target < liabilityWeight) OR imfFactor == 0 (unbounded)
184
+ *
185
+ * Note: a market.maxOpenInterest of 0 means "no configured cap" and is treated
186
+ * as unlimited rather than a hard cap of 0.
184
187
  */
185
188
  function maxSizeForTargetLiabilityWeightBN(target, imfFactor, liabilityWeight, market) {
186
189
  if (target.lt(liabilityWeight))
@@ -212,9 +215,10 @@ function maxSizeForTargetLiabilityWeightBN(target, imfFactor, liabilityWeight, m
212
215
  hi = mid.sub(numericConstants_1.ONE);
213
216
  }
214
217
  }
215
- // cap at max OI
218
+ // cap at max OI. A maxOpenInterest of 0 means no configured cap (unlimited),
219
+ // matching the on-chain convention — do not treat it as a hard cap of 0.
216
220
  const maxOpenInterest = market.maxOpenInterest;
217
- if (lo.gt(maxOpenInterest)) {
221
+ if (!maxOpenInterest.isZero() && lo.gt(maxOpenInterest)) {
218
222
  return maxOpenInterest;
219
223
  }
220
224
  return lo;
@@ -12,7 +12,7 @@ function calculateInitUserFee(stateAccount) {
12
12
  const accountSpaceUtilization = stateAccount.numberOfSubAccounts
13
13
  .addn(1)
14
14
  .mul(numericConstants_1.PERCENTAGE_PRECISION)
15
- .div(getMaxNumberOfSubAccounts(stateAccount));
15
+ .div(anchor_1.BN.max(getMaxNumberOfSubAccounts(stateAccount), new anchor_1.BN(1)));
16
16
  if (accountSpaceUtilization.gt(targetUtilization)) {
17
17
  return maxInitFee
18
18
  .mul(accountSpaceUtilization.sub(targetUtilization))
@@ -16,10 +16,31 @@ function getUserFilter() {
16
16
  };
17
17
  }
18
18
  exports.getUserFilter = getUserFilter;
19
+ /*
20
+ * Byte offsets of the trailing scalar flags in the `User` account.
21
+ *
22
+ * These MUST match the on-chain `User` layout decoded in `decode/user.ts`. The
23
+ * current Velocity layout is 4496 bytes, with the tail block laid out as
24
+ * consecutive single bytes:
25
+ * status(4468) isMarginTradingEnabled(4469) idle(4470) openOrders(4471)
26
+ * hasOpenOrder(4472) openAuctions(4473) hasOpenAuction(4474) poolId(4475)
27
+ * specialUserStatus(4476)
28
+ *
29
+ * NOTE: these were previously hardcoded to the older (4376-byte) layout
30
+ * (idle@4350, hasOpenOrder@4352, ...). After Velocity added fields to
31
+ * `PerpPosition`, the account grew by 120 bytes and these flags shifted, but
32
+ * the filters were not updated — so `getUserWithOrderFilter()` matched zero
33
+ * accounts and the DLOB order book never populated. Keep these in sync with
34
+ * `decode/user.ts` if the `User` layout changes again.
35
+ */
36
+ const USER_IDLE_OFFSET = 4470;
37
+ const USER_HAS_OPEN_ORDER_OFFSET = 4472;
38
+ const USER_HAS_OPEN_AUCTION_OFFSET = 4474;
39
+ const USER_POOL_ID_OFFSET = 4475;
19
40
  function getNonIdleUserFilter() {
20
41
  return {
21
42
  memcmp: {
22
- offset: 4350,
43
+ offset: USER_IDLE_OFFSET,
23
44
  bytes: bs58_1.default.encode(Uint8Array.from([0])),
24
45
  },
25
46
  };
@@ -28,7 +49,7 @@ exports.getNonIdleUserFilter = getNonIdleUserFilter;
28
49
  function getUserWithOrderFilter() {
29
50
  return {
30
51
  memcmp: {
31
- offset: 4352,
52
+ offset: USER_HAS_OPEN_ORDER_OFFSET,
32
53
  bytes: bs58_1.default.encode(Uint8Array.from([1])),
33
54
  },
34
55
  };
@@ -37,7 +58,7 @@ exports.getUserWithOrderFilter = getUserWithOrderFilter;
37
58
  function getUserWithoutOrderFilter() {
38
59
  return {
39
60
  memcmp: {
40
- offset: 4352,
61
+ offset: USER_HAS_OPEN_ORDER_OFFSET,
41
62
  bytes: bs58_1.default.encode(Uint8Array.from([0])),
42
63
  },
43
64
  };
@@ -46,7 +67,7 @@ exports.getUserWithoutOrderFilter = getUserWithoutOrderFilter;
46
67
  function getUserWithAuctionFilter() {
47
68
  return {
48
69
  memcmp: {
49
- offset: 4354,
70
+ offset: USER_HAS_OPEN_AUCTION_OFFSET,
50
71
  bytes: bs58_1.default.encode(Uint8Array.from([1])),
51
72
  },
52
73
  };
@@ -64,7 +85,7 @@ exports.getUserWithName = getUserWithName;
64
85
  function getUsersWithPoolId(poolId) {
65
86
  return {
66
87
  memcmp: {
67
- offset: 4356,
88
+ offset: USER_POOL_ID_OFFSET,
68
89
  bytes: bs58_1.default.encode(Uint8Array.from([poolId])),
69
90
  },
70
91
  };
@@ -13,6 +13,15 @@ const user_1 = require("../decode/user");
13
13
  const grpcSubscription_1 = require("./grpcSubscription");
14
14
  const orders_1 = require("../math/orders");
15
15
  const numericConstants_1 = require("../constants/numericConstants");
16
+ /*
17
+ * Byte offset of `lastActiveSlot` (u64) in the `User` account, used here to
18
+ * cheaply detect stale updates without fully decoding the buffer. Must match
19
+ * the on-chain `User` layout (see `decode/user.ts`). The previous value (4328)
20
+ * was for the older 4376-byte layout; the current Velocity layout is 4496
21
+ * bytes, shifting this field +120 bytes. With the wrong offset this read 8
22
+ * zero-padding bytes, so the staleness guard rejected every post-load update.
23
+ */
24
+ const USER_LAST_ACTIVE_SLOT_OFFSET = 4448;
16
25
  class OrderSubscriber {
17
26
  constructor(config) {
18
27
  var _a, _b, _c, _d, _e;
@@ -121,7 +130,7 @@ class OrderSubscriber {
121
130
  if (dataType === 'raw') {
122
131
  // @ts-ignore
123
132
  const buffer = buffer_1.Buffer.from(data[0], data[1]);
124
- const newLastActiveSlot = new anchor_1.BN(buffer.subarray(4328, 4328 + 8), undefined, 'le');
133
+ const newLastActiveSlot = new anchor_1.BN(buffer.subarray(USER_LAST_ACTIVE_SLOT_OFFSET, USER_LAST_ACTIVE_SLOT_OFFSET + 8), undefined, 'le');
125
134
  if (slotAndUserAccount &&
126
135
  slotAndUserAccount.userAccount.lastActiveSlot.gt(newLastActiveSlot)) {
127
136
  return;
@@ -130,7 +139,7 @@ class OrderSubscriber {
130
139
  }
131
140
  else if (dataType === 'buffer') {
132
141
  const buffer = data;
133
- const newLastActiveSlot = new anchor_1.BN(buffer.subarray(4328, 4328 + 8), undefined, 'le');
142
+ const newLastActiveSlot = new anchor_1.BN(buffer.subarray(USER_LAST_ACTIVE_SLOT_OFFSET, USER_LAST_ACTIVE_SLOT_OFFSET + 8), undefined, 'le');
134
143
  if (slotAndUserAccount &&
135
144
  slotAndUserAccount.userAccount.lastActiveSlot.gt(newLastActiveSlot)) {
136
145
  return;
@@ -71,8 +71,8 @@ class SwiftOrderSubscriber {
71
71
  this.onOrder = onOrder;
72
72
  const env = this.config.velocityEnv;
73
73
  const endpoint = (_a = this.config.endpoint) !== null && _a !== void 0 ? _a : (env === 'devnet'
74
- ? 'wss://master.swift.drift.trade/ws'
75
- : 'wss://swift.drift.trade/ws');
74
+ ? 'wss://swift.master.velocity.exchange/ws'
75
+ : 'wss://swift.velocity.exchange/ws');
76
76
  const ws = new ws_1.default(endpoint + '?pubkey=' + this.config.keypair.publicKey.toBase58());
77
77
  this.ws = ws;
78
78
  ws.on('open', async () => {
@@ -1,5 +1,5 @@
1
- import * as anchor from './isomorphic/anchor29';
2
- import { AnchorProvider, Program } from './isomorphic/anchor29';
1
+ import * as anchor from './isomorphic/anchor';
2
+ import { AnchorProvider, Program } from './isomorphic/anchor';
3
3
  import { Account } from '@solana/spl-token';
4
4
  import { ConfirmOptions, Connection, PublicKey, TransactionInstruction, TransactionSignature } from '@solana/web3.js';
5
5
  import { IWallet } from './types';
@@ -27,8 +27,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.TokenFaucet = void 0;
30
- const anchor = __importStar(require("./isomorphic/anchor29"));
31
- const anchor29_1 = require("./isomorphic/anchor29");
30
+ const anchor = __importStar(require("./isomorphic/anchor"));
31
+ const anchor_1 = require("./isomorphic/anchor");
32
32
  const spl_token_1 = require("@solana/spl-token");
33
33
  const web3_js_1 = require("@solana/web3.js");
34
34
  const token_faucet_json_1 = __importDefault(require("./idl/token_faucet.json"));
@@ -40,11 +40,18 @@ class TokenFaucet {
40
40
  this.wallet = wallet;
41
41
  this.opts = opts || config_1.DEFAULT_CONFIRMATION_OPTS;
42
42
  // @ts-ignore
43
- const provider = new anchor29_1.AnchorProvider(context ? context.connection.toConnection() : this.connection,
43
+ const provider = new anchor_1.AnchorProvider(context ? context.connection.toConnection() : this.connection,
44
44
  // @ts-ignore
45
45
  wallet, this.opts);
46
46
  this.provider = provider;
47
- this.program = new anchor29_1.Program(token_faucet_json_1.default, programId, provider);
47
+ // Anchor (>= 0.30) reads the program id from `idl.address` rather than a
48
+ // constructor argument. Override it with the caller-provided `programId`
49
+ // so PDAs and instructions target the intended program.
50
+ const idl = {
51
+ ...token_faucet_json_1.default,
52
+ address: programId.toBase58(),
53
+ };
54
+ this.program = new anchor_1.Program(idl, provider);
48
55
  this.mint = mint;
49
56
  }
50
57
  async getFaucetConfigPublicKeyAndNonce() {
@@ -28,6 +28,10 @@ export declare enum ExchangeStatus {
28
28
  AMM_IMMEDIATE_FILL_PAUSED = 128,
29
29
  PAUSED = 255
30
30
  }
31
+ export declare enum SolvencyStatus {
32
+ ACTIVE = 0,
33
+ SOLVENCY_REPAIR_PAUSED = 1
34
+ }
31
35
  export declare enum FeatureBitFlags {
32
36
  MM_ORACLE_UPDATE = 1,
33
37
  MEDIAN_TRIGGER_PRICE = 2,
@@ -839,6 +843,7 @@ export type StateAccount = {
839
843
  maxInitializeUserFee: number;
840
844
  featureBitFlags: number;
841
845
  lpPoolFeatureBitFlags: number;
846
+ solvencyStatus: number;
842
847
  };
843
848
  export type PerpMarketAccount = {
844
849
  status: MarketStatus;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ConstituentLpOperation = exports.ConstituentStatus = exports.OracleValidity = exports.SwapReduceOnly = exports.PlaceAndTakeOrderSuccessCondition = exports.ReferrerStatus = exports.DefaultOrderParams = exports.ModifyOrderPolicy = exports.PositionFlag = exports.OrderParamsBitFlag = exports.SizeDistribution = exports.PostOnlyParams = exports.LiquidationBitFlag = exports.LiquidationType = exports.TradeSide = exports.getVariant = exports.isOneOfVariant = exports.isVariant = exports.SettlePnlMode = exports.StakeAction = exports.SettlePnlExplanation = exports.DepositExplanation = exports.OrderTriggerCondition = exports.OrderActionExplanation = exports.OrderAction = exports.OrderBitFlag = exports.OrderStatus = exports.MarketType = exports.OrderType = exports.OracleSourceNum = exports.OracleSource = exports.DepositDirection = exports.PositionDirection = exports.SpotBalanceType = exports.SwapDirection = exports.TokenProgramFlag = exports.AssetTier = exports.ContractTier = exports.ContractType = exports.MarginMode = exports.MarketConfigFlag = exports.UserStatsPausedOperation = exports.SpecialUserStatus = exports.UserStatus = exports.InsuranceFundOperation = exports.SpotOperation = exports.PerpOperation = exports.MarketStatus = exports.FeatureBitFlags = exports.ExchangeStatus = void 0;
4
- exports.TransferFeeAndPnlPoolDirection = void 0;
3
+ exports.ConstituentStatus = exports.OracleValidity = exports.SwapReduceOnly = exports.PlaceAndTakeOrderSuccessCondition = exports.ReferrerStatus = exports.DefaultOrderParams = exports.ModifyOrderPolicy = exports.PositionFlag = exports.OrderParamsBitFlag = exports.SizeDistribution = exports.PostOnlyParams = exports.LiquidationBitFlag = exports.LiquidationType = exports.TradeSide = exports.getVariant = exports.isOneOfVariant = exports.isVariant = exports.SettlePnlMode = exports.StakeAction = exports.SettlePnlExplanation = exports.DepositExplanation = exports.OrderTriggerCondition = exports.OrderActionExplanation = exports.OrderAction = exports.OrderBitFlag = exports.OrderStatus = exports.MarketType = exports.OrderType = exports.OracleSourceNum = exports.OracleSource = exports.DepositDirection = exports.PositionDirection = exports.SpotBalanceType = exports.SwapDirection = exports.TokenProgramFlag = exports.AssetTier = exports.ContractTier = exports.ContractType = exports.MarginMode = exports.MarketConfigFlag = exports.UserStatsPausedOperation = exports.SpecialUserStatus = exports.UserStatus = exports.InsuranceFundOperation = exports.SpotOperation = exports.PerpOperation = exports.MarketStatus = exports.FeatureBitFlags = exports.SolvencyStatus = exports.ExchangeStatus = void 0;
4
+ exports.TransferFeeAndPnlPoolDirection = exports.ConstituentLpOperation = void 0;
5
5
  const numericConstants_1 = require("./constants/numericConstants");
6
6
  // # Utility Types / Enums / Constants
7
7
  var ExchangeStatus;
@@ -17,6 +17,13 @@ var ExchangeStatus;
17
17
  ExchangeStatus[ExchangeStatus["AMM_IMMEDIATE_FILL_PAUSED"] = 128] = "AMM_IMMEDIATE_FILL_PAUSED";
18
18
  ExchangeStatus[ExchangeStatus["PAUSED"] = 255] = "PAUSED";
19
19
  })(ExchangeStatus || (exports.ExchangeStatus = ExchangeStatus = {}));
20
+ // Mirror of the Rust `SolvencyStatus` bitflag (State.solvencyStatus). Gates
21
+ // internal solvency-repair flows independently of ExchangeStatus.WITHDRAW_PAUSED.
22
+ var SolvencyStatus;
23
+ (function (SolvencyStatus) {
24
+ SolvencyStatus[SolvencyStatus["ACTIVE"] = 0] = "ACTIVE";
25
+ SolvencyStatus[SolvencyStatus["SOLVENCY_REPAIR_PAUSED"] = 1] = "SOLVENCY_REPAIR_PAUSED";
26
+ })(SolvencyStatus || (exports.SolvencyStatus = SolvencyStatus = {}));
20
27
  var FeatureBitFlags;
21
28
  (function (FeatureBitFlags) {
22
29
  FeatureBitFlags[FeatureBitFlags["MM_ORACLE_UPDATE"] = 1] = "MM_ORACLE_UPDATE";
@@ -1185,7 +1185,7 @@ export declare class VelocityClient {
1185
1185
  updateMmOracleNative(marketIndex: number, oraclePrice: BN, oracleSequenceId: BN): Promise<TransactionSignature>;
1186
1186
  getUpdateMmOracleNativeIx(marketIndex: number, oraclePrice: BN, oracleSequenceId: BN): Promise<TransactionInstruction>;
1187
1187
  updateAmmSpreadAdjustmentNative(marketIndex: number, ammSpreadAdjustment: number): Promise<TransactionSignature>;
1188
- getUpdateAmmSpreadAdjustmentNativeIx(marketIndex: number, ammSpreadAdjustment: number): TransactionInstruction;
1188
+ getUpdateAmmSpreadAdjustmentNativeIx(marketIndex: number, ammSpreadAdjustment: number): Promise<TransactionInstruction>;
1189
1189
  getLpPoolAccount(lpPoolId: number): Promise<LPPoolAccount>;
1190
1190
  getConstituentTargetBaseAccount(lpPoolId: number): Promise<ConstituentTargetBaseAccount>;
1191
1191
  getAmmCache(): Promise<AmmCache>;
@@ -1300,7 +1300,7 @@ class VelocityClient {
1300
1300
  subAccountId = subAccountId !== null && subAccountId !== void 0 ? subAccountId : this.activeSubAccountId;
1301
1301
  authority = authority !== null && authority !== void 0 ? authority : this.authority;
1302
1302
  if (subAccountId === undefined || authority === undefined) {
1303
- throw new Error('Subaccount ID and authority are required');
1303
+ return false;
1304
1304
  }
1305
1305
  const userMapKey = this.getUserMapKey(subAccountId, authority);
1306
1306
  return this.users.has(userMapKey);
@@ -5365,19 +5365,26 @@ class VelocityClient {
5365
5365
  async updateAmmSpreadAdjustmentNative(marketIndex, ammSpreadAdjustment) {
5366
5366
  const updateMmOracleIx = await this.getUpdateAmmSpreadAdjustmentNativeIx(marketIndex, ammSpreadAdjustment);
5367
5367
  const tx = await this.buildTransaction(updateMmOracleIx, {
5368
- computeUnits: 1000,
5368
+ // Headroom for the native handler's owner + discriminator validation
5369
+ // of the state + perp-market accounts (was 1000 when it bytemuck-cast
5370
+ // the market without any checks). Measured ~1.3k CU; 2000 leaves
5371
+ // margin for the production-only signer check.
5372
+ computeUnits: 2000,
5369
5373
  computeUnitsPrice: 0,
5370
5374
  });
5371
5375
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
5372
5376
  return txSig;
5373
5377
  }
5374
- getUpdateAmmSpreadAdjustmentNativeIx(marketIndex, ammSpreadAdjustment // i8
5378
+ async getUpdateAmmSpreadAdjustmentNativeIx(marketIndex, ammSpreadAdjustment // i8
5375
5379
  ) {
5376
5380
  const discriminatorBuffer = (0, utils_2.createNativeInstructionDiscriminatorBuffer)(1);
5377
5381
  const data = Buffer.alloc(discriminatorBuffer.length + 4);
5378
5382
  data.set(discriminatorBuffer, 0);
5379
5383
  data.writeInt8(ammSpreadAdjustment, 5); // next byte
5380
- // Build the instruction manually
5384
+ // Build the instruction manually. The native handler re-establishes the
5385
+ // account guarantees Anchor would normally provide: it loads `state` as
5386
+ // the program-owned State account and authenticates the signer against
5387
+ // `state.hotAmmSpreadAdjust`, so the state account is required at index 2.
5381
5388
  return new web3_js_1.TransactionInstruction({
5382
5389
  programId: this.program.programId,
5383
5390
  keys: [
@@ -5391,6 +5398,11 @@ class VelocityClient {
5391
5398
  isWritable: false,
5392
5399
  isSigner: true,
5393
5400
  },
5401
+ {
5402
+ pubkey: await this.getStatePublicKey(),
5403
+ isWritable: false,
5404
+ isSigner: false,
5405
+ },
5394
5406
  ],
5395
5407
  data,
5396
5408
  });
@@ -7,7 +7,7 @@
7
7
  * pause/unpause exchange, and all ~126 admin instruction handlers in `instructions/admin.rs`.
8
8
  */
9
9
  import { AddressLookupTableAccount, Keypair, PublicKey, TransactionInstruction, TransactionSignature } from '@solana/web3.js';
10
- import { FeeStructure, OracleGuardRails, OracleSource, ExchangeStatus, MarketStatus, ContractTier, AssetTier, TxParams, AddAmmConstituentMappingDatum, SwapReduceOnly, InitializeConstituentParams, ConstituentStatus, LPPoolAccount, TransferFeeAndPnlPoolDirection, MarketType } from './types';
10
+ import { FeeStructure, OracleGuardRails, OracleSource, ExchangeStatus, SolvencyStatus, MarketStatus, ContractTier, AssetTier, TxParams, AddAmmConstituentMappingDatum, SwapReduceOnly, InitializeConstituentParams, ConstituentStatus, LPPoolAccount, TransferFeeAndPnlPoolDirection, MarketType } from './types';
11
11
  import { BN } from './isomorphic/anchor';
12
12
  import { VelocityClient } from './velocityClient';
13
13
  import { JupiterClient, QuoteResponse } from './jupiter/jupiterClient';
@@ -182,6 +182,8 @@ export declare class AdminClient extends VelocityClient {
182
182
  getUpdatePerpMarketContractTierIx(perpMarketIndex: number, contractTier: ContractTier): Promise<TransactionInstruction>;
183
183
  updateExchangeStatus(exchangeStatus: ExchangeStatus): Promise<TransactionSignature>;
184
184
  getUpdateExchangeStatusIx(exchangeStatus: ExchangeStatus): Promise<TransactionInstruction>;
185
+ updateSolvencyStatus(solvencyStatus: SolvencyStatus): Promise<TransactionSignature>;
186
+ getUpdateSolvencyStatusIx(solvencyStatus: SolvencyStatus): Promise<TransactionInstruction>;
185
187
  updatePerpAuctionDuration(minDuration: BN | number): Promise<TransactionSignature>;
186
188
  getUpdatePerpAuctionDurationIx(minDuration: BN | number): Promise<TransactionInstruction>;
187
189
  updateSpotAuctionDuration(defaultAuctionDuration: number): Promise<TransactionSignature>;