@solana/web3.js 1.41.9 → 1.41.11

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/lib/index.cjs.js CHANGED
@@ -2236,6 +2236,36 @@ function encodeLength(bytes, len) {
2236
2236
  }
2237
2237
  }
2238
2238
 
2239
+ const END_OF_BUFFER_ERROR_MESSAGE = 'Reached end of buffer unexpectedly';
2240
+ /**
2241
+ * Delegates to `Array#shift`, but throws if the array is zero-length.
2242
+ */
2243
+
2244
+ function guardedShift(byteArray) {
2245
+ if (byteArray.length === 0) {
2246
+ throw new Error(END_OF_BUFFER_ERROR_MESSAGE);
2247
+ }
2248
+
2249
+ return byteArray.shift();
2250
+ }
2251
+ /**
2252
+ * Delegates to `Array#splice`, but throws if the section being spliced out extends past the end of
2253
+ * the array.
2254
+ */
2255
+
2256
+ function guardedSplice(byteArray, ...args) {
2257
+ var _args$;
2258
+
2259
+ const [start] = args;
2260
+
2261
+ if (args.length === 2 // Implies that `deleteCount` was supplied
2262
+ ? start + ((_args$ = args[1]) !== null && _args$ !== void 0 ? _args$ : 0) > byteArray.length : start >= byteArray.length) {
2263
+ throw new Error(END_OF_BUFFER_ERROR_MESSAGE);
2264
+ }
2265
+
2266
+ return byteArray.splice(...args);
2267
+ }
2268
+
2239
2269
  /**
2240
2270
  * The message header, identifying signed and read-only account
2241
2271
  */
