@drift-labs/sdk 2.107.0-beta.8 → 2.108.0-beta.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 (57) hide show
  1. package/VERSION +1 -1
  2. package/lib/browser/accounts/webSocketDriftClientAccountSubscriber.d.ts +1 -0
  3. package/lib/browser/accounts/webSocketDriftClientAccountSubscriber.js +12 -3
  4. package/lib/browser/constants/perpMarkets.js +14 -2
  5. package/lib/browser/constants/spotMarkets.js +15 -2
  6. package/lib/browser/dlob/DLOB.d.ts +2 -1
  7. package/lib/browser/dlob/DLOB.js +14 -13
  8. package/lib/browser/dlob/DLOBNode.d.ts +2 -2
  9. package/lib/browser/dlob/DLOBNode.js +2 -2
  10. package/lib/browser/dlob/DLOBSubscriber.d.ts +1 -0
  11. package/lib/browser/dlob/DLOBSubscriber.js +3 -2
  12. package/lib/browser/dlob/types.d.ts +2 -1
  13. package/lib/browser/driftClient.js +10 -2
  14. package/lib/browser/idl/drift.json +1 -1
  15. package/lib/browser/math/funding.d.ts +10 -0
  16. package/lib/browser/math/funding.js +47 -1
  17. package/lib/browser/math/orders.d.ts +1 -1
  18. package/lib/browser/math/orders.js +10 -1
  19. package/lib/browser/orderSubscriber/OrderSubscriber.d.ts +2 -2
  20. package/lib/browser/orderSubscriber/OrderSubscriber.js +4 -4
  21. package/lib/browser/userMap/userMap.d.ts +1 -1
  22. package/lib/browser/userMap/userMap.js +2 -2
  23. package/lib/node/accounts/webSocketDriftClientAccountSubscriber.d.ts +1 -0
  24. package/lib/node/accounts/webSocketDriftClientAccountSubscriber.js +12 -3
  25. package/lib/node/constants/perpMarkets.js +14 -2
  26. package/lib/node/constants/spotMarkets.js +15 -2
  27. package/lib/node/dlob/DLOB.d.ts +2 -1
  28. package/lib/node/dlob/DLOB.js +14 -13
  29. package/lib/node/dlob/DLOBNode.d.ts +2 -2
  30. package/lib/node/dlob/DLOBNode.js +2 -2
  31. package/lib/node/dlob/DLOBSubscriber.d.ts +1 -0
  32. package/lib/node/dlob/DLOBSubscriber.js +3 -2
  33. package/lib/node/dlob/types.d.ts +2 -1
  34. package/lib/node/driftClient.js +10 -2
  35. package/lib/node/idl/drift.json +1 -1
  36. package/lib/node/math/funding.d.ts +10 -0
  37. package/lib/node/math/funding.js +47 -1
  38. package/lib/node/math/orders.d.ts +1 -1
  39. package/lib/node/math/orders.js +10 -1
  40. package/lib/node/orderSubscriber/OrderSubscriber.d.ts +2 -2
  41. package/lib/node/orderSubscriber/OrderSubscriber.js +4 -4
  42. package/lib/node/userMap/userMap.d.ts +1 -1
  43. package/lib/node/userMap/userMap.js +2 -2
  44. package/package.json +1 -1
  45. package/src/accounts/webSocketDriftClientAccountSubscriber.ts +33 -8
  46. package/src/constants/perpMarkets.ts +16 -2
  47. package/src/constants/spotMarkets.ts +17 -2
  48. package/src/dlob/DLOB.ts +43 -13
  49. package/src/dlob/DLOBNode.ts +17 -3
  50. package/src/dlob/DLOBSubscriber.ts +8 -3
  51. package/src/dlob/types.ts +2 -1
  52. package/src/driftClient.ts +12 -5
  53. package/src/idl/drift.json +1 -1
  54. package/src/math/funding.ts +83 -0
  55. package/src/math/orders.ts +12 -1
  56. package/src/orderSubscriber/OrderSubscriber.ts +7 -4
  57. package/src/userMap/userMap.ts +5 -2
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.107.0-beta.8
1
+ 2.108.0-beta.0
@@ -35,6 +35,7 @@ export declare class WebSocketDriftClientAccountSubscriber implements DriftClien
35
35
  protected subscriptionPromiseResolver: (val: boolean) => void;
36
36
  constructor(program: Program, perpMarketIndexes: number[], spotMarketIndexes: number[], oracleInfos: OracleInfo[], shouldFindAllMarketsAndOracles: boolean, delistedMarketSetting: DelistedMarketSetting, resubOpts?: ResubOpts, commitment?: Commitment);
37
37
  subscribe(): Promise<boolean>;
38
+ chunks: <T>(array: readonly T[], size: number) => T[][];
38
39
  setInitialData(): Promise<void>;
39
40
  removeInitialData(): void;
40
41
  subscribeToPerpMarketAccounts(): Promise<boolean>;
