@drift-labs/sdk 2.130.0-beta.14 → 2.130.0-beta.16

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 (51) hide show
  1. package/VERSION +1 -1
  2. package/lib/browser/accounts/grpcAccountSubscriber.d.ts +1 -0
  3. package/lib/browser/accounts/grpcAccountSubscriber.js +16 -12
  4. package/lib/browser/accounts/grpcProgramAccountSubscriber.d.ts +1 -0
  5. package/lib/browser/accounts/grpcProgramAccountSubscriber.js +16 -12
  6. package/lib/browser/accounts/types.d.ts +5 -0
  7. package/lib/browser/adminClient.d.ts +2 -2
  8. package/lib/browser/adminClient.js +14 -14
  9. package/lib/browser/dlob/DLOB.d.ts +1 -1
  10. package/lib/browser/dlob/DLOB.js +3 -3
  11. package/lib/browser/idl/drift.json +40 -7
  12. package/lib/browser/math/market.d.ts +10 -0
  13. package/lib/browser/math/market.js +76 -1
  14. package/lib/browser/math/state.d.ts +1 -0
  15. package/lib/browser/math/state.js +6 -1
  16. package/lib/browser/types.d.ts +7 -0
  17. package/lib/browser/types.js +6 -1
  18. package/lib/node/accounts/grpcAccountSubscriber.d.ts +1 -0
  19. package/lib/node/accounts/grpcAccountSubscriber.d.ts.map +1 -1
  20. package/lib/node/accounts/grpcAccountSubscriber.js +16 -12
  21. package/lib/node/accounts/grpcProgramAccountSubscriber.d.ts +1 -0
  22. package/lib/node/accounts/grpcProgramAccountSubscriber.d.ts.map +1 -1
  23. package/lib/node/accounts/grpcProgramAccountSubscriber.js +16 -12
  24. package/lib/node/accounts/types.d.ts +5 -0
  25. package/lib/node/accounts/types.d.ts.map +1 -1
  26. package/lib/node/adminClient.d.ts +2 -2
  27. package/lib/node/adminClient.d.ts.map +1 -1
  28. package/lib/node/adminClient.js +14 -14
  29. package/lib/node/dlob/DLOB.d.ts +1 -1
  30. package/lib/node/dlob/DLOB.d.ts.map +1 -1
  31. package/lib/node/dlob/DLOB.js +3 -3
  32. package/lib/node/idl/drift.json +40 -7
  33. package/lib/node/math/market.d.ts +10 -0
  34. package/lib/node/math/market.d.ts.map +1 -1
  35. package/lib/node/math/market.js +76 -1
  36. package/lib/node/math/state.d.ts +1 -0
  37. package/lib/node/math/state.d.ts.map +1 -1
  38. package/lib/node/math/state.js +6 -1
  39. package/lib/node/types.d.ts +7 -0
  40. package/lib/node/types.d.ts.map +1 -1
  41. package/lib/node/types.js +6 -1
  42. package/package.json +1 -1
  43. package/src/accounts/grpcAccountSubscriber.ts +24 -11
  44. package/src/accounts/grpcProgramAccountSubscriber.ts +26 -11
  45. package/src/accounts/types.ts +5 -0
  46. package/src/adminClient.ts +29 -27
  47. package/src/dlob/DLOB.ts +3 -3
  48. package/src/idl/drift.json +40 -7
  49. package/src/math/market.ts +105 -0
  50. package/src/math/state.ts +7 -1
  51. package/src/types.ts +9 -0
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.130.0-beta.14
1
+ 2.130.0-beta.16
@@ -9,6 +9,7 @@ export declare class grpcAccountSubscriber<T> extends WebSocketAccountSubscriber
9
9
  private stream;
10
10
  private commitmentLevel;
11
11
  listenerId?: number;
12
+ private enableReconnect;
12
13
  private constructor();
13
14
  static create<U>(grpcConfigs: GrpcConfigs, accountName: string, program: Program, accountPublicKey: PublicKey, decodeBuffer?: (buffer: Buffer) => U, resubOpts?: ResubOpts): Promise<grpcAccountSubscriber<U>>;
14
15
  subscribe(onChange: (data: T) => void): Promise<void>;
@@ -29,10 +29,11 @@ const Buffer = __importStar(require("buffer"));
29
29
  const webSocketAccountSubscriber_1 = require("./webSocketAccountSubscriber");
30
30
  const grpc_1 = require("../isomorphic/grpc");