@@ -2334,32 +2364,28 @@ class Message {
2334
2364
  static from(buffer$1) {
2335
2365
  // Slice up wire data
2336
2366
  let byteArray = [...buffer$1];
2337
- const numRequiredSignatures = byteArray.shift();
2338
- const numReadonlySignedAccounts = byteArray.shift();
2339
- const numReadonlyUnsignedAccounts = byteArray.shift();
2367
+ const numRequiredSignatures = guardedShift(byteArray);
2368
+ const numReadonlySignedAccounts = guardedShift(byteArray);
2369
+ const numReadonlyUnsignedAccounts = guardedShift(byteArray);
2340
2370
  const accountCount = decodeLength(byteArray);
2341
2371
  let accountKeys = [];
2342
2372
 
2343
2373
  for (let i = 0; i < accountCount; i++) {
2344
- const account = byteArray.slice(0, PUBKEY_LENGTH);
2345
- byteArray = byteArray.slice(PUBKEY_LENGTH);
2374
+ const account = guardedSplice(byteArray, 0, PUBKEY_LENGTH);
2346
2375
  accountKeys.push(bs58__default["default"].encode(buffer.Buffer.from(account)));
2347
2376
  }
2348
2377
 
2349
- const recentBlockhash = byteArray.slice(0, PUBKEY_LENGTH);
2350
- byteArray = byteArray.slice(PUBKEY_LENGTH);
2378
+ const recentBlockhash = guardedSplice(byteArray, 0, PUBKEY_LENGTH);
2351
2379
  const instructionCount = decodeLength(byteArray);
2352
2380
  let instructions = [];
2353
2381
 
2354
2382
  for (let i = 0; i < instructionCount; i++) {
2355
- const programIdIndex = byteArray.shift();
2383
+ const programIdIndex = guardedShift(byteArray);
2356
2384
  const accountCount = decodeLength(byteArray);
2357
- const accounts = byteArray.slice(0, accountCount);
2358
- byteArray = byteArray.slice(accountCount);
2385
+ const accounts = guardedSplice(byteArray, 0, accountCount);
2359
2386
  const dataLength = decodeLength(byteArray);
2360
- const dataSlice = byteArray.slice(0, dataLength);
2387
+ const dataSlice = guardedSplice(byteArray, 0, dataLength);
2361
2388
  const data = bs58__default["default"].encode(buffer.Buffer.from(dataSlice));
2362
- byteArray = byteArray.slice(dataLength);
2363
2389
  instructions.push({
2364
2390
  programIdIndex,
2365
2391
  accounts,
@@ -2388,9 +2414,21 @@ function assert (condition, message) {
2388
2414
  }
2389
2415
  }
2390
2416
 
2417
+ /**
2418
+ * Transaction signature as base-58 encoded string
2419
+ */
2420
+
2421
+ exports.TransactionStatus = void 0;
2391
2422
  /**
2392
2423
  * Default (empty) signature
2393
2424
  */
2425
+
2426
+ (function (TransactionStatus) {
2427
+ TransactionStatus[TransactionStatus["BLOCKHEIGHT_EXCEEDED"] = 0] = "BLOCKHEIGHT_EXCEEDED";
2428
+ TransactionStatus[TransactionStatus["PROCESSED"] = 1] = "PROCESSED";
2429
+ TransactionStatus[TransactionStatus["TIMED_OUT"] = 2] = "TIMED_OUT";
2430
+ })(exports.TransactionStatus || (exports.TransactionStatus = {}));
2431
+
2394
2432
  const DEFAULT_SIGNATURE = buffer.Buffer.alloc(SIGNATURE_LENGTH_IN_BYTES).fill(0);
2395
2433
  /**
2396
2434
  * Account metadata used to define instructions
@@ -2481,10 +2519,23 @@ class Transaction {
2481
2519
  this.feePayer = void 0;
2482
2520
  this.instructions = [];
2483
2521
  this.recentBlockhash = void 0;
2522
+ this.lastValidBlockHeight = void 0;
2484
2523
  this.nonceInfo = void 0;
2485
2524
  this._message = void 0;
2486
2525
  this._json = void 0;
2487
- opts && Object.assign(this, opts);
2526
+
2527
+ if (!opts) {
2528
+ return;
2529
+ } else if (Object.prototype.hasOwnProperty.call(opts, 'lastValidBlockHeight')) {
2530
+ const newOpts = opts;
2531
+ Object.assign(this, newOpts);
2532
+ this.recentBlockhash = newOpts.blockhash;
2533
+ this.lastValidBlockHeight = newOpts.lastValidBlockHeight;
2534
+ } else {
2535
+ const oldOpts = opts;
2536
+ Object.assign(this, oldOpts);
2537
+ this.recentBlockhash = oldOpts.recentBlockhash;
2538
+ }
2488
2539
  }
2489
2540
  /**
2490
2541
  * @internal
@@ -3017,8 +3068,7 @@ class Transaction {
3017
3068
  let signatures = [];
3018
3069
 
3019
3070
  for (let i = 0; i < signatureCount; i++) {
3020
- const signature = byteArray.slice(0, SIGNATURE_LENGTH_IN_BYTES);
3021
- byteArray = byteArray.slice(SIGNATURE_LENGTH_IN_BYTES);
3071
+ const signature = guardedSplice(byteArray, 0, SIGNATURE_LENGTH_IN_BYTES);
3022
3072
  signatures.push(bs58__default["default"].encode(buffer.Buffer.from(signature)));
3023
3073
  }
3024
3074
 
@@ -3094,7 +3144,11 @@ async function sendAndConfirmTransaction(connection, transaction, signers, optio
3094
3144
  maxRetries: options.maxRetries
3095
3145
  };
3096
3146
  const signature = await connection.sendTransaction(transaction, signers, sendOptions);
3097
- const status = (await connection.confirmTransaction(signature, options && options.commitment)).value;
3147
+ const status = transaction.recentBlockhash != null && transaction.lastValidBlockHeight != null ? (await connection.confirmTransaction({
3148
+ signature: signature,
3149
+ blockhash: transaction.recentBlockhash,
3150
+ lastValidBlockHeight: transaction.lastValidBlockHeight
3151
+ }, options && options.commitment)).value : (await connection.confirmTransaction(signature, options && options.commitment)).value;
3098
3152
 
3099
3153
  if (status.err) {
3100
3154
  throw new Error(`Transaction ${signature} failed (${JSON.stringify(status)})`);
@@ -4494,16 +4548,28 @@ const NUM_SLOTS_PER_SECOND = NUM_TICKS_PER_SECOND / DEFAULT_TICKS_PER_SLOT;
4494
4548
 
4495
4549
  const MS_PER_SLOT = 1000 / NUM_SLOTS_PER_SECOND;
4496
4550
 
4497
- function promiseTimeout(promise, timeoutMs) {
4498
- let timeoutId;
4499
- const timeoutPromise = new Promise(resolve => {
4500
- timeoutId = setTimeout(() => resolve(null), timeoutMs);
4501
- });
4502
- return Promise.race([promise, timeoutPromise]).then(result => {
4503
- clearTimeout(timeoutId);
4504
- return result;
4505
- });
4551
+ class TransactionExpiredBlockheightExceededError extends Error {
4552
+ constructor(signature) {
4553
+ super(`Signature ${signature} has expired: block height exceeded.`);
4554
+ this.signature = void 0;
4555
+ this.signature = signature;
4556
+ }
4557
+
4506
4558
  }
4559
+ Object.defineProperty(TransactionExpiredBlockheightExceededError.prototype, 'name', {
4560
+ value: 'TransactionExpiredBlockheightExceededError'
4561
+ });
4562
+ class TransactionExpiredTimeoutError extends Error {
4563
+ constructor(signature, timeoutSeconds) {
4564
+ super(`Transaction was not confirmed in ${timeoutSeconds.toFixed(2)} seconds. It is ` + 'unknown if it succeeded or failed. Check signature ' + `${signature} using the Solana Explorer or CLI tools.`);
4565
+ this.signature = void 0;
4566
+ this.signature = signature;
4567
+ }
4568
+
4569
+ }
4570
+ Object.defineProperty(TransactionExpiredTimeoutError.prototype, 'name', {
4571
+ value: 'TransactionExpiredTimeoutError'
4572
+ });
4507
4573
 
4508
4574
  function makeWebsocketUrl(endpoint) {
4509
4575
  let url = new URL(endpoint);
@@ -5979,67 +6045,124 @@ class Connection {
5979
6045
 
5980
6046
  return res.result;
5981
6047
  }
5982
- /**
5983
- * Confirm the transaction identified by the specified signature.
5984
- */
5985
6048
 
6049
+ // eslint-disable-next-line no-dupe-class-members
6050
+ async confirmTransaction(strategy, commitment) {
6051
+ let rawSignature;
6052
+
6053
+ if (typeof strategy == 'string') {
6054
+ rawSignature = strategy;
6055
+ } else {
6056
+ const config = strategy;
6057
+ rawSignature = config.signature;
6058
+ }
5986
6059
 
5987
- async confirmTransaction(signature, commitment) {
5988
6060
  let decodedSignature;
5989
6061
 
5990
6062
  try {
5991
- decodedSignature = bs58__default["default"].decode(signature);
6063
+ decodedSignature = bs58__default["default"].decode(rawSignature);
5992
6064
  } catch (err) {
5993
- throw new Error('signature must be base58 encoded: ' + signature);
6065
+ throw new Error('signature must be base58 encoded: ' + rawSignature);
5994
6066
  }
5995
6067
 
5996
6068
  assert(decodedSignature.length === 64, 'signature has invalid length');
5997
- const start = Date.now();
5998
6069
  const subscriptionCommitment = commitment || this.commitment;
6070
+ let timeoutId;
5999
6071
  let subscriptionId;
6000
- let response = null;
6001
- const confirmPromise = new Promise((resolve, reject) => {
6072
+ let done = false;
6073
+ const confirmationPromise = new Promise((resolve, reject) => {
6002
6074
  try {
6003
- subscriptionId = this.onSignature(signature, (result, context) => {
6075
+ subscriptionId = this.onSignature(rawSignature, (result, context) => {
6004
6076
  subscriptionId = undefined;
6005
- response = {
6077
+ const response = {
6006
6078
  context,
6007
6079
  value: result
6008
6080
  };
6009
- resolve(null);
6081
+ done = true;
6082
+ resolve({
6083
+ __type: exports.TransactionStatus.PROCESSED,
6084
+ response
6085
+ });
6010
6086
  }, subscriptionCommitment);
6011
6087
  } catch (err) {
6012
6088
  reject(err);
6013
6089
  }
6014
6090
  });
6015
- let timeoutMs = this._confirmTransactionInitialTimeout || 60 * 1000;
6016
-
6017
- switch (subscriptionCommitment) {
6018
- case 'processed':
6019
- case 'recent':
6020
- case 'single':
6021
- case 'confirmed':
6022
- case 'singleGossip':
6023
- {
6024
- timeoutMs = this._confirmTransactionInitialTimeout || 30 * 1000;
6025
- break;
6091
+
6092
+ const checkBlockHeight = async () => {
6093
+ try {
6094
+ const blockHeight = await this.getBlockHeight(commitment);
6095
+ return blockHeight;
6096
+ } catch (_e) {
6097
+ return -1;
6098
+ }
6099
+ };
6100
+
6101
+ const expiryPromise = new Promise(resolve => {
6102
+ if (typeof strategy === 'string') {
6103
+ let timeoutMs = this._confirmTransactionInitialTimeout || 60 * 1000;
6104
+
6105
+ switch (subscriptionCommitment) {
6106
+ case 'processed':
6107
+ case 'recent':
6108
+ case 'single':
6109
+ case 'confirmed':
6110
+ case 'singleGossip':
6111
+ {
6112
+ timeoutMs = this._confirmTransactionInitialTimeout || 30 * 1000;
6113
+ break;
6114
+ }
6026
6115
  }
6027
- }
6116
+
6117
+ timeoutId = setTimeout(() => resolve({
6118
+ __type: exports.TransactionStatus.TIMED_OUT,
6119
+ timeoutMs
6120
+ }), timeoutMs);
6121
+ } else {
6122
+ let config = strategy;
6123
+
6124
+ (async () => {
6125
+ let currentBlockHeight = await checkBlockHeight();
6126
+ if (done) return;
6127
+
6128
+ while (currentBlockHeight <= config.lastValidBlockHeight) {
6129
+ await sleep(1000);
6130
+ if (done) return;
6131
+ currentBlockHeight = await checkBlockHeight();
6132
+ if (done) return;
6133
+ }
6134
+
6135
+ resolve({
6136
+ __type: exports.TransactionStatus.BLOCKHEIGHT_EXCEEDED
6137
+ });
6138
+ })();
6139
+ }
6140
+ });
6141
+ let result;
6028
6142
 
6029
6143
  try {
6030
- await promiseTimeout(confirmPromise, timeoutMs);
6144
+ const outcome = await Promise.race([confirmationPromise, expiryPromise]);
6145
+
6146
+ switch (outcome.__type) {
6147
+ case exports.TransactionStatus.BLOCKHEIGHT_EXCEEDED:
6148
+ throw new TransactionExpiredBlockheightExceededError(rawSignature);
6149
+
6150
+ case exports.TransactionStatus.PROCESSED:
6151
+ result = outcome.response;
6152
+ break;
6153
+
6154
+ case exports.TransactionStatus.TIMED_OUT:
6155
+ throw new TransactionExpiredTimeoutError(rawSignature, outcome.timeoutMs / 1000);
6156
+ }
6031
6157
  } finally {
6158
+ clearTimeout(timeoutId);
6159
+
6032
6160
  if (subscriptionId) {
6033
6161
  this.removeSignatureListener(subscriptionId);
6034
6162
  }
6035
6163
  }
6036
6164
 
6037
- if (response === null) {
6038
- const duration = (Date.now() - start) / 1000;
6039
- 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.`);
6040
- }
6041
-
6042
- return response;
6165
+ return result;
6043
6166
  }
6044
6167
  /**
6045
6168
  * Return the list of nodes that are currently participating in the cluster
@@ -9156,10 +9279,8 @@ class ValidatorInfo {
9156
9279
  const configKeys = [];
9157
9280
 
9158
9281
  for (let i = 0; i < 2; i++) {
9159
- const publicKey = new PublicKey(byteArray.slice(0, PUBKEY_LENGTH));
9160
- byteArray = byteArray.slice(PUBKEY_LENGTH);
9161
- const isSigner = byteArray.slice(0, 1)[0] === 1;
9162
- byteArray = byteArray.slice(1);
9282
+ const publicKey = new PublicKey(guardedSplice(byteArray, 0, PUBKEY_LENGTH));
9283
+ const isSigner = guardedShift(byteArray) === 1;
9163
9284
  configKeys.push({
9164
9285
  publicKey,
9165
9286
  isSigner