@solana/web3.js 1.68.1 → 1.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solana/web3.js",
3
- "version": "1.68.1",
3
+ "version": "1.69.0",
4
4
  "description": "Solana Javascript API",
5
5
  "keywords": [
6
6
  "api",
@@ -95,7 +95,7 @@
95
95
  "@types/express-serve-static-core": "^4.17.21",
96
96
  "@types/mocha": "^10.0.0",
97
97
  "@types/mz": "^2.7.3",
98
- "@types/node": "^17.0.24",
98
+ "@types/node": "^18.11.10",
99
99
  "@types/node-fetch": "2",
100
100
  "@types/sinon": "^10.0.0",
101
101
  "@types/sinon-chai": "^3.2.8",
@@ -114,6 +114,7 @@
114
114
  "mocha": "^10.1.0",
115
115
  "mockttp": "^2.0.1",
116
116
  "mz": "^2.7.0",
117
+ "node-abort-controller": "^3.0.1",
117
118
  "npm-run-all": "^4.1.5",
118
119
  "nyc": "^15.1.0",
119
120
  "prettier": "^2.3.0",
@@ -129,8 +130,8 @@
129
130
  "ts-mocha": "^10.0.0",
130
131
  "ts-node": "^10.0.0",
131
132
  "tslib": "^2.1.0",
132
- "typedoc": "^0.22.2",
133
- "typescript": "^4.3.2"
133
+ "typedoc": "^0.23",
134
+ "typescript": "^4.9"
134
135
  },
