@drift-labs/sdk 2.82.0-beta.2 → 2.82.0-beta.20

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 (127) hide show
  1. package/README.md +65 -47
  2. package/VERSION +1 -1
  3. package/lib/accounts/types.d.ts +4 -3
  4. package/lib/accounts/webSocketAccountSubscriber.d.ts +3 -3
  5. package/lib/accounts/webSocketAccountSubscriber.js +16 -9
  6. package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +3 -3
  7. package/lib/accounts/webSocketDriftClientAccountSubscriber.js +5 -5
  8. package/lib/accounts/webSocketInsuranceFundStakeAccountSubscriber.d.ts +2 -2
  9. package/lib/accounts/webSocketInsuranceFundStakeAccountSubscriber.js +5 -3
  10. package/lib/accounts/webSocketProgramAccountSubscriber.d.ts +3 -3
  11. package/lib/accounts/webSocketProgramAccountSubscriber.js +15 -9
  12. package/lib/accounts/webSocketUserAccountSubscriber.d.ts +3 -3
  13. package/lib/accounts/webSocketUserAccountSubscriber.js +3 -3
  14. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +3 -3
  15. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +3 -3
  16. package/lib/auctionSubscriber/auctionSubscriber.d.ts +2 -2
  17. package/lib/auctionSubscriber/auctionSubscriber.js +3 -3
  18. package/lib/auctionSubscriber/types.d.ts +1 -0
  19. package/lib/clock/clockSubscriber.d.ts +29 -0
  20. package/lib/clock/clockSubscriber.js +74 -0
  21. package/lib/constants/perpMarkets.js +2 -2
  22. package/lib/constants/spotMarkets.js +11 -0
  23. package/lib/dlob/DLOB.js +2 -2
  24. package/lib/dlob/orderBookLevels.js +1 -0
  25. package/lib/driftClient.d.ts +21 -14
  26. package/lib/driftClient.js +192 -255
  27. package/lib/driftClientConfig.d.ts +3 -0
  28. package/lib/index.d.ts +2 -0
  29. package/lib/index.js +2 -0
  30. package/lib/jupiter/jupiterClient.d.ts +2 -1
  31. package/lib/jupiter/jupiterClient.js +10 -6
  32. package/lib/math/exchangeStatus.d.ts +2 -2
  33. package/lib/math/orders.d.ts +1 -1
  34. package/lib/math/orders.js +2 -2
  35. package/lib/orderSubscriber/OrderSubscriber.js +6 -3
  36. package/lib/orderSubscriber/WebsocketSubscription.d.ts +4 -3
  37. package/lib/orderSubscriber/WebsocketSubscription.js +3 -3
  38. package/lib/orderSubscriber/types.d.ts +1 -0
  39. package/lib/priorityFee/driftPriorityFeeMethod.d.ts +13 -3
  40. package/lib/priorityFee/driftPriorityFeeMethod.js +2 -2
  41. package/lib/priorityFee/index.d.ts +2 -0
  42. package/lib/priorityFee/index.js +2 -0
  43. package/lib/priorityFee/priorityFeeSubscriber.d.ts +1 -4
  44. package/lib/priorityFee/priorityFeeSubscriber.js +5 -4
  45. package/lib/priorityFee/priorityFeeSubscriberMap.d.ts +48 -0
  46. package/lib/priorityFee/priorityFeeSubscriberMap.js +88 -0
  47. package/lib/priorityFee/types.d.ts +8 -3
  48. package/lib/priorityFee/types.js +2 -1
  49. package/lib/tx/baseTxSender.d.ts +8 -6
  50. package/lib/tx/baseTxSender.js +9 -51
  51. package/lib/tx/fastSingleTxSender.d.ts +6 -6
  52. package/lib/tx/fastSingleTxSender.js +3 -31
  53. package/lib/tx/forwardOnlyTxSender.d.ts +4 -2
  54. package/lib/tx/forwardOnlyTxSender.js +2 -1
  55. package/lib/tx/retryTxSender.d.ts +4 -2
  56. package/lib/tx/retryTxSender.js +2 -1
  57. package/lib/tx/txHandler.d.ts +138 -0
  58. package/lib/tx/txHandler.js +396 -0
  59. package/lib/tx/txParamProcessor.d.ts +6 -10
  60. package/lib/tx/txParamProcessor.js +13 -17
  61. package/lib/tx/types.d.ts +8 -7
  62. package/lib/tx/types.js +12 -1
  63. package/lib/tx/whileValidTxSender.d.ts +7 -6
  64. package/lib/tx/whileValidTxSender.js +7 -28
  65. package/lib/types.d.ts +24 -4
  66. package/lib/types.js +10 -1
  67. package/lib/user.d.ts +0 -10
  68. package/lib/user.js +6 -29
  69. package/lib/userConfig.d.ts +1 -0
  70. package/lib/userMap/WebsocketSubscription.d.ts +4 -3
  71. package/lib/userMap/WebsocketSubscription.js +3 -3
  72. package/lib/userMap/userMap.js +4 -1
  73. package/lib/userMap/userMapConfig.d.ts +1 -0
  74. package/lib/userStats.js +6 -3
  75. package/lib/userStatsConfig.d.ts +1 -0
  76. package/lib/util/chainClock.d.ts +17 -0
  77. package/lib/util/chainClock.js +29 -0
  78. package/package.json +3 -3
  79. package/src/accounts/types.ts +5 -4
  80. package/src/accounts/webSocketAccountSubscriber.ts +35 -23
  81. package/src/accounts/webSocketDriftClientAccountSubscriber.ts +7 -6
  82. package/src/accounts/webSocketInsuranceFundStakeAccountSubscriber.ts +6 -4
  83. package/src/accounts/webSocketProgramAccountSubscriber.ts +32 -22
  84. package/src/accounts/webSocketUserAccountSubscriber.ts +5 -4
  85. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +5 -4
  86. package/src/auctionSubscriber/auctionSubscriber.ts +10 -4
  87. package/src/auctionSubscriber/types.ts +1 -0
  88. package/src/clock/clockSubscriber.ts +113 -0
  89. package/src/constants/perpMarkets.ts +2 -2
  90. package/src/constants/spotMarkets.ts +13 -0
  91. package/src/dlob/DLOB.ts +2 -2
  92. package/src/dlob/orderBookLevels.ts +2 -0
  93. package/src/driftClient.ts +295 -386
  94. package/src/driftClientConfig.ts +3 -0
  95. package/src/index.ts +2 -0
  96. package/src/jupiter/jupiterClient.ts +15 -6
  97. package/src/math/exchangeStatus.ts +2 -1
  98. package/src/math/orders.ts +3 -2
  99. package/src/orderSubscriber/OrderSubscriber.ts +4 -1
  100. package/src/orderSubscriber/WebsocketSubscription.ts +6 -5
  101. package/src/orderSubscriber/types.ts +1 -0
  102. package/src/priorityFee/driftPriorityFeeMethod.ts +16 -4
  103. package/src/priorityFee/index.ts +2 -0
  104. package/src/priorityFee/priorityFeeSubscriber.ts +7 -7
  105. package/src/priorityFee/priorityFeeSubscriberMap.ts +112 -0
  106. package/src/priorityFee/types.ts +16 -3
  107. package/src/tx/baseTxSender.ts +29 -79
  108. package/src/tx/fastSingleTxSender.ts +10 -55
  109. package/src/tx/forwardOnlyTxSender.ts +5 -1
  110. package/src/tx/retryTxSender.ts +5 -1
  111. package/src/tx/txHandler.ts +625 -0
  112. package/src/tx/txParamProcessor.ts +16 -28
  113. package/src/tx/types.ts +14 -18
  114. package/src/tx/whileValidTxSender.ts +24 -48
  115. package/src/types.ts +26 -2
  116. package/src/user.ts +7 -32
  117. package/src/userConfig.ts +1 -0
  118. package/src/userMap/WebsocketSubscription.ts +6 -5
  119. package/src/userMap/userMap.ts +4 -1
  120. package/src/userMap/userMapConfig.ts +1 -0
  121. package/src/userStats.ts +4 -1
  122. package/src/userStatsConfig.ts +1 -0
  123. package/src/util/chainClock.ts +41 -0
  124. package/tests/dlob/helpers.ts +3 -0
  125. package/lib/tx/utils.d.ts +0 -6
  126. package/lib/tx/utils.js +0 -39
  127. package/src/tx/utils.ts +0 -64
