@drift-labs/sdk 2.54.0-beta.6 → 2.54.0-beta.8

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/VERSION CHANGED
@@ -1 +1 @@
1
- 2.54.0-beta.6
1
+ 2.54.0-beta.8
@@ -284,10 +284,11 @@ export declare class DriftClient {
284
284
  * @param cancelExistingOrders - Builds and returns an extra transaciton to cancel the existing orders in the same perp market. Intended use is to auto-cancel TP/SL orders when closing a position. Ignored if orderParams.marketType is not MarketType.PERP
285
285
  * @returns
286
286
  */
287
- sendMarketOrderAndGetSignedFillTx(orderParams: OptionalOrderParams, userAccountPublicKey: PublicKey, userAccount: UserAccount, makerInfo?: MakerInfo | MakerInfo[], txParams?: TxParams, bracketOrdersParams?: OptionalOrderParams[], referrerInfo?: ReferrerInfo, cancelExistingOrders?: boolean): Promise<{
287
+ sendMarketOrderAndGetSignedFillTx(orderParams: OptionalOrderParams, userAccountPublicKey: PublicKey, userAccount: UserAccount, makerInfo?: MakerInfo | MakerInfo[], txParams?: TxParams, bracketOrdersParams?: OptionalOrderParams[], referrerInfo?: ReferrerInfo, cancelExistingOrders?: boolean, settlePnl?: boolean): Promise<{
288
288
  txSig: TransactionSignature;
289
289
  signedFillTx?: Transaction;
290
290
  signedCancelExistingOrdersTx?: Transaction;
291
+ signedSettlePnlTx?: Transaction;
291
292
  }>;
292
293
  placePerpOrder(orderParams: OptionalOrderParams, txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
293
294
  getPlacePerpOrderIx(orderParams: OptionalOrderParams, subAccountId?: number): Promise<TransactionInstruction>;
@@ -427,9 +428,10 @@ export declare class DriftClient {
427
428
  updateUserOpenOrdersCount(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams, fillerPublicKey?: PublicKey): Promise<TransactionSignature>;
428
429
  getUpdateUserOpenOrdersCountIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, fillerPublicKey?: PublicKey): Promise<TransactionInstruction>;
429
430
  placeAndTakePerpOrder(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
430
- placeAndTakePerpWithAdditionalOrders(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, bracketOrdersParams?: OptionalOrderParams[], txParams?: TxParams, subAccountId?: number, cancelExistingOrders?: boolean): Promise<{
431
+ placeAndTakePerpWithAdditionalOrders(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, bracketOrdersParams?: OptionalOrderParams[], txParams?: TxParams, subAccountId?: number, cancelExistingOrders?: boolean, settlePnl?: boolean): Promise<{
431
432
  txSig: TransactionSignature;
432
433
  signedCancelExistingOrdersTx?: Transaction;
434
+ signedSettlePnlTx?: Transaction;
433
435
  }>;
434
436
  getPlaceAndTakePerpOrderIx(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, subAccountId?: number): Promise<TransactionInstruction>;
435
437
  placeAndMakePerpOrder(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo, txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
@@ -1419,17 +1419,24 @@ class DriftClient {
1419
1419
  * @param cancelExistingOrders - Builds and returns an extra transaciton to cancel the existing orders in the same perp market. Intended use is to auto-cancel TP/SL orders when closing a position. Ignored if orderParams.marketType is not MarketType.PERP
1420
1420
  * @returns
1421
1421
  */
1422
- async sendMarketOrderAndGetSignedFillTx(orderParams, userAccountPublicKey, userAccount, makerInfo, txParams, bracketOrdersParams = new Array(), referrerInfo, cancelExistingOrders) {
1422
+ async sendMarketOrderAndGetSignedFillTx(orderParams, userAccountPublicKey, userAccount, makerInfo, txParams, bracketOrdersParams = new Array(), referrerInfo, cancelExistingOrders, settlePnl) {
1423
1423
  const marketIndex = orderParams.marketIndex;
1424
1424
  const orderId = userAccount.nextOrderId;
1425
1425
  const ordersIx = await this.getPlaceOrdersIx([orderParams, ...bracketOrdersParams], userAccount.subAccountId);
1426
- let cancelOrdersIx;
1426
+ /* Cancel open orders in market if requested */
1427
1427
  let cancelExistingOrdersTx;
1428
1428
  if (cancelExistingOrders && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
1429
- cancelOrdersIx = await this.getCancelOrdersIx(orderParams.marketType, orderParams.marketIndex, null, userAccount.subAccountId);
1429
+ const cancelOrdersIx = await this.getCancelOrdersIx(orderParams.marketType, orderParams.marketIndex, null, userAccount.subAccountId);
1430
1430
  //@ts-ignore
1431
1431
  cancelExistingOrdersTx = await this.buildTransaction([cancelOrdersIx], txParams, this.txVersion);
1432
1432
  }
1433
+ /* Settle PnL after fill if requested */
1434
+ let settlePnlTx;
1435
+ if (settlePnl && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
1436
+ const settlePnlIx = await this.settlePNLIx(userAccountPublicKey, userAccount, marketIndex);
1437
+ //@ts-ignore
1438
+ settlePnlTx = await this.buildTransaction([settlePnlIx], txParams, this.txVersion);
1439
+ }
1433
1440
  // use versioned transactions if there is a lookup table account and wallet is compatible
1434
1441
  if (this.txVersion === 0) {
1435
1442
  const versionedMarketOrderTx = await this.buildTransaction(ordersIx, txParams, 0);
@@ -1438,11 +1445,21 @@ class DriftClient {
1438
1445
  marketIndex,
1439
1446
  }, makerInfo, referrerInfo, userAccount.subAccountId);
1440
1447
  const versionedFillTx = await this.buildTransaction([fillPerpOrderIx], txParams, 0);
1441
- const [signedVersionedMarketOrderTx, signedVersionedFillTx, signedCancelExistingOrdersTx,] = await this.provider.wallet.signAllTransactions([
1448
+ const allPossibleTxs = [
1442
1449
  versionedMarketOrderTx,
1443
1450
  versionedFillTx,
1444
1451
  cancelExistingOrdersTx,
1445
- ].filter((tx) => tx !== undefined));
1452
+ settlePnlTx,
1453
+ ];
1454
+ const txKeys = [
1455
+ 'signedVersionedMarketOrderTx',
1456
+ 'signedVersionedFillTx',
1457
+ 'signedCancelExistingOrdersTx',
1458
+ 'signedSettlePnlTx',
1459
+ ];
1460
+ const { signedVersionedMarketOrderTx, signedVersionedFillTx, signedCancelExistingOrdersTx, signedSettlePnlTx, } = await (0, utils_1.getSignedTransactionMap)(
1461
+ //@ts-ignore
1462
+ this.provider.wallet, allPossibleTxs, txKeys);
1446
1463
  const { txSig, slot } = await this.txSender.sendRawTransaction(signedVersionedMarketOrderTx.serialize(), this.opts);
1447
1464
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
1448
1465
  return {
@@ -1451,6 +1468,8 @@ class DriftClient {
1451
1468
  signedFillTx: signedVersionedFillTx,
1452
1469
  // @ts-ignore
1453
1470
  signedCancelExistingOrdersTx,
1471
+ // @ts-ignore
1472
+ signedSettlePnlTx,
1454
1473
  };
1455
1474
  }
1456
1475
  else {
@@ -1463,10 +1482,33 @@ class DriftClient {
1463
1482
  cancelExistingOrdersTx.recentBlockhash = currentBlockHash;
1464
1483
  cancelExistingOrdersTx.feePayer = userAccount.authority;
1465
1484
  }
1466
- const [signedMarketOrderTx, signedCancelExistingOrdersTx] = await this.provider.wallet.signAllTransactions([marketOrderTx, cancelExistingOrdersTx].filter((tx) => tx !== undefined));
1485
+ if (settlePnlTx) {
1486
+ settlePnlTx.recentBlockhash = currentBlockHash;
1487
+ settlePnlTx.feePayer = userAccount.authority;
1488
+ }
1489
+ const allPossibleTxs = [
1490
+ marketOrderTx,
1491
+ cancelExistingOrdersTx,
1492
+ settlePnlTx,
1493
+ ];
1494
+ const txKeys = [
1495
+ 'signedMarketOrderTx',
1496
+ 'signedCancelExistingOrdersTx',
1497
+ 'signedSettlePnlTx',
1498
+ ];
1499
+ const { signedMarketOrderTx, signedCancelExistingOrdersTx, signedSettlePnlTx, } = await (0, utils_1.getSignedTransactionMap)(
1500
+ //@ts-ignore
1501
+ this.provider.wallet, allPossibleTxs, txKeys);
1467
1502
  const { txSig, slot } = await this.sendTransaction(signedMarketOrderTx, [], this.opts, true);
1468
1503
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
1469
- return { txSig, signedFillTx: undefined, signedCancelExistingOrdersTx };
1504
+ return {
1505
+ txSig,
1506
+ signedFillTx: undefined,
1507
+ //@ts-ignore
1508
+ signedCancelExistingOrdersTx,
1509
+ //@ts-ignore
1510
+ signedSettlePnlTx,
1511
+ };
1470
1512
  }
1471
1513
  }
1472
1514
  async placePerpOrder(orderParams, txParams, subAccountId) {
@@ -2404,13 +2446,20 @@ class DriftClient {
2404
2446
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
2405
2447
  return txSig;
2406
2448
  }
2407
- async placeAndTakePerpWithAdditionalOrders(orderParams, makerInfo, referrerInfo, bracketOrdersParams = new Array(), txParams, subAccountId, cancelExistingOrders) {
2408
- let signedCancelExistingOrdersTx;
2449
+ async placeAndTakePerpWithAdditionalOrders(orderParams, makerInfo, referrerInfo, bracketOrdersParams = new Array(), txParams, subAccountId, cancelExistingOrders, settlePnl) {
2450
+ let cancelExistingOrdersTx;
2409
2451
  if (cancelExistingOrders && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
2410
2452
  const cancelOrdersIx = await this.getCancelOrdersIx(orderParams.marketType, orderParams.marketIndex, null, subAccountId);
2411
- const cancelExistingOrdersTx = await this.buildTransaction([cancelOrdersIx], txParams, this.txVersion);
2412
- // @ts-ignore
2413
- signedCancelExistingOrdersTx = await this.provider.wallet.signTransaction(cancelExistingOrdersTx);
2453
+ //@ts-ignore
2454
+ cancelExistingOrdersTx = await this.buildTransaction([cancelOrdersIx], txParams, this.txVersion);
2455
+ }
2456
+ /* Settle PnL after fill if requested */
2457
+ let settlePnlTx;
2458
+ if (settlePnl && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
2459
+ const userAccountPublicKey = await this.getUserAccountPublicKey(subAccountId);
2460
+ const settlePnlIx = await this.settlePNLIx(userAccountPublicKey, this.getUserAccount(subAccountId), orderParams.marketIndex);
2461
+ //@ts-ignore
2462
+ settlePnlTx = await this.buildTransaction([settlePnlIx], txParams, this.txVersion);
2414
2463
  }
2415
2464
  const ixs = [];
2416
2465
  const placeAndTakeIx = await this.getPlaceAndTakePerpOrderIx(orderParams, makerInfo, referrerInfo, subAccountId);
@@ -2419,9 +2468,24 @@ class DriftClient {
2419
2468
  const bracketOrdersIx = await this.getPlaceOrdersIx(bracketOrdersParams, subAccountId);
2420
2469
  ixs.push(bracketOrdersIx);
2421
2470
  }
2422
- const { txSig, slot } = await this.sendTransaction(await this.buildTransaction(ixs, txParams), [], this.opts);
2471
+ const placeAndTakeTx = await this.buildTransaction(ixs, txParams);
2472
+ const allPossibleTxs = [
2473
+ placeAndTakeTx,
2474
+ cancelExistingOrdersTx,
2475
+ settlePnlTx,
2476
+ ];
2477
+ const txKeys = [
2478
+ 'signedPlaceAndTakeTx',
2479
+ 'signedCancelExistingOrdersTx',
2480
+ 'signedSettlePnlTx',
2481
+ ];
2482
+ const { signedPlaceAndTakeTx, signedCancelExistingOrdersTx, signedSettlePnlTx, } = await (0, utils_1.getSignedTransactionMap)(
2483
+ //@ts-ignore
2484
+ this.provider.wallet, allPossibleTxs, txKeys);
2485
+ const { txSig, slot } = await this.sendTransaction(signedPlaceAndTakeTx, [], this.opts, true);
2423
2486
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
2424
- return { txSig, signedCancelExistingOrdersTx };
2487
+ //@ts-ignore
2488
+ return { txSig, signedCancelExistingOrdersTx, signedSettlePnlTx };
2425
2489
  }
2426
2490
  async getPlaceAndTakePerpOrderIx(orderParams, makerInfo, referrerInfo, subAccountId) {
2427
2491
  orderParams = (0, orderParams_1.getOrderParams)(orderParams, { marketType: types_1.MarketType.PERP });
@@ -32,15 +32,8 @@ class RetryTxSender extends baseTxSender_1.BaseTxSender {
32
32
  }
33
33
  async sendRawTransaction(rawTransaction, opts) {
34
34
  const startTime = this.getTimestamp();
35
- let txid;
36
- try {
37
- txid = await this.connection.sendRawTransaction(rawTransaction, opts);
38
- this.sendToAdditionalConnections(rawTransaction, opts);
39
- }
40
- catch (e) {
41
- console.error(e);
42
- throw e;
43
- }
35
+ const txid = await this.connection.sendRawTransaction(rawTransaction, opts);
36
+ this.sendToAdditionalConnections(rawTransaction, opts);
44
37
  let done = false;
45
38
  const resolveReference = {
46
39
  resolve: undefined,
@@ -65,18 +58,8 @@ class RetryTxSender extends baseTxSender_1.BaseTxSender {
65
58
  }
66
59
  }
67
60
  })();
68
- let slot;
69
- try {
70
- const result = await this.confirmTransaction(txid, opts.commitment);
71
- slot = result.context.slot;
72
- }
73
- catch (e) {
74
- console.error(e);
75
- throw e;
76
- }
77
- finally {
78
- stopWaiting();
79
- }
61
+ const result = await this.confirmTransaction(txid, opts.commitment);
62
+ const slot = result.context.slot;
80
63
  return { txSig: txid, slot };
81
64
  }
82
65
  }
package/lib/tx/utils.d.ts CHANGED
@@ -1,2 +1,6 @@
1
- import { Transaction, TransactionInstruction } from '@solana/web3.js';
1
+ import { Wallet } from '@coral-xyz/anchor';
2
+ import { Transaction, TransactionInstruction, VersionedTransaction } from '@solana/web3.js';
2
3
  export declare function wrapInTx(instruction: TransactionInstruction, computeUnits?: number, computeUnitsPrice?: number): Transaction;
4
+ export declare function getSignedTransactionMap(wallet: Wallet, txsToSign: (Transaction | VersionedTransaction | undefined)[], keys: string[]): Promise<{
5
+ [key: string]: Transaction | VersionedTransaction | undefined;
6
+ }>;
package/lib/tx/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.wrapInTx = void 0;
3
+ exports.getSignedTransactionMap = exports.wrapInTx = void 0;
4
4
  const web3_js_1 = require("@solana/web3.js");
5
5
  const COMPUTE_UNITS_DEFAULT = 200000;
6
6
  function wrapInTx(instruction, computeUnits = 600000, computeUnitsPrice = 0) {
@@ -18,3 +18,22 @@ function wrapInTx(instruction, computeUnits = 600000, computeUnitsPrice = 0) {
18
18
  return tx.add(instruction);
19
19
  }
20
20
  exports.wrapInTx = wrapInTx;
21
+ /* Helper function for signing multiple transactions where some may be undefined and mapping the output */
22
+ async function getSignedTransactionMap(wallet, txsToSign, keys) {
23
+ const signedTxMap = {};
24
+ const keysWithTx = [];
25
+ txsToSign.forEach((tx, index) => {
26
+ if (tx == undefined) {
27
+ signedTxMap[keys[index]] = undefined;
28
+ }
29
+ else {
30
+ keysWithTx.push(keys[index]);
31
+ }
32
+ });
33
+ const signedTxs = await wallet.signAllTransactions(txsToSign.filter((tx) => tx !== undefined));
34
+ signedTxs.forEach((signedTx, index) => {
35
+ signedTxMap[keysWithTx[index]] = signedTx;
36
+ });
37
+ return signedTxMap;
38
+ }
39
+ exports.getSignedTransactionMap = getSignedTransactionMap;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.54.0-beta.6",
3
+ "version": "2.54.0-beta.8",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -88,7 +88,7 @@ import {
88
88
  DataAndSlot,
89
89
  } from './accounts/types';
90
90
  import { TxSender, TxSigAndSlot } from './tx/types';
91
- import { wrapInTx } from './tx/utils';
91
+ import { getSignedTransactionMap, wrapInTx } from './tx/utils';
92
92
  import {
93
93
  BASE_PRECISION,
94
94
  PRICE_PRECISION,
@@ -2565,11 +2565,13 @@ export class DriftClient {
2565
2565
  txParams?: TxParams,
2566
2566
  bracketOrdersParams = new Array<OptionalOrderParams>(),
2567
2567
  referrerInfo?: ReferrerInfo,
2568
- cancelExistingOrders?: boolean
2568
+ cancelExistingOrders?: boolean,
2569
+ settlePnl?: boolean
2569
2570
  ): Promise<{
2570
2571
  txSig: TransactionSignature;
2571
2572
  signedFillTx?: Transaction;
2572
2573
  signedCancelExistingOrdersTx?: Transaction;
2574
+ signedSettlePnlTx?: Transaction;
2573
2575
  }> {
2574
2576
  const marketIndex = orderParams.marketIndex;
2575
2577
  const orderId = userAccount.nextOrderId;
@@ -2579,10 +2581,10 @@ export class DriftClient {
2579
2581
  userAccount.subAccountId
2580
2582
  );
2581
2583
 
2582
- let cancelOrdersIx: TransactionInstruction;
2583
- let cancelExistingOrdersTx: Transaction;
2584
+ /* Cancel open orders in market if requested */
2585
+ let cancelExistingOrdersTx;
2584
2586
  if (cancelExistingOrders && isVariant(orderParams.marketType, 'perp')) {
2585
- cancelOrdersIx = await this.getCancelOrdersIx(
2587
+ const cancelOrdersIx = await this.getCancelOrdersIx(
2586
2588
  orderParams.marketType,
2587
2589
  orderParams.marketIndex,
2588
2590
  null,
@@ -2597,6 +2599,23 @@ export class DriftClient {
2597
2599
  );
2598
2600
  }
2599
2601
 
2602
+ /* Settle PnL after fill if requested */
2603
+ let settlePnlTx;
2604
+ if (settlePnl && isVariant(orderParams.marketType, 'perp')) {
2605
+ const settlePnlIx = await this.settlePNLIx(
2606
+ userAccountPublicKey,
2607
+ userAccount,
2608
+ marketIndex
2609
+ );
2610
+
2611
+ //@ts-ignore
2612
+ settlePnlTx = await this.buildTransaction(
2613
+ [settlePnlIx],
2614
+ txParams,
2615
+ this.txVersion
2616
+ );
2617
+ }
2618
+
2600
2619
  // use versioned transactions if there is a lookup table account and wallet is compatible
2601
2620
  if (this.txVersion === 0) {
2602
2621
  const versionedMarketOrderTx = await this.buildTransaction(
@@ -2623,17 +2642,31 @@ export class DriftClient {
2623
2642
  0
2624
2643
  );
2625
2644
 
2626
- const [
2645
+ const allPossibleTxs = [
2646
+ versionedMarketOrderTx,
2647
+ versionedFillTx,
2648
+ cancelExistingOrdersTx,
2649
+ settlePnlTx,
2650
+ ];
2651
+ const txKeys = [
2652
+ 'signedVersionedMarketOrderTx',
2653
+ 'signedVersionedFillTx',
2654
+ 'signedCancelExistingOrdersTx',
2655
+ 'signedSettlePnlTx',
2656
+ ];
2657
+
2658
+ const {
2627
2659
  signedVersionedMarketOrderTx,
2628
2660
  signedVersionedFillTx,
2629
2661
  signedCancelExistingOrdersTx,
2630
- ] = await this.provider.wallet.signAllTransactions(
2631
- [
2632
- versionedMarketOrderTx,
2633
- versionedFillTx,
2634
- cancelExistingOrdersTx,
2635
- ].filter((tx) => tx !== undefined)
2662
+ signedSettlePnlTx,
2663
+ } = await getSignedTransactionMap(
2664
+ //@ts-ignore
2665
+ this.provider.wallet,
2666
+ allPossibleTxs,
2667
+ txKeys
2636
2668
  );
2669
+
2637
2670
  const { txSig, slot } = await this.txSender.sendRawTransaction(
2638
2671
  signedVersionedMarketOrderTx.serialize(),
2639
2672
  this.opts
@@ -2646,6 +2679,8 @@ export class DriftClient {
2646
2679
  signedFillTx: signedVersionedFillTx,
2647
2680
  // @ts-ignore
2648
2681
  signedCancelExistingOrdersTx,
2682
+ // @ts-ignore
2683
+ signedSettlePnlTx,
2649
2684
  };
2650
2685
  } else {
2651
2686
  const marketOrderTx = wrapInTx(
@@ -2667,12 +2702,33 @@ export class DriftClient {
2667
2702
  cancelExistingOrdersTx.feePayer = userAccount.authority;
2668
2703
  }
2669
2704
 
2670
- const [signedMarketOrderTx, signedCancelExistingOrdersTx] =
2671
- await this.provider.wallet.signAllTransactions(
2672
- [marketOrderTx, cancelExistingOrdersTx].filter(
2673
- (tx) => tx !== undefined
2674
- )
2675
- );
2705
+ if (settlePnlTx) {
2706
+ settlePnlTx.recentBlockhash = currentBlockHash;
2707
+ settlePnlTx.feePayer = userAccount.authority;
2708
+ }
2709
+
2710
+ const allPossibleTxs = [
2711
+ marketOrderTx,
2712
+ cancelExistingOrdersTx,
2713
+ settlePnlTx,
2714
+ ];
2715
+ const txKeys = [
2716
+ 'signedMarketOrderTx',
2717
+ 'signedCancelExistingOrdersTx',
2718
+ 'signedSettlePnlTx',
2719
+ ];
2720
+
2721
+ const {
2722
+ signedMarketOrderTx,
2723
+ signedCancelExistingOrdersTx,
2724
+ signedSettlePnlTx,
2725
+ } = await getSignedTransactionMap(
2726
+ //@ts-ignore
2727
+ this.provider.wallet,
2728
+ allPossibleTxs,
2729
+ txKeys
2730
+ );
2731
+
2676
2732
  const { txSig, slot } = await this.sendTransaction(
2677
2733
  signedMarketOrderTx,
2678
2734
  [],
@@ -2681,7 +2737,14 @@ export class DriftClient {
2681
2737
  );
2682
2738
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
2683
2739
 
2684
- return { txSig, signedFillTx: undefined, signedCancelExistingOrdersTx };
2740
+ return {
2741
+ txSig,
2742
+ signedFillTx: undefined,
2743
+ //@ts-ignore
2744
+ signedCancelExistingOrdersTx,
2745
+ //@ts-ignore
2746
+ signedSettlePnlTx,
2747
+ };
2685
2748
  }
2686
2749
  }
2687
2750
 
@@ -4330,13 +4393,14 @@ export class DriftClient {
4330
4393
  bracketOrdersParams = new Array<OptionalOrderParams>(),
4331
4394
  txParams?: TxParams,
4332
4395
  subAccountId?: number,
4333
- cancelExistingOrders?: boolean
4396
+ cancelExistingOrders?: boolean,
4397
+ settlePnl?: boolean
4334
4398
  ): Promise<{
4335
4399
  txSig: TransactionSignature;
4336
4400
  signedCancelExistingOrdersTx?: Transaction;
4401
+ signedSettlePnlTx?: Transaction;
4337
4402
  }> {
4338
- let signedCancelExistingOrdersTx: Transaction;
4339
-
4403
+ let cancelExistingOrdersTx: Transaction;
4340
4404
  if (cancelExistingOrders && isVariant(orderParams.marketType, 'perp')) {
4341
4405
  const cancelOrdersIx = await this.getCancelOrdersIx(
4342
4406
  orderParams.marketType,
@@ -4345,15 +4409,32 @@ export class DriftClient {
4345
4409
  subAccountId
4346
4410
  );
4347
4411
 
4348
- const cancelExistingOrdersTx = await this.buildTransaction(
4412
+ //@ts-ignore
4413
+ cancelExistingOrdersTx = await this.buildTransaction(
4349
4414
  [cancelOrdersIx],
4350
4415
  txParams,
4351
4416
  this.txVersion
4352
4417
  );
4418
+ }
4353
4419
 
4354
- // @ts-ignore
4355
- signedCancelExistingOrdersTx = await this.provider.wallet.signTransaction(
4356
- cancelExistingOrdersTx
4420
+ /* Settle PnL after fill if requested */
4421
+ let settlePnlTx: Transaction;
4422
+ if (settlePnl && isVariant(orderParams.marketType, 'perp')) {
4423
+ const userAccountPublicKey = await this.getUserAccountPublicKey(
4424
+ subAccountId
4425
+ );
4426
+
4427
+ const settlePnlIx = await this.settlePNLIx(
4428
+ userAccountPublicKey,
4429
+ this.getUserAccount(subAccountId),
4430
+ orderParams.marketIndex
4431
+ );
4432
+
4433
+ //@ts-ignore
4434
+ settlePnlTx = await this.buildTransaction(
4435
+ [settlePnlIx],
4436
+ txParams,
4437
+ this.txVersion
4357
4438
  );
4358
4439
  }
4359
4440
 
@@ -4376,14 +4457,40 @@ export class DriftClient {
4376
4457
  ixs.push(bracketOrdersIx);
4377
4458
  }
4378
4459
 
4460
+ const placeAndTakeTx = await this.buildTransaction(ixs, txParams);
4461
+
4462
+ const allPossibleTxs = [
4463
+ placeAndTakeTx,
4464
+ cancelExistingOrdersTx,
4465
+ settlePnlTx,
4466
+ ];
4467
+ const txKeys = [
4468
+ 'signedPlaceAndTakeTx',
4469
+ 'signedCancelExistingOrdersTx',
4470
+ 'signedSettlePnlTx',
4471
+ ];
4472
+
4473
+ const {
4474
+ signedPlaceAndTakeTx,
4475
+ signedCancelExistingOrdersTx,
4476
+ signedSettlePnlTx,
4477
+ } = await getSignedTransactionMap(
4478
+ //@ts-ignore
4479
+ this.provider.wallet,
4480
+ allPossibleTxs,
4481
+ txKeys
4482
+ );
4483
+
4379
4484
  const { txSig, slot } = await this.sendTransaction(
4380
- await this.buildTransaction(ixs, txParams),
4485
+ signedPlaceAndTakeTx,
4381
4486
  [],
4382
- this.opts
4487
+ this.opts,
4488
+ true
4383
4489
  );
4384
4490
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
4385
4491
 
4386
- return { txSig, signedCancelExistingOrdersTx };
4492
+ //@ts-ignore
4493
+ return { txSig, signedCancelExistingOrdersTx, signedSettlePnlTx };
4387
4494
  }
4388
4495
 
4389
4496
  public async getPlaceAndTakePerpOrderIx(
@@ -1,9 +1,5 @@
1
1
  import { ConfirmationStrategy, TxSigAndSlot } from './types';
2
- import {
3
- ConfirmOptions,
4
- TransactionSignature,
5
- Connection,
6
- } from '@solana/web3.js';
2
+ import { ConfirmOptions, Connection } from '@solana/web3.js';
7
3
  import { AnchorProvider } from '@coral-xyz/anchor';
8
4
  import { IWallet } from '../types';
9
5
  import { BaseTxSender } from './baseTxSender';
@@ -70,14 +66,8 @@ export class RetryTxSender extends BaseTxSender {
70
66
  ): Promise<TxSigAndSlot> {
71
67
  const startTime = this.getTimestamp();
72
68
 
73
- let txid: TransactionSignature;
74
- try {
75
- txid = await this.connection.sendRawTransaction(rawTransaction, opts);
76
- this.sendToAdditionalConnections(rawTransaction, opts);
77
- } catch (e) {
78
- console.error(e);
79
- throw e;
80
- }
69
+ const txid = await this.connection.sendRawTransaction(rawTransaction, opts);
70
+ this.sendToAdditionalConnections(rawTransaction, opts);
81
71
 
82
72
  let done = false;
83
73
  const resolveReference: ResolveReference = {
@@ -105,16 +95,8 @@ export class RetryTxSender extends BaseTxSender {
105
95
  }
106
96
  })();
107
97
 
108
- let slot: number;
109
- try {
110
- const result = await this.confirmTransaction(txid, opts.commitment);
111
- slot = result.context.slot;
112
- } catch (e) {
113
- console.error(e);
114
- throw e;
115
- } finally {
116
- stopWaiting();
117
- }
98
+ const result = await this.confirmTransaction(txid, opts.commitment);
99
+ const slot = result.context.slot;
118
100
 
119
101
  return { txSig: txid, slot };
120
102
  }
package/src/tx/utils.ts CHANGED
@@ -1,7 +1,9 @@
1
+ import { Wallet } from '@coral-xyz/anchor';
1
2
  import {
2
3
  Transaction,
3
4
  TransactionInstruction,
4
5
  ComputeBudgetProgram,
6
+ VersionedTransaction,
5
7
  } from '@solana/web3.js';
6
8
 
7
9
  const COMPUTE_UNITS_DEFAULT = 200_000;
@@ -30,3 +32,33 @@ export function wrapInTx(
30
32
 
31
33
  return tx.add(instruction);
32
34
  }
35
+
36
+ /* Helper function for signing multiple transactions where some may be undefined and mapping the output */
37
+ export async function getSignedTransactionMap(
38
+ wallet: Wallet,
39
+ txsToSign: (Transaction | VersionedTransaction | undefined)[],
40
+ keys: string[]
41
+ ): Promise<{ [key: string]: Transaction | VersionedTransaction | undefined }> {
42
+ const signedTxMap: {
43
+ [key: string]: Transaction | VersionedTransaction | undefined;
44
+ } = {};
45
+
46
+ const keysWithTx = [];
47
+ txsToSign.forEach((tx, index) => {
48
+ if (tx == undefined) {
49
+ signedTxMap[keys[index]] = undefined;
50
+ } else {
51
+ keysWithTx.push(keys[index]);
52
+ }
53
+ });
54
+
55
+ const signedTxs = await wallet.signAllTransactions(
56
+ txsToSign.filter((tx) => tx !== undefined)
57
+ );
58
+
59
+ signedTxs.forEach((signedTx, index) => {
60
+ signedTxMap[keysWithTx[index]] = signedTx;
61
+ });
62
+
63
+ return signedTxMap;
64
+ }