@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.
@@ -5,10 +5,13 @@ import {
5
5
  DriftClient,
6
6
  Order,
7
7
  PostOnlyParams,
8
+ SlotSubscriber,
9
+ SwiftOrderSubscriber,
8
10
  UserAccount,
9
11
  UserStatsMap,
10
12
  } from '@drift-labs/sdk';
11
13
  import { BaseJitter } from './baseJitter';
14
+ import { SignedSwiftOrderParams } from '@drift-labs/sdk/lib/node/swift/types';
12
15
 
13
16
  export class JitterShotgun extends BaseJitter {
14
17
  constructor({
@@ -16,17 +19,23 @@ export class JitterShotgun extends BaseJitter {
16
19
  jitProxyClient,
17
20
  driftClient,
18
21
  userStatsMap,
22
+ swiftOrderSubscriber,
23
+ slotSubscriber,
19
24
  }: {
20
25
  driftClient: DriftClient;
21
26
  auctionSubscriber: AuctionSubscriber;
22
27
  jitProxyClient: JitProxyClient;
23
28
  userStatsMap?: UserStatsMap;
29
+ swiftOrderSubscriber?: SwiftOrderSubscriber;
30
+ slotSubscriber?: SlotSubscriber;
24
31
  }) {
25
32
  super({
26
33
  auctionSubscriber,
27
34
  jitProxyClient,
28
35
  driftClient,
29
36
  userStatsMap,
37
+ swiftOrderSubscriber,
38
+ slotSubscriber,
30
39
  });
31
40
  }
32
41
 
@@ -104,6 +113,90 @@ export class JitterShotgun extends BaseJitter {
104
113
  this.deleteOnGoingAuction(orderSignature);
105
114
  };
106
115
  }
116
+
117
+ createTrySwiftFill(
118
+ authorityToUse: PublicKey,
119
+ signedSwiftOrderParams: SignedSwiftOrderParams,
120
+ uuid: Uint8Array,
121
+ taker: UserAccount,
122
+ takerKey: PublicKey,
123
+ takerStatsKey: PublicKey,
124
+ order: Order,
125
+ orderSignature: string,
126
+ marketIndex: number
127
+ ): () => Promise<void> {
128
+ return async () => {
129
+ let i = 0;
130
+
131
+ const takerStats = await this.userStatsMap.mustGet(
132
+ taker.authority.toString()
133
+ );
134
+ const referrerInfo = takerStats.getReferrerInfo();
135
+
136
+ // assumes each preflight simulation takes ~1 slot
137
+ while (i < order.auctionDuration) {
138
+ const params = this.perpParams.get(order.marketIndex);
139
+ if (!params) {
140
+ this.deleteOnGoingAuction(orderSignature);
141
+ return;
142
+ }
143
+
144
+ const txParams = {
145
+ computeUnits: this.computeUnits,
146
+ computeUnitsPrice: this.computeUnitsPrice,
147
+ };
148
+
149
+ console.log(`Trying to fill ${orderSignature}`);
150
+ try {
151
+ const { txSig } = await this.jitProxyClient.jitSwift(
152
+ {
153
+ takerKey,
154
+ takerStatsKey,
155
+ taker,
156
+ takerOrderId: order.orderId,
157
+ maxPosition: params.maxPosition,
158
+ minPosition: params.minPosition,
159
+ bid: params.bid,
160
+ ask: params.ask,
161
+ postOnly: params.postOnlyParams ?? PostOnlyParams.MUST_POST_ONLY,
162
+ priceType: params.priceType,
163
+ referrerInfo,
164
+ subAccountId: params.subAccountId,
165
+ authorityToUse,
166
+ signedSwiftOrderParams,
167
+ uuid,
168
+ marketIndex,
169
+ },
170
+ txParams
171
+ );
172
+
173
+ console.log(
174
+ `Successfully sent tx for ${orderSignature} txSig ${txSig}`
175
+ );
176
+ await sleep(10000);
177
+ this.deleteOnGoingAuction(orderSignature);
178
+ return;
179
+ } catch (e) {
180
+ console.error(`Failed to fill ${orderSignature}`);
181
+ console.log(e);
182
+ if (e.message.includes('0x1770') || e.message.includes('0x1771')) {
183
+ console.log('Order does not cross params yet, retrying');
184
+ } else if (e.message.includes('0x1779')) {
185
+ console.log('Order could not fill');
186
+ } else if (e.message.includes('0x1793')) {
187
+ console.log('Oracle invalid, retrying');
188
+ } else {
189
+ await sleep(10000);
190
+ this.deleteOnGoingAuction(orderSignature);
191
+ return;
192
+ }
193
+ }
194
+ i++;
195
+ }
196
+
197
+ this.deleteOnGoingAuction(orderSignature);
198
+ };
199
+ }
107
200
  }
