@drift-labs/jit-proxy 0.7.0 → 0.9.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.
package/Readme.md ADDED
@@ -0,0 +1,58 @@
1
+ # Jit Proxy SDK
2
+
3
+ ## Jit Proxy Client
4
+
5
+ ```JitProxyClient``` will create and send transactions to the jit proxy program. Instantiate a jit proxy client with a drift client and a program Id. The current public key for the jit proxy program is
6
+
7
+ ```J1TnP8zvVxbtF5KFp5xRmWuvG9McnhzmBd9XGfCyuxFP```. Example instantiation:
8
+
9
+ ```
10
+ const jitProxyClient = new JitProxyClient({
11
+ driftClient,
12
+ programId: new PublicKey('J1TnP8zvVxbtF5KFp5xRmWuvG9McnhzmBd9XGfCyuxFP'),
13
+ });
14
+ ```
15
+
16
+ ## Jitter
17
+
18
+ A jitter takes ```JitParams``` and uses them to determine when and how to use the ```JitProxyClient``` to send a transaction. For bots to make use of the jitter, they should create a jitter instance, and then set the ```JitParams``` according to their strategy for each market they are market making. ```JitParams``` are set on the Jitter object using ```updatePerpParams()``` and ```updateSpotParams()```. There are two kinds of Jitters that can be insantiated: ```JitterShotgun``` and ```JitterSniper```. The difference between the two is how orders are sent.
19
+
20
+ For ```JitterShotgun```, orders are sent immediately when detecting a new eligible auction. The JitterShotgun will try up to 10 times to fill the order, retrying every time the it receives back an error due to the order not crossing the bid/ask in the ```JitParams``` or the oracle price being invalid.
21
+
22
+ For ```JitterSniper```, orders are sent only when it detects that an order might cross the bid/ask of the ```JitParams```, waiting until the right slot, before sending up to 3 orders (retrying on errors). It will not send orders if the price of the order does not cross the bid/ask during the auction, unlike the JitterShotgun, which will immediately attempt.
23
+
24
+ ## Jit Params
25
+
26
+ Type definition for the JitParmas is below:
27
+
28
+ ```
29
+ export type JitParams = {
30
+ bid: BN;
31
+ ask: BN;
32
+ minPosition: BN;
33
+ maxPosition: BN;
34
+ priceType: PriceType;
35
+ subAccountId?: number;
36
+ };
37
+ ```
38
+
39
+ PriceType options are ```ORACLE``` and ```LIMIT```. Limit price type is the BN representaiton of an absolute price; i.e., price type of LIMIT and a market of bid: 10, ask: 11 means your market is 10@11. Oracle price types are offsets relative to the oralce price for a given slot. They are always added to the oracle price, so if the oracle price is 10.5, to get a market of 10@11 when price type is oracle, bid and ask are -0.5 and 0.5 respectively (Remember that bid and ask are of BN type, this example is for illustration purposes only. Remember to use BN math operations).
40
+
41
+ ## Example set up
42
+
43
+ Example set up for the JitterSniper (assuming parameters are already initialized/subscribed to). JitterShotgun is instantiated and initialized in a similar manner.
44
+
45
+ ```
46
+ const jitProxyClient = new JitProxyClient({
47
+ driftClient,
48
+ programId: new PublicKey('J1TnP8zvVxbtF5KFp5xRmWuvG9McnhzmBd9XGfCyuxFP'),
49
+ });
50
+
51
+ const jitter = new JitterSniper({
52
+ auctionSubscriber,
53
+ driftClient,
54
+ slotSubscriber,
55
+ jitProxyClient,
56
+ });
57
+ await jitter.subscribe();
58
+ ```
@@ -1,5 +1,5 @@
1
1
  /// <reference types="bn.js" />