31
31
  class grpcAccountSubscriber extends webSocketAccountSubscriber_1.WebSocketAccountSubscriber {
32
- constructor(client, commitmentLevel, accountName, program, accountPublicKey, decodeBuffer, resubOpts) {
32
+ constructor(client, commitmentLevel, accountName, program, accountPublicKey, decodeBuffer, resubOpts, enableReconnect = false) {
33
33
  super(accountName, program, accountPublicKey, decodeBuffer, resubOpts);
34
34
  this.client = client;
35
35
  this.commitmentLevel = commitmentLevel;
36
+ this.enableReconnect = enableReconnect;
36
37
  }
37
38
  static async create(grpcConfigs, accountName, program, accountPublicKey, decodeBuffer, resubOpts) {
38
39
  var _a, _b;
@@ -40,7 +41,7 @@ class grpcAccountSubscriber extends webSocketAccountSubscriber_1.WebSocketAccoun
40
41
  const commitmentLevel =
41
42
  // @ts-ignore :: isomorphic exported enum fails typescript but will work at runtime
42
43
  (_b = grpcConfigs.commitmentLevel) !== null && _b !== void 0 ? _b : CommitmentLevel.CONFIRMED;
43
- return new grpcAccountSubscriber(client, commitmentLevel, accountName, program, accountPublicKey, decodeBuffer, resubOpts);
44
+ return new grpcAccountSubscriber(client, commitmentLevel, accountName, program, accountPublicKey, decodeBuffer, resubOpts, grpcConfigs.enableReconnect);
44
45
  }
45
46
  async subscribe(onChange) {
46
47
  if (this.listenerId != null || this.isUnsubscribing) {
@@ -70,16 +71,19 @@ class grpcAccountSubscriber extends webSocketAccountSubscriber_1.WebSocketAccoun
70
71
  entry: {},
71
72
  transactionsStatus: {},
72
73
  };
73
- this.stream.on('error', (error) => {
74
- // @ts-ignore
75
- if (error.code === 1) {
76
- // expected: 1 CANCELLED: Cancelled on client
77
- return;
78
- }
79
- else {
80
- console.error('GRPC unexpected error caught:', error);
81
- }
82
- });
74
+ if (this.enableReconnect) {
75
+ this.stream.on('error', (error) => {
76
+ // @ts-ignore
77
+ if (error.code === 1) {
78
+ // expected: 1 CANCELLED: Cancelled on client
79
+ console.error('GRPC (grpcAccountSubscriber) Cancelled on client caught:', error);
80
+ return;
81
+ }
82
+ else {
83
+ console.error('GRPC (grpcAccountSubscriber) unexpected error caught:', error);
84
+ }
85
+ });
86
+ }
83
87
  this.stream.on('data', (chunk) => {
84
88
  var _a;
85
89
  if (!chunk.account) {
@@ -9,6 +9,7 @@ export declare class grpcProgramAccountSubscriber<T> extends WebSocketProgramAcc
9
9
  private stream;
10
10
  private commitmentLevel;
11
11
  listenerId?: number;
12
+ private enableReconnect;
12
13
  private constructor();
13
14
  static create<U>(grpcConfigs: GrpcConfigs, subscriptionName: string, accountDiscriminator: string, program: Program, decodeBufferFn: (accountName: string, ix: Buffer) => U, options?: {
14
15
  filters: MemcmpFilter[];
@@ -35,10 +35,11 @@ const grpc_1 = require("../isomorphic/grpc");
35
35
  class grpcProgramAccountSubscriber extends webSocketProgramAccountSubscriber_1.WebSocketProgramAccountSubscriber {
36
36
  constructor(client, commitmentLevel, subscriptionName, accountDiscriminator, program, decodeBufferFn, options = {
37
37
  filters: [],
38
- }, resubOpts) {
38
+ }, resubOpts, enableReconnect = false) {
39
39
  super(subscriptionName, accountDiscriminator, program, decodeBufferFn, options, resubOpts);
40
40
  this.client = client;
41
41
  this.commitmentLevel = commitmentLevel;
42
+ this.enableReconnect = enableReconnect;
42
43
  }
43
44
  static async create(grpcConfigs, subscriptionName, accountDiscriminator, program, decodeBufferFn, options = {
44
45
  filters: [],
@@ -48,7 +49,7 @@ class grpcProgramAccountSubscriber extends webSocketProgramAccountSubscriber_1.W
48
49
  const commitmentLevel =
49
50
  // @ts-ignore :: isomorphic exported enum fails typescript but will work at runtime
50
51
  (_b = grpcConfigs.commitmentLevel) !== null && _b !== void 0 ? _b : CommitmentLevel.CONFIRMED;
51
- return new grpcProgramAccountSubscriber(client, commitmentLevel, subscriptionName, accountDiscriminator, program, decodeBufferFn, options, resubOpts);
52
+ return new grpcProgramAccountSubscriber(client, commitmentLevel, subscriptionName, accountDiscriminator, program, decodeBufferFn, options, resubOpts, grpcConfigs.enableReconnect);
52
53
  }
53
54
  async subscribe(onChange) {
54
55
  if (this.listenerId != null || this.isUnsubscribing) {
@@ -83,16 +84,19 @@ class grpcProgramAccountSubscriber extends webSocketProgramAccountSubscriber_1.W
83
84
  entry: {},
84
85
  transactionsStatus: {},
85
86
  };
86
- this.stream.on('error', (error) => {
87
- // @ts-ignore
88
- if (error.code === 1) {
89
- // expected: 1 CANCELLED: Cancelled on client
90
- return;
91
- }
92
- else {
93
- console.error('GRPC unexpected error caught:', error);
94
- }
95
- });
87
+ if (this.enableReconnect) {
88
+ this.stream.on('error', (error) => {
89
+ // @ts-ignore
90
+ if (error.code === 1) {
91
+ // expected: 1 CANCELLED: Cancelled on client
92
+ console.error('GRPC (grpcProgramAccountSubscriber) Cancelled on client caught:', error);
93
+ return;
94
+ }
95
+ else {
96
+ console.error('GRPC (grpcProgramAccountSubscriber) unexpected error caught:', error);
97
+ }
98
+ });
99
+ }
96
100
  this.stream.on('data', (chunk) => {
97
101
  var _a;
98
102
  if (!chunk.account) {
@@ -158,6 +158,11 @@ export type GrpcConfigs = {
158
158
  token: string;
159
159
  commitmentLevel?: CommitmentLevel;
160
160
  channelOptions?: ChannelOptions;
161
+ /**
162
+ * Whether to enable automatic reconnection on connection loss .
163
+ * Defaults to false, will throw on connection loss.
164
+ */
165
+ enableReconnect?: boolean;
161
166
  };
162
167
  export interface HighLeverageModeConfigAccountSubscriber {
163
168
  eventEmitter: StrictEventEmitter<EventEmitter, HighLeverageModeConfigAccountEvents>;
@@ -230,8 +230,8 @@ export declare class AdminClient extends DriftClient {
230
230
  getUpdateProtectedMakerModeConfigIx(maxUsers: number, reduceOnly: boolean, currentUsers: undefined): Promise<TransactionInstruction>;
231
231
  adminDeposit(marketIndex: number, amount: BN, depositUserAccount: PublicKey, adminTokenAccount?: PublicKey): Promise<TransactionSignature>;
232
232
  getAdminDepositIx(marketIndex: number, amount: BN, depositUserAccount: PublicKey, adminTokenAccount?: PublicKey): Promise<TransactionInstruction>;
233
- updateDisableBitFlagsMMOracle(disable: boolean): Promise<TransactionSignature>;
234
- getUpdateDisableBitFlagsMMOracleIx(disable: boolean): Promise<TransactionInstruction>;
235
233
  zeroMMOracleFields(marketIndex: number): Promise<TransactionSignature>;
236
234
  getZeroMMOracleFieldsIx(marketIndex: number): Promise<TransactionInstruction>;
235
+ updateFeatureBitFlagsMMOracle(enable: boolean): Promise<TransactionSignature>;
236
+ getUpdateFeatureBitFlagsMMOracleIx(enable: boolean): Promise<TransactionInstruction>;
237
237
  }
@@ -2103,36 +2103,36 @@ class AdminClient extends driftClient_1.DriftClient {
2103
2103
  },
2104
2104
  });
2105
2105
  }
2106
- async updateDisableBitFlagsMMOracle(disable) {
2107
- const updateDisableBitFlagsMMOracleIx = await this.getUpdateDisableBitFlagsMMOracleIx(disable);
2108
- const tx = await this.buildTransaction(updateDisableBitFlagsMMOracleIx);
2106
+ async zeroMMOracleFields(marketIndex) {
2107
+ const zeroMMOracleFieldsIx = await this.getZeroMMOracleFieldsIx(marketIndex);
2108
+ const tx = await this.buildTransaction(zeroMMOracleFieldsIx);
2109
2109
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
2110
2110
  return txSig;
2111
2111
  }
2112
- async getUpdateDisableBitFlagsMMOracleIx(disable) {
2113
- return await this.program.instruction.updateDisableBitflagsMmOracle(disable, {
2112
+ async getZeroMMOracleFieldsIx(marketIndex) {
2113
+ return await this.program.instruction.zeroMmOracleFields({
2114
2114
  accounts: {
2115
2115
  admin: this.isSubscribed
2116
2116
  ? this.getStateAccount().admin
2117
2117
  : this.wallet.publicKey,
2118
2118
  state: await this.getStatePublicKey(),
2119
+ perpMarket: await (0, pda_1.getPerpMarketPublicKey)(this.program.programId, marketIndex),
2119
2120
  },
2120
2121
  });
2121
2122
  }
2122
- async zeroMMOracleFields(marketIndex) {
2123
- const zeroMMOracleFieldsIx = await this.getZeroMMOracleFieldsIx(marketIndex);
2124
- const tx = await this.buildTransaction(zeroMMOracleFieldsIx);
2123
+ async updateFeatureBitFlagsMMOracle(enable) {
2124
+ const updateFeatureBitFlagsMMOracleIx = await this.getUpdateFeatureBitFlagsMMOracleIx(enable);
2125
+ const tx = await this.buildTransaction(updateFeatureBitFlagsMMOracleIx);
2125
2126
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
2126
2127
  return txSig;
2127
2128
  }
2128
- async getZeroMMOracleFieldsIx(marketIndex) {
2129
- return await this.program.instruction.zeroMmOracleFields({
2129
+ async getUpdateFeatureBitFlagsMMOracleIx(enable) {
2130
+ return await this.program.instruction.updateFeatureBitFlagsMmOracle(enable, {
2130
2131
  accounts: {
2131
- admin: this.isSubscribed
2132
- ? this.getStateAccount().admin
2133
- : this.wallet.publicKey,
2132
+ admin: this.useHotWalletAdmin
2133
+ ? this.wallet.publicKey
2134
+ : this.getStateAccount().admin,
2134
2135
  state: await this.getStatePublicKey(),
2135
- perpMarket: await (0, pda_1.getPerpMarketPublicKey)(this.program.programId, marketIndex),
2136
2136
  },
2137
2137
  });
2138
2138
  }
@@ -133,7 +133,7 @@ export declare class DLOB {
133
133
  getTakeProfits(marketIndex: number, marketType: MarketType, direction: PositionDirection): Generator<DLOBNode>;
134
134
  getTakeProfitMarkets(marketIndex: number, marketType: MarketType, direction: PositionDirection): Generator<DLOBNode>;
135
135
  getTakeProfitLimits(marketIndex: number, marketType: MarketType, direction: PositionDirection): Generator<DLOBNode>;
136
- findNodesToTrigger(marketIndex: number, slot: number, oraclePrice: BN, marketType: MarketType, stateAccount: StateAccount): NodeToTrigger[];
136
+ findNodesToTrigger(marketIndex: number, slot: number, triggerPrice: BN, marketType: MarketType, stateAccount: StateAccount): NodeToTrigger[];
137
137
  printTop(driftClient: DriftClient, slotSubscriber: SlotSubscriber, marketIndex: number, marketType: MarketType): void;
138
138
  getDLOBOrders(): DLOBOrders;
139
139
  getNodeLists(): Generator<NodeList<DLOBNodeType>>;
@@ -853,7 +853,7 @@ class DLOB {
853
853
  }
854
854
  }
855
855
  }
856
- findNodesToTrigger(marketIndex, slot, oraclePrice, marketType, stateAccount) {
856
+ findNodesToTrigger(marketIndex, slot, triggerPrice, marketType, stateAccount) {
857
857
  if ((0, exchangeStatus_1.exchangePaused)(stateAccount)) {
858
858
  return [];
859
859
  }
@@ -865,7 +865,7 @@ class DLOB {
865
865
  : undefined;
866
866
  if (triggerAboveList) {
867
867
  for (const node of triggerAboveList.getGenerator()) {
868
- if (oraclePrice.gt(node.order.triggerPrice)) {
868
+ if (triggerPrice.gt(node.order.triggerPrice)) {
869
869
  nodesToTrigger.push({
870
870
  node: node,
871
871
  });
@@ -880,7 +880,7 @@ class DLOB {
880
880
  : undefined;
881
881
  if (triggerBelowList) {
882
882
  for (const node of triggerBelowList.getGenerator()) {
883
- if (oraclePrice.lt(node.order.triggerPrice)) {
883
+ if (triggerPrice.lt(node.order.triggerPrice)) {
884
884
  nodesToTrigger.push({
885
885
  node: node,
886
886
  });
@@ -7536,7 +7536,7 @@
7536
7536
  ]
7537
7537
  },
7538
7538
  {
7539
- "name": "updateDisableBitflagsMmOracle",
7539
+ "name": "updateFeatureBitFlagsMmOracle",
7540
7540
  "accounts": [
7541
7541
  {
7542
7542
  "name": "admin",
@@ -7551,7 +7551,7 @@
7551
7551
  ],
7552
7552
  "args": [
7553
7553
  {
7554
- "name": "disable",
7554
+ "name": "enable",
7555
7555
  "type": "bool"
7556
7556
  }
7557
7557
  ]
@@ -8342,12 +8342,20 @@
8342
8342
  "name": "protectedMakerDynamicDivisor",
8343
8343
  "type": "u8"
8344
8344
  },
8345
+ {
8346
+ "name": "padding1",
8347
+ "type": "u32"
8348
+ },
8349
+ {
8350
+ "name": "lastFillPrice",
8351
+ "type": "u64"
8352
+ },
8345
8353
  {
8346
8354
  "name": "padding",
8347
8355
  "type": {
8348
8356
  "array": [
8349
8357
  "u8",
8350
- 36
8358
+ 24
8351
8359
  ]
8352
8360
  }
8353
8361
  }
@@ -9078,7 +9086,7 @@
9078
9086
  "type": "u16"
9079
9087
  },
9080
9088
  {
9081
- "name": "disableBitFlags",
9089
+ "name": "featureBitFlags",
9082
9090
  "type": "u8"
9083
9091
  },
9084
9092
  {
@@ -10658,7 +10666,7 @@
10658
10666
  "name": "lastFundingRate",
10659
10667
  "docs": [
10660
10668
  "last funding rate in this perp market (unit is quote per base)",
10661
- "precision: QUOTE_PRECISION"
10669
+ "precision: FUNDING_RATE_PRECISION"
10662
10670
  ],
10663
10671
  "type": "i64"
10664
10672
  },
@@ -10666,7 +10674,7 @@
10666
10674
  "name": "lastFundingRateLong",
10667
10675
  "docs": [
10668
10676
  "last funding rate for longs in this perp market (unit is quote per base)",
10669
- "precision: QUOTE_PRECISION"
10677
+ "precision: FUNDING_RATE_PRECISION"
10670
10678
  ],
10671
10679
  "type": "i64"
10672
10680
  },
@@ -11096,9 +11104,13 @@
11096
11104
  "type": {
11097
11105
  "array": [
11098
11106
  "u8",
11099
- 11
11107
+ 3
11100
11108
  ]
11101
11109
  }
11110
+ },
11111
+ {
11112
+ "name": "lastFundingOracleTwap",
11113
+ "type": "i64"
11102
11114
  }
11103
11115
  ]
11104
11116
  }
@@ -12789,6 +12801,20 @@
12789
12801
  ]
12790
12802
  }
12791
12803
  },
12804
+ {
12805
+ "name": "FeatureBitFlags",
12806
+ "type": {
12807
+ "kind": "enum",
12808
+ "variants": [
12809
+ {
12810
+ "name": "MmOracleUpdate"
12811
+ },
12812
+ {
12813
+ "name": "EnableMedianTriggerPrice"
12814
+ }
12815
+ ]
12816
+ }
12817
+ },
12792
12818
  {
12793
12819
  "name": "UserStatus",
12794
12820
  "type": {
@@ -13712,6 +13738,13 @@
13712
13738
  "option": "u64"
13713
13739
  },
13714
13740
  "index": false
13741
+ },
13742
+ {
13743
+ "name": "triggerPrice",
13744
+ "type": {
13745
+ "option": "u64"
13746
+ },
13747
+ "index": false
13715
13748
  }
13716
13749
  ]
13717
13750
  },
@@ -38,3 +38,13 @@ export declare function calculateAvailablePerpLiquidity(market: PerpMarketAccoun
38
38
  asks: BN;
39
39
  };
40
40
  export declare function calculatePerpMarketBaseLiquidatorFee(market: PerpMarketAccount, userHighLeverageMode: boolean): number;
41
+ /**
42
+ * Calculates trigger price for a perp market based on oracle price and current time
43
+ * Implements the same logic as the Rust get_trigger_price function
44
+ *
45
+ * @param market - The perp market account
46
+ * @param oraclePrice - Current oracle price (precision: PRICE_PRECISION)
47
+ * @param now - Current timestamp in seconds
48
+ * @returns trigger price (precision: PRICE_PRECISION)
49
+ */
50
+ export declare function getTriggerPrice(market: PerpMarketAccount, oraclePrice: BN, now: BN, useMedianPrice: boolean): BN;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculatePerpMarketBaseLiquidatorFee = exports.calculateAvailablePerpLiquidity = exports.calculateNetUserPnlImbalance = exports.calculateNetUserPnl = exports.calculateMarketMaxAvailableInsurance = exports.calculateMarketAvailablePNL = exports.calculateUnrealizedAssetWeight = exports.calculateMarketMarginRatio = exports.calculateOracleSpread = exports.calculateOracleReserveSpread = exports.calculateNewMarketAfterTrade = exports.calculateAskPrice = exports.calculateBidPrice = exports.calculateReservePrice = void 0;
3
+ exports.getTriggerPrice = exports.calculatePerpMarketBaseLiquidatorFee = exports.calculateAvailablePerpLiquidity = exports.calculateNetUserPnlImbalance = exports.calculateNetUserPnl = exports.calculateMarketMaxAvailableInsurance = exports.calculateMarketAvailablePNL = exports.calculateUnrealizedAssetWeight = exports.calculateMarketMarginRatio = exports.calculateOracleSpread = exports.calculateOracleReserveSpread = exports.calculateNewMarketAfterTrade = exports.calculateAskPrice = exports.calculateBidPrice = exports.calculateReservePrice = void 0;
4
4
  const anchor_1 = require("@coral-xyz/anchor");
5
5
  const types_1 = require("../types");
6
6
  const amm_1 = require("./amm");
@@ -172,3 +172,78 @@ function calculatePerpMarketBaseLiquidatorFee(market, userHighLeverageMode) {
172
172
  }
173
173
  }
174
174
  exports.calculatePerpMarketBaseLiquidatorFee = calculatePerpMarketBaseLiquidatorFee;
175
+ /**
176
+ * Calculates trigger price for a perp market based on oracle price and current time
177
+ * Implements the same logic as the Rust get_trigger_price function
178
+ *
179
+ * @param market - The perp market account
180
+ * @param oraclePrice - Current oracle price (precision: PRICE_PRECISION)
181
+ * @param now - Current timestamp in seconds
182
+ * @returns trigger price (precision: PRICE_PRECISION)
183
+ */
184
+ function getTriggerPrice(market, oraclePrice, now, useMedianPrice) {
185
+ if (!useMedianPrice) {
186
+ return oraclePrice.abs();
187
+ }
188
+ const lastFillPrice = market.lastFillPrice;
189
+ // Calculate 5-minute basis
190
+ const markPrice5minTwap = market.amm.lastMarkPriceTwap5Min;
191
+ const lastOraclePriceTwap5min = market.amm.historicalOracleData.lastOraclePriceTwap5Min;
192
+ const basis5min = markPrice5minTwap.sub(lastOraclePriceTwap5min);
193
+ const oraclePlusBasis5min = oraclePrice.add(basis5min);
194
+ // Calculate funding basis
195
+ const lastFundingBasis = getLastFundingBasis(market, oraclePrice, now);
196
+ const oraclePlusFundingBasis = oraclePrice.add(lastFundingBasis);
197
+ const prices = [
198
+ lastFillPrice.gt(numericConstants_1.ZERO) ? lastFillPrice : oraclePrice,
199
+ oraclePlusFundingBasis,
200
+ oraclePlusBasis5min,
201
+ ].sort((a, b) => a.cmp(b));
202
+ const medianPrice = prices[1];
203
+ return clampTriggerPrice(market, oraclePrice.abs(), medianPrice);
204
+ }
205
+ exports.getTriggerPrice = getTriggerPrice;
206
+ /**
207
+ * Calculates the last funding basis for trigger price calculation
208
+ * Implements the same logic as the Rust get_last_funding_basis function
209
+ */
210
+ function getLastFundingBasis(market, oraclePrice, now) {
211
+ if (market.amm.lastFundingOracleTwap.gt(numericConstants_1.ZERO)) {
212
+ const lastFundingRate = market.amm.lastFundingRate
213
+ .mul(numericConstants_1.PRICE_PRECISION)
214
+ .div(market.amm.lastFundingOracleTwap)
215
+ .muln(24);
216
+ const lastFundingRatePreAdj = lastFundingRate.sub(numericConstants_1.FUNDING_RATE_PRECISION.div(new anchor_1.BN(5000)) // FUNDING_RATE_OFFSET_PERCENTAGE
217
+ );
218
+ const timeLeftUntilFundingUpdate = anchor_1.BN.min(anchor_1.BN.max(now.sub(market.amm.lastFundingRateTs), numericConstants_1.ZERO), market.amm.fundingPeriod);
219
+ const lastFundingBasis = oraclePrice
220
+ .mul(lastFundingRatePreAdj)
221
+ .div(numericConstants_1.PERCENTAGE_PRECISION)
222
+ .mul(market.amm.fundingPeriod.sub(timeLeftUntilFundingUpdate))
223
+ .div(market.amm.fundingPeriod)
224
+ .div(new anchor_1.BN(1000)); // FUNDING_RATE_BUFFER
225
+ return lastFundingBasis;
226
+ }
227
+ else {
228
+ return numericConstants_1.ZERO;
229
+ }
230
+ }
231
+ /**
232
+ * Clamps trigger price based on contract tier
233
+ * Implements the same logic as the Rust clamp_trigger_price function
234
+ */
235
+ function clampTriggerPrice(market, oraclePrice, medianPrice) {
236
+ let maxBpsDiff;
237
+ const tier = market.contractTier;
238
+ if ((0, types_1.isVariant)(tier, 'a') || (0, types_1.isVariant)(tier, 'b')) {
239
+ maxBpsDiff = new anchor_1.BN(500); // 20 BPS
240
+ }
241
+ else if ((0, types_1.isVariant)(tier, 'c')) {
242
+ maxBpsDiff = new anchor_1.BN(100); // 100 BPS
243
+ }
244
+ else {
245
+ maxBpsDiff = new anchor_1.BN(40); // 250 BPS
246
+ }
247
+ const maxOracleDiff = oraclePrice.div(maxBpsDiff);
248
+ return anchor_1.BN.min(anchor_1.BN.max(medianPrice, oraclePrice.sub(maxOracleDiff)), oraclePrice.add(maxOracleDiff));
249
+ }
@@ -3,3 +3,4 @@ import { BN } from '@coral-xyz/anchor';
3
3
  import { StateAccount } from '../types';
4
4
  export declare function calculateInitUserFee(stateAccount: StateAccount): BN;
5
5
  export declare function getMaxNumberOfSubAccounts(stateAccount: StateAccount): BN;
6
+ export declare function useMedianTriggerPrice(stateAccount: StateAccount): boolean;
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getMaxNumberOfSubAccounts = exports.calculateInitUserFee = void 0;
3
+ exports.useMedianTriggerPrice = exports.getMaxNumberOfSubAccounts = exports.calculateInitUserFee = void 0;
4
4
  const anchor_1 = require("@coral-xyz/anchor");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
+ const types_1 = require("../types");
6
7
  function calculateInitUserFee(stateAccount) {
7
8
  const maxInitFee = new anchor_1.BN(stateAccount.maxInitializeUserFee)
8
9
  .mul(numericConstants_1.LAMPORTS_PRECISION)
@@ -29,3 +30,7 @@ function getMaxNumberOfSubAccounts(stateAccount) {
29
30
  return new anchor_1.BN(stateAccount.maxNumberOfSubAccounts).muln(100);
30
31
  }
31
32
  exports.getMaxNumberOfSubAccounts = getMaxNumberOfSubAccounts;
33
+ function useMedianTriggerPrice(stateAccount) {
34
+ return ((stateAccount.featureBitFlags & types_1.FeatureBitFlags.MEDIAN_TRIGGER_PRICE) > 0);
35
+ }
36
+ exports.useMedianTriggerPrice = useMedianTriggerPrice;
@@ -18,6 +18,10 @@ export declare enum ExchangeStatus {
18
18
  AMM_IMMEDIATE_FILL_PAUSED = 128,
19
19
  PAUSED = 255
20
20
  }
21
+ export declare enum FeatureBitFlags {
22
+ MM_ORACLE_UPDATE = 1,
23
+ MEDIAN_TRIGGER_PRICE = 2
24
+ }
21
25
  export declare class MarketStatus {
22
26
  static readonly INITIALIZED: {
23
27
  initialized: {};
@@ -860,6 +864,7 @@ export type StateAccount = {
860
864
  initialPctToLiquidate: number;
861
865
  liquidationDuration: number;
862
866
  maxInitializeUserFee: number;
867
+ featureBitFlags: number;
863
868
  };
864
869
  export type PerpMarketAccount = {
865
870
  status: MarketStatus;
@@ -903,6 +908,7 @@ export type PerpMarketAccount = {
903
908
  highLeverageMarginRatioMaintenance: number;
904
909
  protectedMakerLimitPriceDivisor: number;
905
910
  protectedMakerDynamicDivisor: number;
911
+ lastFillPrice: BN;
906
912
  };
907
913
  export type HistoricalOracleData = {
908
914
  lastOraclePrice: BN;
@@ -1081,6 +1087,7 @@ export type AMM = {
1081
1087
  takerSpeedBumpOverride: number;
1082
1088
  ammSpreadAdjustment: number;
1083
1089
  ammInventorySpreadAdjustment: number;
1090
+ lastFundingOracleTwap: BN;
1084
1091
  };
1085
1092
  export type PerpPosition = {
1086
1093
  baseAssetAmount: BN;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SwapReduceOnly = exports.PlaceAndTakeOrderSuccessCondition = exports.FuelOverflowStatus = exports.ReferrerStatus = exports.DefaultOrderParams = exports.ModifyOrderPolicy = exports.OrderParamsBitFlag = exports.PostOnlyParams = exports.LiquidationType = exports.LPAction = exports.TradeSide = exports.getVariant = exports.isOneOfVariant = exports.isVariant = exports.SettlePnlMode = exports.StakeAction = exports.SpotFulfillmentConfigStatus = exports.SettlePnlExplanation = exports.DepositExplanation = exports.SpotFulfillmentStatus = exports.SpotFulfillmentType = 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.UserStatus = exports.InsuranceFundOperation = exports.SpotOperation = exports.PerpOperation = exports.MarketStatus = exports.ExchangeStatus = void 0;
3
+ exports.SwapReduceOnly = exports.PlaceAndTakeOrderSuccessCondition = exports.FuelOverflowStatus = exports.ReferrerStatus = exports.DefaultOrderParams = exports.ModifyOrderPolicy = exports.OrderParamsBitFlag = exports.PostOnlyParams = exports.LiquidationType = exports.LPAction = exports.TradeSide = exports.getVariant = exports.isOneOfVariant = exports.isVariant = exports.SettlePnlMode = exports.StakeAction = exports.SpotFulfillmentConfigStatus = exports.SettlePnlExplanation = exports.DepositExplanation = exports.SpotFulfillmentStatus = exports.SpotFulfillmentType = 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.UserStatus = exports.InsuranceFundOperation = exports.SpotOperation = exports.PerpOperation = exports.MarketStatus = exports.FeatureBitFlags = exports.ExchangeStatus = void 0;
4
4
  const numericConstants_1 = require("./constants/numericConstants");
5
5
  // # Utility Types / Enums / Constants
6
6
  var ExchangeStatus;
@@ -16,6 +16,11 @@ var ExchangeStatus;
16
16
  ExchangeStatus[ExchangeStatus["AMM_IMMEDIATE_FILL_PAUSED"] = 128] = "AMM_IMMEDIATE_FILL_PAUSED";
17
17
  ExchangeStatus[ExchangeStatus["PAUSED"] = 255] = "PAUSED";
18
18
  })(ExchangeStatus || (exports.ExchangeStatus = ExchangeStatus = {}));
19
+ var FeatureBitFlags;
20
+ (function (FeatureBitFlags) {
21
+ FeatureBitFlags[FeatureBitFlags["MM_ORACLE_UPDATE"] = 1] = "MM_ORACLE_UPDATE";
22
+ FeatureBitFlags[FeatureBitFlags["MEDIAN_TRIGGER_PRICE"] = 2] = "MEDIAN_TRIGGER_PRICE";
23
+ })(FeatureBitFlags || (exports.FeatureBitFlags = FeatureBitFlags = {}));
19
24
  class MarketStatus {
20
25
  }
21
26
  exports.MarketStatus = MarketStatus;
@@ -9,6 +9,7 @@ export declare class grpcAccountSubscriber<T> extends WebSocketAccountSubscriber
9
9
  private stream;
10
10
  private commitmentLevel;
11
11
  listenerId?: number;
12
+ private enableReconnect;
12
13
  private constructor();
13
14
  static create<U>(grpcConfigs: GrpcConfigs, accountName: string, program: Program, accountPublicKey: PublicKey, decodeBuffer?: (buffer: Buffer) => U, resubOpts?: ResubOpts): Promise<grpcAccountSubscriber<U>>;
14
15
  subscribe(onChange: (data: T) => void): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"grpcAccountSubscriber.d.ts","sourceRoot":"","sources":["../../../src/accounts/grpcAccountSubscriber.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAU1E,qBAAa,qBAAqB,CAAC,CAAC,CAAE,SAAQ,0BAA0B,CAAC,CAAC,CAAC;IAC1E,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAwD;IACtE,OAAO,CAAC,eAAe,CAAkB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE3B,OAAO;WAca,MAAM,CAAC,CAAC,EAC3B,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,OAAO,EAChB,gBAAgB,EAAE,SAAS,EAC3B,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,CAAC,EACpC,SAAS,CAAC,EAAE,SAAS,GACnB,OAAO,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAqBrB,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA6FrD,WAAW,CAAC,OAAO,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAwC1D"}
1
+ {"version":3,"file":"grpcAccountSubscriber.d.ts","sourceRoot":"","sources":["../../../src/accounts/grpcAccountSubscriber.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAU1E,qBAAa,qBAAqB,CAAC,CAAC,CAAE,SAAQ,0BAA0B,CAAC,CAAC,CAAC;IAC1E,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAwD;IACtE,OAAO,CAAC,eAAe,CAAkB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,eAAe,CAAU;IAEjC,OAAO;WAgBa,MAAM,CAAC,CAAC,EAC3B,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,OAAO,EAChB,gBAAgB,EAAE,SAAS,EAC3B,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,CAAC,EACpC,SAAS,CAAC,EAAE,SAAS,GACnB,OAAO,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAsBrB,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAsGrD,WAAW,CAAC,OAAO,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAwC1D"}
@@ -29,10 +29,11 @@ const Buffer = __importStar(require("buffer"));
29
29
  const webSocketAccountSubscriber_1 = require("./webSocketAccountSubscriber");
30
30
  const grpc_1 = require("../isomorphic/grpc");
31
31
  class grpcAccountSubscriber extends webSocketAccountSubscriber_1.WebSocketAccountSubscriber {
32
- constructor(client, commitmentLevel, accountName, program, accountPublicKey, decodeBuffer, resubOpts) {
32
+ constructor(client, commitmentLevel, accountName, program, accountPublicKey, decodeBuffer, resubOpts, enableReconnect = false) {
33
33
  super(accountName, program, accountPublicKey, decodeBuffer, resubOpts);
34
34
  this.client = client;
35
35
  this.commitmentLevel = commitmentLevel;
36
+ this.enableReconnect = enableReconnect;
36
37
  }
37
38
  static async create(grpcConfigs, accountName, program, accountPublicKey, decodeBuffer, resubOpts) {
38
39
  var _a, _b;
@@ -40,7 +41,7 @@ class grpcAccountSubscriber extends webSocketAccountSubscriber_1.WebSocketAccoun
40
41
  const commitmentLevel =
41
42
  // @ts-ignore :: isomorphic exported enum fails typescript but will work at runtime
42
43
  (_b = grpcConfigs.commitmentLevel) !== null && _b !== void 0 ? _b : CommitmentLevel.CONFIRMED;
43
- return new grpcAccountSubscriber(client, commitmentLevel, accountName, program, accountPublicKey, decodeBuffer, resubOpts);
44
+ return new grpcAccountSubscriber(client, commitmentLevel, accountName, program, accountPublicKey, decodeBuffer, resubOpts, grpcConfigs.enableReconnect);
44
45
  }
45
46
  async subscribe(onChange) {
46
47
  if (this.listenerId != null || this.isUnsubscribing) {
@@ -70,16 +71,19 @@ class grpcAccountSubscriber extends webSocketAccountSubscriber_1.WebSocketAccoun
70
71
  entry: {},
71
72
  transactionsStatus: {},
72
73
  };
73
- this.stream.on('error', (error) => {
74
- // @ts-ignore
75
- if (error.code === 1) {
76
- // expected: 1 CANCELLED: Cancelled on client
77
- return;
78
- }
79
- else {
80
- console.error('GRPC unexpected error caught:', error);
81
- }
82
- });
74
+ if (this.enableReconnect) {
75
+ this.stream.on('error', (error) => {
76
+ // @ts-ignore
77
+ if (error.code === 1) {
78
+ // expected: 1 CANCELLED: Cancelled on client
79
+ console.error('GRPC (grpcAccountSubscriber) Cancelled on client caught:', error);
80
+ return;
81
+ }
82
+ else {
83
+ console.error('GRPC (grpcAccountSubscriber) unexpected error caught:', error);
84
+ }
85
+ });
86
+ }
83
87
  this.stream.on('data', (chunk) => {
84
88
  var _a;
85
89
  if (!chunk.account) {
@@ -9,6 +9,7 @@ export declare class grpcProgramAccountSubscriber<T> extends WebSocketProgramAcc
9
9
  private stream;
10
10
  private commitmentLevel;
11
11
  listenerId?: number;
12
+ private enableReconnect;
12
13
  private constructor();
13
14
  static create<U>(grpcConfigs: GrpcConfigs, subscriptionName: string, accountDiscriminator: string, program: Program, decodeBufferFn: (accountName: string, ix: Buffer) => U, options?: {
14
15
  filters: MemcmpFilter[];
@@ -1 +1 @@
1
- {"version":3,"file":"grpcProgramAccountSubscriber.d.ts","sourceRoot":"","sources":["../../../src/accounts/grpcProgramAccountSubscriber.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEnE,OAAO,EAAE,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AAUxF,qBAAa,4BAA4B,CACxC,CAAC,CACA,SAAQ,iCAAiC,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAwD;IACtE,OAAO,CAAC,eAAe,CAAkB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE3B,OAAO;WAwBa,MAAM,CAAC,CAAC,EAC3B,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,MAAM,EACxB,oBAAoB,EAAE,MAAM,EAC5B,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,CAAC,EACtD,OAAO,GAAE;QAAE,OAAO,EAAE,YAAY,EAAE,CAAA;KAEjC,EACD,SAAS,CAAC,EAAE,SAAS,GACnB,OAAO,CAAC,4BAA4B,CAAC,CAAC,CAAC,CAAC;IAsBrC,SAAS,CACd,QAAQ,EAAE,CACT,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,KACV,IAAI,GACP,OAAO,CAAC,IAAI,CAAC;IAsGH,WAAW,CAAC,OAAO,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAwCxD"}
1
+ {"version":3,"file":"grpcProgramAccountSubscriber.d.ts","sourceRoot":"","sources":["../../../src/accounts/grpcProgramAccountSubscriber.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEnE,OAAO,EAAE,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AAUxF,qBAAa,4BAA4B,CACxC,CAAC,CACA,SAAQ,iCAAiC,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAwD;IACtE,OAAO,CAAC,eAAe,CAAkB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,eAAe,CAAU;IAEjC,OAAO;WA0Ba,MAAM,CAAC,CAAC,EAC3B,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,MAAM,EACxB,oBAAoB,EAAE,MAAM,EAC5B,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,CAAC,EACtD,OAAO,GAAE;QAAE,OAAO,EAAE,YAAY,EAAE,CAAA;KAEjC,EACD,SAAS,CAAC,EAAE,SAAS,GACnB,OAAO,CAAC,4BAA4B,CAAC,CAAC,CAAC,CAAC;IAuBrC,SAAS,CACd,QAAQ,EAAE,CACT,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,KACV,IAAI,GACP,OAAO,CAAC,IAAI,CAAC;IAiHH,WAAW,CAAC,OAAO,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAwCxD"}