@drift-labs/jit-proxy 0.12.65 → 0.12.67

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.
@@ -2,6 +2,7 @@
2
2
  import { BN, DriftClient, MakerInfo, MarketType, PostOnlyParams, ReferrerInfo, TxParams, UserAccount } from '@drift-labs/sdk';
3
3
  import { PublicKey, TransactionInstruction } from '@solana/web3.js';
4
4
  import { TxSigAndSlot } from '@drift-labs/sdk';
5
+ import { SignedSwiftOrderParams } from '@drift-labs/sdk/lib/node/swift/types';
5
6
  export type JitIxParams = {
6
7
  takerKey: PublicKey;
7
8
  takerStatsKey: PublicKey;
@@ -16,6 +17,12 @@ export type JitIxParams = {
16
17
  referrerInfo?: ReferrerInfo;
17
18
  subAccountId?: number;
18
19
  };
20
+ export type JitSwiftIxParams = JitIxParams & {
21
+ authorityToUse: PublicKey;
22
+ signedSwiftOrderParams: SignedSwiftOrderParams;
23
+ uuid: Uint8Array;
24
+ marketIndex: number;
25
+ };
19
26
  export declare class PriceType {
20
27
  static readonly LIMIT: {
21
28
  limit: {};
@@ -38,7 +45,9 @@ export declare class JitProxyClient {
38
45
  programId: PublicKey;
39
46
  });
40
47
  jit(params: JitIxParams, txParams?: TxParams): Promise<TxSigAndSlot>;
48
+ jitSwift(params: JitSwiftIxParams, txParams?: TxParams, precedingIxs?: TransactionInstruction[]): Promise<TxSigAndSlot>;
41
49
  getJitIx({ takerKey, takerStatsKey, taker, takerOrderId, maxPosition, minPosition, bid, ask, postOnly, priceType, referrerInfo, subAccountId, }: JitIxParams): Promise<TransactionInstruction>;
50
+ getJitSwiftIx({ takerKey, takerStatsKey, taker, maxPosition, minPosition, bid, ask, postOnly, priceType, referrerInfo, subAccountId, uuid, marketIndex, }: JitSwiftIxParams): Promise<TransactionInstruction>;
42
51
  getCheckOrderConstraintIx({ subAccountId, orderConstraints, }: {
43
52
  subAccountId: number;
44
53
  orderConstraints: OrderConstraint[];
@@ -19,6 +19,16 @@ class JitProxyClient {
19
19
  const tx = await this.driftClient.buildTransaction([ix], txParams);
20
20
  return await this.driftClient.sendTransaction(tx);
21
21
  }
22
+ async jitSwift(params, txParams, precedingIxs) {
23
+ const swiftTakerIxs = await this.driftClient.getPlaceSwiftTakerPerpOrderIxs(params.signedSwiftOrderParams, params.marketIndex, {
24
+ taker: params.takerKey,
25
+ takerStats: params.takerStatsKey,
26
+ takerUserAccount: params.taker,
27
+ }, params.authorityToUse, precedingIxs);
28
+ const ix = await this.getJitSwiftIx(params);
29
+ const tx = await this.driftClient.buildTransaction([...swiftTakerIxs, ix], txParams);
30
+ return await this.driftClient.sendTransaction(tx);
31
+ }
22
32
  async getJitIx({ takerKey, takerStatsKey, taker, takerOrderId, maxPosition, minPosition, bid, ask, postOnly = null, priceType = PriceType.LIMIT, referrerInfo, subAccountId, }) {
23
33
  subAccountId =
24
34
  subAccountId !== undefined
@@ -80,6 +90,52 @@ class JitProxyClient {
80
90
  .remainingAccounts(remainingAccounts)
81
91
  .instruction();
82
92
  }
93
+ async getJitSwiftIx({ takerKey, takerStatsKey, taker, maxPosition, minPosition, bid, ask, postOnly = null, priceType = PriceType.LIMIT, referrerInfo, subAccountId, uuid, marketIndex, }) {
94
+ subAccountId =
95
+ subAccountId !== undefined
96
+ ? subAccountId
97
+ : this.driftClient.activeSubAccountId;
98
+ const remainingAccounts = this.driftClient.getRemainingAccounts({
99
+ userAccounts: [taker, this.driftClient.getUserAccount(subAccountId)],
100
+ writableSpotMarketIndexes: [],
101
+ writablePerpMarketIndexes: [marketIndex],
102
+ });
103
+ if (referrerInfo) {
104
+ remainingAccounts.push({
105
+ pubkey: referrerInfo.referrer,
106
+ isWritable: true,
107
+ isSigner: false,
108
+ });
109
+ remainingAccounts.push({
110
+ pubkey: referrerInfo.referrerStats,
111
+ isWritable: true,
112
+ isSigner: false,
113
+ });
114
+ }
115
+ const jitSwiftParams = {
116
+ swiftOrderUuid: Array.from(uuid),
117
+ maxPosition,
118
+ minPosition,
119
+ bid,
120
+ ask,
121
+ postOnly,
122
+ priceType,
123
+ };
124
+ return this.program.methods
125
+ .jitSwift(jitSwiftParams)
126
+ .accounts({
127
+ taker: takerKey,
128
+ takerStats: takerStatsKey,
129
+ takerSwiftUserOrders: (0, sdk_1.getSwiftUserAccountPublicKey)(this.driftClient.program.programId, taker.authority),
130
+ authority: this.driftClient.wallet.payer.publicKey,
131
+ state: await this.driftClient.getStatePublicKey(),
132
+ user: await this.driftClient.getUserAccountPublicKey(subAccountId),
133
+ userStats: this.driftClient.getUserStatsAccountPublicKey(),
134
+ driftProgram: this.driftClient.program.programId,
135
+ })
136
+ .remainingAccounts(remainingAccounts)
137
+ .instruction();
138
+ }
83
139
  async getCheckOrderConstraintIx({ subAccountId, orderConstraints, }) {
84
140
  subAccountId =
85
141
  subAccountId !== undefined
@@ -1,7 +1,8 @@
1
1
  /// <reference types="bn.js" />
2
2
  import { JitProxyClient, PriceType } from '../jitProxyClient';
3
3
  import { PublicKey } from '@solana/web3.js';
4
- import { AuctionSubscriber, BN, DriftClient, Order, PostOnlyParams, UserAccount, UserStatsMap } from '@drift-labs/sdk';
4
+ import { AuctionSubscriber, BN, DriftClient, Order, PostOnlyParams, SlotSubscriber, SwiftOrderSubscriber, UserAccount, UserStatsMap } from '@drift-labs/sdk';
5
+ import { SignedSwiftOrderParams } from '@drift-labs/sdk/lib/node/swift/types';
5
6
  export type UserFilter = (userAccount: UserAccount, userKey: string, order: Order) => boolean;
6
7
  export type JitParams = {
7
8
  bid: BN;
@@ -14,6 +15,8 @@ export type JitParams = {
14
15
  };
15
16
  export declare abstract class BaseJitter {
16
17
  auctionSubscriber: AuctionSubscriber;
18
+ swiftOrderSubscriber: SwiftOrderSubscriber;
19
+ slotSubscriber: SlotSubscriber;
17
20
  driftClient: DriftClient;
18
21
  jitProxyClient: JitProxyClient;
19
22
  userStatsMap: UserStatsMap;
@@ -24,16 +27,20 @@ export declare abstract class BaseJitter {
24
27
  userFilter: UserFilter;
25
28
  computeUnits: number;
26
29
  computeUnitsPrice: number;
27
- constructor({ auctionSubscriber, jitProxyClient, driftClient, userStatsMap, }: {
30
+ constructor({ auctionSubscriber, jitProxyClient, driftClient, userStatsMap, swiftOrderSubscriber, slotSubscriber, }: {
28
31
  driftClient: DriftClient;
29
32
  auctionSubscriber: AuctionSubscriber;
30
33
  jitProxyClient: JitProxyClient;
31
34
  userStatsMap: UserStatsMap;
35
+ swiftOrderSubscriber?: SwiftOrderSubscriber;
36
+ slotSubscriber?: SlotSubscriber;
32
37
  });
33
38
  subscribe(): Promise<void>;
34
39
  createTryFill(taker: UserAccount, takerKey: PublicKey, takerStatsKey: PublicKey, order: Order, orderSignature: string): () => Promise<void>;
40
+ createTrySwiftFill(authorityToUse: PublicKey, signedSwiftOrderParams: SignedSwiftOrderParams, uuid: Uint8Array, taker: UserAccount, takerKey: PublicKey, takerStatsKey: PublicKey, order: Order, orderSignature: string, marketIndex: number): () => Promise<void>;
35
41
  deleteOnGoingAuction(orderSignature: string): void;
36
42
  getOrderSignatures(takerKey: string, orderId: number): string;
43
+ private convertUuidToNumber;
37
44
  updatePerpParams(marketIndex: number, params: JitParams): void;
38
45
  updateSpotParams(marketIndex: number, params: JitParams): void;
39
46
  setUserFilter(userFilter: UserFilter | undefined): void;
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BaseJitter = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
4
5
  const sdk_1 = require("@drift-labs/sdk");
6
+ const tweetnacl_util_1 = require("tweetnacl-util");
5
7
  class BaseJitter {
6
- constructor({ auctionSubscriber, jitProxyClient, driftClient, userStatsMap, }) {
8
+ constructor({ auctionSubscriber, jitProxyClient, driftClient, userStatsMap, swiftOrderSubscriber, slotSubscriber, }) {
7
9
  this.perpParams = new Map();
8
10
  this.spotParams = new Map();
9
11
  this.seenOrders = new Set();
@@ -14,8 +16,14 @@ class BaseJitter {
14
16
  this.userStatsMap =
15
17
  userStatsMap ||
16
18
  new sdk_1.UserStatsMap(this.driftClient, new sdk_1.BulkAccountLoader(this.driftClient.connection, 'confirmed', 0));
19
+ this.slotSubscriber = slotSubscriber;
20
+ this.swiftOrderSubscriber = swiftOrderSubscriber;
21
+ if (this.swiftOrderSubscriber && !this.slotSubscriber) {
22
+ throw new Error('Slot subscriber is required for swift order subscriber');
23
+ }
17
24
  }
18
25
  async subscribe() {
26
+ var _a, _b;
19
27
  await this.driftClient.subscribe();
20
28
  await this.auctionSubscriber.subscribe();
21
29
  this.auctionSubscriber.eventEmitter.on('onAccountUpdate', async (taker, takerKey, slot) => {
@@ -69,10 +77,78 @@ class BaseJitter {
69
77
  }
70
78
  }
71
79
  });
80
+ await ((_a = this.slotSubscriber) === null || _a === void 0 ? void 0 : _a.subscribe());
81
+ await ((_b = this.swiftOrderSubscriber) === null || _b === void 0 ? void 0 : _b.subscribe(async (orderMessageRaw, swiftOrderParamsMessage) => {
82
+ var _a, _b, _c;
83
+ const swiftOrderParamsBufHex = Buffer.from(orderMessageRaw['order_message']);
84
+ const swiftOrderParamsBuf = Buffer.from(orderMessageRaw['order_message'], 'hex');
85
+ const { swiftOrderParams, subAccountId: takerSubaccountId, } = this.driftClient.decodeSwiftOrderParamsMessage(swiftOrderParamsBuf);
86
+ const takerAuthority = new web3_js_1.PublicKey(orderMessageRaw['taker_authority']);
87
+ const takerUserPubkey = await (0, sdk_1.getUserAccountPublicKey)(this.driftClient.program.programId, takerAuthority, takerSubaccountId);
88
+ const takerUserPubkeyString = takerUserPubkey.toBase58();
89
+ const takerUserAccount = (await this.swiftOrderSubscriber.userMap.mustGet(takerUserPubkey.toString())).getUserAccount();
90
+ const swiftOrder = {
91
+ status: sdk_1.OrderStatus.OPEN,
92
+ orderType: swiftOrderParams.orderType,
93
+ orderId: this.convertUuidToNumber(orderMessageRaw['uuid']),
94
+ slot: swiftOrderParamsMessage.slot,
95
+ marketIndex: swiftOrderParams.marketIndex,
96
+ marketType: sdk_1.MarketType.PERP,
97
+ baseAssetAmount: swiftOrderParams.baseAssetAmount,
98
+ auctionDuration: swiftOrderParams.auctionDuration,
99
+ auctionStartPrice: swiftOrderParams.auctionStartPrice,
100
+ auctionEndPrice: swiftOrderParams.auctionEndPrice,
101
+ immediateOrCancel: swiftOrderParams.immediateOrCancel,
102
+ direction: swiftOrderParams.direction,
103
+ postOnly: false,
104
+ oraclePriceOffset: (_a = swiftOrderParams.oraclePriceOffset) !== null && _a !== void 0 ? _a : 0,
105
+ maxTs: (_b = swiftOrderParams.maxTs) !== null && _b !== void 0 ? _b : sdk_1.ZERO,
106
+ reduceOnly: swiftOrderParams.reduceOnly,
107
+ triggerCondition: swiftOrderParams.triggerCondition,
108
+ // Rest are not necessary and set for type conforming
109
+ price: sdk_1.ZERO,
110
+ existingPositionDirection: sdk_1.PositionDirection.LONG,
111
+ triggerPrice: sdk_1.ZERO,
112
+ baseAssetAmountFilled: sdk_1.ZERO,
113
+ quoteAssetAmountFilled: sdk_1.ZERO,
114
+ quoteAssetAmount: sdk_1.ZERO,
115
+ userOrderId: 0,
116
+ };
117
+ swiftOrder.price = (0, sdk_1.getAuctionPrice)(swiftOrder, (_c = this.slotSubscriber) === null || _c === void 0 ? void 0 : _c.getSlot(), this.driftClient.getOracleDataForPerpMarket(swiftOrder.marketIndex)
118
+ .price);
119
+ if (this.userFilter) {
120
+ if (this.userFilter(takerUserAccount, takerUserPubkeyString, swiftOrder)) {
121
+ return;
122
+ }
123
+ }
124
+ const orderSignature = this.getOrderSignatures(takerUserPubkeyString, swiftOrder.orderId);
125
+ if (this.seenOrders.has(orderSignature)) {
126
+ return;
127
+ }
128
+ this.seenOrders.add(orderSignature);
129
+ if (this.onGoingAuctions.has(orderSignature)) {
130
+ return;
131
+ }
132
+ if (!this.perpParams.has(swiftOrder.marketIndex)) {
133
+ return;
134
+ }
135
+ const perpMarketAccount = this.driftClient.getPerpMarketAccount(swiftOrder.marketIndex);
136
+ if (swiftOrder.baseAssetAmount.lt(perpMarketAccount.amm.minOrderSize)) {
137
+ return;
138
+ }
139
+ const promise = this.createTrySwiftFill(takerAuthority, {
140
+ orderParams: swiftOrderParamsBufHex,
141
+ signature: Buffer.from(orderMessageRaw['order_signature'], 'base64'),
142
+ }, (0, tweetnacl_util_1.decodeUTF8)(orderMessageRaw['uuid']), takerUserAccount, takerUserPubkey, (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, takerUserAccount.authority), swiftOrder, orderSignature, orderMessageRaw['market_index']).bind(this)();
143
+ this.onGoingAuctions.set(orderSignature, promise);
144
+ }));
72
145
  }
73
146
  createTryFill(taker, takerKey, takerStatsKey, order, orderSignature) {
74
147
  throw new Error('Not implemented');
75
148
  }
149
+ createTrySwiftFill(authorityToUse, signedSwiftOrderParams, uuid, taker, takerKey, takerStatsKey, order, orderSignature, marketIndex) {
150
+ throw new Error('Not implemented');
151
+ }
76
152
  deleteOnGoingAuction(orderSignature) {
77
153
  this.onGoingAuctions.delete(orderSignature);
78
154
  this.seenOrders.delete(orderSignature);
@@ -80,6 +156,12 @@ class BaseJitter {
80
156
  getOrderSignatures(takerKey, orderId) {
81
157
  return `${takerKey}-${orderId}`;
82
158
  }
159
+ convertUuidToNumber(uuid) {
160
+ return uuid
161
+ .split('')
162
+ .reduce((n, c) => n * 64 +
163
+ '_~0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.indexOf(c), 0);
164
+ }
83
165
  updatePerpParams(marketIndex, params) {
84
166
  this.perpParams.set(marketIndex, params);
85
167
  }
@@ -1,13 +1,17 @@
1
1
  import { JitProxyClient } from '../jitProxyClient';
2
2
  import { PublicKey } from '@solana/web3.js';
3
- import { AuctionSubscriber, DriftClient, Order, UserAccount, UserStatsMap } from '@drift-labs/sdk';
3
+ import { AuctionSubscriber, DriftClient, Order, SlotSubscriber, SwiftOrderSubscriber, UserAccount, UserStatsMap } from '@drift-labs/sdk';
4
4
  import { BaseJitter } from './baseJitter';
5
+ import { SignedSwiftOrderParams } from '@drift-labs/sdk/lib/node/swift/types';
5
6
  export declare class JitterShotgun extends BaseJitter {
6
- constructor({ auctionSubscriber, jitProxyClient, driftClient, userStatsMap, }: {
7
+ constructor({ auctionSubscriber, jitProxyClient, driftClient, userStatsMap, swiftOrderSubscriber, slotSubscriber, }: {
7
8
  driftClient: DriftClient;
8
9
  auctionSubscriber: AuctionSubscriber;
9
10
  jitProxyClient: JitProxyClient;
10
11
  userStatsMap?: UserStatsMap;
12
+ swiftOrderSubscriber?: SwiftOrderSubscriber;
13
+ slotSubscriber?: SlotSubscriber;
11
14
  });
12
15
  createTryFill(taker: UserAccount, takerKey: PublicKey, takerStatsKey: PublicKey, order: Order, orderSignature: string): () => Promise<void>;
16
+ createTrySwiftFill(authorityToUse: PublicKey, signedSwiftOrderParams: SignedSwiftOrderParams, uuid: Uint8Array, taker: UserAccount, takerKey: PublicKey, takerStatsKey: PublicKey, order: Order, orderSignature: string, marketIndex: number): () => Promise<void>;
13
17
  }
@@ -4,12 +4,14 @@ exports.JitterShotgun = void 0;
4
4
  const sdk_1 = require("@drift-labs/sdk");
5
5
  const baseJitter_1 = require("./baseJitter");
6
6
  class JitterShotgun extends baseJitter_1.BaseJitter {
7
- constructor({ auctionSubscriber, jitProxyClient, driftClient, userStatsMap, }) {
7
+ constructor({ auctionSubscriber, jitProxyClient, driftClient, userStatsMap, swiftOrderSubscriber, slotSubscriber, }) {
8
8
  super({
9
9
  auctionSubscriber,
10
10
  jitProxyClient,
11
11
  driftClient,
12
12
  userStatsMap,
13
+ swiftOrderSubscriber,
14
+ slotSubscriber,
13
15
  });
14
16
  }
15
17
  createTryFill(taker, takerKey, takerStatsKey, order, orderSignature) {
@@ -72,6 +74,71 @@ class JitterShotgun extends baseJitter_1.BaseJitter {
72
74
  this.deleteOnGoingAuction(orderSignature);
73
75
  };
74
76
  }
77
+ createTrySwiftFill(authorityToUse, signedSwiftOrderParams, uuid, taker, takerKey, takerStatsKey, order, orderSignature, marketIndex) {
78
+ return async () => {
79
+ var _a;
80
+ let i = 0;
81
+ const takerStats = await this.userStatsMap.mustGet(taker.authority.toString());
82
+ const referrerInfo = takerStats.getReferrerInfo();
83
+ // assumes each preflight simulation takes ~1 slot
84
+ while (i < order.auctionDuration) {
85
+ const params = this.perpParams.get(order.marketIndex);
86
+ if (!params) {
87
+ this.deleteOnGoingAuction(orderSignature);
88
+ return;
89
+ }
90
+ const txParams = {
91
+ computeUnits: this.computeUnits,
92
+ computeUnitsPrice: this.computeUnitsPrice,
93
+ };
94
+ console.log(`Trying to fill ${orderSignature}`);
95
+ try {
96
+ const { txSig } = await this.jitProxyClient.jitSwift({
97
+ takerKey,
98
+ takerStatsKey,
99
+ taker,
100
+ takerOrderId: order.orderId,
101
+ maxPosition: params.maxPosition,
102
+ minPosition: params.minPosition,
103
+ bid: params.bid,
104
+ ask: params.ask,
105
+ postOnly: (_a = params.postOnlyParams) !== null && _a !== void 0 ? _a : sdk_1.PostOnlyParams.MUST_POST_ONLY,
106
+ priceType: params.priceType,
107
+ referrerInfo,
108
+ subAccountId: params.subAccountId,
109
+ authorityToUse,
110
+ signedSwiftOrderParams,
111
+ uuid,
112
+ marketIndex,
113
+ }, txParams);
114
+ console.log(`Successfully sent tx for ${orderSignature} txSig ${txSig}`);
115
+ await sleep(10000);
116
+ this.deleteOnGoingAuction(orderSignature);
117
+ return;
118
+ }
119
+ catch (e) {
120
+ console.error(`Failed to fill ${orderSignature}`);
121
+ console.log(e);
122
+ if (e.message.includes('0x1770') || e.message.includes('0x1771')) {
123
+ console.log('Order does not cross params yet, retrying');
124
+ }
125
+ else if (e.message.includes('0x1779')) {
126
+ console.log('Order could not fill');
127
+ }
128
+ else if (e.message.includes('0x1793')) {
129
+ console.log('Oracle invalid, retrying');
130
+ }
131
+ else {
132
+ await sleep(10000);
133
+ this.deleteOnGoingAuction(orderSignature);
134
+ return;
135
+ }
136
+ }
137
+ i++;
138
+ }
139
+ this.deleteOnGoingAuction(orderSignature);
140
+ };
141
+ }
75
142
  }
76
143
  exports.JitterShotgun = JitterShotgun;
77
144
  function sleep(ms) {
@@ -1,7 +1,8 @@
1
1
  import { JitProxyClient } from '../jitProxyClient';
2
2
  import { PublicKey } from '@solana/web3.js';
3
- import { AuctionSubscriber, DriftClient, OraclePriceData, Order, SlotSubscriber, UserAccount, UserStatsMap } from '@drift-labs/sdk';
3
+ import { AuctionSubscriber, DriftClient, OraclePriceData, Order, SlotSubscriber, SwiftOrderSubscriber, UserAccount, UserStatsMap } from '@drift-labs/sdk';
4
4
  import { BaseJitter } from './baseJitter';
5
+ import { SignedSwiftOrderParams } from '@drift-labs/sdk/lib/node/swift/types';
5
6
  type AuctionAndOrderDetails = {
6
7
  slotsTilCross: number;
7
8
  willCross: boolean;
@@ -15,14 +16,16 @@ type AuctionAndOrderDetails = {
15
16
  export declare class JitterSniper extends BaseJitter {
16
17
  slotSubscriber: SlotSubscriber;
17
18
  userStatsMap: UserStatsMap;
18
- constructor({ auctionSubscriber, slotSubscriber, jitProxyClient, driftClient, userStatsMap, }: {
19
+ constructor({ auctionSubscriber, slotSubscriber, jitProxyClient, driftClient, userStatsMap, swiftOrderSubscriber, }: {
19
20
  driftClient: DriftClient;
20
21
  slotSubscriber: SlotSubscriber;
21
22
  auctionSubscriber: AuctionSubscriber;
22
23
  jitProxyClient: JitProxyClient;
23
24
  userStatsMap?: UserStatsMap;
25
+ swiftOrderSubscriber?: SwiftOrderSubscriber;
24
26
  });
25
27
  createTryFill(taker: UserAccount, takerKey: PublicKey, takerStatsKey: PublicKey, order: Order, orderSignature: string): () => Promise<void>;
28
+ createTrySwiftFill(authorityToUse: PublicKey, signedSwiftOrderParams: SignedSwiftOrderParams, uuid: Uint8Array, taker: UserAccount, takerKey: PublicKey, takerStatsKey: PublicKey, order: Order, orderSignature: string, marketIndex: number): () => Promise<void>;
26
29
  getAuctionAndOrderDetails(order: Order): AuctionAndOrderDetails;
27
30
  waitForSlotOrCrossOrExpiry(targetSlot: number, order: Order, initialDetails: AuctionAndOrderDetails): Promise<{
28
31
  slot: number;
@@ -4,12 +4,14 @@ exports.JitterSniper = void 0;
4
4
  const sdk_1 = require("@drift-labs/sdk");
5
5
  const baseJitter_1 = require("./baseJitter");
6
6
  class JitterSniper extends baseJitter_1.BaseJitter {
7
- constructor({ auctionSubscriber, slotSubscriber, jitProxyClient, driftClient, userStatsMap, }) {
7
+ constructor({ auctionSubscriber, slotSubscriber, jitProxyClient, driftClient, userStatsMap, swiftOrderSubscriber, }) {
8
8
  super({
9
9
  auctionSubscriber,
10
10
  jitProxyClient,
11
11
  driftClient,
12
12
  userStatsMap,
13
+ swiftOrderSubscriber,
14
+ slotSubscriber,
13
15
  });
14
16
  this.slotSubscriber = slotSubscriber;
15
17
  }
@@ -142,6 +144,139 @@ class JitterSniper extends baseJitter_1.BaseJitter {
142
144
  this.deleteOnGoingAuction(orderSignature);
143
145
  };
144
146
  }
147
+ createTrySwiftFill(authorityToUse, signedSwiftOrderParams, uuid, taker, takerKey, takerStatsKey, order, orderSignature, marketIndex) {
148
+ return async () => {
149
+ const params = this.perpParams.get(order.marketIndex);
150
+ if (!params) {
151
+ this.deleteOnGoingAuction(orderSignature);
152
+ return;
153
+ }
154
+ const takerStats = await this.userStatsMap.mustGet(taker.authority.toString());
155
+ const referrerInfo = takerStats.getReferrerInfo();
156
+ const { slotsTilCross, willCross, bid, ask, auctionStartPrice, auctionEndPrice, stepSize, oraclePrice, } = this.getAuctionAndOrderDetails(order);
157
+ // don't increase risk if we're past max positions
158
+ if ((0, sdk_1.isVariant)(order.marketType, 'perp')) {
159
+ const currPerpPos = this.driftClient.getUser().getPerpPosition(order.marketIndex) ||
160
+ this.driftClient.getUser().getEmptyPosition(order.marketIndex);
161
+ if (currPerpPos.baseAssetAmount.lt(sdk_1.ZERO) &&
162
+ (0, sdk_1.isVariant)(order.direction, 'short')) {
163
+ if (currPerpPos.baseAssetAmount.lte(params.minPosition)) {
164
+ console.log(`Order would increase existing short (mkt ${(0, sdk_1.getVariant)(order.marketType)}-${order.marketIndex}) too much`);
165
+ this.deleteOnGoingAuction(orderSignature);
166
+ return;
167
+ }
168
+ }
169
+ else if (currPerpPos.baseAssetAmount.gt(sdk_1.ZERO) &&
170
+ (0, sdk_1.isVariant)(order.direction, 'long')) {
171
+ if (currPerpPos.baseAssetAmount.gte(params.maxPosition)) {
172
+ console.log(`Order would increase existing long (mkt ${(0, sdk_1.getVariant)(order.marketType)}-${order.marketIndex}) too much`);
173
+ this.deleteOnGoingAuction(orderSignature);
174
+ return;
175
+ }
176
+ }
177
+ }
178
+ console.log(`
179
+ Taker wants to ${JSON.stringify(order.direction)}, order slot is ${order.slot.toNumber()},
180
+ My market: ${bid}@${ask},
181
+ Auction: ${auctionStartPrice} -> ${auctionEndPrice}, step size ${stepSize}
182
+ Current slot: ${this.slotSubscriber.currentSlot}, Order slot: ${order.slot.toNumber()},
183
+ Will cross?: ${willCross}
184
+ Slots to wait: ${slotsTilCross}. Target slot = ${order.slot.toNumber() + slotsTilCross}
185
+ `);
186
+ this.waitForSlotOrCrossOrExpiry(willCross
187
+ ? order.slot.toNumber() + slotsTilCross
188
+ : order.slot.toNumber() + order.auctionDuration + 1, order, {
189
+ slotsTilCross,
190
+ willCross,
191
+ bid,
192
+ ask,
193
+ auctionStartPrice,
194
+ auctionEndPrice,
195
+ stepSize,
196
+ oraclePrice,
197
+ }).then(async ({ slot, updatedDetails }) => {
198
+ var _a;
199
+ if (slot === -1) {
200
+ console.log('Auction expired without crossing');
201
+ this.deleteOnGoingAuction(orderSignature);
202
+ return;
203
+ }
204
+ const params = (0, sdk_1.isVariant)(order.marketType, 'perp')
205
+ ? this.perpParams.get(order.marketIndex)
206
+ : this.spotParams.get(order.marketIndex);
207
+ const bid = (0, sdk_1.isVariant)(params.priceType, 'oracle')
208
+ ? (0, sdk_1.convertToNumber)(oraclePrice.price.add(params.bid), sdk_1.PRICE_PRECISION)
209
+ : (0, sdk_1.convertToNumber)(params.bid, sdk_1.PRICE_PRECISION);
210
+ const ask = (0, sdk_1.isVariant)(params.priceType, 'oracle')
211
+ ? (0, sdk_1.convertToNumber)(oraclePrice.price.add(params.ask), sdk_1.PRICE_PRECISION)
212
+ : (0, sdk_1.convertToNumber)(params.ask, sdk_1.PRICE_PRECISION);
213
+ const auctionPrice = (0, sdk_1.convertToNumber)((0, sdk_1.getAuctionPrice)(order, slot, updatedDetails.oraclePrice.price), sdk_1.PRICE_PRECISION);
214
+ console.log(`
215
+ Expected auction price: ${auctionStartPrice + slotsTilCross * stepSize}
216
+ Actual auction price: ${auctionPrice}
217
+ -----------------
218
+ Looking for slot ${order.slot.toNumber() + slotsTilCross}
219
+ Got slot ${slot}
220
+ `);
221
+ console.log(`Trying to fill ${orderSignature} with:
222
+ market: ${bid}@${ask}
223
+ auction price: ${auctionPrice}
224
+ submitting" ${(0, sdk_1.convertToNumber)(params.bid, sdk_1.PRICE_PRECISION)}@${(0, sdk_1.convertToNumber)(params.ask, sdk_1.PRICE_PRECISION)}
225
+ `);
226
+ let i = 0;
227
+ while (i < 10) {
228
+ try {
229
+ const txParams = {
230
+ computeUnits: this.computeUnits,
231
+ computeUnitsPrice: this.computeUnitsPrice,
232
+ };
233
+ const { txSig } = await this.jitProxyClient.jitSwift({
234
+ takerKey,
235
+ takerStatsKey,
236
+ taker,
237
+ takerOrderId: order.orderId,
238
+ maxPosition: params.maxPosition,
239
+ minPosition: params.minPosition,
240
+ bid: params.bid,
241
+ ask: params.ask,
242
+ postOnly: (_a = params.postOnlyParams) !== null && _a !== void 0 ? _a : sdk_1.PostOnlyParams.MUST_POST_ONLY,
243
+ priceType: params.priceType,
244
+ referrerInfo,
245
+ subAccountId: params.subAccountId,
246
+ authorityToUse,
247
+ signedSwiftOrderParams,
248
+ uuid,
249
+ marketIndex,
250
+ }, txParams);
251
+ console.log(`Filled ${orderSignature} txSig ${txSig}`);
252
+ await sleep(3000);
253
+ this.deleteOnGoingAuction(orderSignature);
254
+ return;
255
+ }
256
+ catch (e) {
257
+ console.error(`Failed to fill ${orderSignature}`);
258
+ if (e.message.includes('0x1770') || e.message.includes('0x1771')) {
259
+ console.log('Order does not cross params yet');
260
+ }
261
+ else if (e.message.includes('0x1779')) {
262
+ console.log('Order could not fill');
263
+ }
264
+ else if (e.message.includes('0x1793')) {
265
+ console.log('Oracle invalid');
266
+ }
267
+ else {
268
+ await sleep(3000);
269
+ this.deleteOnGoingAuction(orderSignature);
270
+ return;
271
+ }
272
+ }
273
+ await sleep(200);
274
+ i++;
275
+ }
276
+ });
277
+ this.deleteOnGoingAuction(orderSignature);
278
+ };
279
+ }
145
280
  getAuctionAndOrderDetails(order) {
146
281
  // Find number of slots until the order is expected to be in cross
147
282
  const params = (0, sdk_1.isVariant)(order.marketType, 'perp')