135
136
  "engines": {
136
137
  "node": ">=12.20.0"
package/src/connection.ts CHANGED
@@ -311,9 +311,39 @@ export type BlockhashWithExpiryBlockHeight = Readonly<{
311
311
  * A strategy for confirming transactions that uses the last valid
312
312
  * block height for a given blockhash to check for transaction expiration.
313
313
  */
314
- export type BlockheightBasedTransactionConfirmationStrategy = {
314
+ export type BlockheightBasedTransactionConfirmationStrategy =
315
+ BaseTransactionConfirmationStrategy & BlockhashWithExpiryBlockHeight;
316
+
317
+ /**
318
+ * A strategy for confirming durable nonce transactions.
319
+ */
320
+ export type DurableNonceTransactionConfirmationStrategy =
321
+ BaseTransactionConfirmationStrategy & {
322
+ /**
323
+ * The lowest slot at which to fetch the nonce value from the
324
+ * nonce account. This should be no lower than the slot at
325
+ * which the last-known value of the nonce was fetched.
326
+ */
327
+ minContextSlot: number;
328
+ /**
329
+ * The account where the current value of the nonce is stored.
330
+ */
331
+ nonceAccountPubkey: PublicKey;
332
+ /**
333
+ * The nonce value that was used to sign the transaction
334
+ * for which confirmation is being sought.
335
+ */
336
+ nonceValue: DurableNonce;
337
+ };
338
+
339
+ /**
340
+ * Properties shared by all transaction confirmation strategies
341
+ */
342
+ export type BaseTransactionConfirmationStrategy = Readonly<{
343
+ /** A signal that, when aborted, cancels any outstanding transaction confirmation operations */
344
+ abortSignal?: AbortSignal;
315
345
  signature: TransactionSignature;
316
- } & BlockhashWithExpiryBlockHeight;
346
+ }>;
317
347
 
318
348
  /* @internal */
319
349
  function assertEndpointUrl(putativeUrl: string) {
@@ -340,28 +370,6 @@ function extractCommitmentFromConfig<TConfig>(
340
370
  return {commitment, config};
341
371
  }
342
372
 
343
- /**
344
- * A strategy for confirming durable nonce transactions.
345
- */
346
- export type DurableNonceTransactionConfirmationStrategy = {
347
- /**
348
- * The lowest slot at which to fetch the nonce value from the
349
- * nonce account. This should be no lower than the slot at
350
- * which the last-known value of the nonce was fetched.
351
- */
352
- minContextSlot: number;
353
- /**
354
- * The account where the current value of the nonce is stored.
355
- */
356
- nonceAccountPubkey: PublicKey;
357
- /**
358
- * The nonce value that was used to sign the transaction
359
- * for which confirmation is being sought.
360
- */
361
- nonceValue: DurableNonce;
362
- signature: TransactionSignature;
363
- };
364
-
365
373
  /**
366
374
  * @internal
367
375
  */
@@ -3571,6 +3579,9 @@ export class Connection {
3571
3579
  const config = strategy as
3572
3580
  | BlockheightBasedTransactionConfirmationStrategy
3573
3581
  | DurableNonceTransactionConfirmationStrategy;
3582
+ if (config.abortSignal?.aborted) {
3583
+ return Promise.reject(config.abortSignal.reason);
3584
+ }
3574
3585
  rawSignature = config.signature;
3575
3586
  }
3576
3587
 
@@ -3602,6 +3613,21 @@ export class Connection {
3602
3613
  }
3603
3614
  }
3604
3615
 
3616
+ private getCancellationPromise(signal?: AbortSignal): Promise<never> {
3617
+ return new Promise<never>((_, reject) => {
3618
+ if (signal == null) {
3619
+ return;
3620
+ }
3621
+ if (signal.aborted) {
3622
+ reject(signal.reason);
3623
+ } else {
3624
+ signal.addEventListener('abort', () => {
3625
+ reject(signal.reason);
3626
+ });
3627
+ }
3628
+ });
3629
+ }
3630
+
3605
3631
  private getTransactionConfirmationPromise({
3606
3632
  commitment,
3607
3633
  signature,
@@ -3722,7 +3748,7 @@ export class Connection {
3722
3748
 
3723
3749
  private async confirmTransactionUsingBlockHeightExceedanceStrategy({
3724
3750
  commitment,
3725
- strategy: {lastValidBlockHeight, signature},
3751
+ strategy: {abortSignal, lastValidBlockHeight, signature},
3726
3752
  }: {
3727
3753
  commitment?: Commitment;
3728
3754
  strategy: BlockheightBasedTransactionConfirmationStrategy;
@@ -3753,9 +3779,14 @@ export class Connection {
3753
3779
  });
3754
3780
  const {abortConfirmation, confirmationPromise} =
3755
3781
  this.getTransactionConfirmationPromise({commitment, signature});
3782
+ const cancellationPromise = this.getCancellationPromise(abortSignal);
3756
3783
  let result: RpcResponseAndContext<SignatureResult>;
3757
3784
  try {
3758
- const outcome = await Promise.race([confirmationPromise, expiryPromise]);
3785
+ const outcome = await Promise.race([
3786
+ cancellationPromise,
3787
+ confirmationPromise,
3788
+ expiryPromise,
3789
+ ]);
3759
3790
  if (outcome.__type === TransactionStatus.PROCESSED) {
3760
3791
  result = outcome.response;
3761
3792
  } else {
@@ -3770,7 +3801,13 @@ export class Connection {
3770
3801
 
3771
3802
  private async confirmTransactionUsingDurableNonceStrategy({
3772
3803
  commitment,
3773
- strategy: {minContextSlot, nonceAccountPubkey, nonceValue, signature},
3804
+ strategy: {
3805
+ abortSignal,
3806
+ minContextSlot,
3807
+ nonceAccountPubkey,
3808
+ nonceValue,
3809
+ signature,
3810
+ },
3774
3811
  }: {
3775
3812
  commitment?: Commitment;
3776
3813
  strategy: DurableNonceTransactionConfirmationStrategy;
@@ -3821,9 +3858,14 @@ export class Connection {
3821
3858
  });
3822
3859
  const {abortConfirmation, confirmationPromise} =
3823
3860
  this.getTransactionConfirmationPromise({commitment, signature});
3861
+ const cancellationPromise = this.getCancellationPromise(abortSignal);
3824
3862
  let result: RpcResponseAndContext<SignatureResult>;
3825
3863
  try {
3826
- const outcome = await Promise.race([confirmationPromise, expiryPromise]);
3864
+ const outcome = await Promise.race([
3865
+ cancellationPromise,
3866
+ confirmationPromise,
3867
+ expiryPromise,
3868
+ ]);
3827
3869
  if (outcome.__type === TransactionStatus.PROCESSED) {
3828
3870
  result = outcome.response;
3829
3871
  } else {
@@ -26,7 +26,7 @@ function nextPowerOfTwo(n: number) {
26
26
  /**
27
27
  * Epoch schedule
28
28
  * (see https://docs.solana.com/terminology#epoch)
29
- * Can be retrieved with the {@link connection.getEpochSchedule} method
29
+ * Can be retrieved with the {@link Connection.getEpochSchedule} method
30
30
  */
31
31
  export class EpochSchedule {
32
32
  /** The maximum number of slots in each epoch */
@@ -19,7 +19,11 @@ export async function sendAndConfirmTransaction(
19
19
  connection: Connection,
20
20
  transaction: Transaction,
21
21
  signers: Array<Signer>,
22
- options?: ConfirmOptions,
22
+ options?: ConfirmOptions &
23
+ Readonly<{
24
+ // A signal that, when aborted, cancels any outstanding transaction confirmation operations
25
+ abortSignal?: AbortSignal;
26
+ }>,
23
27
  ): Promise<TransactionSignature> {
24
28
  const sendOptions = options && {
25
29
  skipPreflight: options.skipPreflight,
@@ -42,6 +46,7 @@ export async function sendAndConfirmTransaction(
42
46
  status = (
43
47
  await connection.confirmTransaction(
44
48
  {
49
+ abortSignal: options?.abortSignal,
45
50
  signature: signature,
46
51
  blockhash: transaction.recentBlockhash,
47
52
  lastValidBlockHeight: transaction.lastValidBlockHeight,
@@ -58,6 +63,7 @@ export async function sendAndConfirmTransaction(
58
63
  status = (
59
64
  await connection.confirmTransaction(
60
65
  {
66
+ abortSignal: options?.abortSignal,
61
67
  minContextSlot: transaction.minNonceContextSlot,
62
68
  nonceAccountPubkey,
63
69
  nonceValue: transaction.nonceInfo.nonce,
@@ -67,6 +73,13 @@ export async function sendAndConfirmTransaction(
67
73
  )
68
74
  ).value;
69
75
  } else {
76
+ if (options?.abortSignal != null) {
77
+ console.warn(
78
+ 'sendAndConfirmTransaction(): A transaction with a deprecated confirmation strategy was ' +
79
+ 'supplied along with an `abortSignal`. Only transactions having `lastValidBlockHeight` ' +
80
+ 'or a combination of `nonceInfo` and `minNonceContextSlot` are abortable.',
81
+ );
82
+ }
70
83
  status = (
71
84
  await connection.confirmTransaction(
72
85
  signature,