2
- import { BN, DriftClient, PostOnlyParams, ReferrerInfo, TxParams, UserAccount } from '@drift-labs/sdk';
2
+ import { BN, DriftClient, 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/lib/tx/types';
5
5
  export declare type JitIxParams = {
@@ -24,6 +24,12 @@ export declare class PriceType {
24
24
  oracle: {};
25
25
  };
26
26
  }
27
+ export declare type OrderConstraint = {
28
+ maxPosition: BN;
29
+ minPosition: BN;
30
+ marketIndex: number;
31
+ marketType: MarketType;
32
+ };
27
33
  export declare class JitProxyClient {
28
34
  private driftClient;
29
35
  private program;
@@ -33,4 +39,8 @@ export declare class JitProxyClient {
33
39
  });
34
40
  jit(params: JitIxParams, txParams?: TxParams): Promise<TxSigAndSlot>;
35
41
  getJitIx({ takerKey, takerStatsKey, taker, takerOrderId, maxPosition, minPosition, bid, ask, postOnly, priceType, referrerInfo, subAccountId, }: JitIxParams): Promise<TransactionInstruction>;
42
+ getCheckOrderConstraintIx({ subAccountId, orderConstraints, }: {
43
+ subAccountId: number;
44
+ orderConstraints: OrderConstraint[];
45
+ }): Promise<TransactionInstruction>;
36
46
  }
@@ -80,5 +80,33 @@ class JitProxyClient {
80
80
  .remainingAccounts(remainingAccounts)
81
81
  .instruction();
82
82
  }
83
+ async getCheckOrderConstraintIx({ subAccountId, orderConstraints, }) {
84
+ subAccountId =
85
+ subAccountId !== undefined
86
+ ? subAccountId
87
+ : this.driftClient.activeSubAccountId;
88
+ const readablePerpMarketIndex = [];
89
+ const readableSpotMarketIndexes = [];
90
+ for (const orderConstraint of orderConstraints) {
91
+ if (sdk_1.isVariant(orderConstraint.marketType, 'perp')) {
92
+ readablePerpMarketIndex.push(orderConstraint.marketIndex);
93
+ }
94
+ else {
95
+ readableSpotMarketIndexes.push(orderConstraint.marketIndex);
96
+ }
97
+ }
98
+ const remainingAccounts = this.driftClient.getRemainingAccounts({
99
+ userAccounts: [this.driftClient.getUserAccount(subAccountId)],
100
+ readableSpotMarketIndexes,
101
+ readablePerpMarketIndex,
102
+ });
103
+ return this.program.methods
104
+ .checkOrderConstraints(orderConstraints)
105
+ .accounts({
106
+ user: await this.driftClient.getUserAccountPublicKey(subAccountId),
107
+ })
108
+ .remainingAccounts(remainingAccounts)
109
+ .instruction();
110
+ }
83
111
  }
84
112
  exports.JitProxyClient = JitProxyClient;
@@ -1,5 +1,5 @@
1
1
  export declare type JitProxy = {
2
- version: '0.1.0';
2
+ version: '0.9.0';
3
3
  name: 'jit_proxy';
4
4
  instructions: [
5
5
  {
@@ -49,6 +49,26 @@ export declare type JitProxy = {
49
49
  };
50
50
  }
51
51
  ];
52
+ },
53
+ {
54
+ name: 'checkOrderConstraints';
55
+ accounts: [
56
+ {
57
+ name: 'user';
58
+ isMut: false;
59
+ isSigner: false;
60
+ }
61
+ ];
62
+ args: [
63
+ {
64
+ name: 'constraints';
65
+ type: {
66
+ vec: {
67
+ defined: 'OrderConstraint';
68
+ };
69
+ };
70
+ }
71
+ ];
52
72
  }
53
73
  ];
54
74
  types: [
@@ -94,6 +114,32 @@ export declare type JitProxy = {
94
114
  ];
95
115
  };
96
116
  },
