@drift-labs/sdk 2.82.0-beta.8 → 2.83.0-beta.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.
Files changed (68) hide show
  1. package/VERSION +1 -1
  2. package/lib/accounts/types.d.ts +0 -3
  3. package/lib/accounts/webSocketAccountSubscriber.js +1 -1
  4. package/lib/clock/clockSubscriber.d.ts +29 -0
  5. package/lib/clock/clockSubscriber.js +74 -0
  6. package/lib/constants/perpMarkets.js +2 -2
  7. package/lib/constants/spotMarkets.js +11 -0
  8. package/lib/dlob/DLOB.js +2 -2
  9. package/lib/dlob/orderBookLevels.js +1 -0
  10. package/lib/driftClient.d.ts +11 -14
  11. package/lib/driftClient.js +157 -260
  12. package/lib/driftClientConfig.d.ts +2 -0
  13. package/lib/idl/drift.json +1 -1
  14. package/lib/index.d.ts +2 -0
  15. package/lib/index.js +2 -0
  16. package/lib/jupiter/jupiterClient.d.ts +2 -1
  17. package/lib/jupiter/jupiterClient.js +10 -6
  18. package/lib/math/exchangeStatus.d.ts +2 -2
  19. package/lib/math/orders.d.ts +1 -1
  20. package/lib/math/orders.js +2 -2
  21. package/lib/tx/baseTxSender.d.ts +8 -6
  22. package/lib/tx/baseTxSender.js +6 -49
  23. package/lib/tx/fastSingleTxSender.d.ts +6 -6
  24. package/lib/tx/fastSingleTxSender.js +3 -31
  25. package/lib/tx/forwardOnlyTxSender.d.ts +4 -2
  26. package/lib/tx/forwardOnlyTxSender.js +2 -1
  27. package/lib/tx/retryTxSender.d.ts +4 -2
  28. package/lib/tx/retryTxSender.js +2 -1
  29. package/lib/tx/txHandler.d.ts +138 -0
  30. package/lib/tx/txHandler.js +396 -0
  31. package/lib/tx/txParamProcessor.d.ts +6 -10
  32. package/lib/tx/txParamProcessor.js +13 -17
  33. package/lib/tx/types.d.ts +3 -7
  34. package/lib/tx/whileValidTxSender.d.ts +7 -6
  35. package/lib/tx/whileValidTxSender.js +7 -28
  36. package/lib/types.d.ts +24 -4
  37. package/lib/types.js +10 -1
  38. package/lib/util/chainClock.d.ts +17 -0
  39. package/lib/util/chainClock.js +29 -0
  40. package/package.json +3 -3
  41. package/src/accounts/types.ts +0 -4
  42. package/src/accounts/webSocketAccountSubscriber.ts +1 -1
  43. package/src/clock/clockSubscriber.ts +113 -0
  44. package/src/constants/perpMarkets.ts +2 -2
  45. package/src/constants/spotMarkets.ts +13 -0
  46. package/src/dlob/DLOB.ts +2 -2
  47. package/src/dlob/orderBookLevels.ts +2 -0
  48. package/src/driftClient.ts +247 -385
  49. package/src/driftClientConfig.ts +2 -0
  50. package/src/idl/drift.json +1 -1
  51. package/src/index.ts +2 -0
  52. package/src/jupiter/jupiterClient.ts +15 -6
  53. package/src/math/exchangeStatus.ts +2 -1
  54. package/src/math/orders.ts +3 -2
  55. package/src/tx/baseTxSender.ts +21 -75
  56. package/src/tx/fastSingleTxSender.ts +10 -55
  57. package/src/tx/forwardOnlyTxSender.ts +5 -1
  58. package/src/tx/retryTxSender.ts +5 -1
  59. package/src/tx/txHandler.ts +625 -0
  60. package/src/tx/txParamProcessor.ts +16 -28
  61. package/src/tx/types.ts +2 -18
  62. package/src/tx/whileValidTxSender.ts +24 -48
  63. package/src/types.ts +26 -2
  64. package/src/util/chainClock.ts +41 -0
  65. package/tests/dlob/helpers.ts +3 -0
  66. package/lib/tx/utils.d.ts +0 -6
  67. package/lib/tx/utils.js +0 -43
  68. package/src/tx/utils.ts +0 -68
@@ -36,7 +36,6 @@ const drift_json_1 = __importDefault(require("./idl/drift.json"));
36
36
  const web3_js_1 = require("@solana/web3.js");
37
37
  const events_1 = require("events");
38
38
  const pda_1 = require("./addresses/pda");
39
- const utils_1 = require("./tx/utils");
40
39
  const numericConstants_1 = require("./constants/numericConstants");
41
40
  const position_1 = require("./math/position");
42
41
  const spotBalance_1 = require("./math/spotBalance");
@@ -55,9 +54,10 @@ const spotMarket_1 = require("./math/spotMarket");
55
54
  const memcmp_1 = require("./memcmp");
56
55
  const marinade_1 = require("./marinade");
57
56
  const orderParams_1 = require("./orderParams");
58
- const utils_2 = require("./math/utils");
57
+ const utils_1 = require("./math/utils");
59
58
  const txParamProcessor_1 = require("./tx/txParamProcessor");
60
59
  const oracles_1 = require("./math/oracles");