@@ -0,0 +1,625 @@
1
+ import {
2
+ AddressLookupTableAccount,
3
+ BlockhashWithExpiryBlockHeight,
4
+ Commitment,
5
+ ComputeBudgetProgram,
6
+ ConfirmOptions,
7
+ Connection,
8
+ Message,
9
+ MessageV0,
10
+ Signer,
11
+ Transaction,
12
+ TransactionInstruction,
13
+ TransactionMessage,
14
+ TransactionVersion,
15
+ VersionedTransaction,
16
+ } from '@solana/web3.js';
17
+ import { TransactionParamProcessor } from './txParamProcessor';
18
+ import bs58 from 'bs58';
19
+ import {
20
+ BaseTxParams,
21
+ DriftClientMetricsEvents,
22
+ IWallet,
23
+ SignedTxData,
24
+ TxParams,
25
+ } from '../types';
26
+
27
+ export const COMPUTE_UNITS_DEFAULT = 200_000;
28
+
29
+ export type TxBuildingProps = {
30
+ instructions: TransactionInstruction | TransactionInstruction[];
31
+ txVersion: TransactionVersion;
32
+ connection: Connection;
33
+ preFlightCommitment: Commitment;
34
+ fetchMarketLookupTableAccount: () => Promise<AddressLookupTableAccount>;
35
+ lookupTables?: AddressLookupTableAccount[];
36
+ forceVersionedTransaction?: boolean;
37
+ txParams?: TxParams;
38
+ recentBlockHash?: BlockhashWithExpiryBlockHeight;
39
+ wallet?: IWallet;
40
+ };
41
+
42
+ /**
43
+ * This class is responsible for creating and signing transactions.
44
+ */
45
+ export class TxHandler {
46
+ private blockHashToLastValidBlockHeightLookup: Record<string, number> = {};
47
+ private returnBlockHeightsWithSignedTxCallbackData = false;
48
+
49
+ private connection: Connection;
50
+ private wallet: IWallet;
51
+ private confirmationOptions: ConfirmOptions;
52
+
53
+ private onSignedCb?: (txSigs: DriftClientMetricsEvents['txSigned']) => void;
54
+
55
+ constructor(props: {
56
+ connection: Connection;
57
+ wallet: IWallet;
58
+ confirmationOptions: ConfirmOptions;
59
+ opts?: {
60
+ returnBlockHeightsWithSignedTxCallbackData?: boolean;
61
+ onSignedCb?: (txSigs: DriftClientMetricsEvents['txSigned']) => void;
62
+ };
63
+ }) {
64
+ this.connection = props.connection;
65
+ this.wallet = props.wallet;
66
+ this.confirmationOptions = props.confirmationOptions;
67
+
68
+ // #Optionals
69
+ this.returnBlockHeightsWithSignedTxCallbackData =
70
+ props.opts?.returnBlockHeightsWithSignedTxCallbackData ?? false;
71
+ this.onSignedCb = props.opts?.onSignedCb;
72
+ }
73
+
74
+ private addHashAndExpiryToLookup(
75
+ hashAndExpiry: BlockhashWithExpiryBlockHeight
76
+ ) {
77
+ if (!this.returnBlockHeightsWithSignedTxCallbackData) return;
78
+
79
+ this.blockHashToLastValidBlockHeightLookup[hashAndExpiry.blockhash] =
80
+ hashAndExpiry.lastValidBlockHeight;
81
+ }
82
+
83
+ private getProps = (wallet?: IWallet, confirmationOpts?: ConfirmOptions) =>
84
+ [wallet ?? this.wallet, confirmationOpts ?? this.confirmationOptions] as [
85
+ IWallet,
86
+ ConfirmOptions,
87
+ ];
88
+
89
+ public updateWallet(wallet: IWallet) {
90
+ this.wallet = wallet;
91
+ }
92
+
93
+ /**
94
+ * Created this to prevent non-finalized blockhashes being used when building transactions. We want to always use finalized because otherwise it's easy to get the BlockHashNotFound error (RPC uses finalized to validate a transaction). Using an older blockhash when building transactions should never really be a problem right now.
95
+ *
96
+ * https://www.helius.dev/blog/how-to-deal-with-blockhash-errors-on-solana#why-do-blockhash-errors-occur
97
+ *
98
+ * @returns
99
+ */
100
+ public getLatestBlockhashForTransaction() {
101
+ return this.connection.getLatestBlockhash('finalized');
102
+ }
103
+
104
+ /**
105
+ * Applies recent blockhash and signs a given transaction
106
+ * @param tx
107
+ * @param additionalSigners
108
+ * @param wallet
109
+ * @param confirmationOpts
110
+ * @param preSigned
111
+ * @param recentBlockhash
112
+ * @returns
113
+ */
114
+ public async prepareTx(
115
+ tx: Transaction,
116
+ additionalSigners: Array<Signer>,
117
+ wallet?: IWallet,
118
+ confirmationOpts?: ConfirmOptions,
119
+ preSigned?: boolean,
120
+ recentBlockhash?: BlockhashWithExpiryBlockHeight
121
+ ): Promise<Transaction> {
122
+ if (preSigned) {
123
+ return tx;
124
+ }
125
+
126
+ [wallet, confirmationOpts] = this.getProps(wallet, confirmationOpts);
127
+
128
+ tx.feePayer = wallet.publicKey;
129
+ recentBlockhash = recentBlockhash
130
+ ? recentBlockhash
131
+ : await this.getLatestBlockhashForTransaction();
132
+ tx.recentBlockhash = recentBlockhash.blockhash;
133
+
134
+ this.addHashAndExpiryToLookup(recentBlockhash);
135
+
136
+ const signedTx = await this.signTx(tx, additionalSigners);
137
+
138
+ return signedTx;
139
+ }
140
+
141
+ private isVersionedTransaction(tx: Transaction | VersionedTransaction) {
142
+ return (tx as VersionedTransaction)?.message && true;
143
+ }
144
+
145
+ private getTxSigFromSignedTx(signedTx: Transaction | VersionedTransaction) {
146
+ if (this.isVersionedTransaction(signedTx)) {
147
+ return bs58.encode(
148
+ Buffer.from((signedTx as VersionedTransaction).signatures[0])
149
+ ) as string;
150
+ } else {
151
+ return bs58.encode(
152
+ Buffer.from((signedTx as Transaction).signature)
153
+ ) as string;
154
+ }
155
+ }
156
+
157
+ private getBlockhashFromSignedTx(
158
+ signedTx: Transaction | VersionedTransaction
159
+ ) {
160
+ if (this.isVersionedTransaction(signedTx)) {
161
+ return (signedTx as VersionedTransaction).message.recentBlockhash;
162
+ } else {
163
+ return (signedTx as Transaction).recentBlockhash;
164
+ }
165
+ }
166
+
167
+ private async signTx(
168
+ tx: Transaction,
169
+ additionalSigners: Array<Signer>,
170
+ wallet?: IWallet
171
+ ): Promise<Transaction> {
172
+ [wallet] = this.getProps(wallet);
173
+
174
+ additionalSigners
175
+ .filter((s): s is Signer => s !== undefined)
176
+ .forEach((kp) => {
177
+ tx.partialSign(kp);
178
+ });
179
+
180
+ const signedTx = await wallet.signTransaction(tx);
181
+
182
+ // Turn txSig Buffer into base58 string
183
+ const txSig = this.getTxSigFromSignedTx(signedTx);
184
+
185
+ this.handleSignedTxData([
186
+ {
187
+ txSig,
188
+ signedTx,
189
+ blockHash: this.getBlockhashFromSignedTx(signedTx),
190
+ },
191
+ ]);
192
+
193
+ return signedTx;
194
+ }
195
+
196
+ public async signVersionedTx(
197
+ tx: VersionedTransaction,
198
+ additionalSigners: Array<Signer>,
199
+ recentBlockHash?: BlockhashWithExpiryBlockHeight,
200
+ wallet?: IWallet
201
+ ): Promise<VersionedTransaction> {
202
+ [wallet] = this.getProps(wallet);
203
+
204
+ if (recentBlockHash) {
205
+ tx.message.recentBlockhash = recentBlockHash.blockhash;
206
+
207
+ this.addHashAndExpiryToLookup(recentBlockHash);
208
+ }
209
+
210
+ additionalSigners
211
+ ?.filter((s): s is Signer => s !== undefined)
212
+ .forEach((kp) => {
213
+ tx.sign([kp]);
214
+ });
215
+
216
+ //@ts-ignore
217
+ const signedTx = (await wallet.signTransaction(tx)) as VersionedTransaction;
218
+
219
+ // Turn txSig Buffer into base58 string
220
+ const txSig = this.getTxSigFromSignedTx(signedTx);
221
+
222
+ this.handleSignedTxData([
223
+ {
224
+ txSig,
225
+ signedTx,
226
+ blockHash: this.getBlockhashFromSignedTx(signedTx),
227
+ },
228
+ ]);
229
+
230
+ return signedTx;
231
+ }
232
+
233
+ private handleSignedTxData(
234
+ txData: Omit<SignedTxData, 'lastValidBlockHeight'>[]
235
+ ) {
236
+ if (!this.returnBlockHeightsWithSignedTxCallbackData) {
237
+ if (this.onSignedCb) {
238
+ this.onSignedCb(txData);
239
+ }
240
+
241
+ return;
242
+ }
243
+
244
+ const fullTxData = txData.map((tx) => {
245
+ const lastValidBlockHeight =
246
+ this.blockHashToLastValidBlockHeightLookup[tx.blockHash];
247
+
248
+ return {
249
+ ...tx,
250
+ lastValidBlockHeight,
251
+ };
252
+ });
253
+
254
+ if (this.onSignedCb) {
255
+ this.onSignedCb(fullTxData);
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Gets transaction params with extra processing applied, like using the simulated compute units or using a dynamically calculated compute unit price.
261
+ * @param txBuildingProps
262
+ * @returns
263
+ */
264
+ private async getProcessedTransactionParams(
265
+ txBuildingProps: TxBuildingProps
266
+ ): Promise<BaseTxParams> {
267
+ const baseTxParams: BaseTxParams = {
268
+ computeUnits: txBuildingProps?.txParams?.computeUnits,
269
+ computeUnitsPrice: txBuildingProps?.txParams?.computeUnitsPrice,
270
+ };
271
+
272
+ const processedTxParams = await TransactionParamProcessor.process({
273
+ baseTxParams,
274
+ txBuilder: (updatedTxParams) =>
275
+ this.buildTransaction({
276
+ ...txBuildingProps,
277
+ txParams: updatedTxParams.txParams ?? baseTxParams,
278
+ forceVersionedTransaction: true,
279
+ }) as Promise<VersionedTransaction>,
280
+ processConfig: {
281
+ useSimulatedComputeUnits:
282
+ txBuildingProps.txParams.useSimulatedComputeUnits,
283
+ computeUnitsBufferMultiplier:
284
+ txBuildingProps.txParams.computeUnitsBufferMultiplier,
285
+ useSimulatedComputeUnitsForCUPriceCalculation:
286
+ txBuildingProps.txParams
287
+ .useSimulatedComputeUnitsForCUPriceCalculation,
288
+ getCUPriceFromComputeUnits:
289
+ txBuildingProps.txParams.getCUPriceFromComputeUnits,
290
+ },
291
+ processParams: {
292
+ connection: this.connection,
293
+ },
294
+ });
295
+
296
+ return processedTxParams;
297
+ }
298
+
299
+ private _generateVersionedTransaction(
300
+ recentBlockHash: BlockhashWithExpiryBlockHeight,
301
+ message: Message | MessageV0
302
+ ) {
303
+ this.addHashAndExpiryToLookup(recentBlockHash);
304
+
305
+ return new VersionedTransaction(message);
306
+ }
307
+
308
+ public generateLegacyVersionedTransaction(
309
+ recentBlockhash: BlockhashWithExpiryBlockHeight,
310
+ ixs: TransactionInstruction[],
311
+ wallet?: IWallet
312
+ ) {
313
+ [wallet] = this.getProps(wallet);
314
+
315
+ const message = new TransactionMessage({
316
+ payerKey: wallet.publicKey,
317
+ recentBlockhash: recentBlockhash.blockhash,
318
+ instructions: ixs,
319
+ }).compileToLegacyMessage();
320
+
321
+ return this._generateVersionedTransaction(recentBlockhash, message);
322
+ }
323
+
324
+ public generateVersionedTransaction(
325
+ recentBlockhash: BlockhashWithExpiryBlockHeight,
326
+ ixs: TransactionInstruction[],
327
+ lookupTableAccounts: AddressLookupTableAccount[],
328
+ wallet?: IWallet
329
+ ) {
330
+ [wallet] = this.getProps(wallet);
331
+
332
+ const message = new TransactionMessage({
333
+ payerKey: wallet.publicKey,
334
+ recentBlockhash: recentBlockhash.blockhash,
335
+ instructions: ixs,
336
+ }).compileToV0Message(lookupTableAccounts);
337
+
338
+ return this._generateVersionedTransaction(recentBlockhash, message);
339
+ }
340
+
341
+ public generateLegacyTransaction(ixs: TransactionInstruction[]) {
342
+ return new Transaction().add(...ixs);
343
+ }
344
+
345
+ /**
346
+ * Accepts multiple instructions and builds a transaction for each. Prevents needing to spam RPC with requests for the same blockhash.
347
+ * @param props
348
+ * @returns
349
+ */
350
+ public async buildBulkTransactions(
351
+ props: Omit<TxBuildingProps, 'instructions'> & {
352
+ instructions: (TransactionInstruction | TransactionInstruction[])[];
353
+ }
354
+ ) {
355
+ const recentBlockHash =
356
+ props?.recentBlockHash ?? (await this.getLatestBlockhashForTransaction());
357
+
358
+ return await Promise.all(
359
+ props.instructions.map((ix) => {
360
+ if (!ix) return undefined;
361
+ return this.buildTransaction({
362
+ ...props,
363
+ instructions: ix,
364
+ recentBlockHash,
365
+ });
366
+ })
367
+ );
368
+ }
369
+
370
+ /**
371
+ *
372
+ * @param instructions
373
+ * @param txParams
374
+ * @param txVersion
375
+ * @param lookupTables
376
+ * @param forceVersionedTransaction Return a VersionedTransaction instance even if the version of the transaction is Legacy
377
+ * @returns
378
+ */
379
+ public async buildTransaction(
380
+ props: TxBuildingProps
381
+ ): Promise<Transaction | VersionedTransaction> {
382
+ const {
383
+ instructions,
384
+ txVersion,
385
+ txParams,
386
+ connection: _connection,
387
+ preFlightCommitment: _preFlightCommitment,
388
+ fetchMarketLookupTableAccount,
389
+ forceVersionedTransaction,
390
+ } = props;
391
+
392
+ let { lookupTables } = props;
393
+
394
+ // # Collect and process Tx Params
395
+ let baseTxParams: BaseTxParams = {
396
+ computeUnits: txParams?.computeUnits,
397
+ computeUnitsPrice: txParams?.computeUnitsPrice,
398
+ };
399
+
400
+ if (txParams?.useSimulatedComputeUnits) {
401
+ const processedTxParams = await this.getProcessedTransactionParams(props);
402
+
403
+ baseTxParams = {
404
+ ...baseTxParams,
405
+ ...processedTxParams,
406
+ };
407
+ }
408
+
409
+ // # Create Tx Instructions
410
+ const allIx = [];
411
+ const computeUnits = baseTxParams?.computeUnits;
412
+ if (computeUnits !== 200_000) {
413
+ allIx.push(
414
+ ComputeBudgetProgram.setComputeUnitLimit({
415
+ units: computeUnits,
416
+ })
417
+ );
418
+ }
419
+
420
+ const computeUnitsPrice = baseTxParams?.computeUnitsPrice;
421
+
422
+ if (computeUnitsPrice !== 0) {
423
+ allIx.push(
424
+ ComputeBudgetProgram.setComputeUnitPrice({
425
+ microLamports: computeUnitsPrice,
426
+ })
427
+ );
428
+ }
429
+
430
+ if (Array.isArray(instructions)) {
431
+ allIx.push(...instructions);
432
+ } else {
433
+ allIx.push(instructions);
434
+ }
435
+
436
+ const recentBlockHash =
437
+ props?.recentBlockHash ?? (await this.getLatestBlockhashForTransaction());
438
+
439
+ // # Create and return Transaction
440
+ if (txVersion === 'legacy') {
441
+ if (forceVersionedTransaction) {
442
+ return this.generateLegacyVersionedTransaction(recentBlockHash, allIx);
443
+ } else {
444
+ return this.generateLegacyTransaction(allIx);
445
+ }
446
+ } else {
447
+ const marketLookupTable = await fetchMarketLookupTableAccount();
448
+
449
+ lookupTables = lookupTables
450
+ ? [...lookupTables, marketLookupTable]
451
+ : [marketLookupTable];
452
+
453
+ return this.generateVersionedTransaction(
454
+ recentBlockHash,
455
+ allIx,
456
+ lookupTables
457
+ );
458
+ }
459
+ }
460
+
461
+ public wrapInTx(
462
+ instruction: TransactionInstruction,
463
+ computeUnits = 600_000,
464
+ computeUnitsPrice = 0
465
+ ): Transaction {
466
+ const tx = new Transaction();
467
+ if (computeUnits != COMPUTE_UNITS_DEFAULT) {
468
+ tx.add(
469
+ ComputeBudgetProgram.setComputeUnitLimit({
470
+ units: computeUnits,
471
+ })
472
+ );
473
+ }
474
+
475
+ if (computeUnitsPrice != 0) {
476
+ tx.add(
477
+ ComputeBudgetProgram.setComputeUnitPrice({
478
+ microLamports: computeUnitsPrice,
479
+ })
480
+ );
481
+ }
482
+
483
+ return tx.add(instruction);
484
+ }
485
+
486
+ /**
487
+ * Build a map of transactions from an array of instructions for multiple transactions.
488
+ * @param txsToSign
489
+ * @param keys
490
+ * @param wallet
491
+ * @param commitment
492
+ * @returns
493
+ */
494
+ public async buildTransactionMap(
495
+ txsToSign: (Transaction | undefined)[],
496
+ keys: string[],
497
+ wallet?: IWallet,
498
+ commitment?: Commitment,
499
+ recentBlockHash?: BlockhashWithExpiryBlockHeight
500
+ ) {
501
+ recentBlockHash = recentBlockHash
502
+ ? recentBlockHash
503
+ : await this.getLatestBlockhashForTransaction();
504
+
505
+ this.addHashAndExpiryToLookup(recentBlockHash);
506
+
507
+ for (const tx of txsToSign) {
508
+ if (!tx) continue;
509
+ tx.recentBlockhash = recentBlockHash.blockhash;
510
+ tx.feePayer = wallet?.publicKey ?? this.wallet?.publicKey;
511
+ }
512
+
513
+ return this.getSignedTransactionMap(txsToSign, keys, wallet);
514
+ }
515
+
516
+ /**
517
+ * Get a map of signed and prepared transactions from an array of legacy transactions
518
+ * @param txsToSign
519
+ * @param keys
520
+ * @param wallet
521
+ * @param commitment
522
+ * @returns
523
+ */
524
+ public async getPreparedAndSignedLegacyTransactionMap(
525
+ txsToSign: (Transaction | undefined)[],
526
+ keys: string[],
527
+ wallet?: IWallet,
528
+ commitment?: Commitment,
529
+ recentBlockHash?: BlockhashWithExpiryBlockHeight
530
+ ) {
531
+ recentBlockHash = recentBlockHash
532
+ ? recentBlockHash
533
+ : await this.getLatestBlockhashForTransaction();
534
+
535
+ this.addHashAndExpiryToLookup(recentBlockHash);
536
+
537
+ for (const tx of txsToSign) {
538
+ if (!tx) continue;
539
+ tx.recentBlockhash = recentBlockHash.blockhash;
540
+ tx.feePayer = wallet?.publicKey ?? this.wallet?.publicKey;
541
+ }
542
+
543
+ return this.getSignedTransactionMap(txsToSign, keys, wallet);
544
+ }
545
+
546
+ /**
547
+ * Get a map of signed transactions from an array of transactions to sign.
548
+ * @param txsToSign
549
+ * @param keys
550
+ * @param wallet
551
+ * @returns
552
+ */
553
+ public async getSignedTransactionMap(
554
+ txsToSign: (Transaction | VersionedTransaction | undefined)[],
555
+ keys: string[],
556
+ wallet?: IWallet
557
+ ): Promise<{
558
+ [key: string]: Transaction | VersionedTransaction | undefined;
559
+ }> {
560
+ [wallet] = this.getProps(wallet);
561
+
562
+ const signedTxMap: {
563
+ [key: string]: Transaction | VersionedTransaction | undefined;
564
+ } = {};
565
+
566
+ const keysWithTx = [];
567
+ txsToSign.forEach((tx, index) => {
568
+ if (tx == undefined) {
569
+ signedTxMap[keys[index]] = undefined;
570
+ } else {
571
+ keysWithTx.push(keys[index]);
572
+ }
573
+ });
574
+
575
+ const signedTxs = await wallet.signAllTransactions(
576
+ txsToSign
577
+ .map((tx) => {
578
+ return tx as Transaction;
579
+ })
580
+ .filter((tx) => tx !== undefined)
581
+ );
582
+
583
+ this.handleSignedTxData(
584
+ signedTxs.map((signedTx) => {
585
+ return {
586
+ txSig: this.getTxSigFromSignedTx(signedTx),
587
+ signedTx,
588
+ blockHash: this.getBlockhashFromSignedTx(signedTx),
589
+ };
590
+ })
591
+ );
592
+
593
+ signedTxs.forEach((signedTx, index) => {
594
+ signedTxMap[keysWithTx[index]] = signedTx;
595
+ });
596
+
597
+ return signedTxMap;
598
+ }
599
+
600
+ /**
601
+ * Builds and signs transactions from a given array of instructions for multiple transactions.
602
+ * @param props
603
+ * @returns
604
+ */
605
+ public async buildAndSignTransactionMap(
606
+ props: Omit<TxBuildingProps, 'instructions'> & {
607
+ keys: string[];
608
+ instructions: (TransactionInstruction | TransactionInstruction[])[];
609
+ }
610
+ ) {
611
+ const transactions = await this.buildBulkTransactions(props);
612
+
613
+ const preppedTransactions =
614
+ props.txVersion === 'legacy'
615
+ ? this.getPreparedAndSignedLegacyTransactionMap(
616
+ transactions as Transaction[],
617
+ props.keys,
618
+ props.wallet,
619
+ props.preFlightCommitment
620
+ )
621
+ : this.getSignedTransactionMap(transactions, props.keys, props.wallet);
622
+
623
+ return preppedTransactions;
624
+ }
625
+ }