117
+ {
118
+ name: 'OrderConstraint';
119
+ type: {
120
+ kind: 'struct';
121
+ fields: [
122
+ {
123
+ name: 'maxPosition';
124
+ type: 'i64';
125
+ },
126
+ {
127
+ name: 'minPosition';
128
+ type: 'i64';
129
+ },
130
+ {
131
+ name: 'marketIndex';
132
+ type: 'u16';
133
+ },
134
+ {
135
+ name: 'marketType';
136
+ type: {
137
+ defined: 'MarketType';
138
+ };
139
+ }
140
+ ];
141
+ };
142
+ },
97
143
  {
98
144
  name: 'PostOnlyParam';
99
145
  type: {
@@ -124,6 +170,20 @@ export declare type JitProxy = {
124
170
  }
125
171
  ];
126
172
  };
173
+ },
174
+ {
175
+ name: 'MarketType';
176
+ type: {
177
+ kind: 'enum';
178
+ variants: [
179
+ {
180
+ name: 'Perp';
181
+ },
182
+ {
183
+ name: 'Spot';
184
+ }
185
+ ];
186
+ };
127
187
  }
128
188
  ];
129
189
  errors: [
@@ -141,6 +201,11 @@ export declare type JitProxy = {
141
201
  code: 6002;
142
202
  name: 'TakerOrderNotFound';
143
203
  msg: 'TakerOrderNotFound';
204
+ },
205
+ {
206
+ code: 6003;
207
+ name: 'OrderSizeBreached';
208
+ msg: 'OrderSizeBreached';
144
209
  }
145
210
  ];
146
211
  };
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.IDL = void 0;
4
4
  exports.IDL = {
5
- version: '0.1.0',
5
+ version: '0.9.0',
6
6
  name: 'jit_proxy',
7
7
  instructions: [
8
8
  {
@@ -53,6 +53,26 @@ exports.IDL = {
53
53
  },
54
54
  ],
55
55
  },
56
+ {
57
+ name: 'checkOrderConstraints',
58
+ accounts: [
59
+ {
60
+ name: 'user',
61
+ isMut: false,
62
+ isSigner: false,
63
+ },
64
+ ],
65
+ args: [
66
+ {
67
+ name: 'constraints',
68
+ type: {
69
+ vec: {
70
+ defined: 'OrderConstraint',
71
+ },
72
+ },
73
+ },
74
+ ],
75
+ },
56
76
  ],
57
77
  types: [
58
78
  {
@@ -97,6 +117,32 @@ exports.IDL = {
97
117
  ],
98
118
  },
99
119
  },
120
+ {
121
+ name: 'OrderConstraint',
122
+ type: {
123
+ kind: 'struct',
124
+ fields: [
125
+ {
126
+ name: 'maxPosition',
127
+ type: 'i64',
128
+ },
129
+ {
130
+ name: 'minPosition',
131
+ type: 'i64',
132
+ },
133
+ {
134
+ name: 'marketIndex',
135
+ type: 'u16',
136
+ },
137
+ {
138
+ name: 'marketType',
139
+ type: {
140
+ defined: 'MarketType',
141
+ },
142
+ },
143
+ ],
144
+ },
145
+ },
100
146
  {
101
147
  name: 'PostOnlyParam',
102
148
  type: {
@@ -128,6 +174,20 @@ exports.IDL = {
128
174
  ],
129
175
  },
130
176
  },
177
+ {
178
+ name: 'MarketType',
179
+ type: {
180
+ kind: 'enum',
181
+ variants: [
182
+ {
183
+ name: 'Perp',
184
+ },
185
+ {
186
+ name: 'Spot',
187
+ },
188
+ ],
189
+ },
190
+ },
131
191
  ],
132
192
  errors: [
133
193
  {
@@ -145,5 +205,10 @@ exports.IDL = {
145
205
  name: 'TakerOrderNotFound',
146
206
  msg: 'TakerOrderNotFound',
147
207
  },
208
+ {
209
+ code: 6003,
210
+ name: 'OrderSizeBreached',
211
+ msg: 'OrderSizeBreached',
212
+ },
148
213
  ],
149
214
  };
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@drift-labs/jit-proxy",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "dependencies": {
5
5
  "@coral-xyz/anchor": "^0.26.0",