60
+ const txHandler_1 = require("./tx/txHandler");
61
61
  /**
62
62
  * # DriftClient
63
63
  * This class is the main way to interact with Drift Protocol. It allows you to subscribe to the various accounts where the Market's state is stored, as well as: opening positions, liquidating, settling funding, depositing & withdrawing, and more.
@@ -70,7 +70,7 @@ class DriftClient {
70
70
  this._isSubscribed = val;
71
71
  }
72
72
  constructor(config) {
73
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5;
73
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6;
74
74
  this.users = new Map();
75
75
  this._isSubscribed = false;
76
76
  this.perpMarketLastSlotCache = new Map();
@@ -96,6 +96,16 @@ class DriftClient {
96
96
  computeUnits: (_j = (_h = config.txParams) === null || _h === void 0 ? void 0 : _h.computeUnits) !== null && _j !== void 0 ? _j : 600000,
97
97
  computeUnitsPrice: (_l = (_k = config.txParams) === null || _k === void 0 ? void 0 : _k.computeUnitsPrice) !== null && _l !== void 0 ? _l : 0,
98
98
  };
99
+ this.txHandler =
100
+ (_m = config === null || config === void 0 ? void 0 : config.txHandler) !== null && _m !== void 0 ? _m : new txHandler_1.TxHandler({
101
+ connection: this.connection,
102
+ wallet: this.provider.wallet,
103
+ confirmationOptions: this.opts,
104
+ opts: {
105
+ returnBlockHeightsWithSignedTxCallbackData: config.enableMetricsEvents,
106
+ onSignedCb: this.handleSignedTransaction.bind(this),
107
+ },
108
+ });
99
109
  if (config.includeDelegates && config.subAccountIds) {
100
110
  throw new Error('Can only pass one of includeDelegates or subAccountIds. If you want to specify subaccount ids for multiple authorities, pass authoritySubaccountMap instead');
101
111
  }
@@ -110,8 +120,8 @@ class DriftClient {
110
120
  : config.subAccountIds
111
121
  ? new Map([[this.authority.toString(), config.subAccountIds]])
112
122
  : new Map();
113
- this.includeDelegates = (_m = config.includeDelegates) !== null && _m !== void 0 ? _m : false;
114
- if (((_o = config.accountSubscription) === null || _o === void 0 ? void 0 : _o.type) === 'polling') {
123
+ this.includeDelegates = (_o = config.includeDelegates) !== null && _o !== void 0 ? _o : false;
124
+ if (((_p = config.accountSubscription) === null || _p === void 0 ? void 0 : _p.type) === 'polling') {
115
125
  this.userAccountSubscriptionConfig = {
116
126
  type: 'polling',
117
127
  accountLoader: config.accountSubscription.accountLoader,
@@ -124,15 +134,15 @@ class DriftClient {
124
134
  else {
125
135
  this.userAccountSubscriptionConfig = {
126
136
  type: 'websocket',
127
- resubTimeoutMs: (_p = config.accountSubscription) === null || _p === void 0 ? void 0 : _p.resubTimeoutMs,
128
- logResubMessages: (_q = config.accountSubscription) === null || _q === void 0 ? void 0 : _q.logResubMessages,
129
- commitment: (_r = config.accountSubscription) === null || _r === void 0 ? void 0 : _r.commitment,
137
+ resubTimeoutMs: (_q = config.accountSubscription) === null || _q === void 0 ? void 0 : _q.resubTimeoutMs,
138
+ logResubMessages: (_r = config.accountSubscription) === null || _r === void 0 ? void 0 : _r.logResubMessages,
139
+ commitment: (_s = config.accountSubscription) === null || _s === void 0 ? void 0 : _s.commitment,
130
140
  };
131
141
  this.userStatsAccountSubscriptionConfig = {
132
142
  type: 'websocket',
133
- resubTimeoutMs: (_s = config.accountSubscription) === null || _s === void 0 ? void 0 : _s.resubTimeoutMs,
134
- logResubMessages: (_t = config.accountSubscription) === null || _t === void 0 ? void 0 : _t.logResubMessages,
135
- commitment: (_u = config.accountSubscription) === null || _u === void 0 ? void 0 : _u.commitment,
143
+ resubTimeoutMs: (_t = config.accountSubscription) === null || _t === void 0 ? void 0 : _t.resubTimeoutMs,
144
+ logResubMessages: (_u = config.accountSubscription) === null || _u === void 0 ? void 0 : _u.logResubMessages,
145
+ commitment: (_v = config.accountSubscription) === null || _v === void 0 ? void 0 : _v.commitment,
136
146
  };
137
147
  }
138
148
  if (config.userStats) {
@@ -149,25 +159,26 @@ class DriftClient {
149
159
  const noMarketsAndOraclesSpecified = config.perpMarketIndexes === undefined &&
150
160
  config.spotMarketIndexes === undefined &&
151
161
  config.oracleInfos === undefined;
152
- if (((_v = config.accountSubscription) === null || _v === void 0 ? void 0 : _v.type) === 'polling') {
153
- this.accountSubscriber = new pollingDriftClientAccountSubscriber_1.PollingDriftClientAccountSubscriber(this.program, config.accountSubscription.accountLoader, (_w = config.perpMarketIndexes) !== null && _w !== void 0 ? _w : [], (_x = config.spotMarketIndexes) !== null && _x !== void 0 ? _x : [], (_y = config.oracleInfos) !== null && _y !== void 0 ? _y : [], noMarketsAndOraclesSpecified);
162
+ if (((_w = config.accountSubscription) === null || _w === void 0 ? void 0 : _w.type) === 'polling') {
163
+ this.accountSubscriber = new pollingDriftClientAccountSubscriber_1.PollingDriftClientAccountSubscriber(this.program, config.accountSubscription.accountLoader, (_x = config.perpMarketIndexes) !== null && _x !== void 0 ? _x : [], (_y = config.spotMarketIndexes) !== null && _y !== void 0 ? _y : [], (_z = config.oracleInfos) !== null && _z !== void 0 ? _z : [], noMarketsAndOraclesSpecified);
154
164
  }
155
165
  else {
156
- this.accountSubscriber = new webSocketDriftClientAccountSubscriber_1.WebSocketDriftClientAccountSubscriber(this.program, (_z = config.perpMarketIndexes) !== null && _z !== void 0 ? _z : [], (_0 = config.spotMarketIndexes) !== null && _0 !== void 0 ? _0 : [], (_1 = config.oracleInfos) !== null && _1 !== void 0 ? _1 : [], noMarketsAndOraclesSpecified, {
157
- resubTimeoutMs: (_2 = config.accountSubscription) === null || _2 === void 0 ? void 0 : _2.resubTimeoutMs,
158
- logResubMessages: (_3 = config.accountSubscription) === null || _3 === void 0 ? void 0 : _3.logResubMessages,
159
- }, (_4 = config.accountSubscription) === null || _4 === void 0 ? void 0 : _4.commitment);
166
+ this.accountSubscriber = new webSocketDriftClientAccountSubscriber_1.WebSocketDriftClientAccountSubscriber(this.program, (_0 = config.perpMarketIndexes) !== null && _0 !== void 0 ? _0 : [], (_1 = config.spotMarketIndexes) !== null && _1 !== void 0 ? _1 : [], (_2 = config.oracleInfos) !== null && _2 !== void 0 ? _2 : [], noMarketsAndOraclesSpecified, {
167
+ resubTimeoutMs: (_3 = config.accountSubscription) === null || _3 === void 0 ? void 0 : _3.resubTimeoutMs,
168
+ logResubMessages: (_4 = config.accountSubscription) === null || _4 === void 0 ? void 0 : _4.logResubMessages,
169
+ }, (_5 = config.accountSubscription) === null || _5 === void 0 ? void 0 : _5.commitment);
160
170
  }
161
171
  this.eventEmitter = this.accountSubscriber.eventEmitter;
172
+ this.metricsEventEmitter = new events_1.EventEmitter();
162
173
  if (config.enableMetricsEvents) {
163
174
  this.enableMetricsEvents = true;
164
- this.metricsEventEmitter = new events_1.EventEmitter();
165
175
  }
166
176
  this.txSender =
167
- (_5 = config.txSender) !== null && _5 !== void 0 ? _5 : new retryTxSender_1.RetryTxSender({
177
+ (_6 = config.txSender) !== null && _6 !== void 0 ? _6 : new retryTxSender_1.RetryTxSender({
168
178
  connection: this.connection,
169
179
  wallet: this.wallet,
170
180
  opts: this.opts,
181
+ txHandler: this.txHandler,
171
182
  });
172
183
  }
173
184
  getUserMapKey(subAccountId, authority) {
@@ -324,6 +335,7 @@ class DriftClient {
324
335
  // Update provider for txSender with new wallet details
325
336
  this.txSender.wallet = newWallet;
326
337
  this.wallet = newWallet;
338
+ this.txHandler.updateWallet(newWallet);
327
339
  this.provider = newProvider;
328
340
  this.program = newProgram;
329
341
  this.authority = newWallet.publicKey;
@@ -448,22 +460,6 @@ class DriftClient {
448
460
  }
449
461
  return result;
450
462
  }
451
- async getProcessedTransactionParams(txParams, txParamProcessingParams) {
452
- const tx = await txParamProcessor_1.TransactionProcessor.process({
453
- txProps: {
454
- instructions: txParams.instructions,
455
- txParams: txParams.txParams,
456
- txVersion: txParams.txVersion,
457
- lookupTables: txParams.lookupTables,
458
- },
459
- txBuilder: (updatedTxParams) => this.buildTransaction(updatedTxParams.instructions, updatedTxParams === null || updatedTxParams === void 0 ? void 0 : updatedTxParams.txParams, updatedTxParams.txVersion, updatedTxParams.lookupTables, true),
460
- processConfig: txParamProcessingParams,
461
- processParams: {
462
- connection: this.connection,
463
- },
464
- });
465
- return tx;
466
- }
467
463
  async initializeUserAccount(subAccountId = 0, name, referrerInfo, txParams) {
468
464
  const initializeIxs = [];
469
465
  const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(subAccountId, name, referrerInfo);
@@ -867,7 +863,7 @@ class DriftClient {
867
863
  */
