@drift-labs/sdk 2.53.0-beta.9 → 2.54.0-beta.1

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.53.0-beta.9
1
+ 2.54.0-beta.1
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.52.0",
2
+ "version": "2.53.0",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { TxSender, TxSigAndSlot } from './types';
2
+ import { ConfirmationStrategy, TxSender, TxSigAndSlot } from './types';
3
3
  import { Commitment, ConfirmOptions, RpcResponseAndContext, Signer, SignatureResult, Transaction, TransactionSignature, Connection, VersionedTransaction, TransactionInstruction, AddressLookupTableAccount } from '@solana/web3.js';
4
4
  import { IWallet } from '../types';
5
5
  export declare abstract class BaseTxSender implements TxSender {
@@ -9,18 +9,22 @@ export declare abstract class BaseTxSender implements TxSender {
9
9
  timeout: number;
10
10
  additionalConnections: Connection[];
11
11
  timeoutCount: number;
12
- constructor({ connection, wallet, opts, timeout, additionalConnections, }: {
12
+ confirmationStrategy: ConfirmationStrategy;
13
+ constructor({ connection, wallet, opts, timeout, additionalConnections, confirmationStrategy, }: {
13
14
  connection: Connection;
14
15
  wallet: IWallet;
15
16
  opts?: ConfirmOptions;
16
17
  timeout?: number;
17
18
  additionalConnections?: any;
19
+ confirmationStrategy?: ConfirmationStrategy;
18
20
  });
19
21
  send(tx: Transaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions, preSigned?: boolean): Promise<TxSigAndSlot>;
20
22
  prepareTx(tx: Transaction, additionalSigners: Array<Signer>, opts: ConfirmOptions): Promise<Transaction>;
21
23
  getVersionedTransaction(ixs: TransactionInstruction[], lookupTableAccounts: AddressLookupTableAccount[], additionalSigners?: Array<Signer>, opts?: ConfirmOptions): Promise<VersionedTransaction>;
22
24
  sendVersionedTransaction(tx: VersionedTransaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions, preSigned?: boolean): Promise<TxSigAndSlot>;
23
25
  sendRawTransaction(rawTransaction: Buffer | Uint8Array, opts: ConfirmOptions): Promise<TxSigAndSlot>;
26
+ confirmTransactionWebSocket(signature: TransactionSignature, commitment?: Commitment): Promise<RpcResponseAndContext<SignatureResult>>;
27
+ confirmTransactionPolling(signature: TransactionSignature, commitment?: Commitment): Promise<RpcResponseAndContext<SignatureResult> | undefined>;
24
28
  confirmTransaction(signature: TransactionSignature, commitment?: Commitment): Promise<RpcResponseAndContext<SignatureResult>>;
25
29
  getTimestamp(): number;
26
30
  promiseTimeout<T>(promises: Promise<T>[], timeoutMs: number): Promise<T | null>;
@@ -4,19 +4,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.BaseTxSender = void 0;
7
+ const types_1 = require("./types");
7
8
  const web3_js_1 = require("@solana/web3.js");
8
9
  const anchor_1 = require("@coral-xyz/anchor");
9
10
  const assert_1 = __importDefault(require("assert"));
10
11
  const bs58_1 = __importDefault(require("bs58"));
11
12
  const DEFAULT_TIMEOUT = 35000;
12
13
  class BaseTxSender {
13
- constructor({ connection, wallet, opts = anchor_1.AnchorProvider.defaultOptions(), timeout = DEFAULT_TIMEOUT, additionalConnections = new Array(), }) {
14
+ constructor({ connection, wallet, opts = anchor_1.AnchorProvider.defaultOptions(), timeout = DEFAULT_TIMEOUT, additionalConnections = new Array(), confirmationStrategy = types_1.ConfirmationStrategy.Combo, }) {
14
15
  this.timeoutCount = 0;
15
16
  this.connection = connection;
16
17
  this.wallet = wallet;
17
18
  this.opts = opts;
18
19
  this.timeout = timeout;
19
20
  this.additionalConnections = additionalConnections;
21
+ this.confirmationStrategy = confirmationStrategy;
20
22
  }
21
23
  async send(tx, additionalSigners, opts, preSigned) {
22
24
  if (additionalSigners === undefined) {
@@ -86,7 +88,8 @@ class BaseTxSender {
86
88
  opts) {
87
89
  throw new Error('Must be implemented by subclass');
88
90
  }
89
- async confirmTransaction(signature, commitment) {
91
+ async confirmTransactionWebSocket(signature, commitment) {
92
+ var _a;
90
93
  let decodedSignature;
91
94
  try {
92
95
  decodedSignature = bs58_1.default.decode(signature);
@@ -131,12 +134,54 @@ class BaseTxSender {
131
134
  }
132
135
  }
133
136
  if (response === null) {
137
+ if (this.confirmationStrategy === types_1.ConfirmationStrategy.Combo) {
138
+ try {
139
+ const rpcResponse = await this.connection.getSignatureStatus(signature);
140
+ if ((_a = rpcResponse === null || rpcResponse === void 0 ? void 0 : rpcResponse.value) === null || _a === void 0 ? void 0 : _a.confirmationStatus) {
141
+ response = {
142
+ context: rpcResponse.context,
143
+ value: { err: rpcResponse.value.err },
144
+ };
145
+ return response;
146
+ }
147
+ }
148
+ catch (error) {
149
+ // Ignore error to pass through to timeout error
150
+ }
151
+ }
134
152
  this.timeoutCount += 1;
135
153
  const duration = (Date.now() - start) / 1000;
136
154
  throw new Error(`Transaction was not confirmed in ${duration.toFixed(2)} seconds. It is unknown if it succeeded or failed. Check signature ${signature} using the Solana Explorer or CLI tools.`);
137
155
  }
138
156
  return response;
139
157
  }
158
+ async confirmTransactionPolling(signature, commitment = 'finalized') {
159
+ var _a;
160
+ let totalTime = 0;
161
+ let backoffTime = 250;
162
+ while (totalTime < this.timeout) {
163
+ const response = await this.connection.getSignatureStatus(signature);
164
+ const result = response && ((_a = response.value) === null || _a === void 0 ? void 0 : _a[0]);
165
+ if (result && result.confirmationStatus === commitment) {
166
+ return { context: result.context, value: { err: null } };
167
+ }
168
+ await new Promise((resolve) => setTimeout(resolve, backoffTime));
169
+ totalTime += backoffTime;
170
+ backoffTime = Math.min(backoffTime * 2, 5000);
171
+ }
172
+ // Transaction not confirmed within 30 seconds
173
+ this.timeoutCount += 1;
174
+ throw new Error(`Transaction was not confirmed in 30 seconds. It is unknown if it succeeded or failed. Check signature ${signature} using the Solana Explorer or CLI tools.`);
175
+ }
176
+ async confirmTransaction(signature, commitment) {
177
+ if (this.confirmationStrategy === types_1.ConfirmationStrategy.WebSocket ||
178
+ this.confirmationStrategy === types_1.ConfirmationStrategy.Combo) {
179
+ return await this.confirmTransactionWebSocket(signature, commitment);
180
+ }
181
+ else if (this.confirmationStrategy === types_1.ConfirmationStrategy.Polling) {
182
+ return await this.confirmTransactionPolling(signature, commitment);
183
+ }
184
+ }
140
185
  getTimestamp() {
141
186
  return new Date().getTime();
142
187
  }
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { TxSigAndSlot } from './types';
2
+ import { ConfirmationStrategy, TxSigAndSlot } from './types';
3
3
  import { ConfirmOptions, Signer, Transaction, Connection, VersionedTransaction, TransactionInstruction, AddressLookupTableAccount, Commitment } from '@solana/web3.js';
4
4
  import { IWallet } from '../types';
5
5
  import { BaseTxSender } from './baseTxSender';
@@ -14,7 +14,7 @@ export declare class FastSingleTxSender extends BaseTxSender {
14
14
  recentBlockhash: string;
15
15
  skipConfirmation: boolean;
16
16
  blockhashCommitment: Commitment;
17
- constructor({ connection, wallet, opts, timeout, blockhashRefreshInterval, additionalConnections, skipConfirmation, blockhashCommitment, }: {
17
+ constructor({ connection, wallet, opts, timeout, blockhashRefreshInterval, additionalConnections, skipConfirmation, blockhashCommitment, confirmationStrategy, }: {
18
18
  connection: Connection;
19
19
  wallet: IWallet;
20
20
  opts?: ConfirmOptions;
@@ -23,6 +23,7 @@ export declare class FastSingleTxSender extends BaseTxSender {
23
23
  additionalConnections?: any;
24
24
  skipConfirmation?: boolean;
25
25
  blockhashCommitment?: Commitment;
26
+ confirmationStrategy?: ConfirmationStrategy;
26
27
  });
27
28
  startBlockhashRefreshLoop(): void;
28
29
  prepareTx(tx: Transaction, additionalSigners: Array<Signer>, _opts: ConfirmOptions): Promise<Transaction>;
@@ -1,14 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FastSingleTxSender = void 0;
4
+ const types_1 = require("./types");
4
5
  const web3_js_1 = require("@solana/web3.js");
5
6
  const anchor_1 = require("@coral-xyz/anchor");
6
7
  const baseTxSender_1 = require("./baseTxSender");
7
8
  const DEFAULT_TIMEOUT = 35000;
8
9
  const DEFAULT_BLOCKHASH_REFRESH = 10000;
9
10
  class FastSingleTxSender extends baseTxSender_1.BaseTxSender {
10
- constructor({ connection, wallet, opts = anchor_1.AnchorProvider.defaultOptions(), timeout = DEFAULT_TIMEOUT, blockhashRefreshInterval = DEFAULT_BLOCKHASH_REFRESH, additionalConnections = new Array(), skipConfirmation = false, blockhashCommitment = 'finalized', }) {
11
- super({ connection, wallet, opts, timeout, additionalConnections });
11
+ constructor({ connection, wallet, opts = anchor_1.AnchorProvider.defaultOptions(), timeout = DEFAULT_TIMEOUT, blockhashRefreshInterval = DEFAULT_BLOCKHASH_REFRESH, additionalConnections = new Array(), skipConfirmation = false, blockhashCommitment = 'finalized', confirmationStrategy = types_1.ConfirmationStrategy.Combo, }) {
12
+ super({
13
+ connection,
14
+ wallet,
15
+ opts,
16
+ timeout,
17
+ additionalConnections,
18
+ confirmationStrategy,
19
+ });
12
20
  this.timoutCount = 0;
13
21
  this.connection = connection;
14
22
  this.wallet = wallet;
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { TxSigAndSlot } from './types';
2
+ import { ConfirmationStrategy, TxSigAndSlot } from './types';
3
3
  import { ConfirmOptions, Connection } from '@solana/web3.js';
4
4
  import { IWallet } from '../types';
5
5
  import { BaseTxSender } from './baseTxSender';
@@ -14,13 +14,14 @@ export declare class RetryTxSender extends BaseTxSender {
14
14
  retrySleep: number;
15
15
  additionalConnections: Connection[];
16
16
  timoutCount: number;
17
- constructor({ connection, wallet, opts, timeout, retrySleep, additionalConnections, }: {
17
+ constructor({ connection, wallet, opts, timeout, retrySleep, additionalConnections, confirmationStrategy, }: {
18
18
  connection: Connection;
19
19
  wallet: IWallet;
20
20
  opts?: ConfirmOptions;
21
21
  timeout?: number;
22
22
  retrySleep?: number;
23
23
  additionalConnections?: any;
24
+ confirmationStrategy?: ConfirmationStrategy;
24
25
  });
25
26
  sleep(reference: ResolveReference): Promise<void>;
26
27
  sendRawTransaction(rawTransaction: Buffer | Uint8Array, opts: ConfirmOptions): Promise<TxSigAndSlot>;
@@ -1,13 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RetryTxSender = void 0;
4
+ const types_1 = require("./types");
4
5
  const anchor_1 = require("@coral-xyz/anchor");
5
6
  const baseTxSender_1 = require("./baseTxSender");
6
7
  const DEFAULT_TIMEOUT = 35000;
7
8
  const DEFAULT_RETRY = 8000;
8
9
  class RetryTxSender extends baseTxSender_1.BaseTxSender {
9
- constructor({ connection, wallet, opts = anchor_1.AnchorProvider.defaultOptions(), timeout = DEFAULT_TIMEOUT, retrySleep = DEFAULT_RETRY, additionalConnections = new Array(), }) {
10
- super({ connection, wallet, opts, timeout, additionalConnections });
10
+ constructor({ connection, wallet, opts = anchor_1.AnchorProvider.defaultOptions(), timeout = DEFAULT_TIMEOUT, retrySleep = DEFAULT_RETRY, additionalConnections = new Array(), confirmationStrategy = types_1.ConfirmationStrategy.Combo, }) {
11
+ super({
12
+ connection,
13
+ wallet,
14
+ opts,
15
+ timeout,
16
+ additionalConnections,
17
+ confirmationStrategy,
18
+ });
11
19
  this.timoutCount = 0;
12
20
  this.connection = connection;
13
21
  this.wallet = wallet;
package/lib/tx/types.d.ts CHANGED
@@ -1,6 +1,11 @@
1
1
  /// <reference types="node" />
2
2
  import { AddressLookupTableAccount, ConfirmOptions, Signer, Transaction, TransactionInstruction, TransactionSignature, VersionedTransaction } from '@solana/web3.js';
3
3
  import { IWallet } from '../types';
4
+ export declare enum ConfirmationStrategy {
5
+ WebSocket = "websocket",
6
+ Polling = "polling",
7
+ Combo = "combo"
8
+ }
4
9
  export type TxSigAndSlot = {
5
10
  txSig: TransactionSignature;
6
11
  slot: number;
package/lib/tx/types.js CHANGED
@@ -1,2 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConfirmationStrategy = void 0;
4
+ var ConfirmationStrategy;
5
+ (function (ConfirmationStrategy) {
6
+ ConfirmationStrategy["WebSocket"] = "websocket";
7
+ ConfirmationStrategy["Polling"] = "polling";
8
+ ConfirmationStrategy["Combo"] = "combo";
9
+ })(ConfirmationStrategy = exports.ConfirmationStrategy || (exports.ConfirmationStrategy = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.53.0-beta.9",
3
+ "version": "2.54.0-beta.1",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.52.0",
2
+ "version": "2.53.0",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
@@ -1,4 +1,4 @@
1
- import { TxSender, TxSigAndSlot } from './types';
1
+ import { ConfirmationStrategy, TxSender, TxSigAndSlot } from './types';
2
2
  import {
3
3
  Commitment,
4
4
  ConfirmOptions,
@@ -28,6 +28,7 @@ export abstract class BaseTxSender implements TxSender {
28
28
  timeout: number;
29
29
  additionalConnections: Connection[];
30
30
  timeoutCount = 0;
31
+ confirmationStrategy: ConfirmationStrategy;
31
32
 
32
33
  public constructor({
33
34
  connection,
@@ -35,18 +36,21 @@ export abstract class BaseTxSender implements TxSender {
35
36
  opts = AnchorProvider.defaultOptions(),
36
37
  timeout = DEFAULT_TIMEOUT,
37
38
  additionalConnections = new Array<Connection>(),
39
+ confirmationStrategy = ConfirmationStrategy.Combo,
38
40
  }: {
39
41
  connection: Connection;
40
42
  wallet: IWallet;
41
43
  opts?: ConfirmOptions;
42
44
  timeout?: number;
43
45
  additionalConnections?;
46
+ confirmationStrategy?: ConfirmationStrategy;
44
47
  }) {
45
48
  this.connection = connection;
46
49
  this.wallet = wallet;
47
50
  this.opts = opts;
48
51
  this.timeout = timeout;
49
52
  this.additionalConnections = additionalConnections;
53
+ this.confirmationStrategy = confirmationStrategy;
50
54
  }
51
55
 
52
56
  async send(
@@ -156,7 +160,7 @@ export abstract class BaseTxSender implements TxSender {
156
160
  throw new Error('Must be implemented by subclass');
157
161
  }
158
162
 
159
- async confirmTransaction(
163
+ async confirmTransactionWebSocket(
160
164
  signature: TransactionSignature,
161
165
  commitment?: Commitment
162
166
  ): Promise<RpcResponseAndContext<SignatureResult>> {
@@ -210,6 +214,22 @@ export abstract class BaseTxSender implements TxSender {
210
214
  }
211
215
 
212
216
  if (response === null) {
217
+ if (this.confirmationStrategy === ConfirmationStrategy.Combo) {
218
+ try {
219
+ const rpcResponse = await this.connection.getSignatureStatus(
220
+ signature
221
+ );
222
+ if (rpcResponse?.value?.confirmationStatus) {
223
+ response = {
224
+ context: rpcResponse.context,
225
+ value: { err: rpcResponse.value.err },
226
+ };
227
+ return response;
228
+ }
229
+ } catch (error) {
230
+ // Ignore error to pass through to timeout error
231
+ }
232
+ }
213
233
  this.timeoutCount += 1;
214
234
  const duration = (Date.now() - start) / 1000;
215
235
  throw new Error(
@@ -222,6 +242,47 @@ export abstract class BaseTxSender implements TxSender {
222
242
  return response;
223
243
  }
224
244
 
245
+ async confirmTransactionPolling(
246
+ signature: TransactionSignature,
247
+ commitment: Commitment = 'finalized'
248
+ ): Promise<RpcResponseAndContext<SignatureResult> | undefined> {
249
+ let totalTime = 0;
250
+ let backoffTime = 250;
251
+
252
+ while (totalTime < this.timeout) {
253
+ const response = await this.connection.getSignatureStatus(signature);
254
+ const result = response && response.value?.[0];
255
+
256
+ if (result && result.confirmationStatus === commitment) {
257
+ return { context: result.context, value: { err: null } };
258
+ }
259
+
260
+ await new Promise((resolve) => setTimeout(resolve, backoffTime));
261
+ totalTime += backoffTime;
262
+ backoffTime = Math.min(backoffTime * 2, 5000);
263
+ }
264
+
265
+ // Transaction not confirmed within 30 seconds
266
+ this.timeoutCount += 1;
267
+ throw new Error(
268
+ `Transaction was not confirmed in 30 seconds. It is unknown if it succeeded or failed. Check signature ${signature} using the Solana Explorer or CLI tools.`
269
+ );
270
+ }
271
+
272
+ async confirmTransaction(
273
+ signature: TransactionSignature,
274
+ commitment?: Commitment
275
+ ): Promise<RpcResponseAndContext<SignatureResult>> {
276
+ if (
277
+ this.confirmationStrategy === ConfirmationStrategy.WebSocket ||
278
+ this.confirmationStrategy === ConfirmationStrategy.Combo
279
+ ) {
280
+ return await this.confirmTransactionWebSocket(signature, commitment);
281
+ } else if (this.confirmationStrategy === ConfirmationStrategy.Polling) {
282
+ return await this.confirmTransactionPolling(signature, commitment);
283
+ }
284
+ }
285
+
225
286
  getTimestamp(): number {
226
287
  return new Date().getTime();
227
288
  }
@@ -1,4 +1,4 @@
1
- import { TxSigAndSlot } from './types';
1
+ import { ConfirmationStrategy, TxSigAndSlot } from './types';
2
2
  import {
3
3
  ConfirmOptions,
4
4
  Signer,
@@ -39,6 +39,7 @@ export class FastSingleTxSender extends BaseTxSender {
39
39
  additionalConnections = new Array<Connection>(),
40
40
  skipConfirmation = false,
41
41
  blockhashCommitment = 'finalized',
42
+ confirmationStrategy = ConfirmationStrategy.Combo,
42
43
  }: {
43
44
  connection: Connection;
44
45
  wallet: IWallet;
@@ -48,8 +49,16 @@ export class FastSingleTxSender extends BaseTxSender {
48
49
  additionalConnections?;
49
50
  skipConfirmation?: boolean;
50
51
  blockhashCommitment?: Commitment;
52
+ confirmationStrategy?: ConfirmationStrategy;
51
53
  }) {
52
- super({ connection, wallet, opts, timeout, additionalConnections });
54
+ super({
55
+ connection,
56
+ wallet,
57
+ opts,
58
+ timeout,
59
+ additionalConnections,
60
+ confirmationStrategy,
61
+ });
53
62
  this.connection = connection;
54
63
  this.wallet = wallet;
55
64
  this.opts = opts;
@@ -1,4 +1,4 @@
1
- import { TxSigAndSlot } from './types';
1
+ import { ConfirmationStrategy, TxSigAndSlot } from './types';
2
2
  import {
3
3
  ConfirmOptions,
4
4
  TransactionSignature,
@@ -31,6 +31,7 @@ export class RetryTxSender extends BaseTxSender {
31
31
  timeout = DEFAULT_TIMEOUT,
32
32
  retrySleep = DEFAULT_RETRY,
33
33
  additionalConnections = new Array<Connection>(),
34
+ confirmationStrategy = ConfirmationStrategy.Combo,
34
35
  }: {
35
36
  connection: Connection;
36
37
  wallet: IWallet;
@@ -38,8 +39,16 @@ export class RetryTxSender extends BaseTxSender {
38
39
  timeout?: number;
39
40
  retrySleep?: number;
40
41
  additionalConnections?;
42
+ confirmationStrategy?: ConfirmationStrategy;
41
43
  }) {
42
- super({ connection, wallet, opts, timeout, additionalConnections });
44
+ super({
45
+ connection,
46
+ wallet,
47
+ opts,
48
+ timeout,
49
+ additionalConnections,
50
+ confirmationStrategy,
51
+ });
43
52
  this.connection = connection;
44
53
  this.wallet = wallet;
45
54
  this.opts = opts;
package/src/tx/types.ts CHANGED
@@ -9,6 +9,12 @@ import {
9
9
  } from '@solana/web3.js';
10
10
  import { IWallet } from '../types';
11
11
 
12
+ export enum ConfirmationStrategy {
13
+ WebSocket = 'websocket',
14
+ Polling = 'polling',
15
+ Combo = 'combo',
16
+ }
17
+
12
18
  export type TxSigAndSlot = {
13
19
  txSig: TransactionSignature;
14
20
  slot: number;