6
6
  "@solana/web3.js": "1.73.2",
7
- "@drift-labs/sdk": "^2.37.1-beta.2"
7
+ "@drift-labs/sdk": "^2.38.0"
8
8
  },
9
9
  "engines": {
10
10
  "node": ">=16"
@@ -2,6 +2,7 @@ import {
2
2
  BN,
3
3
  DriftClient,
4
4
  isVariant,
5
+ MarketType,
5
6
  PostOnlyParams,
6
7
  QUOTE_SPOT_MARKET_INDEX,
7
8
  ReferrerInfo,
@@ -33,6 +34,13 @@ export class PriceType {
33
34
  static readonly ORACLE = { oracle: {} };
34
35
  }
35
36
 
37
+ export type OrderConstraint = {
38
+ maxPosition: BN;
39
+ minPosition: BN;
40
+ marketIndex: number;
41
+ marketType: MarketType;
42
+ };
43
+
36
44
  export class JitProxyClient {
37
45
  private driftClient: DriftClient;
38
46
  private program: Program<JitProxy>;
@@ -135,4 +143,41 @@ export class JitProxyClient {
135
143
  .remainingAccounts(remainingAccounts)
136
144
  .instruction();
137
145
  }
146
+
147
+ public async getCheckOrderConstraintIx({
148
+ subAccountId,
149
+ orderConstraints,
150
+ }: {
151
+ subAccountId: number;
152
+ orderConstraints: OrderConstraint[];
153
+ }): Promise<TransactionInstruction> {
154
+ subAccountId =
155
+ subAccountId !== undefined
156
+ ? subAccountId
157
+ : this.driftClient.activeSubAccountId;
158
+
159
+ const readablePerpMarketIndex = [];
160
+ const readableSpotMarketIndexes = [];
161
+ for (const orderConstraint of orderConstraints) {
162
+ if (isVariant(orderConstraint.marketType, 'perp')) {
163
+ readablePerpMarketIndex.push(orderConstraint.marketIndex);
164
+ } else {
165
+ readableSpotMarketIndexes.push(orderConstraint.marketIndex);
166
+ }
167
+ }
168
+
169
+ const remainingAccounts = this.driftClient.getRemainingAccounts({
170
+ userAccounts: [this.driftClient.getUserAccount(subAccountId)],
171
+ readableSpotMarketIndexes,
172
+ readablePerpMarketIndex,
173
+ });
174
+
175
+ return this.program.methods
176
+ .checkOrderConstraints(orderConstraints)
177
+ .accounts({
178
+ user: await this.driftClient.getUserAccountPublicKey(subAccountId),
179
+ })
180
+ .remainingAccounts(remainingAccounts)
181
+ .instruction();
182
+ }
138
183
  }
@@ -1,5 +1,5 @@
1
1
  export type JitProxy = {
2
- version: '0.1.0';
2
+ version: '0.9.0';
3
3
  name: 'jit_proxy';
4
4
  instructions: [
5
5
  {
@@ -49,6 +49,26 @@ export type JitProxy = {
49
49
  };
50
50
  }
51
51
  ];
52
+ },
53
+ {
54
+ name: 'checkOrderConstraints';
55
+ accounts: [
56
+ {
57
+ name: 'user';
58
+ isMut: false;
59
+ isSigner: false;
60
+ }
61
+ ];
62
+ args: [
63
+ {
64
+ name: 'constraints';
65
+ type: {
66
+ vec: {
67
+ defined: 'OrderConstraint';
68
+ };
69
+ };
70
+ }
71
+ ];
52
72
  }
53
73
  ];
54
74
  types: [
@@ -94,6 +114,32 @@ export type JitProxy = {
94
114
  ];
95
115
  };
96
116
  },
