@velocity-exchange/sdk 0.2.3 → 0.2.5

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 (54) hide show
  1. package/CHANGELOG.md +23 -3
  2. package/README.md +5 -5
  3. package/lib/browser/accounts/grpcMultiAccountSubscriber.d.ts +0 -1
  4. package/lib/browser/accounts/grpcMultiAccountSubscriber.js +2 -7
  5. package/lib/browser/accounts/grpcMultiUserAccountSubscriber.js +3 -0
  6. package/lib/browser/accounts/webSocketAccountSubscriberV2.js +1 -2
  7. package/lib/browser/accounts/websocketProgramUserAccountSubscriber.js +3 -0
  8. package/lib/browser/config.js +1 -1
  9. package/lib/browser/constants/spotMarkets.js +1 -1
  10. package/lib/browser/math/liquidation.d.ts +14 -0
  11. package/lib/browser/math/liquidation.js +14 -0
  12. package/lib/browser/types.d.ts +75 -9
  13. package/lib/browser/user.d.ts +22 -6
  14. package/lib/browser/user.js +24 -8
  15. package/lib/browser/userMap/userMap.js +5 -1
  16. package/lib/browser/velocityClient.d.ts +0 -2
  17. package/lib/browser/velocityClient.js +0 -18
  18. package/lib/node/accounts/grpcMultiAccountSubscriber.d.ts +0 -1
  19. package/lib/node/accounts/grpcMultiAccountSubscriber.d.ts.map +1 -1
  20. package/lib/node/accounts/grpcMultiAccountSubscriber.js +2 -7
  21. package/lib/node/accounts/grpcMultiUserAccountSubscriber.d.ts.map +1 -1
  22. package/lib/node/accounts/grpcMultiUserAccountSubscriber.js +3 -0
  23. package/lib/node/accounts/webSocketAccountSubscriberV2.d.ts.map +1 -1
  24. package/lib/node/accounts/webSocketAccountSubscriberV2.js +1 -2
  25. package/lib/node/accounts/websocketProgramUserAccountSubscriber.d.ts.map +1 -1
  26. package/lib/node/accounts/websocketProgramUserAccountSubscriber.js +3 -0
  27. package/lib/node/config.js +1 -1
  28. package/lib/node/constants/spotMarkets.js +1 -1
  29. package/lib/node/math/liquidation.d.ts +14 -0
  30. package/lib/node/math/liquidation.d.ts.map +1 -1
  31. package/lib/node/math/liquidation.js +14 -0
  32. package/lib/node/types.d.ts +75 -9
  33. package/lib/node/types.d.ts.map +1 -1
  34. package/lib/node/user.d.ts +22 -6
  35. package/lib/node/user.d.ts.map +1 -1
  36. package/lib/node/user.js +24 -8
  37. package/lib/node/userMap/userMap.d.ts.map +1 -1
  38. package/lib/node/userMap/userMap.js +5 -1
  39. package/lib/node/velocityClient.d.ts +0 -2
  40. package/lib/node/velocityClient.d.ts.map +1 -1
  41. package/lib/node/velocityClient.js +0 -18
  42. package/package.json +2 -2
  43. package/src/accounts/grpcMultiAccountSubscriber.ts +2 -10
  44. package/src/accounts/grpcMultiUserAccountSubscriber.ts +5 -0
  45. package/src/accounts/webSocketAccountSubscriberV2.ts +1 -5
  46. package/src/accounts/websocketProgramUserAccountSubscriber.ts +5 -0
  47. package/src/config.ts +1 -1
  48. package/src/constants/spotMarkets.ts +1 -1
  49. package/src/math/liquidation.ts +14 -0
  50. package/src/types.ts +82 -9
  51. package/src/user.ts +24 -8
  52. package/src/userMap/userMap.ts +5 -1
  53. package/src/velocityClient.ts +0 -31
  54. package/tests/dlob/helpers.ts +24 -4
package/src/types.ts CHANGED
@@ -371,6 +371,8 @@ export type DepositRecord = {
371
371
  depositRecordId: BN;
372
372
  explanation: DepositExplanation;
373
373
  transferUser?: PublicKey;
374
+ signer?: PublicKey;
375
+ userTokenAmountAfter: BN;
374
376
  };