868
864
  convertToPerpPrecision(amount) {
869
865
  if (typeof amount === 'number') {
870
- return (0, utils_2.numberToSafeBN)(amount, numericConstants_1.BASE_PRECISION);
866
+ return (0, utils_1.numberToSafeBN)(amount, numericConstants_1.BASE_PRECISION);
871
867
  }
872
868
  else {
873
869
  return amount.mul(numericConstants_1.BASE_PRECISION);
@@ -879,7 +875,7 @@ class DriftClient {
879
875
  */
880
876
  convertToPricePrecision(amount) {
881
877
  if (typeof amount === 'number') {
882
- return (0, utils_2.numberToSafeBN)(amount, numericConstants_1.PRICE_PRECISION);
878
+ return (0, utils_1.numberToSafeBN)(amount, numericConstants_1.PRICE_PRECISION);
883
879
  }
884
880
  else {
885
881
  return amount.mul(numericConstants_1.BASE_PRECISION);
@@ -1509,8 +1505,8 @@ class DriftClient {
1509
1505
  price: limitPrice,
1510
1506
  }, undefined, undefined, undefined, subAccountId);
1511
1507
  }
1512
- async sendSignedTx(tx) {
1513
- const { txSig } = await this.sendTransaction(tx, undefined, this.opts, true);
1508
+ async sendSignedTx(tx, opts) {
1509
+ const { txSig } = await this.sendTransaction(tx, undefined, opts !== null && opts !== void 0 ? opts : this.opts, true);
1514
1510
  return txSig;
1515
1511
  }
1516
1512
  /**
@@ -1528,93 +1524,51 @@ class DriftClient {
1528
1524
  const marketIndex = orderParams.marketIndex;
1529
1525
  const orderId = userAccount.nextOrderId;
1530
1526
  const ordersIx = await this.getPlaceOrdersIx([orderParams, ...bracketOrdersParams], userAccount.subAccountId);
1527
+ const ixsToSign = [];
1528
+ const keys = {
1529
+ signedCancelExistingOrdersTx: 'signedCancelExistingOrdersTx',
1530
+ signedSettlePnlTx: 'signedSettlePnlTx',
1531
+ signedFillTx: 'signedFillTx',
1532
+ signedMarketOrderTx: 'signedMarketOrderTx',
1533
+ };
1531
1534
  /* Cancel open orders in market if requested */
1532
- let cancelExistingOrdersTx;
1533
1535
  if (cancelExistingOrders && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
1534
- const cancelOrdersIx = await this.getCancelOrdersIx(orderParams.marketType, orderParams.marketIndex, null, userAccount.subAccountId);
1535
- //@ts-ignore
1536
- cancelExistingOrdersTx = await this.buildTransaction([cancelOrdersIx], txParams, this.txVersion);
1536
+ ixsToSign.push({
1537
+ key: keys.signedCancelExistingOrdersTx,
1538
+ ix: await this.getCancelOrdersIx(orderParams.marketType, orderParams.marketIndex, null, userAccount.subAccountId),
1539
+ });
1537
1540
  }
1538
1541
  /* Settle PnL after fill if requested */
1539
- let settlePnlTx;
1540
1542
  if (settlePnl && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
1541
- const settlePnlIx = await this.settlePNLIx(userAccountPublicKey, userAccount, marketIndex);
1542
- //@ts-ignore
1543
- settlePnlTx = await this.buildTransaction([settlePnlIx], txParams, this.txVersion);
1543
+ ixsToSign.push({
1544
+ key: keys.signedSettlePnlTx,
1545
+ ix: await this.settlePNLIx(userAccountPublicKey, userAccount, marketIndex),
1546
+ });
1544
1547
  }
1545
1548
  // use versioned transactions if there is a lookup table account and wallet is compatible
1546
1549
  if (this.txVersion === 0) {
1547
- const versionedMarketOrderTx = await this.buildTransaction(ordersIx, txParams, 0);
1548
- const fillPerpOrderIx = await this.getFillPerpOrderIx(userAccountPublicKey, userAccount, {
1549
- orderId,
1550
- marketIndex,
1551
- }, makerInfo, referrerInfo, userAccount.subAccountId);
1552
- const versionedFillTx = await this.buildTransaction([fillPerpOrderIx], txParams, 0);
1553
- const allPossibleTxs = [
1554
- versionedMarketOrderTx,
1555
- versionedFillTx,
1556
- cancelExistingOrdersTx,
1557
- settlePnlTx,
1558
- ];
1559
- const txKeys = [
1560
- 'signedVersionedMarketOrderTx',
1561
- 'signedVersionedFillTx',
1562
- 'signedCancelExistingOrdersTx',
1563
- 'signedSettlePnlTx',
1564
- ];
1565
- const { signedVersionedMarketOrderTx, signedVersionedFillTx, signedCancelExistingOrdersTx, signedSettlePnlTx, } = await (0, utils_1.getSignedTransactionMap)(
1566
- //@ts-ignore
1567
- this.provider.wallet, allPossibleTxs, txKeys);
1568
- const { txSig, slot } = await this.sendTransaction(signedVersionedMarketOrderTx, [], this.opts, true);
1569
- this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
1570
- return {
1571
- txSig,
1572
- // @ts-ignore
1573
- signedFillTx: signedVersionedFillTx,
1574
- // @ts-ignore
1575
- signedCancelExistingOrdersTx,
1576
- // @ts-ignore
1577
- signedSettlePnlTx,
1578
- };
1579
- }
1580
- else {
1581
- const marketOrderTx = (0, utils_1.wrapInTx)(ordersIx, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice);
1582
- // Apply the latest blockhash to the txs so that we can sign before sending them
1583
- const currentBlockHash = (await this.connection.getLatestBlockhash('finalized')).blockhash;
1584
- marketOrderTx.recentBlockhash = currentBlockHash;
1585
- marketOrderTx.feePayer = userAccount.authority;
1586
- if (cancelExistingOrdersTx) {
1587
- cancelExistingOrdersTx.recentBlockhash = currentBlockHash;
1588
- cancelExistingOrdersTx.feePayer = userAccount.authority;
1589
- }
1590
- if (settlePnlTx) {
1591
- settlePnlTx.recentBlockhash = currentBlockHash;
1592
- settlePnlTx.feePayer = userAccount.authority;
1593
- }
1594
- const allPossibleTxs = [
1595
- marketOrderTx,
1596
- cancelExistingOrdersTx,
1597
- settlePnlTx,
1598
- ];
1599
- const txKeys = [
1600
- 'signedMarketOrderTx',
1601
- 'signedCancelExistingOrdersTx',
1602
- 'signedSettlePnlTx',
1603
- ];
1604
- const { signedMarketOrderTx, signedCancelExistingOrdersTx, signedSettlePnlTx, } = await (0, utils_1.getSignedTransactionMap)(
1605
- //@ts-ignore
1606
- this.provider.wallet, allPossibleTxs, txKeys);
1607
- const { txSig, slot } = await this.sendTransaction(signedMarketOrderTx, [], this.opts, true);
1608
- this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
1609
- return {
1610
- txSig,
1611
- signedFillTx: undefined,
1612
- //@ts-ignore
1613
- signedCancelExistingOrdersTx,
1614
- //@ts-ignore
1615
- signedSettlePnlTx,
1616
- };
1550
+ ixsToSign.push({
1551
+ key: keys.signedFillTx,
1552
+ ix: await this.getFillPerpOrderIx(userAccountPublicKey, userAccount, {
1553
+ orderId,
1554
+ marketIndex,
1555
+ }, makerInfo, referrerInfo, userAccount.subAccountId),
1556
+ });
1617
1557
  }
1558
+ // Apply the latest blockhash to the txs so that we can sign before sending them
1559
+ ixsToSign.push({
1560
+ key: keys.signedMarketOrderTx,
1561
+ ix: ordersIx,
1562
+ });
1563
+ const signedTransactions = await this.buildAndSignBulkTransactions(ixsToSign.map((ix) => ix.ix), ixsToSign.map((ix) => ix.key), txParams);
1564
+ const { txSig, slot } = await this.sendTransaction(signedTransactions[keys.signedMarketOrderTx], [], this.opts, true);
1565
+ this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
1566
+ return {
1567
+ txSig,
1568
+ signedFillTx: signedTransactions === null || signedTransactions === void 0 ? void 0 : signedTransactions[keys.signedFillTx],
1569
+ signedCancelExistingOrdersTx: signedTransactions === null || signedTransactions === void 0 ? void 0 : signedTransactions[keys.signedCancelExistingOrdersTx],
1570
+ signedSettlePnlTx: signedTransactions === null || signedTransactions === void 0 ? void 0 : signedTransactions[keys.signedSettlePnlTx],
1571
+ };
1618
1572
  }
1619
1573
  async placePerpOrder(orderParams, txParams, subAccountId) {
1620
1574
  const { txSig, slot } = await this.sendTransaction(await this.buildTransaction(await this.getPlacePerpOrderIx(orderParams, subAccountId), txParams), [], this.opts);
@@ -2277,7 +2231,7 @@ class DriftClient {
2277
2231
  const { beginSwapIx, endSwapIx } = await this.getSwapIx({
2278
2232
  outMarketIndex,
2279
2233
  inMarketIndex,
2280
- amountIn: amount,
2234
+ amountIn: new anchor_1.BN(route.inAmount),
2281
2235
  inTokenAccount: inAssociatedTokenAccount,
2282
2236
  outTokenAccount: outAssociatedTokenAccount,
2283
2237
  reduceOnly,
@@ -2339,7 +2293,7 @@ class DriftClient {
2339
2293
  const { beginSwapIx, endSwapIx } = await this.getSwapIx({
2340
2294
  outMarketIndex,
2341
2295
  inMarketIndex,
2342
- amountIn: amount,
2296
+ amountIn: new anchor_1.BN(quote.inAmount),
2343
2297
  inTokenAccount: inAssociatedTokenAccount,
2344
2298
  outTokenAccount: outAssociatedTokenAccount,
2345
2299
  reduceOnly,
@@ -2546,12 +2500,18 @@ class DriftClient {
2546
2500
  return txSig;
2547
2501
  }
2548
2502
  async placeAndTakePerpWithAdditionalOrders(orderParams, makerInfo, referrerInfo, bracketOrdersParams = new Array(), txParams, subAccountId, cancelExistingOrders, settlePnl, simulateFirst) {
2549
- const ixs = [];
2503
+ const placeAndTakeIxs = [];
2550
2504
  const placeAndTakeIx = await this.getPlaceAndTakePerpOrderIx(orderParams, makerInfo, referrerInfo, subAccountId);
2551
- ixs.push(placeAndTakeIx);
2505
+ const txsToSign = [];
2506
+ const keys = {
2507
+ placeAndTakeIx: 'placeAndTakeIx',
2508
+ cancelExistingOrdersTx: 'cancelExistingOrdersTx',
2509
+ settlePnlTx: 'settlePnlTx',
2510
+ };
2511
+ placeAndTakeIxs.push(placeAndTakeIx);
2552
2512
  if (bracketOrdersParams.length > 0) {
2553
2513
  const bracketOrdersIx = await this.getPlaceOrdersIx(bracketOrdersParams, subAccountId);
2554
- ixs.push(bracketOrdersIx);
2514
+ placeAndTakeIxs.push(bracketOrdersIx);
2555
2515
  }
2556
2516
  const shouldUseSimulationComputeUnits = txParams === null || txParams === void 0 ? void 0 : txParams.useSimulatedComputeUnits;
2557
2517
  const shouldExitIfSimulationFails = simulateFirst;
@@ -2559,57 +2519,51 @@ class DriftClient {
2559
2519
  ...txParams,
2560
2520
  useSimulationComputeUnits: false,
2561
2521
  };
2562
- let placeAndTakeTx = await this.buildTransaction(ixs, txParamsWithoutImplicitSimulation);
2522
+ // Get recent block hash so that we can re-use it for all transactions. Makes this logic run faster with fewer RPC requests
2523
+ const recentBlockHash = await this.txHandler.getLatestBlockhashForTransaction();
2563
2524
  if (shouldUseSimulationComputeUnits || shouldExitIfSimulationFails) {
2564
- let versionedPlaceAndTakeTx;
2565
- if (this.isVersionedTransaction(placeAndTakeTx)) {
2566
- versionedPlaceAndTakeTx = placeAndTakeTx;
2567
- }
2568
- else {
2569
- versionedPlaceAndTakeTx = (await this.buildTransaction(ixs, txParamsWithoutImplicitSimulation, undefined, undefined, true));
2570
- }
2571
- const simulationResult = await txParamProcessor_1.TransactionProcessor.getTxSimComputeUnits(versionedPlaceAndTakeTx, this.connection);
2525
+ const placeAndTakeTxToSim = (await this.buildTransaction(placeAndTakeIxs, txParamsWithoutImplicitSimulation, undefined, undefined, true, recentBlockHash));
2526
+ const simulationResult = await txParamProcessor_1.TransactionParamProcessor.getTxSimComputeUnits(placeAndTakeTxToSim, this.connection);
2572
2527
  if (shouldExitIfSimulationFails && !simulationResult.success) {
2573
2528
  return;
2574
2529
  }
2575
- if (shouldUseSimulationComputeUnits) {
2576
- placeAndTakeTx = await this.buildTransaction(ixs, {
2530
+ txsToSign.push({
2531
+ key: keys.placeAndTakeIx,
2532
+ tx: await this.buildTransaction(placeAndTakeIxs, {
2577
2533
  ...txParamsWithoutImplicitSimulation,
2578
2534
  computeUnits: simulationResult.computeUnits,
2579
- });
2580
- }
2535
+ }, undefined, undefined, undefined, recentBlockHash),
2536
+ });
2537
+ }
2538
+ else {
2539
+ txsToSign.push({
2540
+ key: keys.placeAndTakeIx,
2541
+ tx: await this.buildTransaction(placeAndTakeIxs, txParamsWithoutImplicitSimulation, undefined, undefined, undefined, recentBlockHash),
2542
+ });
2581
2543
  }
2582
- let cancelExistingOrdersTx;
2583
2544
  if (cancelExistingOrders && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
2584
2545
  const cancelOrdersIx = await this.getCancelOrdersIx(orderParams.marketType, orderParams.marketIndex, null, subAccountId);
2585
- //@ts-ignore
2586
- cancelExistingOrdersTx = await this.buildTransaction([cancelOrdersIx], txParams, this.txVersion);
2546
+ txsToSign.push({
2547
+ key: keys.cancelExistingOrdersTx,
2548
+ tx: await this.buildTransaction([cancelOrdersIx], txParams, this.txVersion, undefined, undefined, recentBlockHash),
2549
+ });
2587
2550
  }
2588
- /* Settle PnL after fill if requested */
2589
- let settlePnlTx;
2590
2551
  if (settlePnl && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
2591
2552
  const userAccountPublicKey = await this.getUserAccountPublicKey(subAccountId);
2592
2553
  const settlePnlIx = await this.settlePNLIx(userAccountPublicKey, this.getUserAccount(subAccountId), orderParams.marketIndex);
2593
- //@ts-ignore
2594
- settlePnlTx = await this.buildTransaction([settlePnlIx], txParams, this.txVersion);
2554
+ txsToSign.push({
2555
+ key: keys.settlePnlTx,
2556
+ tx: await this.buildTransaction([settlePnlIx], txParams, this.txVersion, undefined, undefined, recentBlockHash),
2557
+ });
2595
2558
  }
2596
- const allPossibleTxs = [
2597
- placeAndTakeTx,
2598
- cancelExistingOrdersTx,
2599
- settlePnlTx,
2600
- ];
2601
- const txKeys = [
2602
- 'signedPlaceAndTakeTx',
2603
- 'signedCancelExistingOrdersTx',
2604
- 'signedSettlePnlTx',
2605
- ];
2606
- const { signedPlaceAndTakeTx, signedCancelExistingOrdersTx, signedSettlePnlTx, } = await (0, utils_1.getSignedTransactionMap)(
2607
- //@ts-ignore
2608
- this.provider.wallet, allPossibleTxs, txKeys);
2609
- const { txSig, slot } = await this.sendTransaction(signedPlaceAndTakeTx, [], this.opts, true);
2559
+ const signedTxs = await this.txHandler.getSignedTransactionMap(txsToSign.map((tx) => tx.tx), txsToSign.map((tx) => tx.key), this.provider.wallet);
2560
+ const { txSig, slot } = await this.sendTransaction(signedTxs[keys.placeAndTakeIx], [], this.opts, true);
2610
2561
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
2611
- //@ts-ignore
2612
- return { txSig, signedCancelExistingOrdersTx, signedSettlePnlTx };
2562
+ return {
2563
+ txSig,
2564
+ signedCancelExistingOrdersTx: signedTxs[keys.cancelExistingOrdersTx],
2565
+ signedSettlePnlTx: signedTxs[keys.settlePnlTx],
2566
+ };
2613
2567
  }
2614
2568
  async getPlaceAndTakePerpOrderIx(orderParams, makerInfo, referrerInfo, subAccountId) {
2615
2569
  orderParams = (0, orderParams_1.getOrderParams)(orderParams, { marketType: types_1.MarketType.PERP });
@@ -3614,8 +3568,10 @@ class DriftClient {
3614
3568
  }
3615
3569
  return undefined;
3616
3570
  }
3617
- handleSignedTransaction() {
3618
- this.metricsEventEmitter.emit('txSigned');
3571
+ handleSignedTransaction(signedTxs) {
3572
+ if (this.enableMetricsEvents && this.metricsEventEmitter) {
3573
+ this.metricsEventEmitter.emit('txSigned', signedTxs);
3574
+ }
3619
3575
  }
3620
3576
  isVersionedTransaction(tx) {
3621
3577
  const version = tx === null || tx === void 0 ? void 0 : tx.version;
@@ -3623,110 +3579,51 @@ class DriftClient {
3623
3579
  return isVersionedTx;
3624
3580
  }
3625
3581
  sendTransaction(tx, additionalSigners, opts, preSigned) {
3626
- const extraConfirmationOptions = this
3627
- .enableMetricsEvents
3628
- ? {
3629
- onSignedCb: this.handleSignedTransaction.bind(this),
3630
- }
3631
- : undefined;
3632
3582
  const isVersionedTx = this.isVersionedTransaction(tx);
3633
3583
  if (isVersionedTx) {
3634
- return this.txSender.sendVersionedTransaction(tx, additionalSigners, opts, preSigned, extraConfirmationOptions);
3584
+ return this.txSender.sendVersionedTransaction(tx, additionalSigners, opts, preSigned);
3635
3585
  }
3636
3586
  else {
3637
- return this.txSender.send(tx, additionalSigners, opts, preSigned, extraConfirmationOptions);
3638
- }
3639
- }
3640
- /**
3641
- *
3642
- * @param instructions
3643
- * @param txParams
3644
- * @param txVersion
3645
- * @param lookupTables
3646
- * @param forceVersionedTransaction Return a VersionedTransaction instance even if the version of the transaction is Legacy
3647
- * @returns
3648
- */
3649
- async buildTransaction(instructions, txParams, txVersion, lookupTables, forceVersionedTransaction) {
3650
- var _a, _b;
3651
- txVersion = txVersion !== null && txVersion !== void 0 ? txVersion : this.txVersion;
3652
- // # Collect and process Tx Params
3653
- let baseTxParams = {
3654
- computeUnits: (_a = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits) !== null && _a !== void 0 ? _a : this.txParams.computeUnits,
3655
- computeUnitsPrice: (_b = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice) !== null && _b !== void 0 ? _b : this.txParams.computeUnitsPrice,
3656
- };
3657
- if (txParams === null || txParams === void 0 ? void 0 : txParams.useSimulatedComputeUnits) {
3658
- const splitTxParams = {
3659
- baseTxParams: {
3660
- computeUnits: txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits,
3661
- computeUnitsPrice: txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice,
3662
- },
3663
- txParamProcessingParams: {
3664
- useSimulatedComputeUnits: txParams === null || txParams === void 0 ? void 0 : txParams.useSimulatedComputeUnits,
3665
- computeUnitsBufferMultiplier: txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsBufferMultiplier,
3666
- useSimulatedComputeUnitsForCUPriceCalculation: txParams === null || txParams === void 0 ? void 0 : txParams.useSimulatedComputeUnitsForCUPriceCalculation,
3667
- getCUPriceFromComputeUnits: txParams === null || txParams === void 0 ? void 0 : txParams.getCUPriceFromComputeUnits,
3668
- },
3669
- };
3670
- const processedTxParams = await this.getProcessedTransactionParams({
3671
- instructions,
3672
- txParams: splitTxParams.baseTxParams,
3673
- txVersion,
3674
- lookupTables,
3675
- }, splitTxParams.txParamProcessingParams);
3676
- baseTxParams = {
3677
- ...baseTxParams,
3678
- ...processedTxParams,
3679
- };
3680
- }
3681
- // # Create Tx Instructions
3682
- const allIx = [];
3683
- const computeUnits = baseTxParams === null || baseTxParams === void 0 ? void 0 : baseTxParams.computeUnits;
3684
- if (computeUnits !== 200000) {
3685
- allIx.push(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
3686
- units: computeUnits,
3687
- }));
3688
- }
3689
- const computeUnitsPrice = baseTxParams === null || baseTxParams === void 0 ? void 0 : baseTxParams.computeUnitsPrice;
3690
- if (computeUnitsPrice !== 0) {
3691
- allIx.push(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
3692
- microLamports: computeUnitsPrice,
3693
- }));
3694
- }
3695
- if (Array.isArray(instructions)) {
3696
- allIx.push(...instructions);
3697
- }
3698
- else {
3699
- allIx.push(instructions);
3700
- }
3701
- const latestBlockHashAndContext = await this.connection.getLatestBlockhashAndContext({
3702
- commitment: this.opts.preflightCommitment,
3703
- });
3704
- // # Create and return Transaction
3705
- if (txVersion === 'legacy') {
3706
- if (forceVersionedTransaction) {
3707
- const message = new web3_js_1.TransactionMessage({
3708
- payerKey: this.provider.wallet.publicKey,
3709
- recentBlockhash: latestBlockHashAndContext.value.blockhash,
3710
- instructions: allIx,
3711
- }).compileToLegacyMessage();
3712
- return new web3_js_1.VersionedTransaction(message);
3713
- }
3714
- else {
3715
- return new web3_js_1.Transaction().add(...allIx);
3716
- }
3717
- }
3718
- else {
3719
- const marketLookupTable = await this.fetchMarketLookupTableAccount();
3720
- lookupTables = lookupTables
3721
- ? [...lookupTables, marketLookupTable]
3722
- : [marketLookupTable];
3723
- const message = new web3_js_1.TransactionMessage({
3724
- payerKey: this.provider.wallet.publicKey,
3725
- recentBlockhash: latestBlockHashAndContext.value.blockhash,
3726
- instructions: allIx,
3727
- }).compileToV0Message(lookupTables);
3728
- return new web3_js_1.VersionedTransaction(message);
3729
- }
3587
+ return this.txSender.send(tx, additionalSigners, opts, preSigned);
3588
+ }
3589
+ }
3590
+ async buildTransaction(instructions, txParams, txVersion, lookupTables, forceVersionedTransaction, recentBlockHash) {
3591
+ return this.txHandler.buildTransaction({
3592
+ instructions,
3593
+ txVersion: txVersion !== null && txVersion !== void 0 ? txVersion : this.txVersion,
3594
+ txParams,
3595
+ connection: this.connection,
3596
+ preFlightCommitment: this.opts.preflightCommitment,
3597
+ fetchMarketLookupTableAccount: this.fetchMarketLookupTableAccount.bind(this),
3598
+ lookupTables,
3599
+ forceVersionedTransaction,
3600
+ recentBlockHash,
3601
+ });
3602
+ }
3603
+ async buildBulkTransactions(instructions, txParams, txVersion, lookupTables, forceVersionedTransaction) {
3604
+ return this.txHandler.buildBulkTransactions({
3605
+ instructions,
3606
+ txVersion: txVersion !== null && txVersion !== void 0 ? txVersion : this.txVersion,
3607
+ txParams,
3608
+ connection: this.connection,
3609
+ preFlightCommitment: this.opts.preflightCommitment,
3610
+ fetchMarketLookupTableAccount: this.fetchMarketLookupTableAccount.bind(this),
3611
+ lookupTables,
3612
+ forceVersionedTransaction,
3613
+ });
3614
+ }
3615
+ async buildAndSignBulkTransactions(instructions, keys, txParams, txVersion, lookupTables, forceVersionedTransaction) {
3616
+ return this.txHandler.buildAndSignTransactionMap({
3617
+ instructions,
3618
+ txVersion: txVersion !== null && txVersion !== void 0 ? txVersion : this.txVersion,
3619
+ txParams,
3620
+ connection: this.connection,
3621
+ preFlightCommitment: this.opts.preflightCommitment,
3622
+ fetchMarketLookupTableAccount: this.fetchMarketLookupTableAccount.bind(this),
3623
+ lookupTables,
3624
+ forceVersionedTransaction,
3625
+ keys,
3626
+ });
3730
3627
  }
3731
3628
  }
3732
3629
  exports.DriftClient = DriftClient;
@@ -4,6 +4,7 @@ import { OracleInfo } from './oracles/types';
4
4
  import { BulkAccountLoader } from './accounts/bulkAccountLoader';
5
5
  import { DriftEnv } from './config';
6
6
  import { TxSender } from './tx/types';
7
+ import { TxHandler } from './tx/txHandler';
7
8
  export type DriftClientConfig = {
8
9
  connection: Connection;
9
10
  wallet: IWallet;
@@ -12,6 +13,7 @@ export type DriftClientConfig = {
12
13
  accountSubscription?: DriftClientSubscriptionConfig;
13
14
  opts?: ConfirmOptions;
14
15
  txSender?: TxSender;
16
+ txHandler?: TxHandler;
15
17
  subAccountIds?: number[];
16
18
  activeSubAccountId?: number;
17
19
  perpMarketIndexes?: number[];
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.81.0",
2
+ "version": "2.82.0",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
package/lib/index.d.ts CHANGED
@@ -101,4 +101,6 @@ export * from './auctionSubscriber/types';
101
101
  export * from './memcmp';
102
102
  export * from './decode/user';
103
103
  export * from './blockhashSubscriber';
104
+ export * from './util/chainClock';
105
+ export * from './clock/clockSubscriber';
104
106
  export { BN, PublicKey, pyth };
package/lib/index.js CHANGED
@@ -124,3 +124,5 @@ __exportStar(require("./auctionSubscriber/types"), exports);
124
124
  __exportStar(require("./memcmp"), exports);
125
125
  __exportStar(require("./decode/user"), exports);
126
126
  __exportStar(require("./blockhashSubscriber"), exports);
127
+ __exportStar(require("./util/chainClock"), exports);
128
+ __exportStar(require("./clock/clockSubscriber"), exports);
@@ -206,8 +206,9 @@ export declare class JupiterClient {
206
206
  url: string;
207
207
  connection: Connection;
208
208
  lookupTableCahce: Map<string, AddressLookupTableAccount>;
209
- constructor({ connection }: {
209
+ constructor({ connection, url }: {
210
210
  connection: Connection;
211
+ url?: string;
211
212
  });
212
213
  /**
213
214
  * ** @deprecated - use getQuote