@drift-labs/sdk 2.108.0-beta.6 → 2.108.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.108.0-beta.6
1
+ 2.108.0-beta.8
@@ -389,8 +389,8 @@ export declare class DriftClient {
389
389
  marketIndex?: number;
390
390
  direction?: PositionDirection;
391
391
  }, placeOrderParams: OrderParams[], txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
392
- placeOrders(params: OrderParams[], txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
393
- preparePlaceOrdersTx(params: OrderParams[], txParams?: TxParams, subAccountId?: number): Promise<{
392
+ placeOrders(params: OrderParams[], txParams?: TxParams, subAccountId?: number, optionalIxs?: TransactionInstruction[]): Promise<TransactionSignature>;
393
+ preparePlaceOrdersTx(params: OrderParams[], txParams?: TxParams, subAccountId?: number, optionalIxs?: TransactionInstruction[]): Promise<{
394
394
  placeOrdersTx: anchor.web3.Transaction | anchor.web3.VersionedTransaction;
395
395
  }>;
396
396
  getPlaceOrdersIx(params: OptionalOrderParams[], subAccountId?: number): Promise<TransactionInstruction>;
@@ -520,7 +520,7 @@ export declare class DriftClient {
520
520
  updateUserOpenOrdersCount(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams, fillerPublicKey?: PublicKey): Promise<TransactionSignature>;
521
521
  getUpdateUserOpenOrdersCountIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, fillerPublicKey?: PublicKey): Promise<TransactionInstruction>;
522
522
  placeAndTakePerpOrder(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, successCondition?: PlaceAndTakeOrderSuccessCondition, auctionDurationPercentage?: number, txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
523
- preparePlaceAndTakePerpOrderWithAdditionalOrders(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, bracketOrdersParams?: OptionalOrderParams[], txParams?: TxParams, subAccountId?: number, cancelExistingOrders?: boolean, settlePnl?: boolean, exitEarlyIfSimFails?: boolean, auctionDurationPercentage?: number): Promise<{
523
+ preparePlaceAndTakePerpOrderWithAdditionalOrders(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, bracketOrdersParams?: OptionalOrderParams[], txParams?: TxParams, subAccountId?: number, cancelExistingOrders?: boolean, settlePnl?: boolean, exitEarlyIfSimFails?: boolean, auctionDurationPercentage?: number, optionalIxs?: TransactionInstruction[]): Promise<{
524
524
  placeAndTakeTx: Transaction | VersionedTransaction;
525
525
  cancelExistingOrdersTx: Transaction | VersionedTransaction;
526
526
  settlePnlTx: Transaction | VersionedTransaction;
@@ -706,7 +706,7 @@ export declare class DriftClient {
706
706
  settleeUserAccountPublicKey: PublicKey;
707
707
  settleeUserAccount: UserAccount;
708
708
  }[], marketIndexes: number[]): Promise<Array<TransactionInstruction>>;
709
- settlePNL(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndex: number, txParams?: TxParams): Promise<TransactionSignature>;
709
+ settlePNL(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndex: number, txParams?: TxParams, optionalIxs?: TransactionInstruction[]): Promise<TransactionSignature>;
710
710
  settlePNLIx(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndex: number): Promise<TransactionInstruction>;
711
711
  settleMultiplePNLs(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndexes: number[], mode: SettlePnlMode, txParams?: TxParams): Promise<TransactionSignature>;
712
712
  settleMultiplePNLsMultipleTxs(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndexes: number[], mode: SettlePnlMode, txParams?: TxParams): Promise<TransactionSignature[]>;
@@ -896,7 +896,7 @@ export declare class DriftClient {
896
896
  * @returns
897
897
  */
898
898
  sendTransaction(tx: Transaction | VersionedTransaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions, preSigned?: boolean): Promise<TxSigAndSlot>;
899
- buildTransaction(instructions: TransactionInstruction | TransactionInstruction[], txParams?: TxParams, txVersion?: TransactionVersion, lookupTables?: AddressLookupTableAccount[], forceVersionedTransaction?: boolean, recentBlockhash?: BlockhashWithExpiryBlockHeight): Promise<Transaction | VersionedTransaction>;
899
+ buildTransaction(instructions: TransactionInstruction | TransactionInstruction[], txParams?: TxParams, txVersion?: TransactionVersion, lookupTables?: AddressLookupTableAccount[], forceVersionedTransaction?: boolean, recentBlockhash?: BlockhashWithExpiryBlockHeight, optionalIxs?: TransactionInstruction[]): Promise<Transaction | VersionedTransaction>;
900
900
  buildBulkTransactions(instructions: (TransactionInstruction | TransactionInstruction[])[], txParams?: TxParams, txVersion?: TransactionVersion, lookupTables?: AddressLookupTableAccount[], forceVersionedTransaction?: boolean): Promise<(Transaction | VersionedTransaction)[]>;
901
901
  buildTransactionsMap(instructionsMap: Record<string, TransactionInstruction | TransactionInstruction[]>, txParams?: TxParams, txVersion?: TransactionVersion, lookupTables?: AddressLookupTableAccount[], forceVersionedTransaction?: boolean): Promise<MappedRecord<Record<string, anchor.web3.TransactionInstruction | anchor.web3.TransactionInstruction[]>, anchor.web3.Transaction | anchor.web3.VersionedTransaction>>;
902
902
  buildAndSignTransactionsMap(instructionsMap: Record<string, TransactionInstruction | TransactionInstruction[]>, txParams?: TxParams, txVersion?: TransactionVersion, lookupTables?: AddressLookupTableAccount[], forceVersionedTransaction?: boolean): Promise<{
@@ -2069,13 +2069,13 @@ class DriftClient {
2069
2069
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
2070
2070
  return txSig;
2071
2071
  }
2072
- async placeOrders(params, txParams, subAccountId) {
2073
- const { txSig } = await this.sendTransaction((await this.preparePlaceOrdersTx(params, txParams, subAccountId))
2074
- .placeOrdersTx, [], this.opts, false);
2072
+ async placeOrders(params, txParams, subAccountId, optionalIxs) {
2073
+ const { txSig } = await this.sendTransaction((await this.preparePlaceOrdersTx(params, txParams, subAccountId, optionalIxs)).placeOrdersTx, [], this.opts, false);
2075
2074
  return txSig;
2076
2075
  }
2077
- async preparePlaceOrdersTx(params, txParams, subAccountId) {
2078
- const tx = await this.buildTransaction(await this.getPlaceOrdersIx(params, subAccountId), txParams);
2076
+ async preparePlaceOrdersTx(params, txParams, subAccountId, optionalIxs) {
2077
+ const lookupTableAccount = await this.fetchMarketLookupTableAccount();
2078
+ const tx = await this.buildTransaction(await this.getPlaceOrdersIx(params, subAccountId), txParams, undefined, [lookupTableAccount], undefined, undefined, optionalIxs);
2079
2079
  return {
2080
2080
  placeOrdersTx: tx,
2081
2081
  };
@@ -2989,7 +2989,7 @@ class DriftClient {
2989
2989
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
2990
2990
  return txSig;
2991
2991
  }
2992
- async preparePlaceAndTakePerpOrderWithAdditionalOrders(orderParams, makerInfo, referrerInfo, bracketOrdersParams = new Array(), txParams, subAccountId, cancelExistingOrders, settlePnl, exitEarlyIfSimFails, auctionDurationPercentage) {
2992
+ async preparePlaceAndTakePerpOrderWithAdditionalOrders(orderParams, makerInfo, referrerInfo, bracketOrdersParams = new Array(), txParams, subAccountId, cancelExistingOrders, settlePnl, exitEarlyIfSimFails, auctionDurationPercentage, optionalIxs) {
2993
2993
  const placeAndTakeIxs = [];
2994
2994
  const txsToSign = {
2995
2995
  placeAndTakeTx: undefined,
@@ -2998,6 +2998,7 @@ class DriftClient {
2998
2998
  };
2999
2999
  // Get recent block hash so that we can re-use it for all transactions. Makes this logic run faster with fewer RPC requests
3000
3000
  const recentBlockHash = await this.txHandler.getLatestBlockhashForTransaction();
3001
+ const lookupTableAccount = await this.fetchMarketLookupTableAccount();
3001
3002
  let earlyExitFailedPlaceAndTakeSim = false;
3002
3003
  const prepPlaceAndTakeTx = async () => {
3003
3004
  var _a;
@@ -3014,7 +3015,7 @@ class DriftClient {
3014
3015
  useSimulatedComputeUnits: false,
3015
3016
  };
3016
3017
  if (shouldUseSimulationComputeUnits || shouldExitIfSimulationFails) {
3017
- const placeAndTakeTxToSim = (await this.buildTransaction(placeAndTakeIxs, txParams, undefined, undefined, true, recentBlockHash));
3018
+ const placeAndTakeTxToSim = (await this.buildTransaction(placeAndTakeIxs, txParams, undefined, [lookupTableAccount], true, recentBlockHash, optionalIxs));
3018
3019
  const simulationResult = await txParamProcessor_1.TransactionParamProcessor.getTxSimComputeUnits(placeAndTakeTxToSim, this.connection, (_a = txParams.computeUnitsBufferMultiplier) !== null && _a !== void 0 ? _a : 1.2, txParams.lowerBoundCu);
3019
3020
  if (shouldExitIfSimulationFails && !simulationResult.success) {
3020
3021
  earlyExitFailedPlaceAndTakeSim = true;
@@ -3023,17 +3024,17 @@ class DriftClient {
3023
3024
  txsToSign.placeAndTakeTx = await this.buildTransaction(placeAndTakeIxs, {
3024
3025
  ...txParamsWithoutImplicitSimulation,
3025
3026
  computeUnits: simulationResult.computeUnits,
3026
- }, undefined, undefined, undefined, recentBlockHash);
3027
+ }, undefined, [lookupTableAccount], undefined, recentBlockHash, optionalIxs);
3027
3028
  }
3028
3029
  else {
3029
- txsToSign.placeAndTakeTx = await this.buildTransaction(placeAndTakeIxs, txParams, undefined, undefined, undefined, recentBlockHash);
3030
+ txsToSign.placeAndTakeTx = await this.buildTransaction(placeAndTakeIxs, txParams, undefined, [lookupTableAccount], undefined, recentBlockHash, optionalIxs);
3030
3031
  }
3031
3032
  return;
3032
3033
  };
3033
3034
  const prepCancelOrderTx = async () => {
3034
3035
  if (cancelExistingOrders && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
3035
3036
  const cancelOrdersIx = await this.getCancelOrdersIx(orderParams.marketType, orderParams.marketIndex, null, subAccountId);
3036
- txsToSign.cancelExistingOrdersTx = await this.buildTransaction([cancelOrdersIx], txParams, this.txVersion, undefined, undefined, recentBlockHash);
3037
+ txsToSign.cancelExistingOrdersTx = await this.buildTransaction([cancelOrdersIx], txParams, this.txVersion, [lookupTableAccount], undefined, recentBlockHash, optionalIxs);
3037
3038
  }
3038
3039
  return;
3039
3040
  };
@@ -3041,7 +3042,7 @@ class DriftClient {
3041
3042
  if (settlePnl && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
3042
3043
  const userAccountPublicKey = await this.getUserAccountPublicKey(subAccountId);
3043
3044
  const settlePnlIx = await this.settlePNLIx(userAccountPublicKey, this.getUserAccount(subAccountId), orderParams.marketIndex);
3044
- txsToSign.settlePnlTx = await this.buildTransaction([settlePnlIx], txParams, this.txVersion, undefined, undefined, recentBlockHash);
3045
+ txsToSign.settlePnlTx = await this.buildTransaction([settlePnlIx], txParams, this.txVersion, [lookupTableAccount], undefined, recentBlockHash, optionalIxs);
3045
3046
  }
3046
3047
  return;
3047
3048
  };
@@ -3647,8 +3648,9 @@ class DriftClient {
3647
3648
  }
3648
3649
  return ixs;
3649
3650
  }
3650
- async settlePNL(settleeUserAccountPublicKey, settleeUserAccount, marketIndex, txParams) {
3651
- const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex), txParams), [], this.opts);
3651
+ async settlePNL(settleeUserAccountPublicKey, settleeUserAccount, marketIndex, txParams, optionalIxs) {
3652
+ const lookupTableAccount = await this.fetchMarketLookupTableAccount();
3653
+ const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex), txParams, undefined, [lookupTableAccount], undefined, undefined, optionalIxs), [], this.opts);
3652
3654
  return txSig;
3653
3655
  }
3654
3656
  async settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex) {
@@ -4894,7 +4896,7 @@ class DriftClient {
4894
4896
  return this.txSender.send(tx, additionalSigners, opts !== null && opts !== void 0 ? opts : this.opts, preSigned);
4895
4897
  }
4896
4898
  }
4897
- async buildTransaction(instructions, txParams, txVersion, lookupTables, forceVersionedTransaction, recentBlockhash) {
4899
+ async buildTransaction(instructions, txParams, txVersion, lookupTables, forceVersionedTransaction, recentBlockhash, optionalIxs) {
4898
4900
  return this.txHandler.buildTransaction({
4899
4901
  instructions,
4900
4902
  txVersion: txVersion !== null && txVersion !== void 0 ? txVersion : this.txVersion,
@@ -4905,6 +4907,7 @@ class DriftClient {
4905
4907
  lookupTables,
4906
4908
  forceVersionedTransaction,
4907
4909
  recentBlockhash,
4910
+ optionalIxs,
4908
4911
  });
4909
4912
  }
4910
4913
  async buildBulkTransactions(instructions, txParams, txVersion, lookupTables, forceVersionedTransaction) {
@@ -86,6 +86,7 @@ export * from './oracles/pythClient';
86
86
  export * from './oracles/pythPullClient';
87
87
  export * from './oracles/pythLazerClient';
88
88
  export * from './oracles/switchboardOnDemandClient';
89
+ export * from './oracles/oracleId';
89
90
  export * from './swift/swiftOrderSubscriber';
90
91
  export * from './tx/fastSingleTxSender';
91
92
  export * from './tx/retryTxSender';
@@ -109,6 +109,7 @@ __exportStar(require("./oracles/pythClient"), exports);
109
109
  __exportStar(require("./oracles/pythPullClient"), exports);
110
110
  __exportStar(require("./oracles/pythLazerClient"), exports);
111
111
  __exportStar(require("./oracles/switchboardOnDemandClient"), exports);
112
+ __exportStar(require("./oracles/oracleId"), exports);
112
113
  __exportStar(require("./swift/swiftOrderSubscriber"), exports);
113
114
  __exportStar(require("./tx/fastSingleTxSender"), exports);
114
115
  __exportStar(require("./tx/retryTxSender"), exports);
@@ -149,6 +149,22 @@ function getMultipleBetweenOracleSources(firstOracleSource, secondOracleSource)
149
149
  (0, types_1.isVariant)(secondOracleSource, 'pythPull')) {
150
150
  return { numerator: new index_1.BN(1), denominator: new index_1.BN(1000) };
151
151
  }
152
+ if ((0, types_1.isVariant)(firstOracleSource, 'pythLazer') &&
153
+ (0, types_1.isVariant)(secondOracleSource, 'pythLazer1M')) {
154
+ return { numerator: new index_1.BN(1000000), denominator: new index_1.BN(1) };
155
+ }
156
+ if ((0, types_1.isVariant)(firstOracleSource, 'pythLazer') &&
157
+ (0, types_1.isVariant)(secondOracleSource, 'pythLazer1K')) {
158
+ return { numerator: new index_1.BN(1000), denominator: new index_1.BN(1) };
159
+ }
160
+ if ((0, types_1.isVariant)(firstOracleSource, 'pythLazer1M') &&
161
+ (0, types_1.isVariant)(secondOracleSource, 'pythLazer')) {
162
+ return { numerator: new index_1.BN(1), denominator: new index_1.BN(1000000) };
163
+ }
164
+ if ((0, types_1.isVariant)(firstOracleSource, 'pythLazer1K') &&
165
+ (0, types_1.isVariant)(secondOracleSource, 'pythLazer')) {
166
+ return { numerator: new index_1.BN(1), denominator: new index_1.BN(1000) };
167
+ }
152
168
  return { numerator: new index_1.BN(1), denominator: new index_1.BN(1) };
153
169
  }
154
170
  exports.getMultipleBetweenOracleSources = getMultipleBetweenOracleSources;
@@ -12,6 +12,7 @@ export type TxBuildingProps = {
12
12
  txParams?: TxParams;
13
13
  recentBlockhash?: BlockhashWithExpiryBlockHeight;
14
14
  wallet?: IWallet;
15
+ optionalIxs?: TransactionInstruction[];
15
16
  };
16
17
  export type TxHandlerConfig = {
17
18
  blockhashCachingEnabled?: boolean;
@@ -277,24 +277,35 @@ class TxHandler {
277
277
  */
278
278
  async buildTransaction(props) {
279
279
  var _a;
280
- const { instructions, txVersion, txParams, connection: _connection, preFlightCommitment: _preFlightCommitment, fetchMarketLookupTableAccount, forceVersionedTransaction, } = props;
280
+ const { txVersion, txParams, connection: _connection, preFlightCommitment: _preFlightCommitment, fetchMarketLookupTableAccount, forceVersionedTransaction, instructions, } = props;
281
281
  let { lookupTables } = props;
282
282
  // # Collect and process Tx Params
283
283
  let baseTxParams = {
284
284
  computeUnits: txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits,
285
285
  computeUnitsPrice: txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice,
286
286
  };
287
+ const instructionsArray = Array.isArray(instructions)
288
+ ? instructions
289
+ : [instructions];
290
+ let instructionsToUse;
291
+ // add optional ixs if there's room (usually oracle cranks)
292
+ if (props.optionalIxs && txVersion === 0) {
293
+ instructionsToUse = (0, utils_1.getCombinedInstructions)(instructionsArray, props.optionalIxs, txVersion === 0, lookupTables);
294
+ }
295
+ else {
296
+ instructionsToUse = instructionsArray;
297
+ }
287
298
  if (txParams === null || txParams === void 0 ? void 0 : txParams.useSimulatedComputeUnits) {
288
- const processedTxParams = await this.getProcessedTransactionParams(props);
299
+ const processedTxParams = await this.getProcessedTransactionParams({
300
+ ...props,
301
+ instructions: instructionsToUse,
302
+ });
289
303
  baseTxParams = {
290
304
  ...baseTxParams,
291
305
  ...processedTxParams,
292
306
  };
293
307
  }
294
- const instructionsArray = Array.isArray(instructions)
295
- ? instructions
296
- : [instructions];
297
- const { hasSetComputeUnitLimitIx, hasSetComputeUnitPriceIx } = (0, computeUnits_1.containsComputeUnitIxs)(instructionsArray);
308
+ const { hasSetComputeUnitLimitIx, hasSetComputeUnitPriceIx } = (0, computeUnits_1.containsComputeUnitIxs)(instructionsToUse);
298
309
  // # Create Tx Instructions
299
310
  const allIx = [];
300
311
  const computeUnits = baseTxParams === null || baseTxParams === void 0 ? void 0 : baseTxParams.computeUnits;
@@ -314,7 +325,7 @@ class TxHandler {
314
325
  microLamports: computeUnitsPrice,
315
326
  }));
316
327
  }
317
- allIx.push(...instructionsArray);
328
+ allIx.push(...instructionsToUse);
318
329
  const recentBlockhash = (_a = props === null || props === void 0 ? void 0 : props.recentBlockhash) !== null && _a !== void 0 ? _a : (await this.getLatestBlockhashForTransaction());
319
330
  // # Create and return Transaction
320
331
  if (txVersion === 'legacy') {
@@ -1,2 +1,4 @@
1
- import { Transaction, VersionedTransaction } from '@solana/web3.js';
1
+ import { AddressLookupTableAccount, Transaction, TransactionInstruction, VersionedTransaction } from '@solana/web3.js';
2
2
  export declare const isVersionedTransaction: (tx: Transaction | VersionedTransaction) => boolean;
3
+ export declare const getSizeOfTransaction: (instructions: TransactionInstruction[], versionedTransaction?: boolean, addressLookupTables?: AddressLookupTableAccount[]) => number;
4
+ export declare const getCombinedInstructions: (baseInstructions: TransactionInstruction[], optionalInstructions?: TransactionInstruction[], versionedTransaction?: boolean, addressLookupTables?: AddressLookupTableAccount[]) => TransactionInstruction[];
@@ -1,10 +1,82 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isVersionedTransaction = void 0;
3
+ exports.getCombinedInstructions = exports.getSizeOfTransaction = exports.isVersionedTransaction = void 0;
4
4
  const web3_js_1 = require("@solana/web3.js");
5
+ const MAX_SIZE = 1232;
5
6
  const isVersionedTransaction = (tx) => {
6
7
  const version = tx === null || tx === void 0 ? void 0 : tx.version;
7
8
  const isVersionedTx = tx instanceof web3_js_1.VersionedTransaction || version !== undefined;
8
9
  return isVersionedTx;
9
10
  };
10
11
  exports.isVersionedTransaction = isVersionedTransaction;
12
+ const getSizeOfTransaction = (instructions, versionedTransaction = true, addressLookupTables = []) => {
13
+ const programs = new Set();
14
+ const signers = new Set();
15
+ let accounts = new Set();
16
+ instructions.forEach((ix) => {
17
+ try {
18
+ if (ix.programId) {
19
+ programs.add(ix.programId.toBase58());
20
+ accounts.add(ix.programId.toBase58());
21
+ }
22
+ if (ix.keys) {
23
+ ix.keys.forEach((key) => {
24
+ if (key.isSigner) {
25
+ signers.add(key.pubkey.toBase58());
26
+ }
27
+ accounts.add(key.pubkey.toBase58());
28
+ });
29
+ }
30
+ }
31
+ catch (e) {
32
+ console.log(e);
33
+ }
34
+ });
35
+ const instructionSizes = instructions
36
+ .map((ix) => 1 +
37
+ getSizeOfCompressedU16(ix.keys.length) +
38
+ ix.keys.length +
39
+ getSizeOfCompressedU16(ix.data.length) +
40
+ ix.data.length)
41
+ .reduce((a, b) => a + b, 0);
42
+ let numberOfAddressLookups = 0;
43
+ if (addressLookupTables.length > 0) {
44
+ const lookupTableAddresses = addressLookupTables
45
+ .map((addressLookupTable) => addressLookupTable.state.addresses.map((address) => address.toBase58()))
46
+ .flat();
47
+ const totalNumberOfAccounts = accounts.size;
48
+ accounts = new Set([...accounts].filter((account) => !lookupTableAddresses.includes(account)));
49
+ accounts = new Set([...accounts, ...programs, ...signers]);
50
+ numberOfAddressLookups = totalNumberOfAccounts - accounts.size;
51
+ }
52
+ return (getSizeOfCompressedU16(signers.size) +
53
+ signers.size * 64 + // array of signatures
54
+ 3 +
55
+ getSizeOfCompressedU16(accounts.size) +
56
+ 32 * accounts.size + // array of account addresses
57
+ 32 + // recent blockhash
58
+ getSizeOfCompressedU16(instructions.length) +
59
+ instructionSizes + // array of instructions
60
+ (versionedTransaction ? 1 + getSizeOfCompressedU16(0) : 0) +
61
+ (versionedTransaction ? 32 * addressLookupTables.length : 0) +
62
+ (versionedTransaction && addressLookupTables.length > 0 ? 2 : 0) +
63
+ numberOfAddressLookups);
64
+ };
65
+ exports.getSizeOfTransaction = getSizeOfTransaction;
66
+ const getCombinedInstructions = (baseInstructions, optionalInstructions = [], versionedTransaction = true, addressLookupTables = []) => {
67
+ if (optionalInstructions.length === 0) {
68
+ return baseInstructions;
69
+ }
70
+ let allInstructions = [...optionalInstructions, ...baseInstructions];
71
+ let txSize = (0, exports.getSizeOfTransaction)(allInstructions, versionedTransaction, addressLookupTables);
72
+ while (txSize > MAX_SIZE &&
73
+ allInstructions.length > baseInstructions.length) {
74
+ allInstructions = allInstructions.slice(1);
75
+ txSize = (0, exports.getSizeOfTransaction)(allInstructions, versionedTransaction, addressLookupTables);
76
+ }
77
+ return allInstructions;
78
+ };
79
+ exports.getCombinedInstructions = getCombinedInstructions;
80
+ function getSizeOfCompressedU16(n) {
81
+ return 1 + Number(n >= 128) + Number(n >= 16384);
82
+ }
@@ -389,8 +389,8 @@ export declare class DriftClient {
389
389
  marketIndex?: number;
390
390
  direction?: PositionDirection;
391
391
  }, placeOrderParams: OrderParams[], txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
392
- placeOrders(params: OrderParams[], txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
393
- preparePlaceOrdersTx(params: OrderParams[], txParams?: TxParams, subAccountId?: number): Promise<{
392
+ placeOrders(params: OrderParams[], txParams?: TxParams, subAccountId?: number, optionalIxs?: TransactionInstruction[]): Promise<TransactionSignature>;
393
+ preparePlaceOrdersTx(params: OrderParams[], txParams?: TxParams, subAccountId?: number, optionalIxs?: TransactionInstruction[]): Promise<{
394
394
  placeOrdersTx: anchor.web3.Transaction | anchor.web3.VersionedTransaction;
395
395
  }>;
396
396
  getPlaceOrdersIx(params: OptionalOrderParams[], subAccountId?: number): Promise<TransactionInstruction>;
@@ -520,7 +520,7 @@ export declare class DriftClient {
520
520
  updateUserOpenOrdersCount(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams, fillerPublicKey?: PublicKey): Promise<TransactionSignature>;
521
521
  getUpdateUserOpenOrdersCountIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, fillerPublicKey?: PublicKey): Promise<TransactionInstruction>;
522
522
  placeAndTakePerpOrder(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, successCondition?: PlaceAndTakeOrderSuccessCondition, auctionDurationPercentage?: number, txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
523
- preparePlaceAndTakePerpOrderWithAdditionalOrders(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, bracketOrdersParams?: OptionalOrderParams[], txParams?: TxParams, subAccountId?: number, cancelExistingOrders?: boolean, settlePnl?: boolean, exitEarlyIfSimFails?: boolean, auctionDurationPercentage?: number): Promise<{
523
+ preparePlaceAndTakePerpOrderWithAdditionalOrders(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, bracketOrdersParams?: OptionalOrderParams[], txParams?: TxParams, subAccountId?: number, cancelExistingOrders?: boolean, settlePnl?: boolean, exitEarlyIfSimFails?: boolean, auctionDurationPercentage?: number, optionalIxs?: TransactionInstruction[]): Promise<{
524
524
  placeAndTakeTx: Transaction | VersionedTransaction;
525
525
  cancelExistingOrdersTx: Transaction | VersionedTransaction;
526
526
  settlePnlTx: Transaction | VersionedTransaction;
@@ -706,7 +706,7 @@ export declare class DriftClient {
706
706
  settleeUserAccountPublicKey: PublicKey;
707
707
  settleeUserAccount: UserAccount;
708
708
  }[], marketIndexes: number[]): Promise<Array<TransactionInstruction>>;
709
- settlePNL(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndex: number, txParams?: TxParams): Promise<TransactionSignature>;
709
+ settlePNL(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndex: number, txParams?: TxParams, optionalIxs?: TransactionInstruction[]): Promise<TransactionSignature>;
710
710
  settlePNLIx(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndex: number): Promise<TransactionInstruction>;
711
711
  settleMultiplePNLs(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndexes: number[], mode: SettlePnlMode, txParams?: TxParams): Promise<TransactionSignature>;
712
712
  settleMultiplePNLsMultipleTxs(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndexes: number[], mode: SettlePnlMode, txParams?: TxParams): Promise<TransactionSignature[]>;
@@ -896,7 +896,7 @@ export declare class DriftClient {
896
896
  * @returns
897
897
  */
898
898
  sendTransaction(tx: Transaction | VersionedTransaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions, preSigned?: boolean): Promise<TxSigAndSlot>;
899
- buildTransaction(instructions: TransactionInstruction | TransactionInstruction[], txParams?: TxParams, txVersion?: TransactionVersion, lookupTables?: AddressLookupTableAccount[], forceVersionedTransaction?: boolean, recentBlockhash?: BlockhashWithExpiryBlockHeight): Promise<Transaction | VersionedTransaction>;
899
+ buildTransaction(instructions: TransactionInstruction | TransactionInstruction[], txParams?: TxParams, txVersion?: TransactionVersion, lookupTables?: AddressLookupTableAccount[], forceVersionedTransaction?: boolean, recentBlockhash?: BlockhashWithExpiryBlockHeight, optionalIxs?: TransactionInstruction[]): Promise<Transaction | VersionedTransaction>;
900
900
  buildBulkTransactions(instructions: (TransactionInstruction | TransactionInstruction[])[], txParams?: TxParams, txVersion?: TransactionVersion, lookupTables?: AddressLookupTableAccount[], forceVersionedTransaction?: boolean): Promise<(Transaction | VersionedTransaction)[]>;
901
901
  buildTransactionsMap(instructionsMap: Record<string, TransactionInstruction | TransactionInstruction[]>, txParams?: TxParams, txVersion?: TransactionVersion, lookupTables?: AddressLookupTableAccount[], forceVersionedTransaction?: boolean): Promise<MappedRecord<Record<string, anchor.web3.TransactionInstruction | anchor.web3.TransactionInstruction[]>, anchor.web3.Transaction | anchor.web3.VersionedTransaction>>;
902
902
  buildAndSignTransactionsMap(instructionsMap: Record<string, TransactionInstruction | TransactionInstruction[]>, txParams?: TxParams, txVersion?: TransactionVersion, lookupTables?: AddressLookupTableAccount[], forceVersionedTransaction?: boolean): Promise<{
@@ -2069,13 +2069,13 @@ class DriftClient {
2069
2069
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
2070
2070
  return txSig;
2071
2071
  }
2072
- async placeOrders(params, txParams, subAccountId) {
2073
- const { txSig } = await this.sendTransaction((await this.preparePlaceOrdersTx(params, txParams, subAccountId))
2074
- .placeOrdersTx, [], this.opts, false);
2072
+ async placeOrders(params, txParams, subAccountId, optionalIxs) {
2073
+ const { txSig } = await this.sendTransaction((await this.preparePlaceOrdersTx(params, txParams, subAccountId, optionalIxs)).placeOrdersTx, [], this.opts, false);
2075
2074
  return txSig;
2076
2075
  }
2077
- async preparePlaceOrdersTx(params, txParams, subAccountId) {
2078
- const tx = await this.buildTransaction(await this.getPlaceOrdersIx(params, subAccountId), txParams);
2076
+ async preparePlaceOrdersTx(params, txParams, subAccountId, optionalIxs) {
2077
+ const lookupTableAccount = await this.fetchMarketLookupTableAccount();
2078
+ const tx = await this.buildTransaction(await this.getPlaceOrdersIx(params, subAccountId), txParams, undefined, [lookupTableAccount], undefined, undefined, optionalIxs);
2079
2079
  return {
2080
2080
  placeOrdersTx: tx,
2081
2081
  };
@@ -2989,7 +2989,7 @@ class DriftClient {
2989
2989
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
2990
2990
  return txSig;
2991
2991
  }
2992
- async preparePlaceAndTakePerpOrderWithAdditionalOrders(orderParams, makerInfo, referrerInfo, bracketOrdersParams = new Array(), txParams, subAccountId, cancelExistingOrders, settlePnl, exitEarlyIfSimFails, auctionDurationPercentage) {
2992
+ async preparePlaceAndTakePerpOrderWithAdditionalOrders(orderParams, makerInfo, referrerInfo, bracketOrdersParams = new Array(), txParams, subAccountId, cancelExistingOrders, settlePnl, exitEarlyIfSimFails, auctionDurationPercentage, optionalIxs) {
2993
2993
  const placeAndTakeIxs = [];
2994
2994
  const txsToSign = {
2995
2995
  placeAndTakeTx: undefined,
@@ -2998,6 +2998,7 @@ class DriftClient {
2998
2998
  };
2999
2999
  // Get recent block hash so that we can re-use it for all transactions. Makes this logic run faster with fewer RPC requests
3000
3000
  const recentBlockHash = await this.txHandler.getLatestBlockhashForTransaction();
3001
+ const lookupTableAccount = await this.fetchMarketLookupTableAccount();
3001
3002
  let earlyExitFailedPlaceAndTakeSim = false;
3002
3003
  const prepPlaceAndTakeTx = async () => {
3003
3004
  var _a;
@@ -3014,7 +3015,7 @@ class DriftClient {
3014
3015
  useSimulatedComputeUnits: false,
3015
3016
  };
3016
3017
  if (shouldUseSimulationComputeUnits || shouldExitIfSimulationFails) {
3017
- const placeAndTakeTxToSim = (await this.buildTransaction(placeAndTakeIxs, txParams, undefined, undefined, true, recentBlockHash));
3018
+ const placeAndTakeTxToSim = (await this.buildTransaction(placeAndTakeIxs, txParams, undefined, [lookupTableAccount], true, recentBlockHash, optionalIxs));
3018
3019
  const simulationResult = await txParamProcessor_1.TransactionParamProcessor.getTxSimComputeUnits(placeAndTakeTxToSim, this.connection, (_a = txParams.computeUnitsBufferMultiplier) !== null && _a !== void 0 ? _a : 1.2, txParams.lowerBoundCu);
3019
3020
  if (shouldExitIfSimulationFails && !simulationResult.success) {
3020
3021
  earlyExitFailedPlaceAndTakeSim = true;
@@ -3023,17 +3024,17 @@ class DriftClient {
3023
3024
  txsToSign.placeAndTakeTx = await this.buildTransaction(placeAndTakeIxs, {
3024
3025
  ...txParamsWithoutImplicitSimulation,
3025
3026
  computeUnits: simulationResult.computeUnits,
3026
- }, undefined, undefined, undefined, recentBlockHash);
3027
+ }, undefined, [lookupTableAccount], undefined, recentBlockHash, optionalIxs);
3027
3028
  }
3028
3029
  else {
3029
- txsToSign.placeAndTakeTx = await this.buildTransaction(placeAndTakeIxs, txParams, undefined, undefined, undefined, recentBlockHash);
3030
+ txsToSign.placeAndTakeTx = await this.buildTransaction(placeAndTakeIxs, txParams, undefined, [lookupTableAccount], undefined, recentBlockHash, optionalIxs);
3030
3031
  }
3031
3032
  return;
3032
3033
  };
3033
3034
  const prepCancelOrderTx = async () => {
3034
3035
  if (cancelExistingOrders && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
3035
3036
  const cancelOrdersIx = await this.getCancelOrdersIx(orderParams.marketType, orderParams.marketIndex, null, subAccountId);
3036
- txsToSign.cancelExistingOrdersTx = await this.buildTransaction([cancelOrdersIx], txParams, this.txVersion, undefined, undefined, recentBlockHash);
3037
+ txsToSign.cancelExistingOrdersTx = await this.buildTransaction([cancelOrdersIx], txParams, this.txVersion, [lookupTableAccount], undefined, recentBlockHash, optionalIxs);
3037
3038
  }
3038
3039
  return;
3039
3040
  };
@@ -3041,7 +3042,7 @@ class DriftClient {
3041
3042
  if (settlePnl && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
3042
3043
  const userAccountPublicKey = await this.getUserAccountPublicKey(subAccountId);
3043
3044
  const settlePnlIx = await this.settlePNLIx(userAccountPublicKey, this.getUserAccount(subAccountId), orderParams.marketIndex);
3044
- txsToSign.settlePnlTx = await this.buildTransaction([settlePnlIx], txParams, this.txVersion, undefined, undefined, recentBlockHash);
3045
+ txsToSign.settlePnlTx = await this.buildTransaction([settlePnlIx], txParams, this.txVersion, [lookupTableAccount], undefined, recentBlockHash, optionalIxs);
3045
3046
  }
3046
3047
  return;
3047
3048
  };
@@ -3647,8 +3648,9 @@ class DriftClient {
3647
3648
  }
3648
3649
  return ixs;
3649
3650
  }
3650
- async settlePNL(settleeUserAccountPublicKey, settleeUserAccount, marketIndex, txParams) {
3651
- const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex), txParams), [], this.opts);
3651
+ async settlePNL(settleeUserAccountPublicKey, settleeUserAccount, marketIndex, txParams, optionalIxs) {
3652
+ const lookupTableAccount = await this.fetchMarketLookupTableAccount();
3653
+ const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex), txParams, undefined, [lookupTableAccount], undefined, undefined, optionalIxs), [], this.opts);
3652
3654
  return txSig;
3653
3655
  }
3654
3656
  async settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex) {
@@ -4894,7 +4896,7 @@ class DriftClient {
4894
4896
  return this.txSender.send(tx, additionalSigners, opts !== null && opts !== void 0 ? opts : this.opts, preSigned);
4895
4897
  }
4896
4898
  }
4897
- async buildTransaction(instructions, txParams, txVersion, lookupTables, forceVersionedTransaction, recentBlockhash) {
4899
+ async buildTransaction(instructions, txParams, txVersion, lookupTables, forceVersionedTransaction, recentBlockhash, optionalIxs) {
4898
4900
  return this.txHandler.buildTransaction({
4899
4901
  instructions,
4900
4902
  txVersion: txVersion !== null && txVersion !== void 0 ? txVersion : this.txVersion,
@@ -4905,6 +4907,7 @@ class DriftClient {
4905
4907
  lookupTables,
4906
4908
  forceVersionedTransaction,
4907
4909
  recentBlockhash,
4910
+ optionalIxs,
4908
4911
  });
4909
4912
  }
4910
4913
  async buildBulkTransactions(instructions, txParams, txVersion, lookupTables, forceVersionedTransaction) {
@@ -86,6 +86,7 @@ export * from './oracles/pythClient';
86
86
  export * from './oracles/pythPullClient';
87
87
  export * from './oracles/pythLazerClient';
88
88
  export * from './oracles/switchboardOnDemandClient';
89
+ export * from './oracles/oracleId';
89
90
  export * from './swift/swiftOrderSubscriber';
90
91
  export * from './tx/fastSingleTxSender';
91
92
  export * from './tx/retryTxSender';
package/lib/node/index.js CHANGED
@@ -109,6 +109,7 @@ __exportStar(require("./oracles/pythClient"), exports);
109
109
  __exportStar(require("./oracles/pythPullClient"), exports);
110
110
  __exportStar(require("./oracles/pythLazerClient"), exports);
111
111
  __exportStar(require("./oracles/switchboardOnDemandClient"), exports);
112
+ __exportStar(require("./oracles/oracleId"), exports);
112
113
  __exportStar(require("./swift/swiftOrderSubscriber"), exports);
113
114
  __exportStar(require("./tx/fastSingleTxSender"), exports);
114
115
  __exportStar(require("./tx/retryTxSender"), exports);
@@ -149,6 +149,22 @@ function getMultipleBetweenOracleSources(firstOracleSource, secondOracleSource)
149
149
  (0, types_1.isVariant)(secondOracleSource, 'pythPull')) {
150
150
  return { numerator: new index_1.BN(1), denominator: new index_1.BN(1000) };
151
151
  }
152
+ if ((0, types_1.isVariant)(firstOracleSource, 'pythLazer') &&
153
+ (0, types_1.isVariant)(secondOracleSource, 'pythLazer1M')) {
154
+ return { numerator: new index_1.BN(1000000), denominator: new index_1.BN(1) };
155
+ }
156
+ if ((0, types_1.isVariant)(firstOracleSource, 'pythLazer') &&
157
+ (0, types_1.isVariant)(secondOracleSource, 'pythLazer1K')) {
158
+ return { numerator: new index_1.BN(1000), denominator: new index_1.BN(1) };
159
+ }
160
+ if ((0, types_1.isVariant)(firstOracleSource, 'pythLazer1M') &&
161
+ (0, types_1.isVariant)(secondOracleSource, 'pythLazer')) {
162
+ return { numerator: new index_1.BN(1), denominator: new index_1.BN(1000000) };
163
+ }
164
+ if ((0, types_1.isVariant)(firstOracleSource, 'pythLazer1K') &&
165
+ (0, types_1.isVariant)(secondOracleSource, 'pythLazer')) {
166
+ return { numerator: new index_1.BN(1), denominator: new index_1.BN(1000) };
167
+ }
152
168
  return { numerator: new index_1.BN(1), denominator: new index_1.BN(1) };
153
169
  }
154
170
  exports.getMultipleBetweenOracleSources = getMultipleBetweenOracleSources;
@@ -12,6 +12,7 @@ export type TxBuildingProps = {
12
12
  txParams?: TxParams;
13
13
  recentBlockhash?: BlockhashWithExpiryBlockHeight;
14
14
  wallet?: IWallet;
15
+ optionalIxs?: TransactionInstruction[];
15
16
  };
16
17
  export type TxHandlerConfig = {
17
18
  blockhashCachingEnabled?: boolean;
@@ -277,24 +277,35 @@ class TxHandler {
277
277
  */
278
278
  async buildTransaction(props) {
279
279
  var _a;
280
- const { instructions, txVersion, txParams, connection: _connection, preFlightCommitment: _preFlightCommitment, fetchMarketLookupTableAccount, forceVersionedTransaction, } = props;
280
+ const { txVersion, txParams, connection: _connection, preFlightCommitment: _preFlightCommitment, fetchMarketLookupTableAccount, forceVersionedTransaction, instructions, } = props;
281
281
  let { lookupTables } = props;
282
282
  // # Collect and process Tx Params
283
283
  let baseTxParams = {
284
284
  computeUnits: txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits,
285
285
  computeUnitsPrice: txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice,
286
286
  };
287
+ const instructionsArray = Array.isArray(instructions)
288
+ ? instructions
289
+ : [instructions];
290
+ let instructionsToUse;
291
+ // add optional ixs if there's room (usually oracle cranks)
292
+ if (props.optionalIxs && txVersion === 0) {
293
+ instructionsToUse = (0, utils_1.getCombinedInstructions)(instructionsArray, props.optionalIxs, txVersion === 0, lookupTables);
294
+ }
295
+ else {
296
+ instructionsToUse = instructionsArray;
297
+ }
287
298
  if (txParams === null || txParams === void 0 ? void 0 : txParams.useSimulatedComputeUnits) {
288
- const processedTxParams = await this.getProcessedTransactionParams(props);
299
+ const processedTxParams = await this.getProcessedTransactionParams({
300
+ ...props,
301
+ instructions: instructionsToUse,
302
+ });
289
303
  baseTxParams = {
290
304
  ...baseTxParams,
291
305
  ...processedTxParams,
292
306
  };
293
307
  }
294
- const instructionsArray = Array.isArray(instructions)
295
- ? instructions
296
- : [instructions];
297
- const { hasSetComputeUnitLimitIx, hasSetComputeUnitPriceIx } = (0, computeUnits_1.containsComputeUnitIxs)(instructionsArray);
308
+ const { hasSetComputeUnitLimitIx, hasSetComputeUnitPriceIx } = (0, computeUnits_1.containsComputeUnitIxs)(instructionsToUse);
298
309
  // # Create Tx Instructions
299
310
  const allIx = [];
300
311
  const computeUnits = baseTxParams === null || baseTxParams === void 0 ? void 0 : baseTxParams.computeUnits;
@@ -314,7 +325,7 @@ class TxHandler {
314
325
  microLamports: computeUnitsPrice,
315
326
  }));
316
327
  }
317
- allIx.push(...instructionsArray);
328
+ allIx.push(...instructionsToUse);
318
329
  const recentBlockhash = (_a = props === null || props === void 0 ? void 0 : props.recentBlockhash) !== null && _a !== void 0 ? _a : (await this.getLatestBlockhashForTransaction());
319
330
  // # Create and return Transaction
320
331
  if (txVersion === 'legacy') {
@@ -1,2 +1,4 @@
1
- import { Transaction, VersionedTransaction } from '@solana/web3.js';
1
+ import { AddressLookupTableAccount, Transaction, TransactionInstruction, VersionedTransaction } from '@solana/web3.js';
2
2
  export declare const isVersionedTransaction: (tx: Transaction | VersionedTransaction) => boolean;
3
+ export declare const getSizeOfTransaction: (instructions: TransactionInstruction[], versionedTransaction?: boolean, addressLookupTables?: AddressLookupTableAccount[]) => number;
4
+ export declare const getCombinedInstructions: (baseInstructions: TransactionInstruction[], optionalInstructions?: TransactionInstruction[], versionedTransaction?: boolean, addressLookupTables?: AddressLookupTableAccount[]) => TransactionInstruction[];
@@ -1,10 +1,82 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isVersionedTransaction = void 0;
3
+ exports.getCombinedInstructions = exports.getSizeOfTransaction = exports.isVersionedTransaction = void 0;
4
4
  const web3_js_1 = require("@solana/web3.js");
5
+ const MAX_SIZE = 1232;
5
6
  const isVersionedTransaction = (tx) => {
6
7
  const version = tx === null || tx === void 0 ? void 0 : tx.version;
7
8
  const isVersionedTx = tx instanceof web3_js_1.VersionedTransaction || version !== undefined;
8
9
  return isVersionedTx;
9
10
  };
10
11
  exports.isVersionedTransaction = isVersionedTransaction;
12
+ const getSizeOfTransaction = (instructions, versionedTransaction = true, addressLookupTables = []) => {
13
+ const programs = new Set();
14
+ const signers = new Set();
15
+ let accounts = new Set();
16
+ instructions.forEach((ix) => {
17
+ try {
18
+ if (ix.programId) {
19
+ programs.add(ix.programId.toBase58());
20
+ accounts.add(ix.programId.toBase58());
21
+ }
22
+ if (ix.keys) {
23
+ ix.keys.forEach((key) => {
24
+ if (key.isSigner) {
25
+ signers.add(key.pubkey.toBase58());
26
+ }
27
+ accounts.add(key.pubkey.toBase58());
28
+ });
29
+ }
30
+ }
31
+ catch (e) {
32
+ console.log(e);
33
+ }
34
+ });
35
+ const instructionSizes = instructions
36
+ .map((ix) => 1 +
37
+ getSizeOfCompressedU16(ix.keys.length) +
38
+ ix.keys.length +
39
+ getSizeOfCompressedU16(ix.data.length) +
40
+ ix.data.length)
41
+ .reduce((a, b) => a + b, 0);
42
+ let numberOfAddressLookups = 0;
43
+ if (addressLookupTables.length > 0) {
44
+ const lookupTableAddresses = addressLookupTables
45
+ .map((addressLookupTable) => addressLookupTable.state.addresses.map((address) => address.toBase58()))
46
+ .flat();
47
+ const totalNumberOfAccounts = accounts.size;
48
+ accounts = new Set([...accounts].filter((account) => !lookupTableAddresses.includes(account)));
49
+ accounts = new Set([...accounts, ...programs, ...signers]);
50
+ numberOfAddressLookups = totalNumberOfAccounts - accounts.size;
51
+ }
52
+ return (getSizeOfCompressedU16(signers.size) +
53
+ signers.size * 64 + // array of signatures
54
+ 3 +
55
+ getSizeOfCompressedU16(accounts.size) +
56
+ 32 * accounts.size + // array of account addresses
57
+ 32 + // recent blockhash
58
+ getSizeOfCompressedU16(instructions.length) +
59
+ instructionSizes + // array of instructions
60
+ (versionedTransaction ? 1 + getSizeOfCompressedU16(0) : 0) +
61
+ (versionedTransaction ? 32 * addressLookupTables.length : 0) +
62
+ (versionedTransaction && addressLookupTables.length > 0 ? 2 : 0) +
63
+ numberOfAddressLookups);
64
+ };
65
+ exports.getSizeOfTransaction = getSizeOfTransaction;
66
+ const getCombinedInstructions = (baseInstructions, optionalInstructions = [], versionedTransaction = true, addressLookupTables = []) => {
67
+ if (optionalInstructions.length === 0) {
68
+ return baseInstructions;
69
+ }
70
+ let allInstructions = [...optionalInstructions, ...baseInstructions];
71
+ let txSize = (0, exports.getSizeOfTransaction)(allInstructions, versionedTransaction, addressLookupTables);
72
+ while (txSize > MAX_SIZE &&
73
+ allInstructions.length > baseInstructions.length) {
74
+ allInstructions = allInstructions.slice(1);
75
+ txSize = (0, exports.getSizeOfTransaction)(allInstructions, versionedTransaction, addressLookupTables);
76
+ }
77
+ return allInstructions;
78
+ };
79
+ exports.getCombinedInstructions = getCombinedInstructions;
80
+ function getSizeOfCompressedU16(n) {
81
+ return 1 + Number(n >= 128) + Number(n >= 16384);
82
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.108.0-beta.6",
3
+ "version": "2.108.0-beta.8",
4
4
  "main": "lib/node/index.js",
5
5
  "types": "lib/node/index.d.ts",
6
6
  "browser": "./lib/browser/index.js",
@@ -3919,11 +3919,18 @@ export class DriftClient {
3919
3919
  public async placeOrders(
3920
3920
  params: OrderParams[],
3921
3921
  txParams?: TxParams,
3922
- subAccountId?: number
3922
+ subAccountId?: number,
3923
+ optionalIxs?: TransactionInstruction[]
3923
3924
  ): Promise<TransactionSignature> {
3924
3925
  const { txSig } = await this.sendTransaction(
3925
- (await this.preparePlaceOrdersTx(params, txParams, subAccountId))
3926
- .placeOrdersTx,
3926
+ (
3927
+ await this.preparePlaceOrdersTx(
3928
+ params,
3929
+ txParams,
3930
+ subAccountId,
3931
+ optionalIxs
3932
+ )
3933
+ ).placeOrdersTx,
3927
3934
  [],
3928
3935
  this.opts,
3929
3936
  false
@@ -3934,11 +3941,19 @@ export class DriftClient {
3934
3941
  public async preparePlaceOrdersTx(
3935
3942
  params: OrderParams[],
3936
3943
  txParams?: TxParams,
3937
- subAccountId?: number
3944
+ subAccountId?: number,
3945
+ optionalIxs?: TransactionInstruction[]
3938
3946
  ) {
3947
+ const lookupTableAccount = await this.fetchMarketLookupTableAccount();
3948
+
3939
3949
  const tx = await this.buildTransaction(
3940
3950
  await this.getPlaceOrdersIx(params, subAccountId),
3941
- txParams
3951
+ txParams,
3952
+ undefined,
3953
+ [lookupTableAccount],
3954
+ undefined,
3955
+ undefined,
3956
+ optionalIxs
3942
3957
  );
3943
3958
 
3944
3959
  return {
@@ -5494,7 +5509,8 @@ export class DriftClient {
5494
5509
  cancelExistingOrders?: boolean,
5495
5510
  settlePnl?: boolean,
5496
5511
  exitEarlyIfSimFails?: boolean,
5497
- auctionDurationPercentage?: number
5512
+ auctionDurationPercentage?: number,
5513
+ optionalIxs?: TransactionInstruction[]
5498
5514
  ): Promise<{
5499
5515
  placeAndTakeTx: Transaction | VersionedTransaction;
5500
5516
  cancelExistingOrdersTx: Transaction | VersionedTransaction;
@@ -5514,6 +5530,8 @@ export class DriftClient {
5514
5530
  const recentBlockHash =
5515
5531
  await this.txHandler.getLatestBlockhashForTransaction();
5516
5532
 
5533
+ const lookupTableAccount = await this.fetchMarketLookupTableAccount();
5534
+
5517
5535
  let earlyExitFailedPlaceAndTakeSim = false;
5518
5536
 
5519
5537
  const prepPlaceAndTakeTx = async () => {
@@ -5550,9 +5568,10 @@ export class DriftClient {
5550
5568
  placeAndTakeIxs,
5551
5569
  txParams,
5552
5570
  undefined,
5553
- undefined,
5571
+ [lookupTableAccount],
5554
5572
  true,
5555
- recentBlockHash
5573
+ recentBlockHash,
5574
+ optionalIxs
5556
5575
  )) as VersionedTransaction;
5557
5576
 
5558
5577
  const simulationResult =
@@ -5575,18 +5594,20 @@ export class DriftClient {
5575
5594
  computeUnits: simulationResult.computeUnits,
5576
5595
  },
5577
5596
  undefined,
5597
+ [lookupTableAccount],
5578
5598
  undefined,
5579
- undefined,
5580
- recentBlockHash
5599
+ recentBlockHash,
5600
+ optionalIxs
5581
5601
  );
5582
5602
  } else {
5583
5603
  txsToSign.placeAndTakeTx = await this.buildTransaction(
5584
5604
  placeAndTakeIxs,
5585
5605
  txParams,
5586
5606
  undefined,
5607
+ [lookupTableAccount],
5587
5608
  undefined,
5588
- undefined,
5589
- recentBlockHash
5609
+ recentBlockHash,
5610
+ optionalIxs
5590
5611
  );
5591
5612
  }
5592
5613
 
@@ -5606,9 +5627,10 @@ export class DriftClient {
5606
5627
  [cancelOrdersIx],
5607
5628
  txParams,
5608
5629
  this.txVersion,
5630
+ [lookupTableAccount],
5609
5631
  undefined,
5610
- undefined,
5611
- recentBlockHash
5632
+ recentBlockHash,
5633
+ optionalIxs
5612
5634
  );
5613
5635
  }
5614
5636
 
@@ -5631,9 +5653,10 @@ export class DriftClient {
5631
5653
  [settlePnlIx],
5632
5654
  txParams,
5633
5655
  this.txVersion,
5656
+ [lookupTableAccount],
5634
5657
  undefined,
5635
- undefined,
5636
- recentBlockHash
5658
+ recentBlockHash,
5659
+ optionalIxs
5637
5660
  );
5638
5661
  }
5639
5662
  return;
@@ -6818,8 +6841,11 @@ export class DriftClient {
6818
6841
  settleeUserAccountPublicKey: PublicKey,
6819
6842
  settleeUserAccount: UserAccount,
6820
6843
  marketIndex: number,
6821
- txParams?: TxParams
6844
+ txParams?: TxParams,
6845
+ optionalIxs?: TransactionInstruction[]
6822
6846
  ): Promise<TransactionSignature> {
6847
+ const lookupTableAccount = await this.fetchMarketLookupTableAccount();
6848
+
6823
6849
  const { txSig } = await this.sendTransaction(
6824
6850
  await this.buildTransaction(
6825
6851
  await this.settlePNLIx(
@@ -6827,7 +6853,12 @@ export class DriftClient {
6827
6853
  settleeUserAccount,
6828
6854
  marketIndex
6829
6855
  ),
6830
- txParams
6856
+ txParams,
6857
+ undefined,
6858
+ [lookupTableAccount],
6859
+ undefined,
6860
+ undefined,
6861
+ optionalIxs
6831
6862
  ),
6832
6863
  [],
6833
6864
  this.opts
@@ -8700,6 +8731,7 @@ export class DriftClient {
8700
8731
  guardianSetIndex,
8701
8732
  DEFAULT_WORMHOLE_PROGRAM_ID
8702
8733
  );
8734
+
8703
8735
  const trimmedVaa = trimVaaSignatures(
8704
8736
  accumulatorUpdateData.vaa,
8705
8737
  numSignatures
@@ -9287,7 +9319,8 @@ export class DriftClient {
9287
9319
  txVersion?: TransactionVersion,
9288
9320
  lookupTables?: AddressLookupTableAccount[],
9289
9321
  forceVersionedTransaction?: boolean,
9290
- recentBlockhash?: BlockhashWithExpiryBlockHeight
9322
+ recentBlockhash?: BlockhashWithExpiryBlockHeight,
9323
+ optionalIxs?: TransactionInstruction[]
9291
9324
  ): Promise<Transaction | VersionedTransaction> {
9292
9325
  return this.txHandler.buildTransaction({
9293
9326
  instructions,
@@ -9300,6 +9333,7 @@ export class DriftClient {
9300
9333
  lookupTables,
9301
9334
  forceVersionedTransaction,
9302
9335
  recentBlockhash,
9336
+ optionalIxs,
9303
9337
  });
9304
9338
  }
9305
9339
 
package/src/index.ts CHANGED
@@ -87,6 +87,7 @@ export * from './oracles/pythClient';
87
87
  export * from './oracles/pythPullClient';
88
88
  export * from './oracles/pythLazerClient';
89
89
  export * from './oracles/switchboardOnDemandClient';
90
+ export * from './oracles/oracleId';
90
91
  export * from './swift/swiftOrderSubscriber';
91
92
  export * from './tx/fastSingleTxSender';
92
93
  export * from './tx/retryTxSender';
@@ -264,5 +264,33 @@ export function getMultipleBetweenOracleSources(
264
264
  return { numerator: new BN(1), denominator: new BN(1000) };
265
265
  }
266
266
 
267
+ if (
268
+ isVariant(firstOracleSource, 'pythLazer') &&
269
+ isVariant(secondOracleSource, 'pythLazer1M')
270
+ ) {
271
+ return { numerator: new BN(1000000), denominator: new BN(1) };
272
+ }
273
+
274
+ if (
275
+ isVariant(firstOracleSource, 'pythLazer') &&
276
+ isVariant(secondOracleSource, 'pythLazer1K')
277
+ ) {
278
+ return { numerator: new BN(1000), denominator: new BN(1) };
279
+ }
280
+
281
+ if (
282
+ isVariant(firstOracleSource, 'pythLazer1M') &&
283
+ isVariant(secondOracleSource, 'pythLazer')
284
+ ) {
285
+ return { numerator: new BN(1), denominator: new BN(1000000) };
286
+ }
287
+
288
+ if (
289
+ isVariant(firstOracleSource, 'pythLazer1K') &&
290
+ isVariant(secondOracleSource, 'pythLazer')
291
+ ) {
292
+ return { numerator: new BN(1), denominator: new BN(1000) };
293
+ }
294
+
267
295
  return { numerator: new BN(1), denominator: new BN(1) };
268
296
  }
@@ -28,7 +28,7 @@ import { containsComputeUnitIxs } from '../util/computeUnits';
28
28
  import { CachedBlockhashFetcher } from './blockhashFetcher/cachedBlockhashFetcher';
29
29
  import { BaseBlockhashFetcher } from './blockhashFetcher/baseBlockhashFetcher';
30
30
  import { BlockhashFetcher } from './blockhashFetcher/types';
31
- import { isVersionedTransaction } from './utils';
31
+ import { getCombinedInstructions, isVersionedTransaction } from './utils';
32
32
  import { DEFAULT_CONFIRMATION_OPTS } from '../config';
33
33
 
34
34
  /**
@@ -57,6 +57,7 @@ export type TxBuildingProps = {
57
57
  txParams?: TxParams;
58
58
  recentBlockhash?: BlockhashWithExpiryBlockHeight;
59
59
  wallet?: IWallet;
60
+ optionalIxs?: TransactionInstruction[]; // additional instructions to add to the front of ixs if there's enough room, such as oracle cranks
60
61
  };
61
62
 
62
63
  export type TxHandlerConfig = {
@@ -470,13 +471,13 @@ export class TxHandler {
470
471
  props: TxBuildingProps
471
472
  ): Promise<Transaction | VersionedTransaction> {
472
473
  const {
473
- instructions,
474
474
  txVersion,
475
475
  txParams,
476
476
  connection: _connection,
477
477
  preFlightCommitment: _preFlightCommitment,
478
478
  fetchMarketLookupTableAccount,
479
479
  forceVersionedTransaction,
480
+ instructions,
480
481
  } = props;
481
482
 
482
483
  let { lookupTables } = props;
@@ -487,8 +488,29 @@ export class TxHandler {
487
488
  computeUnitsPrice: txParams?.computeUnitsPrice,
488
489
  };
489
490
 
491
+ const instructionsArray = Array.isArray(instructions)
492
+ ? instructions
493
+ : [instructions];
494
+
495
+ let instructionsToUse: TransactionInstruction[];
496
+
497
+ // add optional ixs if there's room (usually oracle cranks)
498
+ if (props.optionalIxs && txVersion === 0) {
499
+ instructionsToUse = getCombinedInstructions(
500
+ instructionsArray,
501
+ props.optionalIxs,
502
+ txVersion === 0,
503
+ lookupTables
504
+ );
505
+ } else {
506
+ instructionsToUse = instructionsArray;
507
+ }
508
+
490
509
  if (txParams?.useSimulatedComputeUnits) {
491
- const processedTxParams = await this.getProcessedTransactionParams(props);
510
+ const processedTxParams = await this.getProcessedTransactionParams({
511
+ ...props,
512
+ instructions: instructionsToUse,
513
+ });
492
514
 
493
515
  baseTxParams = {
494
516
  ...baseTxParams,
@@ -496,11 +518,8 @@ export class TxHandler {
496
518
  };
497
519
  }
498
520
 
499
- const instructionsArray = Array.isArray(instructions)
500
- ? instructions
501
- : [instructions];
502
521
  const { hasSetComputeUnitLimitIx, hasSetComputeUnitPriceIx } =
503
- containsComputeUnitIxs(instructionsArray);
522
+ containsComputeUnitIxs(instructionsToUse);
504
523
 
505
524
  // # Create Tx Instructions
506
525
  const allIx = [];
@@ -529,7 +548,7 @@ export class TxHandler {
529
548
  );
530
549
  }
531
550
 
532
- allIx.push(...instructionsArray);
551
+ allIx.push(...instructionsToUse);
533
552
 
534
553
  const recentBlockhash =
535
554
  props?.recentBlockhash ?? (await this.getLatestBlockhashForTransaction());
package/src/tx/utils.ts CHANGED
@@ -1,4 +1,11 @@
1
- import { Transaction, VersionedTransaction } from '@solana/web3.js';
1
+ import {
2
+ AddressLookupTableAccount,
3
+ Transaction,
4
+ TransactionInstruction,
5
+ VersionedTransaction,
6
+ } from '@solana/web3.js';
7
+
8
+ const MAX_SIZE = 1232;
2
9
 
3
10
  export const isVersionedTransaction = (
4
11
  tx: Transaction | VersionedTransaction
@@ -9,3 +16,110 @@ export const isVersionedTransaction = (
9
16
 
10
17
  return isVersionedTx;
11
18
  };
19
+
20
+ export const getSizeOfTransaction = (
21
+ instructions: TransactionInstruction[],
22
+ versionedTransaction = true,
23
+ addressLookupTables: AddressLookupTableAccount[] = []
24
+ ): number => {
25
+ const programs = new Set<string>();
26
+ const signers = new Set<string>();
27
+ let accounts = new Set<string>();
28
+
29
+ instructions.forEach((ix) => {
30
+ try {
31
+ if (ix.programId) {
32
+ programs.add(ix.programId.toBase58());
33
+ accounts.add(ix.programId.toBase58());
34
+ }
35
+ if (ix.keys) {
36
+ ix.keys.forEach((key) => {
37
+ if (key.isSigner) {
38
+ signers.add(key.pubkey.toBase58());
39
+ }
40
+ accounts.add(key.pubkey.toBase58());
41
+ });
42
+ }
43
+ } catch (e) {
44
+ console.log(e);
45
+ }
46
+ });
47
+
48
+ const instructionSizes: number = instructions
49
+ .map(
50
+ (ix) =>
51
+ 1 +
52
+ getSizeOfCompressedU16(ix.keys.length) +
53
+ ix.keys.length +
54
+ getSizeOfCompressedU16(ix.data.length) +
55
+ ix.data.length
56
+ )
57
+ .reduce((a, b) => a + b, 0);
58
+
59
+ let numberOfAddressLookups = 0;
60
+ if (addressLookupTables.length > 0) {
61
+ const lookupTableAddresses = addressLookupTables
62
+ .map((addressLookupTable) =>
63
+ addressLookupTable.state.addresses.map((address) => address.toBase58())
64
+ )
65
+ .flat();
66
+ const totalNumberOfAccounts = accounts.size;
67
+ accounts = new Set(
68
+ [...accounts].filter((account) => !lookupTableAddresses.includes(account))
69
+ );
70
+ accounts = new Set([...accounts, ...programs, ...signers]);
71
+ numberOfAddressLookups = totalNumberOfAccounts - accounts.size;
72
+ }
73
+
74
+ return (
75
+ getSizeOfCompressedU16(signers.size) +
76
+ signers.size * 64 + // array of signatures
77
+ 3 +
78
+ getSizeOfCompressedU16(accounts.size) +
79
+ 32 * accounts.size + // array of account addresses
80
+ 32 + // recent blockhash
81
+ getSizeOfCompressedU16(instructions.length) +
82
+ instructionSizes + // array of instructions
83
+ (versionedTransaction ? 1 + getSizeOfCompressedU16(0) : 0) +
84
+ (versionedTransaction ? 32 * addressLookupTables.length : 0) +
85
+ (versionedTransaction && addressLookupTables.length > 0 ? 2 : 0) +
86
+ numberOfAddressLookups
87
+ );
88
+ };
89
+
90
+ export const getCombinedInstructions = (
91
+ baseInstructions: TransactionInstruction[],
92
+ optionalInstructions: TransactionInstruction[] = [],
93
+ versionedTransaction = true,
94
+ addressLookupTables: AddressLookupTableAccount[] = []
95
+ ): TransactionInstruction[] => {
96
+ if (optionalInstructions.length === 0) {
97
+ return baseInstructions;
98
+ }
99
+
100
+ let allInstructions = [...optionalInstructions, ...baseInstructions];
101
+
102
+ let txSize = getSizeOfTransaction(
103
+ allInstructions,
104
+ versionedTransaction,
105
+ addressLookupTables
106
+ );
107
+
108
+ while (
109
+ txSize > MAX_SIZE &&
110
+ allInstructions.length > baseInstructions.length
111
+ ) {
112
+ allInstructions = allInstructions.slice(1);
113
+ txSize = getSizeOfTransaction(
114
+ allInstructions,
115
+ versionedTransaction,
116
+ addressLookupTables
117
+ );
118
+ }
119
+
120
+ return allInstructions;
121
+ };
122
+
123
+ function getSizeOfCompressedU16(n: number) {
124
+ return 1 + Number(n >= 128) + Number(n >= 16384);
125
+ }