108
201
 
109
202
  function sleep(ms: number): Promise<void> {
@@ -14,11 +14,13 @@ import {
14
14
  PostOnlyParams,
15
15
  PRICE_PRECISION,
16
16
  SlotSubscriber,
17
+ SwiftOrderSubscriber,
17
18
  UserAccount,
18
19
  UserStatsMap,
19
20
  ZERO,
20
21
  } from '@drift-labs/sdk';
21
22
  import { BaseJitter } from './baseJitter';
23
+ import { SignedSwiftOrderParams } from '@drift-labs/sdk/lib/node/swift/types';
22
24
 
23
25
  type AuctionAndOrderDetails = {
24
26
  slotsTilCross: number;
@@ -41,18 +43,22 @@ export class JitterSniper extends BaseJitter {
41
43
  jitProxyClient,
42
44
  driftClient,
43
45
  userStatsMap,
46
+ swiftOrderSubscriber,
44
47
  }: {
45
48
  driftClient: DriftClient;
46
49
  slotSubscriber: SlotSubscriber;
47
50
  auctionSubscriber: AuctionSubscriber;
48
51
  jitProxyClient: JitProxyClient;
49
52
  userStatsMap?: UserStatsMap;
53
+ swiftOrderSubscriber?: SwiftOrderSubscriber;
50
54
  }) {
51
55
  super({
52
56
  auctionSubscriber,
53
57
  jitProxyClient,
54
58
  driftClient,
55
59
  userStatsMap,
60
+ swiftOrderSubscriber,
61
+ slotSubscriber,
56
62
  });
57
63
  this.slotSubscriber = slotSubscriber;
58
64
  }
@@ -239,6 +245,196 @@ export class JitterSniper extends BaseJitter {
239
245
  };
240
246
  }
241
247
 
