@drift-labs/sdk 2.49.0-beta.1 → 2.49.0-beta.10

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/accounts/{mockUserAccountSubscriber.d.ts → basicUserAccountSubscriber.d.ts} +2 -2
  3. package/lib/accounts/{mockUserAccountSubscriber.js → basicUserAccountSubscriber.js} +9 -6
  4. package/lib/accounts/pollingInsuranceFundStakeAccountSubscriber.d.ts +29 -0
  5. package/lib/accounts/pollingInsuranceFundStakeAccountSubscriber.js +110 -0
  6. package/lib/accounts/types.d.ts +14 -1
  7. package/lib/accounts/webSocketInsuranceFundStakeAccountSubscriber.d.ts +23 -0
  8. package/lib/accounts/webSocketInsuranceFundStakeAccountSubscriber.js +65 -0
  9. package/lib/dlob/DLOB.d.ts +6 -2
  10. package/lib/dlob/DLOB.js +37 -12
  11. package/lib/driftClient.d.ts +66 -66
  12. package/lib/driftClient.js +208 -194
  13. package/lib/events/eventSubscriber.js +2 -1
  14. package/lib/events/sort.d.ts +2 -2
  15. package/lib/events/sort.js +6 -23
  16. package/lib/examples/loadDlob.js +10 -5
  17. package/lib/index.d.ts +3 -1
  18. package/lib/index.js +3 -1
  19. package/lib/orderSubscriber/OrderSubscriber.js +4 -0
  20. package/lib/orderSubscriber/WebsocketSubscription.d.ts +1 -1
  21. package/lib/orderSubscriber/WebsocketSubscription.js +8 -6
  22. package/lib/types.d.ts +0 -2
  23. package/lib/userMap/PollingSubscription.d.ts +15 -0
  24. package/lib/userMap/PollingSubscription.js +26 -0
  25. package/lib/userMap/WebsocketSubscription.d.ts +19 -0
  26. package/lib/userMap/WebsocketSubscription.js +40 -0
  27. package/lib/userMap/userMap.d.ts +15 -18
  28. package/lib/userMap/userMap.js +62 -31
  29. package/lib/userMap/userMapConfig.d.ts +20 -0
  30. package/lib/userMap/userMapConfig.js +2 -0
  31. package/package.json +1 -1
  32. package/src/accounts/{mockUserAccountSubscriber.ts → basicUserAccountSubscriber.ts} +8 -6
  33. package/src/accounts/pollingInsuranceFundStakeAccountSubscriber.ts +185 -0
  34. package/src/accounts/types.ts +21 -0
  35. package/src/accounts/webSocketInsuranceFundStakeAccountSubscriber.ts +127 -0
  36. package/src/dlob/DLOB.ts +55 -15
  37. package/src/driftClient.ts +429 -272
  38. package/src/events/eventSubscriber.ts +2 -1
  39. package/src/events/sort.ts +7 -29
  40. package/src/examples/loadDlob.ts +11 -6
  41. package/src/index.ts +3 -1
  42. package/src/orderSubscriber/OrderSubscriber.ts +4 -0
  43. package/src/orderSubscriber/WebsocketSubscription.ts +19 -16
  44. package/src/types.ts +0 -2
  45. package/src/userMap/PollingSubscription.ts +46 -0
  46. package/src/userMap/WebsocketSubscription.ts +74 -0
  47. package/src/userMap/userMap.ts +88 -60
  48. package/src/userMap/userMapConfig.ts +31 -0
  49. package/tests/amm/test.ts +6 -3
  50. package/tests/dlob/helpers.ts +2 -6
  51. package/tests/dlob/test.ts +194 -0
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.49.0-beta.1
1
+ 2.49.0-beta.10
@@ -4,14 +4,14 @@ import { PublicKey } from '@solana/web3.js';
4
4
  import StrictEventEmitter from 'strict-event-emitter-types';
5
5
  import { EventEmitter } from 'events';