117
+ {
118
+ name: 'OrderConstraint';
119
+ type: {
120
+ kind: 'struct';
121
+ fields: [
122
+ {
123
+ name: 'maxPosition';
124
+ type: 'i64';
125
+ },
126
+ {
127
+ name: 'minPosition';
128
+ type: 'i64';
129
+ },
130
+ {
131
+ name: 'marketIndex';
132
+ type: 'u16';
133
+ },
134
+ {
135
+ name: 'marketType';
136
+ type: {
137
+ defined: 'MarketType';
138
+ };
139
+ }
140
+ ];
141
+ };
142
+ },
97
143
  {
98
144
  name: 'PostOnlyParam';
99
145
  type: {
@@ -124,6 +170,20 @@ export type JitProxy = {
124
170
  }
125
171
  ];
126
172
  };
173
+ },
174
+ {
175
+ name: 'MarketType';
176
+ type: {
177
+ kind: 'enum';
178
+ variants: [
179
+ {
180
+ name: 'Perp';
181
+ },
182
+ {
183
+ name: 'Spot';
184
+ }
185
+ ];
186
+ };
127
187
  }
128
188
  ];
129
189
  errors: [
@@ -141,12 +201,17 @@ export type JitProxy = {
141
201
  code: 6002;
142
202
  name: 'TakerOrderNotFound';
143
203
  msg: 'TakerOrderNotFound';
204
+ },
205
+ {
206
+ code: 6003;
207
+ name: 'OrderSizeBreached';
208
+ msg: 'OrderSizeBreached';
144
209
  }
145
210
  ];
146
211
  };
147
212
 
148
213
  export const IDL: JitProxy = {
149
- version: '0.1.0',
214
+ version: '0.9.0',
150
215
  name: 'jit_proxy',
151
216
  instructions: [
152
217
  {
@@ -197,6 +262,26 @@ export const IDL: JitProxy = {
197
262
  },
198
263
  ],
199
264
  },
265
+ {
266
+ name: 'checkOrderConstraints',
267
+ accounts: [
268
+ {
269
+ name: 'user',
270
+ isMut: false,
271
+ isSigner: false,
272
+ },
273
+ ],
274
+ args: [
275
+ {
276
+ name: 'constraints',
277
+ type: {
278
+ vec: {
279
+ defined: 'OrderConstraint',
280
+ },
281
+ },
282
+ },
283
+ ],
284
+ },
200
285
  ],
201
286
  types: [
202
287
  {
@@ -241,6 +326,32 @@ export const IDL: JitProxy = {
241
326
  ],
242
327
  },
243
328
  },
329
+ {
330
+ name: 'OrderConstraint',
331
+ type: {
332
+ kind: 'struct',
333
+ fields: [
334
+ {
335
+ name: 'maxPosition',
336
+ type: 'i64',
337
+ },
338
+ {
339
+ name: 'minPosition',
340
+ type: 'i64',
341
+ },
342
+ {
343
+ name: 'marketIndex',
344
+ type: 'u16',
345
+ },
346
+ {
347
+ name: 'marketType',
348
+ type: {
349
+ defined: 'MarketType',
350
+ },
351
+ },
352
+ ],
353
+ },
354
+ },
244
355
  {
245
356
  name: 'PostOnlyParam',
246
357
  type: {
@@ -272,6 +383,20 @@ export const IDL: JitProxy = {
272
383
  ],
273
384
  },
274
385
  },
386
+ {
387
+ name: 'MarketType',
388
+ type: {
389
+ kind: 'enum',
390
+ variants: [
391
+ {
392
+ name: 'Perp',
393
+ },
394
+ {
395
+ name: 'Spot',
396
+ },
397
+ ],
398
+ },
399
+ },
275
400
  ],
276
401
  errors: [
277
402
  {
@@ -289,5 +414,10 @@ export const IDL: JitProxy = {
289
414
  name: 'TakerOrderNotFound',
290
415
  msg: 'TakerOrderNotFound',
291
416
  },
417
+ {
418
+ code: 6003,
419
+ name: 'OrderSizeBreached',
420
+ msg: 'OrderSizeBreached',
421
+ },
292
422
  ],
293
423
  };