@drift-labs/sdk 2.75.0-beta.1 → 2.75.0-beta.2

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.
@@ -3483,7 +3483,7 @@ export class DriftClient {
3483
3483
  fulfillmentConfig?:
3484
3484
  | SerumV3FulfillmentConfigAccount
3485
3485
  | PhoenixV1FulfillmentConfigAccount,
3486
- makerInfo?: MakerInfo,
3486
+ makerInfo?: MakerInfo | MakerInfo[],
3487
3487
  referrerInfo?: ReferrerInfo,
3488
3488
  txParams?: TxParams
3489
3489
  ): Promise<TransactionSignature> {
@@ -3512,7 +3512,7 @@ export class DriftClient {
3512
3512
  fulfillmentConfig?:
3513
3513
  | SerumV3FulfillmentConfigAccount
3514
3514
  | PhoenixV1FulfillmentConfigAccount,
3515
- makerInfo?: MakerInfo,
3515
+ makerInfo?: MakerInfo | MakerInfo[],
3516
3516
  referrerInfo?: ReferrerInfo,
3517
3517
  fillerPublicKey?: PublicKey
3518
3518
  ): Promise<TransactionInstruction> {
@@ -3530,23 +3530,29 @@ export class DriftClient {
3530
3530
  (order) => order.orderId === userAccount.nextOrderId - 1
3531
3531
  ).marketIndex;
3532
3532
 
3533
+ makerInfo = Array.isArray(makerInfo)
3534
+ ? makerInfo
3535
+ : makerInfo
3536
+ ? [makerInfo]
3537
+ : [];
3538
+
3533
3539
  const userAccounts = [userAccount];
3534
- if (makerInfo !== undefined) {
3535
- userAccounts.push(makerInfo.makerUserAccount);
3540
+ for (const maker of makerInfo) {
3541
+ userAccounts.push(maker.makerUserAccount);
3536
3542
  }
3537
3543
  const remainingAccounts = this.getRemainingAccounts({
3538
3544
  userAccounts,
3539
3545
  writableSpotMarketIndexes: [marketIndex, QUOTE_SPOT_MARKET_INDEX],
3540
3546
  });
3541
3547
 
3542
- if (makerInfo) {
3548
+ for (const maker of makerInfo) {
3543
3549
  remainingAccounts.push({
3544
- pubkey: makerInfo.maker,
3550
+ pubkey: maker.maker,
3545
3551
  isWritable: true,
3546
3552
  isSigner: false,
3547
3553
  });
3548
3554
  remainingAccounts.push({
3549
- pubkey: makerInfo.makerStats,
3555
+ pubkey: maker.makerStats,
3550
3556
  isWritable: true,
3551
3557
  isSigner: false,
3552
3558
  });
@@ -3566,7 +3572,6 @@ export class DriftClient {
3566
3572
  }
3567
3573
 
3568
3574
  const orderId = order.orderId;
3569
- const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
3570
3575
 
3571
3576
  this.addSpotFulfillmentAccounts(
3572
3577
  marketIndex,
@@ -3577,7 +3582,7 @@ export class DriftClient {
3577
3582
  return await this.program.instruction.fillSpotOrder(
3578
3583
  orderId,
3579
3584
  fulfillmentConfig ? fulfillmentConfig.fulfillmentType : null,
3580
- makerOrderId,
3585
+ null,
3581
3586
  {
3582
3587
  accounts: {
3583
3588
  state: await this.getStatePublicKey(),
@@ -8997,7 +8997,11 @@
8997
8997
  "name": "ExternalMarket"
8998
8998
  },
8999
8999
  {
9000
- "name": "Match"
9000
+ "name": "Match",
9001
+ "fields": [
9002
+ "publicKey",
9003
+ "u16"
9004
+ ]
9001
9005
  }
9002
9006
  ]
9003
9007
  }
package/src/index.ts CHANGED
@@ -74,6 +74,7 @@ export * from './priorityFee';
74
74
  export * from './phoenix/phoenixFulfillmentConfigMap';
75
75
  export * from './tx/fastSingleTxSender';
76
76
  export * from './tx/retryTxSender';
77
+ export * from './tx/whileValidTxSender';
77
78
  export * from './tx/priorityFeeCalculator';
78
79
  export * from './tx/types';
79
80
  export * from './util/computeUnits';
@@ -76,9 +76,12 @@ export abstract class BaseTxSender implements TxSender {
76
76
  opts = this.opts;
77
77
  }
78
78
 
79
- const signedTx = preSigned
80
- ? tx
81
- : await this.prepareTx(tx, additionalSigners, opts);
79
+ const signedTx = await this.prepareTx(
80
+ tx,
81
+ additionalSigners,
82
+ opts,
83
+ preSigned
84
+ );
82
85
 
83
86
  if (extraConfirmationOptions?.onSignedCb) {
84
87
  extraConfirmationOptions.onSignedCb();
@@ -90,8 +93,13 @@ export abstract class BaseTxSender implements TxSender {
90
93
  async prepareTx(
91
94
  tx: Transaction,
92
95
  additionalSigners: Array<Signer>,
93
- opts: ConfirmOptions
96
+ opts: ConfirmOptions,
97
+ preSigned?: boolean
94
98
  ): Promise<Transaction> {
99
+ if (preSigned) {
100
+ return tx;
101
+ }
102
+
95
103
  tx.feePayer = this.wallet.publicKey;
96
104
  tx.recentBlockhash = (
97
105
  await this.connection.getLatestBlockhash(opts.preflightCommitment)
@@ -85,24 +85,10 @@ export class FastSingleTxSender extends BaseTxSender {
85
85
  async prepareTx(
86
86
  tx: Transaction,
87
87
  additionalSigners: Array<Signer>,
88
- _opts: ConfirmOptions
88
+ _opts: ConfirmOptions,
89
+ preSigned?: boolean
89
90
  ): Promise<Transaction> {
90
- tx.feePayer = this.wallet.publicKey;
91
-
92
- tx.recentBlockhash =
93
- this.recentBlockhash ??
94
- (await this.connection.getLatestBlockhash(this.blockhashCommitment))
95
- .blockhash;
96
-
97
- additionalSigners
98
- .filter((s): s is Signer => s !== undefined)
99
- .forEach((kp) => {
100
- tx.partialSign(kp);
101
- });
102
-
103
- const signedTx = await this.wallet.signTransaction(tx);
104
-
105
- return signedTx;
91
+ return super.prepareTx(tx, additionalSigners, _opts, preSigned);
106
92
  }
107
93
 
108
94
  async getVersionedTransaction(
@@ -0,0 +1,215 @@
1
+ import { ExtraConfirmationOptions, TxSigAndSlot } from './types';
2
+ import {
3
+ AddressLookupTableAccount,
4
+ ConfirmOptions,
5
+ Connection,
6
+ Signer,
7
+ Transaction,
8
+ TransactionInstruction,
9
+ TransactionMessage,
10
+ VersionedTransaction,
11
+ } from '@solana/web3.js';
12
+ import { AnchorProvider } from '@coral-xyz/anchor';
13
+ import { IWallet } from '../types';
14
+ import { BaseTxSender } from './baseTxSender';
15
+ import bs58 from 'bs58';
16
+
17
+ const DEFAULT_RETRY = 8000;
18
+
19
+ type ResolveReference = {
20
+ resolve?: () => void;
21
+ };
22
+
23
+ export class WhileValidTxSender extends BaseTxSender {
24
+ connection: Connection;
25
+ wallet: IWallet;
26
+ opts: ConfirmOptions;
27
+ timeout: number;
28
+ retrySleep: number;
29
+ additionalConnections: Connection[];
30
+ timoutCount = 0;
31
+ untilValid = new Map<
32
+ string,
33
+ { blockhash: string; lastValidBlockHeight: number }
34
+ >();
35
+
36
+ public constructor({
37
+ connection,
38
+ wallet,
39
+ opts = AnchorProvider.defaultOptions(),
40
+ retrySleep = DEFAULT_RETRY,
41
+ additionalConnections = new Array<Connection>(),
42
+ additionalTxSenderCallbacks = [],
43
+ }: {
44
+ connection: Connection;
45
+ wallet: IWallet;
46
+ opts?: ConfirmOptions;
47
+ retrySleep?: number;
48
+ additionalConnections?;
49
+ additionalTxSenderCallbacks?: ((base58EncodedTx: string) => void)[];
50
+ }) {
51
+ super({
52
+ connection,
53
+ wallet,
54
+ opts,
55
+ additionalConnections,
56
+ additionalTxSenderCallbacks,
57
+ });
58
+ this.retrySleep = retrySleep;
59
+ }
60
+
61
+ async sleep(reference: ResolveReference): Promise<void> {
62
+ return new Promise((resolve) => {
63
+ reference.resolve = resolve;
64
+ setTimeout(resolve, this.retrySleep);
65
+ });
66
+ }
67
+
68
+ async prepareTx(
69
+ tx: Transaction,
70
+ additionalSigners: Array<Signer>,
71
+ opts: ConfirmOptions,
72
+ preSigned?: boolean
73
+ ): Promise<Transaction> {
74
+ const latestBlockhash = await this.connection.getLatestBlockhash(
75
+ opts.preflightCommitment
76
+ );
77
+
78
+ // handle tx
79
+ let signedTx = tx;
80
+ if (!preSigned) {
81
+ tx.feePayer = this.wallet.publicKey;
82
+ tx.recentBlockhash = latestBlockhash.blockhash;
83
+
84
+ additionalSigners
85
+ .filter((s): s is Signer => s !== undefined)
86
+ .forEach((kp) => {
87
+ tx.partialSign(kp);
88
+ });
89
+
90
+ signedTx = await this.wallet.signTransaction(tx);
91
+ }
92
+
93
+ // handle subclass-specific side effects
94
+ const txSig = bs58.encode(tx.signatures[0]?.signature || tx.signatures[0]);
95
+ this.untilValid.set(txSig, latestBlockhash);
96
+
97
+ return signedTx;
98
+ }
99
+
100
+ async getVersionedTransaction(
101
+ ixs: TransactionInstruction[],
102
+ lookupTableAccounts: AddressLookupTableAccount[],
103
+ _additionalSigners?: Array<Signer>,
104
+ _opts?: ConfirmOptions
105
+ ): Promise<VersionedTransaction> {
106
+ const message = new TransactionMessage({
107
+ payerKey: this.wallet.publicKey,
108
+ recentBlockhash: '', // set blank and reset in sendVersionTransaction
109
+ instructions: ixs,
110
+ }).compileToV0Message(lookupTableAccounts);
111
+
112
+ const tx = new VersionedTransaction(message);
113
+
114
+ return tx;
115
+ }
116
+
117
+ async sendVersionedTransaction(
118
+ tx: VersionedTransaction,
119
+ additionalSigners?: Array<Signer>,
120
+ opts?: ConfirmOptions,
121
+ preSigned?: boolean,
122
+ extraConfirmationOptions?: ExtraConfirmationOptions
123
+ ): Promise<TxSigAndSlot> {
124
+ const latestBlockhash = await this.connection.getLatestBlockhash();
125
+ tx.message.recentBlockhash = latestBlockhash.blockhash;
126
+
127
+ let signedTx;
128
+ if (preSigned) {
129
+ signedTx = tx;
130
+ // @ts-ignore
131
+ } else if (this.wallet.payer) {
132
+ // @ts-ignore
133
+ tx.sign((additionalSigners ?? []).concat(this.wallet.payer));
134
+ signedTx = tx;
135
+ } else {
136
+ additionalSigners
137
+ ?.filter((s): s is Signer => s !== undefined)
138
+ .forEach((kp) => {
139
+ tx.sign([kp]);
140
+ });
141
+ // @ts-ignore
142
+ signedTx = await this.wallet.signTransaction(tx);
143
+ }
144
+
145
+ if (extraConfirmationOptions?.onSignedCb) {
146
+ extraConfirmationOptions.onSignedCb();
147
+ }
148
+
149
+ if (opts === undefined) {
150
+ opts = this.opts;
151
+ }
152
+
153
+ const txSig = bs58.encode(signedTx.signatures[0]);
154
+ this.untilValid.set(txSig, latestBlockhash);
155
+
156
+ return this.sendRawTransaction(signedTx.serialize(), opts);
157
+ }
158
+
159
+ async sendRawTransaction(
160
+ rawTransaction: Buffer | Uint8Array,
161
+ opts: ConfirmOptions
162
+ ): Promise<TxSigAndSlot> {
163
+ const startTime = this.getTimestamp();
164
+
165
+ const txid = await this.connection.sendRawTransaction(rawTransaction, opts);
166
+ this.sendToAdditionalConnections(rawTransaction, opts);
167
+
168
+ let done = false;
169
+ const resolveReference: ResolveReference = {
170
+ resolve: undefined,
171
+ };
172
+ const stopWaiting = () => {
173
+ done = true;
174
+ if (resolveReference.resolve) {
175
+ resolveReference.resolve();
176
+ }
177
+ };
178
+
179
+ (async () => {
180
+ while (!done && this.getTimestamp() - startTime < this.timeout) {
181
+ await this.sleep(resolveReference);
182
+ if (!done) {
183
+ this.connection
184
+ .sendRawTransaction(rawTransaction, opts)
185
+ .catch((e) => {
186
+ console.error(e);
187
+ stopWaiting();
188
+ });
189
+ this.sendToAdditionalConnections(rawTransaction, opts);
190
+ }
191
+ }
192
+ })();
193
+
194
+ let slot: number;
195
+ try {
196
+ const { blockhash, lastValidBlockHeight } = this.untilValid.get(txid);
197
+ const result = await this.connection.confirmTransaction(
198
+ {
199
+ signature: txid,
200
+ lastValidBlockHeight,
201
+ blockhash,
202
+ },
203
+ opts.commitment
204
+ );
205
+ slot = result.context.slot;
206
+ // eslint-disable-next-line no-useless-catch
207
+ } catch (e) {
208
+ throw e;
209
+ } finally {
210
+ stopWaiting();
211
+ }
212
+
213
+ return { txSig: txid, slot };
214
+ }
215
+ }