248
+ createTrySwiftFill(
249
+ authorityToUse: PublicKey,
250
+ signedSwiftOrderParams: SignedSwiftOrderParams,
251
+ uuid: Uint8Array,
252
+ taker: UserAccount,
253
+ takerKey: PublicKey,
254
+ takerStatsKey: PublicKey,
255
+ order: Order,
256
+ orderSignature: string,
257
+ marketIndex: number
258
+ ): () => Promise<void> {
259
+ return async () => {
260
+ const params = this.perpParams.get(order.marketIndex);
261
+ if (!params) {
262
+ this.deleteOnGoingAuction(orderSignature);
263
+ return;
264
+ }
265
+
266
+ const takerStats = await this.userStatsMap.mustGet(
267
+ taker.authority.toString()
268
+ );
269
+ const referrerInfo = takerStats.getReferrerInfo();
270
+
271
+ const {
272
+ slotsTilCross,
273
+ willCross,
274
+ bid,
275
+ ask,
276
+ auctionStartPrice,
277
+ auctionEndPrice,
278
+ stepSize,
279
+ oraclePrice,
280
+ } = this.getAuctionAndOrderDetails(order);
281
+
282
+ // don't increase risk if we're past max positions
283
+ if (isVariant(order.marketType, 'perp')) {
284
+ const currPerpPos =
285
+ this.driftClient.getUser().getPerpPosition(order.marketIndex) ||
286
+ this.driftClient.getUser().getEmptyPosition(order.marketIndex);
287
+ if (
288
+ currPerpPos.baseAssetAmount.lt(ZERO) &&
289
+ isVariant(order.direction, 'short')
290
+ ) {
291
+ if (currPerpPos.baseAssetAmount.lte(params.minPosition)) {
292
+ console.log(
293
+ `Order would increase existing short (mkt ${getVariant(
294
+ order.marketType
295
+ )}-${order.marketIndex}) too much`
296
+ );
297
+ this.deleteOnGoingAuction(orderSignature);
298
+ return;
299
+ }
300
+ } else if (
301
+ currPerpPos.baseAssetAmount.gt(ZERO) &&
302
+ isVariant(order.direction, 'long')
303
+ ) {
304
+ if (currPerpPos.baseAssetAmount.gte(params.maxPosition)) {
305
+ console.log(
306
+ `Order would increase existing long (mkt ${getVariant(
307
+ order.marketType
308
+ )}-${order.marketIndex}) too much`
309
+ );
310
+ this.deleteOnGoingAuction(orderSignature);
311
+ return;
312
+ }
313
+ }
314
+ }
315
+
316
+ console.log(`
317
+ Taker wants to ${JSON.stringify(
318
+ order.direction
319
+ )}, order slot is ${order.slot.toNumber()},
320
+ My market: ${bid}@${ask},
321
+ Auction: ${auctionStartPrice} -> ${auctionEndPrice}, step size ${stepSize}
322
+ Current slot: ${
323
+ this.slotSubscriber.currentSlot
324
+ }, Order slot: ${order.slot.toNumber()},
325
+ Will cross?: ${willCross}
326
+ Slots to wait: ${slotsTilCross}. Target slot = ${
327
+ order.slot.toNumber() + slotsTilCross
328
+ }
329
+ `);
330
+
331
+ this.waitForSlotOrCrossOrExpiry(
332
+ willCross
333
+ ? order.slot.toNumber() + slotsTilCross
334
+ : order.slot.toNumber() + order.auctionDuration + 1,
335
+ order,
336
+ {
337
+ slotsTilCross,
338
+ willCross,
339
+ bid,
340
+ ask,
341
+ auctionStartPrice,
342
+ auctionEndPrice,
343
+ stepSize,
344
+ oraclePrice,
345
+ }
346
+ ).then(async ({ slot, updatedDetails }) => {
347
+ if (slot === -1) {
348
+ console.log('Auction expired without crossing');
349
+ this.deleteOnGoingAuction(orderSignature);
350
+ return;
351
+ }
352
+
353
+ const params = isVariant(order.marketType, 'perp')
354
+ ? this.perpParams.get(order.marketIndex)
355
+ : this.spotParams.get(order.marketIndex);
356
+ const bid = isVariant(params.priceType, 'oracle')
357
+ ? convertToNumber(oraclePrice.price.add(params.bid), PRICE_PRECISION)
358
+ : convertToNumber(params.bid, PRICE_PRECISION);
359
+ const ask = isVariant(params.priceType, 'oracle')
360
+ ? convertToNumber(oraclePrice.price.add(params.ask), PRICE_PRECISION)
361
+ : convertToNumber(params.ask, PRICE_PRECISION);
362
+ const auctionPrice = convertToNumber(
363
+ getAuctionPrice(order, slot, updatedDetails.oraclePrice.price),
364
+ PRICE_PRECISION
365
+ );
366
+ console.log(`
367
+ Expected auction price: ${auctionStartPrice + slotsTilCross * stepSize}
368
+ Actual auction price: ${auctionPrice}
369
+ -----------------
370
+ Looking for slot ${order.slot.toNumber() + slotsTilCross}
371
+ Got slot ${slot}
372
+ `);
373
+
374
+ console.log(`Trying to fill ${orderSignature} with:
375
+ market: ${bid}@${ask}
376
+ auction price: ${auctionPrice}
377
+ submitting" ${convertToNumber(params.bid, PRICE_PRECISION)}@${convertToNumber(
378
+ params.ask,
379
+ PRICE_PRECISION
380
+ )}
381
+ `);
382
+ let i = 0;
383
+ while (i < 10) {
384
+ try {
385
+ const txParams = {
386
+ computeUnits: this.computeUnits,
387
+ computeUnitsPrice: this.computeUnitsPrice,
388
+ };
389
+ const { txSig } = await this.jitProxyClient.jitSwift(
390
+ {
391
+ takerKey,
392
+ takerStatsKey,
393
+ taker,
394
+ takerOrderId: order.orderId,
395
+ maxPosition: params.maxPosition,
396
+ minPosition: params.minPosition,
397
+ bid: params.bid,
398
+ ask: params.ask,
399
+ postOnly:
400
+ params.postOnlyParams ?? PostOnlyParams.MUST_POST_ONLY,
401
+ priceType: params.priceType,
402
+ referrerInfo,
403
+ subAccountId: params.subAccountId,
404
+ authorityToUse,
405
+ signedSwiftOrderParams,
406
+ uuid,
407
+ marketIndex,
408
+ },
409
+ txParams
410
+ );
411
+
412
+ console.log(`Filled ${orderSignature} txSig ${txSig}`);
413
+ await sleep(3000);
414
+ this.deleteOnGoingAuction(orderSignature);
415
+ return;
416
+ } catch (e) {
417
+ console.error(`Failed to fill ${orderSignature}`);
418
+ if (e.message.includes('0x1770') || e.message.includes('0x1771')) {
419
+ console.log('Order does not cross params yet');
420
+ } else if (e.message.includes('0x1779')) {
421
+ console.log('Order could not fill');
422
+ } else if (e.message.includes('0x1793')) {
423
+ console.log('Oracle invalid');
424
+ } else {
425
+ await sleep(3000);
426
+ this.deleteOnGoingAuction(orderSignature);
427
+ return;
428
+ }
429
+ }
430
+ await sleep(200);
431
+ i++;
432
+ }
433
+ });
434
+ this.deleteOnGoingAuction(orderSignature);
435
+ };
436
+ }
437
+
242
438
  getAuctionAndOrderDetails(order: Order): AuctionAndOrderDetails {
243
439
  // Find number of slots until the order is expected to be in cross
244
440
  const params = isVariant(order.marketType, 'perp')
@@ -1,5 +1,5 @@
1
1
  export type JitProxy = {
2
- version: '0.10.2';
2
+ version: '0.12.0';
3
3
  name: 'jit_proxy';
4
4
  instructions: [
5
5
  {
@@ -50,6 +50,59 @@ export type JitProxy = {
50
50
  }
51
51
  ];
52
52
  },
53
+ {
54
+ name: 'jitSwift';
55
+ accounts: [
56
+ {
57
+ name: 'state';
58
+ isMut: false;
59
+ isSigner: false;
60
+ },
61
+ {
62
+ name: 'user';
63
+ isMut: true;
64
+ isSigner: false;
65
+ },
66
+ {
67
+ name: 'userStats';
68
+ isMut: true;
69
+ isSigner: false;
70
+ },
71
+ {
72
+ name: 'taker';
73
+ isMut: true;
74
+ isSigner: false;
75
+ },
76
+ {
77
+ name: 'takerStats';
78
+ isMut: true;
79
+ isSigner: false;
80
+ },
81
+ {
82
+ name: 'takerSwiftUserOrders';
83
+ isMut: true;
84
+ isSigner: false;
85
+ },
86
+ {
87
+ name: 'authority';
88
+ isMut: false;
89
+ isSigner: true;
90
+ },
91
+ {
92
+ name: 'driftProgram';
93
+ isMut: false;
94
+ isSigner: false;
95
+ }
96
+ ];
97
+ args: [
98
+ {
99
+ name: 'params';
100
+ type: {
101
+ defined: 'JitSwiftParams';
102
+ };
103
+ }
104
+ ];
105
+ },
53
106
  {
54
107
  name: 'checkOrderConstraints';
55
108
  accounts: [
@@ -176,6 +229,50 @@ export type JitProxy = {
176
229
  ];
177
230
  };
178
231
  },
232
+ {
233
+ name: 'JitSwiftParams';
234
+ type: {
235
+ kind: 'struct';
236
+ fields: [
237
+ {
238
+ name: 'swiftOrderUuid';
239
+ type: {
240
+ array: ['u8', 8];
241
+ };
242
+ },
243
+ {
244
+ name: 'maxPosition';
245
+ type: 'i64';
246
+ },
247
+ {
248
+ name: 'minPosition';
249
+ type: 'i64';
250
+ },
251
+ {
252
+ name: 'bid';
253
+ type: 'i64';
254
+ },
255
+ {
256
+ name: 'ask';
257
+ type: 'i64';
258
+ },
259
+ {
260
+ name: 'priceType';
261
+ type: {
262
+ defined: 'PriceType';
263
+ };
264
+ },
265
+ {
266
+ name: 'postOnly';
267
+ type: {
268
+ option: {
269
+ defined: 'PostOnlyParam';
270
+ };
271
+ };
272
+ }
273
+ ];
274
+ };
275
+ },
179
276
  {
180
277
  name: 'PostOnlyParam';
181
278
  type: {
@@ -275,12 +372,17 @@ export type JitProxy = {
275
372
  code: 6009;
276
373
  name: 'NoFill';
277
374
  msg: 'NoFill';
375
+ },
376
+ {
377
+ code: 6010;
378
+ name: 'SwiftOrderDoesNotExist';
379
+ msg: 'SwiftOrderDoesNotExist';
278
380
  }
279
381
  ];
280
382
  };
281
383
 
282
384
  export const IDL: JitProxy = {
283
- version: '0.10.2',
385
+ version: '0.12.0',
284
386
  name: 'jit_proxy',
285
387
  instructions: [
286
388
  {
@@ -331,6 +433,59 @@ export const IDL: JitProxy = {
331
433
  },
332
434
  ],
333
435
  },
436
+ {
437
+ name: 'jitSwift',
438
+ accounts: [
439
+ {
440
+ name: 'state',
441
+ isMut: false,
442
+ isSigner: false,
443
+ },
444
+ {
445
+ name: 'user',
446
+ isMut: true,
447
+ isSigner: false,
448
+ },
449
+ {
450
+ name: 'userStats',
451
+ isMut: true,
452
+ isSigner: false,
453
+ },
454
+ {
455
+ name: 'taker',
456
+ isMut: true,
457
+ isSigner: false,
458
+ },
459
+ {
460
+ name: 'takerStats',
461
+ isMut: true,
462
+ isSigner: false,
463
+ },
464
+ {
465
+ name: 'takerSwiftUserOrders',
466
+ isMut: true,
467
+ isSigner: false,
468
+ },
469
+ {
470
+ name: 'authority',
471
+ isMut: false,
472
+ isSigner: true,
473
+ },
474
+ {
475
+ name: 'driftProgram',
476
+ isMut: false,
477
+ isSigner: false,
478
+ },
479
+ ],
480
+ args: [
481
+ {
482
+ name: 'params',
483
+ type: {
484
+ defined: 'JitSwiftParams',
485
+ },
486
+ },
487
+ ],
488
+ },
334
489
  {
335
490
  name: 'checkOrderConstraints',
336
491
  accounts: [
@@ -457,6 +612,50 @@ export const IDL: JitProxy = {
457
612
  ],
458
613
  },
459
614
  },
615
+ {
616
+ name: 'JitSwiftParams',
617
+ type: {
618
+ kind: 'struct',
619
+ fields: [
620
+ {
621
+ name: 'swiftOrderUuid',
622
+ type: {
623
+ array: ['u8', 8],
624
+ },
625
+ },
626
+ {
627
+ name: 'maxPosition',
628
+ type: 'i64',
629
+ },
630
+ {
631
+ name: 'minPosition',
632
+ type: 'i64',
633
+ },
634
+ {
635
+ name: 'bid',
636
+ type: 'i64',
637
+ },
638
+ {
639
+ name: 'ask',
640
+ type: 'i64',
641
+ },
642
+ {
643
+ name: 'priceType',
644
+ type: {
645
+ defined: 'PriceType',
646
+ },
647
+ },
648
+ {
649
+ name: 'postOnly',
650
+ type: {
651
+ option: {
652
+ defined: 'PostOnlyParam',
653
+ },
654
+ },
655
+ },
656
+ ],
657
+ },
658
+ },
460
659
  {
461
660
  name: 'PostOnlyParam',
462
661
  type: {
@@ -557,5 +756,10 @@ export const IDL: JitProxy = {
557
756
  name: 'NoFill',
558
757
  msg: 'NoFill',
559
758
  },
759
+ {
760
+ code: 6010,
761
+ name: 'SwiftOrderDoesNotExist',
762
+ msg: 'SwiftOrderDoesNotExist',
763
+ },
560
764
  ],
561
765
  };