6
6
  import { UserAccount } from '../types';
7
- export declare class MockUserAccountSubscriber implements UserAccountSubscriber {
7
+ export declare class BasicUserAccountSubscriber implements UserAccountSubscriber {
8
8
  isSubscribed: boolean;
9
9
  eventEmitter: StrictEventEmitter<EventEmitter, UserAccountEvents>;
10
10
  userAccountPublicKey: PublicKey;
11
11
  callbackId?: string;
12
12
  errorCallbackId?: string;
13
13
  user: DataAndSlot<UserAccount>;
14
- constructor(userAccountPublicKey: PublicKey, data: UserAccount, slot: number);
14
+ constructor(userAccountPublicKey: PublicKey, data?: UserAccount, slot?: number);
15
15
  subscribe(_userAccount?: UserAccount): Promise<boolean>;
16
16
  addToAccountLoader(): Promise<void>;
17
17
  fetch(): Promise<void>;
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MockUserAccountSubscriber = void 0;
3
+ exports.BasicUserAccountSubscriber = void 0;
4
4
  const events_1 = require("events");
5
- class MockUserAccountSubscriber {
5
+ class BasicUserAccountSubscriber {
6
6
  constructor(userAccountPublicKey, data, slot) {
7
7
  this.isSubscribed = true;
8
8
  this.eventEmitter = new events_1.EventEmitter();
@@ -23,9 +23,12 @@ class MockUserAccountSubscriber {
23
23
  return this.user;
24
24
  }
25
25
  updateData(userAccount, slot) {
26
- this.user = { data: userAccount, slot };
27
- this.eventEmitter.emit('userAccountUpdate', userAccount);
28
- this.eventEmitter.emit('update');
26
+ var _a;
27
+ if (!this.user || slot >= ((_a = this.user.slot) !== null && _a !== void 0 ? _a : 0)) {
28
+ this.user = { data: userAccount, slot };
29
+ this.eventEmitter.emit('userAccountUpdate', userAccount);
30
+ this.eventEmitter.emit('update');
31
+ }
29
32
  }
30
33
  }
31
- exports.MockUserAccountSubscriber = MockUserAccountSubscriber;
34
+ exports.BasicUserAccountSubscriber = BasicUserAccountSubscriber;
@@ -0,0 +1,29 @@
1
+ /// <reference types="node" />
2
+ import { DataAndSlot, InsuranceFundStakeAccountEvents, InsuranceFundStakeAccountSubscriber } from './types';
3
+ import { Program } from '@coral-xyz/anchor';
4
+ import StrictEventEmitter from 'strict-event-emitter-types';
5
+ import { EventEmitter } from 'events';
6
+ import { PublicKey } from '@solana/web3.js';
7
+ import { BulkAccountLoader } from './bulkAccountLoader';
8
+ import { InsuranceFundStake } from '../types';
9
+ export declare class PollingInsuranceFundStakeAccountSubscriber implements InsuranceFundStakeAccountSubscriber {
10
+ isSubscribed: boolean;
11
+ program: Program;
12
+ eventEmitter: StrictEventEmitter<EventEmitter, InsuranceFundStakeAccountEvents>;
13
+ insuranceFundStakeAccountPublicKey: PublicKey;
14
+ accountLoader: BulkAccountLoader;
15
+ callbackId?: string;
16
+ errorCallbackId?: string;
17
+ insuranceFundStakeAccountAndSlot?: DataAndSlot<InsuranceFundStake>;
18
+ constructor(program: Program, publicKey: PublicKey, accountLoader: BulkAccountLoader);
19
+ subscribe(insuranceFundStake?: InsuranceFundStake): Promise<boolean>;
20
+ addToAccountLoader(): Promise<void>;
21
+ fetchIfUnloaded(): Promise<void>;
22
+ fetch(): Promise<void>;
23
+ doesAccountExist(): boolean;
24
+ unsubscribe(): Promise<void>;
25
+ assertIsSubscribed(): void;
26
+ getInsuranceFundStakeAccountAndSlot(): DataAndSlot<InsuranceFundStake>;
27
+ didSubscriptionSucceed(): boolean;
28
+ updateData(insuranceFundStake: InsuranceFundStake, slot: number): void;
29
+ }
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PollingInsuranceFundStakeAccountSubscriber = void 0;
4
+ const types_1 = require("./types");
5
+ const events_1 = require("events");
6
+ class PollingInsuranceFundStakeAccountSubscriber {
7
+ constructor(program, publicKey, accountLoader) {
8
+ this.isSubscribed = false;
9
+ this.program = program;
10
+ this.insuranceFundStakeAccountPublicKey = publicKey;
11
+ this.accountLoader = accountLoader;
12
+ this.eventEmitter = new events_1.EventEmitter();
13
+ }
14
+ async subscribe(insuranceFundStake) {
15
+ if (this.isSubscribed) {
16
+ return true;
17
+ }
18
+ if (insuranceFundStake) {
19
+ this.insuranceFundStakeAccountAndSlot = {
20
+ data: insuranceFundStake,
21
+ slot: undefined,
22
+ };
23
+ }
24
+ await this.addToAccountLoader();
25
+ if (this.doesAccountExist()) {
26
+ this.eventEmitter.emit('update');
27
+ }
28
+ this.isSubscribed = true;
29
+ return true;
30
+ }
31
+ async addToAccountLoader() {
32
+ if (this.callbackId) {
33
+ return;
34
+ }
35
+ this.callbackId = await this.accountLoader.addAccount(this.insuranceFundStakeAccountPublicKey, (buffer, slot) => {
36
+ if (!buffer) {
37
+ return;
38
+ }
39
+ if (this.insuranceFundStakeAccountAndSlot &&
40
+ this.insuranceFundStakeAccountAndSlot.slot > slot) {
41
+ return;
42
+ }
43
+ const account = this.program.account.user.coder.accounts.decode('InsuranceFundStake', buffer);
44
+ this.insuranceFundStakeAccountAndSlot = { data: account, slot };
45
+ this.eventEmitter.emit('insuranceFundStakeAccountUpdate', account);
46
+ this.eventEmitter.emit('update');
47
+ });
48
+ this.errorCallbackId = this.accountLoader.addErrorCallbacks((error) => {
49
+ this.eventEmitter.emit('error', error);
50
+ });
51
+ }
52
+ async fetchIfUnloaded() {
53
+ if (this.insuranceFundStakeAccountAndSlot === undefined) {
54
+ await this.fetch();
55
+ }
56
+ }
57
+ async fetch() {
58
+ var _a, _b;
59
+ try {
60
+ const dataAndContext = await this.program.account.insuranceFundStake.fetchAndContext(this.insuranceFundStakeAccountPublicKey, this.accountLoader.commitment);
61
+ if (dataAndContext.context.slot >
62
+ ((_b = (_a = this.insuranceFundStakeAccountAndSlot) === null || _a === void 0 ? void 0 : _a.slot) !== null && _b !== void 0 ? _b : 0)) {
63
+ this.insuranceFundStakeAccountAndSlot = {
64
+ data: dataAndContext.data,
65
+ slot: dataAndContext.context.slot,
66
+ };
67
+ }
68
+ }
69
+ catch (e) {
70
+ console.log(`PollingInsuranceFundStakeAccountSubscriber.fetch() InsuranceFundStake does not exist: ${e.message}`);
71
+ }
72
+ }
73
+ doesAccountExist() {
74
+ return this.insuranceFundStakeAccountAndSlot !== undefined;
75
+ }
76
+ async unsubscribe() {
77
+ if (!this.isSubscribed) {
78
+ return;
79
+ }
80
+ this.accountLoader.removeAccount(this.insuranceFundStakeAccountPublicKey, this.callbackId);
81
+ this.callbackId = undefined;
82
+ this.accountLoader.removeErrorCallbacks(this.errorCallbackId);
83
+ this.errorCallbackId = undefined;
84
+ this.isSubscribed = false;
85
+ }
86
+ assertIsSubscribed() {
87
+ if (!this.isSubscribed) {
88
+ throw new types_1.NotSubscribedError('You must call `subscribe` before using this function');
89
+ }
90
+ }
91
+ getInsuranceFundStakeAccountAndSlot() {
92
+ this.assertIsSubscribed();
93
+ return this.insuranceFundStakeAccountAndSlot;
94
+ }
95
+ didSubscriptionSucceed() {
96
+ return !!this.insuranceFundStakeAccountAndSlot;
97
+ }
98
+ updateData(insuranceFundStake, slot) {
99
+ if (!this.insuranceFundStakeAccountAndSlot ||
100
+ this.insuranceFundStakeAccountAndSlot.slot < slot) {
101
+ this.insuranceFundStakeAccountAndSlot = {
102
+ data: insuranceFundStake,
103
+ slot,
104
+ };
105
+ this.eventEmitter.emit('insuranceFundStakeAccountUpdate', insuranceFundStake);
106
+ this.eventEmitter.emit('update');
107
+ }
108
+ }
109
+ }
110
+ exports.PollingInsuranceFundStakeAccountSubscriber = PollingInsuranceFundStakeAccountSubscriber;
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
- import { SpotMarketAccount, PerpMarketAccount, OracleSource, StateAccount, UserAccount, UserStatsAccount } from '../types';
3
+ import { SpotMarketAccount, PerpMarketAccount, OracleSource, StateAccount, UserAccount, UserStatsAccount, InsuranceFundStake } from '../types';
4
4
  import StrictEventEmitter from 'strict-event-emitter-types';
5
5
  import { EventEmitter } from 'events';
6
6
  import { Context, PublicKey } from '@solana/web3.js';
@@ -73,6 +73,19 @@ export interface TokenAccountSubscriber {
73
73
  unsubscribe(): Promise<void>;
74
74
  getTokenAccountAndSlot(): DataAndSlot<Account>;
75
75
  }
76
+ export interface InsuranceFundStakeAccountSubscriber {
77
+ eventEmitter: StrictEventEmitter<EventEmitter, InsuranceFundStakeAccountEvents>;
78
+ isSubscribed: boolean;
79
+ subscribe(): Promise<boolean>;
80
+ fetch(): Promise<void>;
81
+ unsubscribe(): Promise<void>;
82
+ getInsuranceFundStakeAccountAndSlot(): DataAndSlot<InsuranceFundStake>;
83
+ }
84
+ export interface InsuranceFundStakeAccountEvents {
85
+ insuranceFundStakeAccountUpdate: (payload: InsuranceFundStake) => void;
86
+ update: void;
87
+ error: (e: Error) => void;
88
+ }
76
89
  export interface OracleEvents {
77
90
  oracleUpdate: (payload: OraclePriceData) => void;
78
91
  update: void;
@@ -0,0 +1,23 @@
1
+ /// <reference types="node" />
2
+ import { DataAndSlot, AccountSubscriber, InsuranceFundStakeAccountEvents, InsuranceFundStakeAccountSubscriber } from './types';
3
+ import { Program } from '@coral-xyz/anchor';
4
+ import StrictEventEmitter from 'strict-event-emitter-types';
5
+ import { EventEmitter } from 'events';
6
+ import { Commitment, PublicKey } from '@solana/web3.js';
7
+ import { InsuranceFundStake } from '../types';
8
+ export declare class WebSocketInsuranceFundStakeAccountSubscriber implements InsuranceFundStakeAccountSubscriber {
9
+ isSubscribed: boolean;
10
+ reconnectTimeoutMs?: number;
11
+ commitment?: Commitment;
12
+ program: Program;
13
+ eventEmitter: StrictEventEmitter<EventEmitter, InsuranceFundStakeAccountEvents>;
14
+ insuranceFundStakeAccountPublicKey: PublicKey;
15
+ insuranceFundStakeDataAccountSubscriber: AccountSubscriber<InsuranceFundStake>;
16
+ constructor(program: Program, insuranceFundStakeAccountPublicKey: PublicKey, reconnectTimeoutMs?: number, commitment?: Commitment);
17
+ subscribe(insuranceFundStakeAccount?: InsuranceFundStake): Promise<boolean>;
18
+ fetch(): Promise<void>;
19
+ unsubscribe(): Promise<void>;
20
+ assertIsSubscribed(): void;
21
+ getInsuranceFundStakeAccountAndSlot(): DataAndSlot<InsuranceFundStake>;
22
+ updateData(insuranceFundStake: InsuranceFundStake, slot: number): void;
23
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebSocketInsuranceFundStakeAccountSubscriber = void 0;
4
+ const types_1 = require("./types");
5
+ const events_1 = require("events");
6
+ const webSocketAccountSubscriber_1 = require("./webSocketAccountSubscriber");
7
+ class WebSocketInsuranceFundStakeAccountSubscriber {
8
+ constructor(program, insuranceFundStakeAccountPublicKey, reconnectTimeoutMs, commitment) {
9
+ this.isSubscribed = false;
10
+ this.program = program;
11
+ this.insuranceFundStakeAccountPublicKey =
12
+ insuranceFundStakeAccountPublicKey;
13
+ this.eventEmitter = new events_1.EventEmitter();
14
+ this.reconnectTimeoutMs = reconnectTimeoutMs;
15
+ this.commitment = commitment;
16
+ }
17
+ async subscribe(insuranceFundStakeAccount) {
18
+ if (this.isSubscribed) {
19
+ return true;
20
+ }
21
+ this.insuranceFundStakeDataAccountSubscriber =
22
+ new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('insuranceFundStake', this.program, this.insuranceFundStakeAccountPublicKey, undefined, this.reconnectTimeoutMs, this.commitment);
23
+ if (insuranceFundStakeAccount) {
24
+ this.insuranceFundStakeDataAccountSubscriber.setData(insuranceFundStakeAccount);
25
+ }
26
+ await this.insuranceFundStakeDataAccountSubscriber.subscribe((data) => {
27
+ this.eventEmitter.emit('insuranceFundStakeAccountUpdate', data);
28
+ this.eventEmitter.emit('update');
29
+ });
30
+ this.eventEmitter.emit('update');
31
+ this.isSubscribed = true;
32
+ return true;
33
+ }
34
+ async fetch() {
35
+ await Promise.all([this.insuranceFundStakeDataAccountSubscriber.fetch()]);
36
+ }
37
+ async unsubscribe() {
38
+ if (!this.isSubscribed) {
39
+ return;
40
+ }
41
+ await Promise.all([
42
+ this.insuranceFundStakeDataAccountSubscriber.unsubscribe(),
43
+ ]);
44
+ this.isSubscribed = false;
45
+ }
46
+ assertIsSubscribed() {
47
+ if (!this.isSubscribed) {
48
+ throw new types_1.NotSubscribedError('You must call `subscribe` before using this function');
49
+ }
50
+ }
51
+ getInsuranceFundStakeAccountAndSlot() {
52
+ this.assertIsSubscribed();
53
+ return this.insuranceFundStakeDataAccountSubscriber.dataAndSlot;
54
+ }
55
+ updateData(insuranceFundStake, slot) {
56
+ var _a;
57
+ const currentDataSlot = ((_a = this.insuranceFundStakeDataAccountSubscriber.dataAndSlot) === null || _a === void 0 ? void 0 : _a.slot) || 0;
58
+ if (currentDataSlot <= slot) {
59
+ this.insuranceFundStakeDataAccountSubscriber.setData(insuranceFundStake, slot);
60
+ this.eventEmitter.emit('insuranceFundStakeAccountUpdate', insuranceFundStake);
61
+ this.eventEmitter.emit('update');
62
+ }
63
+ }
64
+ }
65
+ exports.WebSocketInsuranceFundStakeAccountSubscriber = WebSocketInsuranceFundStakeAccountSubscriber;
@@ -68,11 +68,15 @@ export declare class DLOB {
68
68
  updateRestingLimitOrdersForMarketType(slot: number, marketTypeStr: MarketTypeStr): void;
69
69
  getOrder(orderId: number, userAccount: PublicKey): Order | undefined;
70
70
  findNodesToFill(marketIndex: number, fallbackBid: BN | undefined, fallbackAsk: BN | undefined, slot: number, ts: number, marketType: MarketType, oraclePriceData: OraclePriceData, stateAccount: StateAccount, marketAccount: PerpMarketAccount | SpotMarketAccount): NodeToFill[];
71
+ getMakerRebate(marketType: MarketType, stateAccount: StateAccount, marketAccount: PerpMarketAccount | SpotMarketAccount): {
72
+ makerRebateNumerator: number;
73
+ makerRebateDenominator: number;
74
+ };
71
75
  mergeNodesToFill(restingLimitOrderNodesToFill: NodeToFill[], takingOrderNodesToFill: NodeToFill[]): NodeToFill[];
72
- findRestingLimitOrderNodesToFill(marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData, isAmmPaused: boolean, minAuctionDuration: number, fallbackAsk: BN | undefined, fallbackBid: BN | undefined): NodeToFill[];
76
+ findRestingLimitOrderNodesToFill(marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData, isAmmPaused: boolean, minAuctionDuration: number, makerRebateNumerator: number, makerRebateDenominator: number, fallbackAsk: BN | undefined, fallbackBid: BN | undefined): NodeToFill[];
73
77
  findTakingNodesToFill(marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData, isAmmPaused: boolean, minAuctionDuration: number, fallbackAsk: BN | undefined, fallbackBid?: BN | undefined): NodeToFill[];
74
78
  findTakingNodesCrossingMakerNodes(marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData, takerNodeGenerator: Generator<DLOBNode>, makerNodeGeneratorFn: (marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData) => Generator<DLOBNode>, doesCross: (takerPrice: BN | undefined, makerPrice: BN) => boolean): NodeToFill[];
75
- findNodesCrossingFallbackLiquidity(marketType: MarketType, slot: number, oraclePriceData: OraclePriceData, nodeGenerator: Generator<DLOBNode>, fallbackPrice: BN, doesCross: (nodePrice: BN | undefined, fallbackPrice: BN) => boolean, minAuctionDuration: number): NodeToFill[];
79
+ findNodesCrossingFallbackLiquidity(marketType: MarketType, slot: number, oraclePriceData: OraclePriceData, nodeGenerator: Generator<DLOBNode>, doesCross: (nodePrice: BN | undefined) => boolean, minAuctionDuration: number): NodeToFill[];
76
80
  findExpiredNodesToFill(marketIndex: number, ts: number, marketType: MarketType): NodeToFill[];
77
81
  findJitAuctionNodesToFill(marketIndex: number, slot: number, oraclePriceData: OraclePriceData, marketType: MarketType): NodeToFill[];
78
82
  getTakingBids(marketIndex: number, marketType: MarketType, slot: number, oraclePriceData: OraclePriceData): Generator<DLOBNode>;
package/lib/dlob/DLOB.js CHANGED
@@ -304,7 +304,8 @@ class DLOB {
304
304
  const minAuctionDuration = (0, __1.isVariant)(marketType, 'perp')
305
305
  ? stateAccount.minPerpAuctionDuration
306
306
  : 0;
307
- const restingLimitOrderNodesToFill = this.findRestingLimitOrderNodesToFill(marketIndex, slot, marketType, oraclePriceData, isAmmPaused, minAuctionDuration, fallbackAsk, fallbackBid);
307
+ const { makerRebateNumerator, makerRebateDenominator } = this.getMakerRebate(marketType, stateAccount, marketAccount);
308
+ const restingLimitOrderNodesToFill = this.findRestingLimitOrderNodesToFill(marketIndex, slot, marketType, oraclePriceData, isAmmPaused, minAuctionDuration, makerRebateNumerator, makerRebateDenominator, fallbackAsk, fallbackBid);
308
309
  const takingOrderNodesToFill = this.findTakingNodesToFill(marketIndex, slot, marketType, oraclePriceData, isAmmPaused, minAuctionDuration, fallbackAsk, fallbackBid);
309
310
  // get expired market nodes
310
311
  const expiredNodesToFill = this.findExpiredNodesToFill(marketIndex, ts, marketType);
@@ -314,6 +315,28 @@ class DLOB {
314
315
  }
315
316
  return this.mergeNodesToFill(restingLimitOrderNodesToFill, takingOrderNodesToFill).concat(expiredNodesToFill);
316
317
  }
318
+ getMakerRebate(marketType, stateAccount, marketAccount) {
319
+ let makerRebateNumerator;
320
+ let makerRebateDenominator;
321
+ if ((0, __1.isVariant)(marketType, 'perp')) {
322
+ makerRebateNumerator =
323
+ stateAccount.perpFeeStructure.feeTiers[0].makerRebateNumerator;
324
+ makerRebateDenominator =
325
+ stateAccount.perpFeeStructure.feeTiers[0].makerRebateDenominator;
326
+ }
327
+ else {
328
+ makerRebateNumerator =
329
+ stateAccount.spotFeeStructure.feeTiers[0].makerRebateNumerator;
330
+ makerRebateDenominator =
331
+ stateAccount.spotFeeStructure.feeTiers[0].makerRebateDenominator;
332
+ }
333
+ // @ts-ignore
334
+ const feeAdjustment = marketAccount.feeAdjustment || 0;
335
+ if (feeAdjustment !== 0) {
336
+ makerRebateNumerator += (makerRebateNumerator * feeAdjustment) / 100;
337
+ }
338
+ return { makerRebateNumerator, makerRebateDenominator };
339
+ }
317
340
  mergeNodesToFill(restingLimitOrderNodesToFill, takingOrderNodesToFill) {
318
341
  const mergedNodesToFill = new Map();
319
342
  const mergeNodesToFillHelper = (nodesToFillArray) => {
@@ -336,7 +359,7 @@ class DLOB {
336
359
  mergeNodesToFillHelper(takingOrderNodesToFill);
337
360
  return Array.from(mergedNodesToFill.values());
338
361
  }
339
- findRestingLimitOrderNodesToFill(marketIndex, slot, marketType, oraclePriceData, isAmmPaused, minAuctionDuration, fallbackAsk, fallbackBid) {
362
+ findRestingLimitOrderNodesToFill(marketIndex, slot, marketType, oraclePriceData, isAmmPaused, minAuctionDuration, makerRebateNumerator, makerRebateDenominator, fallbackAsk, fallbackBid) {
340
363
  const nodesToFill = new Array();
341
364
  const crossingNodes = this.findCrossingRestingLimitOrders(marketIndex, slot, marketType, oraclePriceData);
342
365
  for (const crossingNode of crossingNodes) {
@@ -344,8 +367,9 @@ class DLOB {
344
367
  }
345
368
  if (fallbackBid && !isAmmPaused) {
346
369
  const askGenerator = this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData);
347
- const asksCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, askGenerator, fallbackBid, (askPrice, fallbackPrice) => {
348
- return askPrice.lte(fallbackPrice);
370
+ const fallbackBidWithBuffer = fallbackBid.sub(fallbackBid.muln(makerRebateNumerator).divn(makerRebateDenominator));
371
+ const asksCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, askGenerator, (askPrice) => {
372
+ return askPrice.lte(fallbackBidWithBuffer);
349
373
  }, minAuctionDuration);
350
374
  for (const askCrossingFallback of asksCrossingFallback) {
351
375
  nodesToFill.push(askCrossingFallback);
@@ -353,8 +377,9 @@ class DLOB {
353
377
  }
354
378
  if (fallbackAsk && !isAmmPaused) {
355
379
  const bidGenerator = this.getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData);
356
- const bidsCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, bidGenerator, fallbackAsk, (bidPrice, fallbackPrice) => {
357
- return bidPrice.gte(fallbackPrice);
380
+ const fallbackAskWithBuffer = fallbackAsk.add(fallbackAsk.muln(makerRebateNumerator).divn(makerRebateDenominator));
381
+ const bidsCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, bidGenerator, (bidPrice) => {
382
+ return bidPrice.gte(fallbackAskWithBuffer);
358
383
  }, minAuctionDuration);
359
384
  for (const bidCrossingFallback of bidsCrossingFallback) {
360
385
  nodesToFill.push(bidCrossingFallback);
@@ -381,8 +406,8 @@ class DLOB {
381
406
  }
382
407
  if (fallbackBid && !isAmmPaused) {
383
408
  takingOrderGenerator = this.getTakingAsks(marketIndex, marketType, slot, oraclePriceData);
384
- const takingAsksCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, takingOrderGenerator, fallbackBid, (takerPrice, fallbackPrice) => {
385
- return takerPrice === undefined || takerPrice.lte(fallbackPrice);
409
+ const takingAsksCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, takingOrderGenerator, (takerPrice) => {
410
+ return takerPrice === undefined || takerPrice.lte(fallbackBid);
386
411
  }, minAuctionDuration);
387
412
  for (const takingAskCrossingFallback of takingAsksCrossingFallback) {
388
413
  nodesToFill.push(takingAskCrossingFallback);
@@ -405,8 +430,8 @@ class DLOB {
405
430
  }
406
431
  if (fallbackAsk && !isAmmPaused) {
407
432
  takingOrderGenerator = this.getTakingBids(marketIndex, marketType, slot, oraclePriceData);
408
- const takingBidsCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, takingOrderGenerator, fallbackAsk, (takerPrice, fallbackPrice) => {
409
- return takerPrice === undefined || takerPrice.gte(fallbackPrice);
433
+ const takingBidsCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, takingOrderGenerator, (takerPrice) => {
434
+ return takerPrice === undefined || takerPrice.gte(fallbackAsk);
410
435
  }, minAuctionDuration);
411
436
  for (const marketBidCrossingFallback of takingBidsCrossingFallback) {
412
437
  nodesToFill.push(marketBidCrossingFallback);
@@ -456,7 +481,7 @@ class DLOB {
456
481
  }
457
482
  return nodesToFill;
458
483
  }
459
- findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, nodeGenerator, fallbackPrice, doesCross, minAuctionDuration) {
484
+ findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, nodeGenerator, doesCross, minAuctionDuration) {
460
485
  var _a;
461
486
  const nodesToFill = new Array();
462
487
  let nextNode = nodeGenerator.next();
@@ -468,7 +493,7 @@ class DLOB {
468
493
  }
469
494
  const nodePrice = (0, __1.getLimitPrice)(node.order, oraclePriceData, slot);
470
495
  // order crosses if there is no limit price or it crosses fallback price
471
- const crosses = doesCross(nodePrice, fallbackPrice);
496
+ const crosses = doesCross(nodePrice);
472
497
  // fallback is available if auction is complete or it's a spot order
473
498
  const fallbackAvailable = (0, __1.isVariant)(marketType, 'spot') ||
474
499
  (0, __1.isFallbackAvailableLiquiditySource)(node.order, minAuctionDuration, slot);