375
377
 
376
378
  export type SpotInterestRecord = {
@@ -465,13 +467,14 @@ export type LiquidationRecord = {
465
467
  marginFreed: BN;
466
468
  liquidationId: number;
467
469
  bankrupt: boolean;
468
- canceledOrderIds: BN[];
470
+ canceledOrderIds: number[];
469
471
  liquidatePerp: LiquidatePerpRecord;
470
472
  liquidateSpot: LiquidateSpotRecord;
471
473
  liquidateBorrowForPerpPnl: LiquidateBorrowForPerpPnlRecord;
472
474
  liquidatePerpPnlForDeposit: LiquidatePerpPnlForDepositRecord;
473
475
  perpBankruptcy: PerpBankruptcyRecord;
474
476
  spotBankruptcy: SpotBankruptcyRecord;
477
+ bitFlags: number;
475
478
  };
476
479
 
477
480
  export class LiquidationType {
@@ -498,11 +501,12 @@ export type LiquidatePerpRecord = {
498
501
  oraclePrice: BN;
499
502
  baseAssetAmount: BN;
500
503
  quoteAssetAmount: BN;
501
- userOrderId: BN;
502
- liquidatorOrderId: BN;
504
+ userOrderId: number;
505
+ liquidatorOrderId: number;
503
506
  fillRecordId: BN;
504
507
  liquidatorFee: BN;
505
508
  ifFee: BN;
509
+ protocolFee: BN;
506
510
  };
507
511
 
508
512
  export type LiquidateSpotRecord = {
@@ -513,6 +517,7 @@ export type LiquidateSpotRecord = {
513
517
  liabilityPrice: BN;
514
518
  liabilityTransfer: BN;
515
519
  ifFee: BN;
520
+ protocolFee: BN;
516
521
  };
517
522
 
518
523
  export type LiquidateBorrowForPerpPnlRecord = {
@@ -615,6 +620,9 @@ export type OrderActionRecord = {
615
620
  takerExistingBaseAssetAmount: BN | null;
616
621
  makerExistingQuoteEntryAmount: BN | null;
617
622
  makerExistingBaseAssetAmount: BN | null;
623
+ triggerPrice: BN | null;
624
+ builderIdx: number | null;
625
+ builderFee: BN | null;
618
626
  };
619
627
 
620
628
  export type SwapRecord = {
@@ -661,8 +669,6 @@ export type LPSwapRecord = {
661
669
  inConstituentIndex: number;
662
670
  outOraclePrice: BN;
663
671
  inOraclePrice: BN;
664
- outMint: PublicKey;
665
- inMint: PublicKey;
666
672
  lastAum: BN;
667
673
  lastAumSlot: BN;
668
674
  inMarketCurrentWeight: BN;
@@ -685,7 +691,6 @@ export type LPMintRedeemRecord = {
685
691
  constituentIndex: number;
686
692
  oraclePrice: BN;
687
693
  mint: PublicKey;
688
- lpMint: PublicKey;
689
694
  lpAmount: BN;
690
695
  lpFee: BN;
691
696
  lpPrice: BN;
@@ -728,6 +733,7 @@ export type LPBorrowLendDepositRecord = {
728
733
  export type StateAccount = {
729
734
  coldAdmin: PublicKey;
730
735
  warmAdmin: PublicKey;
736
+ pauseAdmin: PublicKey;
731
737
  hotAmmCrank: PublicKey;
732
738
  hotLpCache: PublicKey;
733
739
  hotLpSwap: PublicKey;
@@ -764,6 +770,7 @@ export type StateAccount = {
764
770
  liquidationDuration: number;
765
771
  maxInitializeUserFee: number;
766
772
  featureBitFlags: number;
773
+ lpPoolFeatureBitFlags: number;
767
774
  };
768
775
 
769
776
  export type PerpMarketAccount = {
@@ -807,6 +814,7 @@ export type PerpMarketAccount = {
807
814
  pausedOperations: number;
808
815
 
809
816
  lastFillPrice: BN;
817
+ poolId: number;
810
818
 
811
819
  hedgeConfig: {
812
820
  poolId: number;
@@ -908,6 +916,7 @@ export type SpotMarketAccount = {
908
916
 
909
917
  lastInterestTs: BN;
910
918
  lastTwapTs: BN;
919
+ expiryTs: BN;
911
920
  initialAssetWeight: number;
912
921
  maintenanceAssetWeight: number;
913
922
  initialLiabilityWeight: number;
@@ -988,12 +997,21 @@ export type AMM = {
988
997
  totalFeeMinusDistributions: BN;
989
998
  /// @deprecated frozen pre-isolation analytics counter
990
999
  totalFeeWithdrawn: BN;
1000
+ askBaseAssetReserve: BN;
1001
+ askQuoteAssetReserve: BN;
1002
+ bidBaseAssetReserve: BN;
1003
+ bidQuoteAssetReserve: BN;
991
1004
  lastUpdateSlot: BN;
992
1005
  netRevenueSinceLastFunding: BN;
993
1006
  lastCumulativeFundingRateLong: BN;
994
1007
  lastCumulativeFundingRateShort: BN;
1008
+ lastOracleReservePriceSpreadPct: BN;
1009
+ lastSpreadUpdateSlot: BN;
995
1010
  baseSpread: number;
996
1011
  maxSpread: number;
1012
+ longSpread: number;
1013
+ shortSpread: number;
1014
+ referencePriceOffset: number;
997
1015
  maxFillReserveFraction: number;
998
1016
  maxSlippageRatio: number;
999
1017
  curveUpdateIntensity: number;
@@ -1066,6 +1084,8 @@ export type UserStatsAccount = {
1066
1084
  };
1067
1085
  referrer: PublicKey;
1068
1086
  referrerStatus: number;
1087
+ disableUpdatePerpBidAskTwap: number;
1088
+ pausedOperations: number;
1069
1089
  authority: PublicKey;
1070
1090
  ifStakedQuoteAssetAmount: BN;
1071
1091
  delegatePermissions: number;
@@ -1388,8 +1408,8 @@ export type FeeTier = {
1388
1408
  };
1389
1409
 
1390
1410
  export type OrderFillerRewardStructure = {
1391
- rewardNumerator: BN;
1392
- rewardDenominator: BN;
1411
+ rewardNumerator: number;
1412
+ rewardDenominator: number;
1393
1413
  timeBasedRewardLowerBound: BN;
1394
1414
  };
1395
1415
 
@@ -1426,6 +1446,25 @@ export type PrelaunchOracle = {
1426
1446
  perpMarketIndex: number;
1427
1447
  };
1428
1448
 
1449
+ export type PrelaunchOracleParams = {
1450
+ perpMarketIndex: number;
1451
+ price: BN | null;
1452
+ maxPrice: BN | null;
1453
+ };
1454
+
1455
+ export type PythLazerOracle = {
1456
+ price: BN;
1457
+ publishTime: BN;
1458
+ postedSlot: BN;
1459
+ exponent: number;
1460
+ conf: BN;
1461
+ };
1462
+
1463
+ export type UpdatePerpMarketSummaryStatsParams = {
1464
+ netUnsettledFundingPnl: BN | null;
1465
+ updateAmmSummaryStats: boolean | null;
1466
+ };
1467
+
1429
1468
  export type MarginCategory = 'Initial' | 'Maintenance';
1430
1469
 
1431
1470
  export type InsuranceFundStake = {
@@ -1436,6 +1475,7 @@ export type InsuranceFundStake = {
1436
1475
 
1437
1476
  ifShares: BN;
1438
1477
  ifBase: BN;
1478
+ lastValidTs: BN;
1439
1479
 
1440
1480
  lastWithdrawRequestShares: BN;
1441
1481
  lastWithdrawRequestValue: BN;
@@ -1523,6 +1563,10 @@ export type SignedMsgUserOrdersAccount = {
1523
1563
  signedMsgOrderData: SignedMsgOrderId[];
1524
1564
  };
1525
1565
 
1566
+ export type SignedMsgWsDelegatesAccount = {
1567
+ delegates: PublicKey[];
1568
+ };
1569
+
1526
1570
  export type RevenueShareAccount = {
1527
1571
  authority: PublicKey;
1528
1572
  totalReferrerRewards: BN;
@@ -1557,8 +1601,25 @@ export type BuilderInfo = {
1557
1601
  padding: number[];
1558
1602
  };
1559
1603
 
1604
+ export type PerpMarketFeeSweepRecord = {
1605
+ ts: BN;
1606
+ marketIndex: number;
1607
+ ifSwept: BN;
1608
+ protocolSwept: BN;
1609
+ ammProvisionTokenized: BN;
1610
+ };
1611
+
1612
+ export type ProtocolFeeWithdrawRecord = {
1613
+ ts: BN;
1614
+ marketIndex: number;
1615
+ isPerp: boolean;
1616
+ spotMarketIndex: number;
1617
+ amount: BN;
1618
+ recipientTokenAccount: PublicKey;
1619
+ };
1620
+
1560
1621
  export type RevenueShareSettleRecord = {
1561
- ts: number;
1622
+ ts: BN;
1562
1623
  builder: PublicKey | null;
1563
1624
  referrer: PublicKey | null;
1564
1625
  feeSettled: BN;
@@ -1628,6 +1689,8 @@ export type LPPoolAccount = {
1628
1689
  bump: number;
1629
1690
  gammaExecution: number;
1630
1691
  xi: number;
1692
+ targetOracleDelayFeeBpsPer10Slots: number;
1693
+ targetPositionDelayFeeBpsPer10Slots: number;
1631
1694
  };
1632
1695
 
1633
1696
  export type ConstituentSpotBalance = {
@@ -1726,6 +1789,7 @@ export type CacheInfo = {
1726
1789
  };
1727
1790
 
1728
1791
  export type AmmCache = {
1792
+ bump: number;
1729
1793
  cache: CacheInfo[];
1730
1794
  };
1731
1795
 
@@ -1739,3 +1803,12 @@ export class TransferFeeAndPnlPoolDirection {
1739
1803
  static readonly FEE_TO_PNL_POOL = { feeToPnlPool: {} };
1740
1804
  static readonly PNL_TO_FEE_POOL = { pnlToFeePool: {} };
1741
1805
  }
1806
+
1807
+ export type TransferFeeAndPnlPoolRecord = {
1808
+ ts: BN;
1809
+ slot: BN;
1810
+ perpMarketIndexWithFeePool: number;
1811
+ perpMarketIndexWithPnlPool: number;
1812
+ direction: TransferFeeAndPnlPoolDirection;
1813
+ amount: BN;
1814
+ };
package/src/user.ts CHANGED
@@ -225,20 +225,35 @@ export class User {
225
225
  this.isSubscribed = false;
226
226
  }
227
227
 
228
+ /**
229
+ * Returns the cached user account.
230
+ *
231
+ * - **Throws** `NotSubscribedError` if the subscriber has not been subscribed
232
+ * yet — reading the account before {@link subscribe} resolves is a
233
+ * programming error, not a missing-account condition.
234
+ * - Returns `undefined` when subscribed but no account was found on chain.
235
+ * Because `subscribe()` awaits the initial fetch, an `undefined` here means
236
+ * the account does not exist (or has not yet been observed), not that data
237
+ * is "still loading".
238
+ */
228
239
  public getUserAccount(): UserAccount | undefined {
229
240
  return this.accountSubscriber.getUserAccountAndSlot()?.data;
230
241
  }
231
242
 
232
243
  /**
233
- * Like {@link getUserAccount} but throws a named error instead of returning
234
- * `undefined` when the account has not been loaded yet. Use at call sites
235
- * that structurally require a loaded account.
244
+ * Like {@link getUserAccount} but throws instead of returning `undefined`
245
+ * when the account was not found. Use at call sites that structurally
246
+ * require the account to exist. (Still propagates `NotSubscribedError` when
247
+ * called before subscribing.)
248
+ *
249
+ * Delegates to {@link getUserAccount} (rather than the subscriber directly)
250
+ * so callers that override `getUserAccount` see the override here too.
236
251
  */
237
252
  public getUserAccountOrThrow(): UserAccount {
238
253
  const userAccount = this.getUserAccount();
239
254
  if (!userAccount) {
240
255
  throw new Error(
241
- `User account not loaded: ${this.getUserAccountPublicKey().toString()}`
256
+ `User account not found: ${this.getUserAccountPublicKey().toString()}`
242
257
  );
243
258
  }
244
259
  return userAccount;
@@ -255,14 +270,15 @@ export class User {
255
270
  }
256
271
 
257
272
  /**
258
- * Like {@link getUserAccountAndSlot} but throws a named error instead of
259
- * returning `undefined` when the account has not been loaded yet. Use at
260
- * call sites that structurally require a loaded account.
273
+ * Like {@link getUserAccountAndSlot} but throws instead of returning
274
+ * `undefined` when the account was not found. Use at call sites that
275
+ * structurally require the account to exist. (Still propagates
276
+ * `NotSubscribedError` when called before subscribing.)
261
277
  */
262
278
  public getUserAccountAndSlotOrThrow(): DataAndSlot<UserAccount> {
263
279
  return assertDataAndSlot(
264
280
  this.accountSubscriber.getUserAccountAndSlot(),
265
- `User account not loaded: ${this.getUserAccountPublicKey().toString()}`
281
+ `User account not found: ${this.getUserAccountPublicKey().toString()}`
266
282
  );
267
283
  }
268
284
 
@@ -44,7 +44,11 @@ import { grpcSubscription } from './grpcSubscription';
44
44
  import StrictEventEmitter from 'strict-event-emitter-types';
45
45
  import { EventEmitter } from 'events';
46
46
 
47
- const MAX_USER_ACCOUNT_SIZE_BYTES = 4376;
47
+ // Velocity's User account is 4496 bytes (8-byte discriminator + 4488 struct);
48
+ // drift's was 4376. This caps the zstd-decompressed buffer in defaultSync — if it's
49
+ // smaller than the real account, the buffer is truncated and decodeUser reads past
50
+ // the end (RangeError: ERR_BUFFER_OUT_OF_BOUNDS). Must be >= the on-chain User size.
51
+ const MAX_USER_ACCOUNT_SIZE_BYTES = 4496;
48
52
 
49
53
  export interface UserMapInterface {
50
54
  eventEmitter: StrictEventEmitter<EventEmitter, UserEvents>;
@@ -1297,37 +1297,6 @@ export class VelocityClient {
1297
1297
  });
1298
1298
  }
1299
1299
 
1300
- public async migrateReferrer(
1301
- authority: PublicKey,
1302
- txParams?: TxParams
1303
- ): Promise<TransactionSignature> {
1304
- const ix = await this.getMigrateReferrerIx(authority);
1305
- const tx = await this.buildTransaction([ix], txParams);
1306
- const { txSig } = await this.sendTransaction(tx, [], this.opts);
1307
- return txSig;
1308
- }
1309
-
1310
- public async getMigrateReferrerIx(
1311
- authority: PublicKey
1312
- ): Promise<TransactionInstruction> {
1313
- const escrow = getRevenueShareEscrowAccountPublicKey(
1314
- this.program.programId,
1315
- authority
1316
- );
1317
- return (this.program.instruction as any).migrateReferrer({
1318
- accounts: {
1319
- escrow,
1320
- authority,
1321
- userStats: getUserStatsAccountPublicKey(
1322
- this.program.programId,
1323
- authority
1324
- ),
1325
- state: await this.getStatePublicKey(),
1326
- payer: this.wallet.publicKey,
1327
- },
1328
- });
1329
- }
1330
-
1331
1300
  public async resizeRevenueShareEscrowOrders(
1332
1301
  authority: PublicKey,
1333
1302
  numOrders: number,
@@ -52,9 +52,23 @@ export const mockAMM: AMM = {
52
52
  quoteAssetReserve: new BN(12)
53
53
  .mul(QUOTE_PRECISION)
54
54
  .mul(AMM_TO_QUOTE_PRECISION_RATIO),
55
+ // zero-spread mock: bid/ask reserves mirror the base/quote reserves
56
+ askBaseAssetReserve: new BN(1).mul(BASE_PRECISION),
57
+ askQuoteAssetReserve: new BN(12)
58
+ .mul(QUOTE_PRECISION)
59
+ .mul(AMM_TO_QUOTE_PRECISION_RATIO),
60
+ bidBaseAssetReserve: new BN(1).mul(BASE_PRECISION),
61
+ bidQuoteAssetReserve: new BN(12)
62
+ .mul(QUOTE_PRECISION)
63
+ .mul(AMM_TO_QUOTE_PRECISION_RATIO),
55
64
  sqrtK: new BN(1),
56
65
  pegMultiplier: new BN(1),
57
66
  maxSlippageRatio: 1_000_000,
67
+ lastOracleReservePriceSpreadPct: new BN(0),
68
+ lastSpreadUpdateSlot: new BN(0),
69
+ longSpread: 0,
70
+ shortSpread: 0,
71
+ referencePriceOffset: 0,
58
72
 
59
73
  feePool: {
60
74
  scaledBalance: new BN(0),
@@ -177,6 +191,7 @@ function mockPerpMarketCommon(): Omit<
177
191
  },
178
192
  quoteSpotMarketIndex: 0,
179
193
  feeAdjustment: 0,
194
+ poolId: 0,
180
195
  pausedOperations: 0,
181
196
  hedgeConfig: {
182
197
  poolId: 0,
@@ -285,6 +300,7 @@ export const mockSpotMarkets: Array<SpotMarketAccount> = [
285
300
  borrowBalance: new BN(0),
286
301
  lastInterestTs: new BN(0),
287
302
  lastTwapTs: new BN(0),
303
+ expiryTs: new BN(0),
288
304
  oracle: PublicKey.default,
289
305
  initialAssetWeight: SPOT_MARKET_WEIGHT_PRECISION.toNumber(),
290
306
  maintenanceAssetWeight: SPOT_MARKET_WEIGHT_PRECISION.toNumber(),
@@ -378,6 +394,7 @@ export const mockSpotMarkets: Array<SpotMarketAccount> = [
378
394
  borrowBalance: new BN(0),
379
395
  lastInterestTs: new BN(0),
380
396
  lastTwapTs: new BN(0),
397
+ expiryTs: new BN(0),
381
398
  oracle: PublicKey.default,
382
399
  initialAssetWeight: 0,
383
400
  maintenanceAssetWeight: 0,
@@ -473,6 +490,7 @@ export const mockSpotMarkets: Array<SpotMarketAccount> = [
473
490
  borrowBalance: new BN(0),
474
491
  lastInterestTs: new BN(0),
475
492
  lastTwapTs: new BN(0),
493
+ expiryTs: new BN(0),
476
494
  oracle: PublicKey.default,
477
495
  initialAssetWeight: 0,
478
496
  maintenanceAssetWeight: 0,
@@ -526,6 +544,7 @@ export const mockSpotMarkets: Array<SpotMarketAccount> = [
526
544
  export const mockStateAccount: StateAccount = {
527
545
  coldAdmin: PublicKey.default,
528
546
  warmAdmin: PublicKey.default,
547
+ pauseAdmin: PublicKey.default,
529
548
  hotAmmCrank: PublicKey.default,
530
549
  hotLpCache: PublicKey.default,
531
550
  hotLpSwap: PublicKey.default,
@@ -540,6 +559,7 @@ export const mockStateAccount: StateAccount = {
540
559
  protocolFeeRecipientPerp: PublicKey.default,
541
560
  protocolFeeRecipientSpot: PublicKey.default,
542
561
  featureBitFlags: 0,
562
+ lpPoolFeatureBitFlags: 0,
543
563
  defaultMarketOrderTimeInForce: 0,
544
564
  defaultSpotAuctionDuration: 0,
545
565
  discountMint: PublicKey.default,
@@ -578,8 +598,8 @@ export const mockStateAccount: StateAccount = {
578
598
  },
579
599
  ],
580
600
  fillerRewardStructure: {
581
- rewardNumerator: new BN(0),
582
- rewardDenominator: new BN(0),
601
+ rewardNumerator: 0,
602
+ rewardDenominator: 0,
583
603
  timeBasedRewardLowerBound: new BN(0),
584
604
  },
585
605
  flatFillerFee: new BN(0),
@@ -603,8 +623,8 @@ export const mockStateAccount: StateAccount = {
603
623
  },
604
624
  ],
605
625
  fillerRewardStructure: {
606
- rewardNumerator: new BN(0),
607
- rewardDenominator: new BN(0),
626
+ rewardNumerator: 0,
627
+ rewardDenominator: 0,
608
628
  timeBasedRewardLowerBound: new BN(0),
609
629
  },
610
630
  flatFillerFee: new BN(0),