@@ -24,6 +24,12 @@ class WebSocketDriftClientAccountSubscriber {
24
24
  this.spotOracleStringMap = new Map();
25
25
  this.oracleSubscribers = new Map();
26
26
  this.isSubscribing = false;
27
+ this.chunks = (array, size) => {
28
+ return new Array(Math.ceil(array.length / size))
29
+ .fill(null)
30
+ .map((_, index) => index * size)
31
+ .map((begin) => array.slice(begin, begin + size));
32
+ };
27
33
  this.isSubscribed = false;
28
34
  this.program = program;
29
35
  this.eventEmitter = new events_1.EventEmitter();
@@ -86,7 +92,8 @@ class WebSocketDriftClientAccountSubscriber {
86
92
  const connection = this.program.provider.connection;
87
93
  if (!this.initialPerpMarketAccountData) {
88
94
  const perpMarketPublicKeys = this.perpMarketIndexes.map((marketIndex) => (0, pda_1.getPerpMarketPublicKeySync)(this.program.programId, marketIndex));
89
- const perpMarketAccountInfos = await connection.getMultipleAccountsInfo(perpMarketPublicKeys);
95
+ const perpMarketPublicKeysChunks = this.chunks(perpMarketPublicKeys, 75);
96
+ const perpMarketAccountInfos = (await Promise.all(perpMarketPublicKeysChunks.map((perpMarketPublicKeysChunk) => connection.getMultipleAccountsInfo(perpMarketPublicKeysChunk)))).flat();
90
97
  this.initialPerpMarketAccountData = new Map(perpMarketAccountInfos
91
98
  .filter((accountInfo) => !!accountInfo)
92
99
  .map((accountInfo) => {
@@ -96,7 +103,8 @@ class WebSocketDriftClientAccountSubscriber {
96
103
  }
97
104
  if (!this.initialSpotMarketAccountData) {
98
105
  const spotMarketPublicKeys = this.spotMarketIndexes.map((marketIndex) => (0, pda_1.getSpotMarketPublicKeySync)(this.program.programId, marketIndex));
99
- const spotMarketAccountInfos = await connection.getMultipleAccountsInfo(spotMarketPublicKeys);
106
+ const spotMarketPublicKeysChunks = this.chunks(spotMarketPublicKeys, 75);
107
+ const spotMarketAccountInfos = (await Promise.all(spotMarketPublicKeysChunks.map((spotMarketPublicKeysChunk) => connection.getMultipleAccountsInfo(spotMarketPublicKeysChunk)))).flat();
100
108
  this.initialSpotMarketAccountData = new Map(spotMarketAccountInfos
101
109
  .filter((accountInfo) => !!accountInfo)
102
110
  .map((accountInfo) => {
@@ -104,7 +112,8 @@ class WebSocketDriftClientAccountSubscriber {
104
112
  return [spotMarket.marketIndex, spotMarket];
105
113
  }));
106
114
  }
107
- const oracleAccountInfos = await connection.getMultipleAccountsInfo(this.oracleInfos.map((oracleInfo) => oracleInfo.publicKey));
115
+ const oracleAccountPubkeyChunks = this.chunks(this.oracleInfos.map((oracleInfo) => oracleInfo.publicKey), 75);
116
+ const oracleAccountInfos = (await Promise.all(oracleAccountPubkeyChunks.map((oracleAccountPublicKeysChunk) => connection.getMultipleAccountsInfo(oracleAccountPublicKeysChunk)))).flat();
108
117
  this.initialOraclePriceData = new Map(this.oracleInfos.reduce((result, oracleInfo, i) => {
109
118
  if (!oracleAccountInfos[i]) {
110
119
  return result;
@@ -1073,9 +1073,21 @@ exports.MainnetPerpMarkets = [
1073
1073
  symbol: 'TRUMP-PERP',
1074
1074
  baseAssetSymbol: 'TRUMP',
1075
1075
  marketIndex: 64,
1076
- oracle: new web3_js_1.PublicKey('FgPVZKJQyoCyDgu1aFzgfbSFFySX8Y9hX1Gp6zJpUug3'),
1076
+ oracle: new web3_js_1.PublicKey('AmSLxftd19EPDR9NnZDxvdStqtRW7k9zWto7FfGaz24K'),
1077
1077
  launchTs: 1737219250000,
1078
- oracleSource: __1.OracleSource.SWITCHBOARD_ON_DEMAND,
1078
+ oracleSource: __1.OracleSource.PYTH_PULL,
1079
+ pythFeedId: '0x879551021853eec7a7dc827578e8e69da7e4fa8148339aa0d3d5296405be4b1a',
1080
+ },
1081
+ {
1082
+ fullName: 'MELANIA',
1083
+ category: ['Meme'],
1084
+ symbol: 'MELANIA-PERP',
1085
+ baseAssetSymbol: 'MELANIA',
1086
+ marketIndex: 65,
1087
+ oracle: new web3_js_1.PublicKey('28Zk42cxbg4MxiTewSwoedvW6MUgjoVHSTvTW7zQ7ESi'),
1088
+ launchTs: 1737360280000,
1089
+ oracleSource: __1.OracleSource.PYTH_PULL,
1090
+ pythFeedId: '0x8fef7d52c7f4e3a6258d663f9d27e64a1b6fd95ab5f7d545dbf9a515353d0064',
1079
1091
  },
1080
1092
  ];
1081
1093
  exports.PerpMarkets = {
@@ -548,13 +548,26 @@ exports.MainnetSpotMarkets = [
548
548
  symbol: 'TRUMP',
549
549
  marketIndex: 36,
550
550
  poolId: 0,
551
- oracle: new web3_js_1.PublicKey('FgPVZKJQyoCyDgu1aFzgfbSFFySX8Y9hX1Gp6zJpUug3'),
552
- oracleSource: __1.OracleSource.SWITCHBOARD_ON_DEMAND,
551
+ oracle: new web3_js_1.PublicKey('AmSLxftd19EPDR9NnZDxvdStqtRW7k9zWto7FfGaz24K'),
552
+ oracleSource: __1.OracleSource.PYTH_PULL,
553
553
  mint: new web3_js_1.PublicKey('6p6xgHyF7AeE6TZkSmFsko444wqoP15icUSqi2jfGiPN'),
554
554
  precision: new __1.BN(10).pow(numericConstants_1.SIX),
555
555
  precisionExp: numericConstants_1.SIX,
556
+ pythFeedId: '0x879551021853eec7a7dc827578e8e69da7e4fa8148339aa0d3d5296405be4b1a',
556
557
  launchTs: 1737219250000,
557
558
  },
559
+ {
560
+ symbol: 'MELANIA',
561
+ marketIndex: 37,
562
+ poolId: 0,
563
+ oracle: new web3_js_1.PublicKey('28Zk42cxbg4MxiTewSwoedvW6MUgjoVHSTvTW7zQ7ESi'),
564
+ oracleSource: __1.OracleSource.PYTH_PULL,
565
+ mint: new web3_js_1.PublicKey('FUAfBo2jgks6gB4Z4LfZkqSZgzNucisEHqnNebaRxM1P'),
566
+ precision: new __1.BN(10).pow(numericConstants_1.SIX),
567
+ precisionExp: numericConstants_1.SIX,
568
+ pythFeedId: '0x8fef7d52c7f4e3a6258d663f9d27e64a1b6fd95ab5f7d545dbf9a515353d0064',
569
+ launchTs: 1737360280000,
570
+ },
558
571
  ];
559
572
  exports.SpotMarkets = {
560
573
  devnet: exports.DevnetSpotMarkets,
@@ -54,7 +54,8 @@ export declare class DLOB {
54
54
  orderLists: Map<MarketTypeStr, Map<number, MarketNodeLists>>;
55
55
  maxSlotForRestingLimitOrders: number;
56
56
  initialized: boolean;
57
- constructor();
57
+ protectedMakerView: boolean;
58
+ constructor(protectedMakerView?: boolean);
58
59
  private init;
59
60
  clear(): void;
60
61
  /**
@@ -14,11 +14,12 @@ const SUPPORTED_ORDER_TYPES = [
14
14
  'oracle',
15
15
  ];
16
16
  class DLOB {
17
- constructor() {
17
+ constructor(protectedMakerView) {
18
18
  this.openOrders = new Map();
19
19
  this.orderLists = new Map();
20
20
  this.maxSlotForRestingLimitOrders = 0;
21
21
  this.initialized = false;
22
+ this.protectedMakerView = protectedMakerView || false;
22
23
  this.init();
23
24
  }
24
25
  init() {
@@ -373,7 +374,7 @@ class DLOB {
373
374
  if (sameUser) {
374
375
  continue;
375
376
  }
376
- const makerPrice = makerNode.getPrice(oraclePriceData, slot);
377
+ const makerPrice = makerNode.getPrice(oraclePriceData, slot, this.protectedMakerView);
377
378
  const takerPrice = takerNode.getPrice(oraclePriceData, slot);
378
379
  const ordersCross = doesCross(takerPrice, makerPrice);
379
380
  if (!ordersCross) {
@@ -571,8 +572,8 @@ class DLOB {
571
572
  ];
572
573
  yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
573
574
  return bestNode
574
- .getPrice(oraclePriceData, slot)
575
- .lt(currentNode.getPrice(oraclePriceData, slot));
575
+ .getPrice(oraclePriceData, slot, this.protectedMakerView)
576
+ .lt(currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView));
576
577
  }, filterFcn);
577
578
  }
578
579
  *getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData, filterFcn) {
@@ -591,8 +592,8 @@ class DLOB {
591
592
  ];
592
593
  yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
593
594
  return bestNode
594
- .getPrice(oraclePriceData, slot)
595
- .gt(currentNode.getPrice(oraclePriceData, slot));
595
+ .getPrice(oraclePriceData, slot, this.protectedMakerView)
596
+ .gt(currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView));
596
597
  }, filterFcn);
597
598
  }
598
599
  /**
@@ -614,8 +615,8 @@ class DLOB {
614
615
  ];
615
616
  yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
616
617
  var _a, _b;
617
- const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot)) !== null && _a !== void 0 ? _a : __1.ZERO;
618
- const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot)) !== null && _b !== void 0 ? _b : __1.ZERO;
618
+ const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot, this.protectedMakerView)) !== null && _a !== void 0 ? _a : __1.ZERO;
619
+ const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView)) !== null && _b !== void 0 ? _b : __1.ZERO;
619
620
  if (bestNodePrice.eq(currentNodePrice)) {
620
621
  return bestNode.order.slot.lt(currentNode.order.slot);
621
622
  }
@@ -641,8 +642,8 @@ class DLOB {
641
642
  ];
642
643
  yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
643
644
  var _a, _b;
644
- const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot)) !== null && _a !== void 0 ? _a : __1.BN_MAX;
645
- const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot)) !== null && _b !== void 0 ? _b : __1.BN_MAX;
645
+ const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot, this.protectedMakerView)) !== null && _a !== void 0 ? _a : __1.BN_MAX;
646
+ const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView)) !== null && _b !== void 0 ? _b : __1.BN_MAX;
646
647
  if (bestNodePrice.eq(currentNodePrice)) {
647
648
  return bestNode.order.slot.lt(currentNode.order.slot);
648
649
  }
@@ -654,8 +655,8 @@ class DLOB {
654
655
  for (const askNode of this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData)) {
655
656
  const bidGenerator = this.getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData);
656
657
  for (const bidNode of bidGenerator) {
657
- const bidPrice = bidNode.getPrice(oraclePriceData, slot);
658
- const askPrice = askNode.getPrice(oraclePriceData, slot);
658
+ const bidPrice = bidNode.getPrice(oraclePriceData, slot, this.protectedMakerView);
659
+ const askPrice = askNode.getPrice(oraclePriceData, slot, this.protectedMakerView);
659
660
  // orders don't cross
660
661
  if (bidPrice.lt(askPrice)) {
661
662
  break;
@@ -730,7 +731,7 @@ class DLOB {
730
731
  getBestAsk(marketIndex, slot, marketType, oraclePriceData) {
731
732
  const bestAsk = this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData).next().value;
732
733
  if (bestAsk) {
733
- return bestAsk.getPrice(oraclePriceData, slot);
734
+ return bestAsk.getPrice(oraclePriceData, slot, this.protectedMakerView);
734
735
  }
735
736
  return undefined;
736
737
  }
@@ -1,7 +1,7 @@
1
1
  /// <reference types="bn.js" />
2
2
  import { BN, OraclePriceData, Order } from '..';
3
3
  export interface DLOBNode {
4
- getPrice(oraclePriceData: OraclePriceData, slot: number): BN;
4
+ getPrice(oraclePriceData: OraclePriceData, slot: number, protectedMakerView?: boolean): BN;
5
5
  isVammNode(): boolean;
6
6
  order: Order | undefined;
7
7
  isBaseFilled(): boolean;
@@ -21,7 +21,7 @@ export declare abstract class OrderNode implements DLOBNode {
21
21
  constructor(order: Order, userAccount: string, isUserProtectedMaker: boolean, isSwift?: boolean);
22
22
  abstract getSortValue(order: Order): BN;
23
23
  getLabel(): string;
24
- getPrice(oraclePriceData: OraclePriceData, slot: number): BN;
24
+ getPrice(oraclePriceData: OraclePriceData, slot: number, protectedMakerView?: boolean): BN;
25
25
  isBaseFilled(): boolean;
26
26
  isVammNode(): boolean;
27
27
  }
@@ -28,8 +28,8 @@ class OrderNode {
28
28
  }
29
29
  return msg;
30
30
  }
31
- getPrice(oraclePriceData, slot) {
32
- return (0, __1.getLimitPrice)(this.order, oraclePriceData, slot);
31
+ getPrice(oraclePriceData, slot, protectedMakerView) {
32
+ return (0, __1.getLimitPrice)(this.order, oraclePriceData, slot, undefined, protectedMakerView && this.isUserProtectedMaker);
33
33
  }
34
34
  isBaseFilled() {
35
35
  return this.order.baseAssetAmountFilled.eq(this.order.baseAssetAmount);
@@ -15,6 +15,7 @@ export declare class DLOBSubscriber {
15
15
  intervalId?: NodeJS.Timeout;
16
16
  dlob: DLOB;
17
17
  eventEmitter: StrictEventEmitter<EventEmitter, DLOBSubscriberEvents>;
18
+ protectedMakerView: boolean;
18
19
  constructor(config: DLOBSubscriptionConfig);
19
20
  subscribe(): Promise<void>;
20
21
  updateDLOB(): Promise<void>;
@@ -7,11 +7,12 @@ const types_1 = require("../types");
7
7
  const orderBookLevels_1 = require("./orderBookLevels");
8
8
  class DLOBSubscriber {
9
9
  constructor(config) {
10
- this.dlob = new DLOB_1.DLOB();
11
10
  this.driftClient = config.driftClient;
12
11
  this.dlobSource = config.dlobSource;
13
12
  this.slotSource = config.slotSource;
14
13
  this.updateFrequency = config.updateFrequency;
14
+ this.protectedMakerView = config.protectedMakerView || false;
15
+ this.dlob = new DLOB_1.DLOB(this.protectedMakerView);
15
16
  this.eventEmitter = new events_1.EventEmitter();
16
17
  }
17
18
  async subscribe() {
@@ -30,7 +31,7 @@ class DLOBSubscriber {
30
31
  }, this.updateFrequency);
31
32
  }
32
33
  async updateDLOB() {
33
- this.dlob = await this.dlobSource.getDLOB(this.slotSource.getSlot());
34
+ this.dlob = await this.dlobSource.getDLOB(this.slotSource.getSlot(), this.protectedMakerView);
34
35
  }
35
36
  getDLOB() {
36
37
  return this.dlob;
@@ -5,13 +5,14 @@ export type DLOBSubscriptionConfig = {
5
5
  dlobSource: DLOBSource;
6
6
  slotSource: SlotSource;
7
7
  updateFrequency: number;
8
+ protectedMakerView?: boolean;
8
9
  };
9
10
  export interface DLOBSubscriberEvents {
10
11
  update: (dlob: DLOB) => void;
11
12
  error: (e: Error) => void;
12
13
  }
13
14
  export interface DLOBSource {
14
- getDLOB(slot: number): Promise<DLOB>;
15
+ getDLOB(slot: number, protectedMakerView?: boolean): Promise<DLOB>;
15
16
  }
16
17
  export interface SlotSource {
17
18
  getSlot(): number;
@@ -70,6 +70,7 @@ const on_demand_1 = require("@switchboard-xyz/on-demand");
70
70
  const grpcDriftClientAccountSubscriber_1 = require("./accounts/grpcDriftClientAccountSubscriber");
71
71
  const tweetnacl_1 = __importDefault(require("tweetnacl"));
72
72
  const oracleId_1 = require("./oracles/oracleId");
73
+ const sha256_1 = require("@noble/hashes/sha256");
73
74
  /**
74
75
  * # DriftClient
75
76
  * This class is the main way to interact with Drift Protocol. It allows you to subscribe to the various accounts where the Market's state is stored, as well as: opening positions, liquidating, settling funding, depositing & withdrawing, and more.
@@ -3185,13 +3186,20 @@ class DriftClient {
3185
3186
  * Borsh encode swift taker order params
3186
3187
  */
3187
3188
  encodeSwiftOrderParamsMessage(orderParamsMessage) {
3188
- return this.program.coder.types.encode('SwiftOrderParamsMessage', orderParamsMessage);
3189
+ const anchorIxName = 'global' + ':' + 'swiftOrderMessageParams';
3190
+ const prefix = Buffer.from((0, sha256_1.sha256)(anchorIxName).slice(0, 8));
3191
+ const buf = Buffer.concat([
3192
+ prefix,
3193
+ this.program.coder.types.encode('SwiftOrderParamsMessage', orderParamsMessage),
3194
+ ]);
3195
+ return buf;
3189
3196
  }
3190
3197
  /*
3191
3198
  * Decode swift taker order params from borsh buffer
3192
3199
  */
3193
3200
  decodeSwiftOrderParamsMessage(encodedMessage) {
3194
- return this.program.coder.types.decode('SwiftOrderParamsMessage', encodedMessage);
3201
+ return this.program.coder.types.decode('SwiftOrderParamsMessage', encodedMessage.slice(8) // assumes discriminator
3202
+ );
3195
3203
  }
3196
3204
  signMessage(message, keypair = this.wallet.payer) {
3197
3205
  return Buffer.from(tweetnacl_1.default.sign.detached(message, keypair.secretKey));
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.106.0",
2
+ "version": "2.107.0",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
@@ -10,6 +10,16 @@ import { OraclePriceData } from '../oracles/types';
10
10
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
11
11
  */
12
12
  export declare function calculateAllEstimatedFundingRate(market: PerpMarketAccount, oraclePriceData?: OraclePriceData, markPrice?: BN, now?: BN): Promise<[BN, BN, BN, BN, BN]>;
13
+ /**
14
+ * Calculate funding rates in human-readable form. Values will have some lost precision and shouldn't be used in strict accounting.
15
+ * @param period : 'hour' | 'year' :: Use 'hour' for the hourly payment as a percentage, 'year' for the payment as an estimated APR.
16
+ */
17
+ export declare function calculateFormattedLiveFundingRate(market: PerpMarketAccount, oraclePriceData: OraclePriceData, period: 'hour' | 'year'): Promise<{
18
+ longRate: number;
19
+ shortRate: number;
20
+ fundingRateUnit: string;
21
+ formattedFundingRateSummary: string;
22
+ }>;
13
23
  /**
14
24
  *
15
25
  * @param market
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateFundingPool = exports.calculateLongShortFundingRateAndLiveTwaps = exports.calculateLongShortFundingRate = exports.calculateAllEstimatedFundingRate = void 0;
3
+ exports.calculateFundingPool = exports.calculateLongShortFundingRateAndLiveTwaps = exports.calculateLongShortFundingRate = exports.calculateFormattedLiveFundingRate = exports.calculateAllEstimatedFundingRate = void 0;
4
4
  const anchor_1 = require("@coral-xyz/anchor");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
+ const bigNum_1 = require("../factory/bigNum");
6
7
  const types_1 = require("../types");
7
8
  const amm_1 = require("./amm");
8
9
  const oracles_1 = require("./oracles");
9
10
  const utils_1 = require("./utils");
11
+ const numericConstants_2 = require("../constants/numericConstants");
10
12
  function calculateLiveMarkTwap(market, oraclePriceData, markPrice, now, period = new anchor_1.BN(3600)) {
11
13
  now = now || new anchor_1.BN((Date.now() / 1000).toFixed(0));
12
14
  const lastMarkTwapWithMantissa = market.amm.lastMarkPriceTwap;
@@ -138,6 +140,50 @@ async function calculateAllEstimatedFundingRate(market, oraclePriceData, markPri
138
140
  return [markTwap, oracleTwap, lowerboundEst, cappedAltEst, interpEst];
139
141
  }
140
142
  exports.calculateAllEstimatedFundingRate = calculateAllEstimatedFundingRate;
143
+ /**
144
+ * To get funding rate as a percentage, you need to multiply by the funding rate buffer precision
145
+ * @param rawFundingRate
146
+ * @returns
147
+ */
148
+ const getFundingRatePct = (rawFundingRate) => {
149
+ return bigNum_1.BigNum.from(rawFundingRate.mul(numericConstants_2.FUNDING_RATE_BUFFER_PRECISION), numericConstants_2.FUNDING_RATE_PRECISION_EXP).toNum();
150
+ };
151
+ /**
152
+ * Calculate funding rates in human-readable form. Values will have some lost precision and shouldn't be used in strict accounting.
153
+ * @param period : 'hour' | 'year' :: Use 'hour' for the hourly payment as a percentage, 'year' for the payment as an estimated APR.
154
+ */
155
+ async function calculateFormattedLiveFundingRate(market, oraclePriceData, period) {
156
+ const nowBN = new anchor_1.BN(Date.now() / 1000);
157
+ const [_markTwapLive, _oracleTwapLive, longFundingRate, shortFundingRate] = await calculateLongShortFundingRateAndLiveTwaps(market, oraclePriceData, undefined, nowBN);
158
+ let longFundingRateNum = getFundingRatePct(longFundingRate);
159
+ let shortFundingRateNum = getFundingRatePct(shortFundingRate);
160
+ if (period == 'year') {
161
+ const paymentsPerYear = 24 * 365.25;
162
+ longFundingRateNum *= paymentsPerYear;
163
+ shortFundingRateNum *= paymentsPerYear;
164
+ }
165
+ const longsArePaying = longFundingRateNum > 0;
166
+ const shortsArePaying = !(shortFundingRateNum > 0);
167
+ const longsAreString = longsArePaying ? 'pay' : 'receive';
168
+ const shortsAreString = !shortsArePaying ? 'receive' : 'pay';
169
+ const absoluteLongFundingRateNum = Math.abs(longFundingRateNum);
170
+ const absoluteShortFundingRateNum = Math.abs(shortFundingRateNum);
171
+ const formattedLongRatePct = absoluteLongFundingRateNum.toFixed(period == 'hour' ? 5 : 2);
172
+ const formattedShortRatePct = absoluteShortFundingRateNum.toFixed(period == 'hour' ? 5 : 2);
173
+ const fundingRateUnit = period == 'year' ? '% APR' : '%';
174
+ const formattedFundingRateSummary = `At this rate, longs would ${longsAreString} ${formattedLongRatePct} ${fundingRateUnit} and shorts would ${shortsAreString} ${formattedShortRatePct} ${fundingRateUnit} at the end of the hour.`;
175
+ return {
176
+ longRate: longsArePaying
177
+ ? -absoluteLongFundingRateNum
178
+ : absoluteLongFundingRateNum,
179
+ shortRate: shortsArePaying
180
+ ? -absoluteShortFundingRateNum
181
+ : absoluteShortFundingRateNum,
182
+ fundingRateUnit: fundingRateUnit,
183
+ formattedFundingRateSummary,
184
+ };
185
+ }
186
+ exports.calculateFormattedLiveFundingRate = calculateFormattedLiveFundingRate;
141
187
  function getMaxPriceDivergenceForFundingRate(market, oracleTwap) {
142
188
  if ((0, types_1.isVariant)(market.contractTier, 'a')) {
143
189
  return oracleTwap.divn(33);
@@ -8,7 +8,7 @@ export declare function isOrderRiskIncreasingInSameDirection(user: User, order:
8
8
  export declare function isOrderReduceOnly(user: User, order: Order): boolean;
9
9
  export declare function standardizeBaseAssetAmount(baseAssetAmount: BN, stepSize: BN): BN;
10
10
  export declare function standardizePrice(price: BN, tickSize: BN, direction: PositionDirection): BN;
11
- export declare function getLimitPrice(order: Order, oraclePriceData: OraclePriceData, slot: number, fallbackPrice?: BN): BN | undefined;
11
+ export declare function getLimitPrice(order: Order, oraclePriceData: OraclePriceData, slot: number, fallbackPrice?: BN, protectedMaker?: boolean): BN | undefined;
12
12
  export declare function hasLimitPrice(order: Order, slot: number): boolean;
13
13
  export declare function hasAuctionPrice(order: Order, slot: number): boolean;
14
14
  export declare function isFillableByVAMM(order: Order, market: PerpMarketAccount, oraclePriceData: OraclePriceData, slot: number, ts: number, minAuctionDuration: number): boolean;
@@ -96,7 +96,7 @@ function standardizePrice(price, tickSize, direction) {
96
96
  }
97
97
  }
98
98
  exports.standardizePrice = standardizePrice;
99
- function getLimitPrice(order, oraclePriceData, slot, fallbackPrice) {
99
+ function getLimitPrice(order, oraclePriceData, slot, fallbackPrice, protectedMaker) {
100
100
  let limitPrice;
101
101
  if (hasAuctionPrice(order, slot)) {
102
102
  limitPrice = (0, auction_1.getAuctionPrice)(order, slot, oraclePriceData.price);
@@ -110,6 +110,15 @@ function getLimitPrice(order, oraclePriceData, slot, fallbackPrice) {
110
110
  else {
111
111
  limitPrice = order.price;
112
112
  }
113
+ if (protectedMaker) {
114
+ const offset = limitPrice.divn(1000);
115
+ if ((0, types_1.isVariant)(order.direction, 'long')) {
116
+ limitPrice = limitPrice.sub(offset);
117
+ }
118
+ else {
119
+ limitPrice = limitPrice.add(offset);
120
+ }
121
+ }
113
122
  return limitPrice;
114
123
  }
115
124
  exports.getLimitPrice = getLimitPrice;
@@ -35,8 +35,8 @@ export declare class OrderSubscriber {
35
35
  * caller to extend the DLOB Subscriber with a custom DLOB type.
36
36
  * @returns New, empty DLOB object.
37
37
  */
38
- protected createDLOB(): DLOB;
39
- getDLOB(slot: number): Promise<DLOB>;
38
+ protected createDLOB(protectedMakerView?: boolean): DLOB;
39
+ getDLOB(slot: number, protectedMakerView?: boolean): Promise<DLOB>;
40
40
  getSlot(): number;
41
41
  unsubscribe(): Promise<void>;
42
42
  }
@@ -147,11 +147,11 @@ class OrderSubscriber {
147
147
  * caller to extend the DLOB Subscriber with a custom DLOB type.
148
148
  * @returns New, empty DLOB object.
149
149
  */
150
- createDLOB() {
151
- return new DLOB_1.DLOB();
150
+ createDLOB(protectedMakerView) {
151
+ return new DLOB_1.DLOB(protectedMakerView);
152
152
  }
153
- async getDLOB(slot) {
154
- const dlob = this.createDLOB();
153
+ async getDLOB(slot, protectedMakerView) {
154
+ const dlob = this.createDLOB(protectedMakerView);
155
155
  for (const [key, { userAccount }] of this.usersAccounts.entries()) {
156
156
  const protectedMaker = (0, userStatus_1.isUserProtectedMaker)(userAccount);
157
157
  for (const order of userAccount.orders) {
@@ -66,7 +66,7 @@ export declare class UserMap implements UserMapInterface {
66
66
  * create a DLOB from all the subscribed users
67
67
  * @param slot
68
68
  */
69
- getDLOB(slot: number): Promise<DLOB>;
69
+ getDLOB(slot: number, protectedMakerView?: boolean): Promise<DLOB>;
70
70
  updateWithOrderRecord(record: OrderRecord): Promise<void>;
71
71
  updateWithEventRecord(record: WrappedEvent<any>): Promise<void>;
72
72
  values(): IterableIterator<User>;
@@ -165,8 +165,8 @@ class UserMap {
165
165
  * create a DLOB from all the subscribed users
166
166
  * @param slot
167
167
  */
168
- async getDLOB(slot) {
169
- const dlob = new __1.DLOB();
168
+ async getDLOB(slot, protectedMakerView) {
169
+ const dlob = new __1.DLOB(protectedMakerView);
170
170
  await dlob.initFromUserMap(this, slot);
171
171
  return dlob;
172
172
  }
@@ -35,6 +35,7 @@ export declare class WebSocketDriftClientAccountSubscriber implements DriftClien
35
35
  protected subscriptionPromiseResolver: (val: boolean) => void;
36
36
  constructor(program: Program, perpMarketIndexes: number[], spotMarketIndexes: number[], oracleInfos: OracleInfo[], shouldFindAllMarketsAndOracles: boolean, delistedMarketSetting: DelistedMarketSetting, resubOpts?: ResubOpts, commitment?: Commitment);
37
37
  subscribe(): Promise<boolean>;
38
+ chunks: <T>(array: readonly T[], size: number) => T[][];
38
39
  setInitialData(): Promise<void>;
39
40
  removeInitialData(): void;
40
41
  subscribeToPerpMarketAccounts(): Promise<boolean>;
@@ -24,6 +24,12 @@ class WebSocketDriftClientAccountSubscriber {
24
24
  this.spotOracleStringMap = new Map();
25
25
  this.oracleSubscribers = new Map();
26
26
  this.isSubscribing = false;
27
+ this.chunks = (array, size) => {
28
+ return new Array(Math.ceil(array.length / size))
29
+ .fill(null)
30
+ .map((_, index) => index * size)
31
+ .map((begin) => array.slice(begin, begin + size));
32
+ };
27
33
  this.isSubscribed = false;
28
34
  this.program = program;
29
35
  this.eventEmitter = new events_1.EventEmitter();
@@ -86,7 +92,8 @@ class WebSocketDriftClientAccountSubscriber {
86
92
  const connection = this.program.provider.connection;
87
93
  if (!this.initialPerpMarketAccountData) {
88
94
  const perpMarketPublicKeys = this.perpMarketIndexes.map((marketIndex) => (0, pda_1.getPerpMarketPublicKeySync)(this.program.programId, marketIndex));
89
- const perpMarketAccountInfos = await connection.getMultipleAccountsInfo(perpMarketPublicKeys);
95
+ const perpMarketPublicKeysChunks = this.chunks(perpMarketPublicKeys, 75);
96
+ const perpMarketAccountInfos = (await Promise.all(perpMarketPublicKeysChunks.map((perpMarketPublicKeysChunk) => connection.getMultipleAccountsInfo(perpMarketPublicKeysChunk)))).flat();
90
97
  this.initialPerpMarketAccountData = new Map(perpMarketAccountInfos
91
98
  .filter((accountInfo) => !!accountInfo)
92
99
  .map((accountInfo) => {
@@ -96,7 +103,8 @@ class WebSocketDriftClientAccountSubscriber {
96
103
  }
97
104
  if (!this.initialSpotMarketAccountData) {
98
105
  const spotMarketPublicKeys = this.spotMarketIndexes.map((marketIndex) => (0, pda_1.getSpotMarketPublicKeySync)(this.program.programId, marketIndex));
99
- const spotMarketAccountInfos = await connection.getMultipleAccountsInfo(spotMarketPublicKeys);
106
+ const spotMarketPublicKeysChunks = this.chunks(spotMarketPublicKeys, 75);
107
+ const spotMarketAccountInfos = (await Promise.all(spotMarketPublicKeysChunks.map((spotMarketPublicKeysChunk) => connection.getMultipleAccountsInfo(spotMarketPublicKeysChunk)))).flat();
100
108
  this.initialSpotMarketAccountData = new Map(spotMarketAccountInfos
101
109
  .filter((accountInfo) => !!accountInfo)
102
110
  .map((accountInfo) => {
@@ -104,7 +112,8 @@ class WebSocketDriftClientAccountSubscriber {
104
112
  return [spotMarket.marketIndex, spotMarket];
105
113
  }));
106
114
  }
107
- const oracleAccountInfos = await connection.getMultipleAccountsInfo(this.oracleInfos.map((oracleInfo) => oracleInfo.publicKey));
115
+ const oracleAccountPubkeyChunks = this.chunks(this.oracleInfos.map((oracleInfo) => oracleInfo.publicKey), 75);
116
+ const oracleAccountInfos = (await Promise.all(oracleAccountPubkeyChunks.map((oracleAccountPublicKeysChunk) => connection.getMultipleAccountsInfo(oracleAccountPublicKeysChunk)))).flat();
108
117
  this.initialOraclePriceData = new Map(this.oracleInfos.reduce((result, oracleInfo, i) => {
109
118
  if (!oracleAccountInfos[i]) {
110
119
  return result;
@@ -1073,9 +1073,21 @@ exports.MainnetPerpMarkets = [
1073
1073
  symbol: 'TRUMP-PERP',
1074
1074
  baseAssetSymbol: 'TRUMP',
1075
1075
  marketIndex: 64,
1076
- oracle: new web3_js_1.PublicKey('FgPVZKJQyoCyDgu1aFzgfbSFFySX8Y9hX1Gp6zJpUug3'),
1076
+ oracle: new web3_js_1.PublicKey('AmSLxftd19EPDR9NnZDxvdStqtRW7k9zWto7FfGaz24K'),
1077
1077
  launchTs: 1737219250000,
1078
- oracleSource: __1.OracleSource.SWITCHBOARD_ON_DEMAND,
1078
+ oracleSource: __1.OracleSource.PYTH_PULL,
1079
+ pythFeedId: '0x879551021853eec7a7dc827578e8e69da7e4fa8148339aa0d3d5296405be4b1a',
1080
+ },
1081
+ {
1082
+ fullName: 'MELANIA',
1083
+ category: ['Meme'],
1084
+ symbol: 'MELANIA-PERP',
1085
+ baseAssetSymbol: 'MELANIA',
1086
+ marketIndex: 65,
1087
+ oracle: new web3_js_1.PublicKey('28Zk42cxbg4MxiTewSwoedvW6MUgjoVHSTvTW7zQ7ESi'),
1088
+ launchTs: 1737360280000,
1089
+ oracleSource: __1.OracleSource.PYTH_PULL,
1090
+ pythFeedId: '0x8fef7d52c7f4e3a6258d663f9d27e64a1b6fd95ab5f7d545dbf9a515353d0064',
1079
1091
  },
1080
1092
  ];
1081
1093
  exports.PerpMarkets = {
@@ -548,13 +548,26 @@ exports.MainnetSpotMarkets = [
548
548
  symbol: 'TRUMP',
549
549
  marketIndex: 36,
550
550
  poolId: 0,
551
- oracle: new web3_js_1.PublicKey('FgPVZKJQyoCyDgu1aFzgfbSFFySX8Y9hX1Gp6zJpUug3'),
552
- oracleSource: __1.OracleSource.SWITCHBOARD_ON_DEMAND,
551
+ oracle: new web3_js_1.PublicKey('AmSLxftd19EPDR9NnZDxvdStqtRW7k9zWto7FfGaz24K'),
552
+ oracleSource: __1.OracleSource.PYTH_PULL,
553
553
  mint: new web3_js_1.PublicKey('6p6xgHyF7AeE6TZkSmFsko444wqoP15icUSqi2jfGiPN'),
554
554
  precision: new __1.BN(10).pow(numericConstants_1.SIX),
555
555
  precisionExp: numericConstants_1.SIX,
556
+ pythFeedId: '0x879551021853eec7a7dc827578e8e69da7e4fa8148339aa0d3d5296405be4b1a',
556
557
  launchTs: 1737219250000,
557
558
  },
559
+ {
560
+ symbol: 'MELANIA',
561
+ marketIndex: 37,
562
+ poolId: 0,
563
+ oracle: new web3_js_1.PublicKey('28Zk42cxbg4MxiTewSwoedvW6MUgjoVHSTvTW7zQ7ESi'),
564
+ oracleSource: __1.OracleSource.PYTH_PULL,
565
+ mint: new web3_js_1.PublicKey('FUAfBo2jgks6gB4Z4LfZkqSZgzNucisEHqnNebaRxM1P'),
566
+ precision: new __1.BN(10).pow(numericConstants_1.SIX),
567
+ precisionExp: numericConstants_1.SIX,
568
+ pythFeedId: '0x8fef7d52c7f4e3a6258d663f9d27e64a1b6fd95ab5f7d545dbf9a515353d0064',
569
+ launchTs: 1737360280000,
570
+ },
558
571
  ];
559
572
  exports.SpotMarkets = {
560
573
  devnet: exports.DevnetSpotMarkets,
@@ -54,7 +54,8 @@ export declare class DLOB {
54
54
  orderLists: Map<MarketTypeStr, Map<number, MarketNodeLists>>;
55
55
  maxSlotForRestingLimitOrders: number;
56
56
  initialized: boolean;
57
- constructor();
57
+ protectedMakerView: boolean;
58
+ constructor(protectedMakerView?: boolean);
58
59
  private init;
59
60
  clear(): void;
60
61
  /**