@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.
@@ -2224,6 +2224,36 @@ function encodeLength(bytes, len) {
2224
2224
  }
2225
2225
  }
2226
2226
 
2227
+ const END_OF_BUFFER_ERROR_MESSAGE = 'Reached end of buffer unexpectedly';
2228
+ /**
2229
+ * Delegates to `Array#shift`, but throws if the array is zero-length.
2230
+ */
2231
+
2232
+ function guardedShift(byteArray) {
2233
+ if (byteArray.length === 0) {
2234
+ throw new Error(END_OF_BUFFER_ERROR_MESSAGE);
2235
+ }
2236
+
2237
+ return byteArray.shift();
2238
+ }
2239
+ /**
2240
+ * Delegates to `Array#splice`, but throws if the section being spliced out extends past the end of
2241
+ * the array.
2242
+ */
2243
+
2244
+ function guardedSplice(byteArray, ...args) {
2245
+ var _args$;
2246
+
2247
+ const [start] = args;
2248
+
2249
+ if (args.length === 2 // Implies that `deleteCount` was supplied
2250
+ ? start + ((_args$ = args[1]) !== null && _args$ !== void 0 ? _args$ : 0) > byteArray.length : start >= byteArray.length) {
2251
+ throw new Error(END_OF_BUFFER_ERROR_MESSAGE);
2252
+ }
2253
+
2254
+ return byteArray.splice(...args);
2255
+ }
2256
+
2227
2257
  /**
2228
2258
  * The message header, identifying signed and read-only account
2229
2259
  */
@@ -2322,32 +2352,28 @@ class Message {
2322
2352
  static from(buffer$1) {
2323
2353
  // Slice up wire data
2324
2354
  let byteArray = [...buffer$1];
2325
- const numRequiredSignatures = byteArray.shift();
2326
- const numReadonlySignedAccounts = byteArray.shift();
2327
- const numReadonlyUnsignedAccounts = byteArray.shift();
2355
+ const numRequiredSignatures = guardedShift(byteArray);
2356
+ const numReadonlySignedAccounts = guardedShift(byteArray);
2357
+ const numReadonlyUnsignedAccounts = guardedShift(byteArray);
2328
2358
  const accountCount = decodeLength(byteArray);
2329
2359
  let accountKeys = [];
2330
2360
 
2331
2361
  for (let i = 0; i < accountCount; i++) {
2332
- const account = byteArray.slice(0, PUBKEY_LENGTH);
2333
- byteArray = byteArray.slice(PUBKEY_LENGTH);
2362
+ const account = guardedSplice(byteArray, 0, PUBKEY_LENGTH);
2334
2363
  accountKeys.push(bs58__default["default"].encode(buffer.Buffer.from(account)));
2335
2364
  }
2336
2365
 
2337
- const recentBlockhash = byteArray.slice(0, PUBKEY_LENGTH);
2338
- byteArray = byteArray.slice(PUBKEY_LENGTH);
2366
+ const recentBlockhash = guardedSplice(byteArray, 0, PUBKEY_LENGTH);
2339
2367
  const instructionCount = decodeLength(byteArray);
2340
2368
  let instructions = [];
2341
2369
 
2342
2370
  for (let i = 0; i < instructionCount; i++) {
2343
- const programIdIndex = byteArray.shift();
2371
+ const programIdIndex = guardedShift(byteArray);
2344
2372
  const accountCount = decodeLength(byteArray);
2345
- const accounts = byteArray.slice(0, accountCount);
2346
- byteArray = byteArray.slice(accountCount);
2373
+ const accounts = guardedSplice(byteArray, 0, accountCount);
2347
2374
  const dataLength = decodeLength(byteArray);
2348
- const dataSlice = byteArray.slice(0, dataLength);
2375
+ const dataSlice = guardedSplice(byteArray, 0, dataLength);
2349
2376
  const data = bs58__default["default"].encode(buffer.Buffer.from(dataSlice));
2350
- byteArray = byteArray.slice(dataLength);
2351
2377
  instructions.push({
2352
2378
  programIdIndex,
2353
2379
  accounts,
@@ -2376,9 +2402,21 @@ function assert (condition, message) {
2376
2402
  }
2377
2403
  }
2378
2404
 
2405
+ /**
2406
+ * Transaction signature as base-58 encoded string
2407
+ */
2408
+
2409
+ exports.TransactionStatus = void 0;
2379
2410
  /**
2380
2411
  * Default (empty) signature
2381
2412
  */
2413
+
2414
+ (function (TransactionStatus) {
2415
+ TransactionStatus[TransactionStatus["BLOCKHEIGHT_EXCEEDED"] = 0] = "BLOCKHEIGHT_EXCEEDED";
2416
+ TransactionStatus[TransactionStatus["PROCESSED"] = 1] = "PROCESSED";
2417
+ TransactionStatus[TransactionStatus["TIMED_OUT"] = 2] = "TIMED_OUT";
2418
+ })(exports.TransactionStatus || (exports.TransactionStatus = {}));
2419
+
2382
2420
  const DEFAULT_SIGNATURE = buffer.Buffer.alloc(SIGNATURE_LENGTH_IN_BYTES).fill(0);
2383
2421
  /**
2384
2422
  * Account metadata used to define instructions
@@ -2469,10 +2507,23 @@ class Transaction {
2469
2507
  this.feePayer = void 0;
2470
2508
  this.instructions = [];
2471
2509
  this.recentBlockhash = void 0;
2510
+ this.lastValidBlockHeight = void 0;
2472
2511
  this.nonceInfo = void 0;
2473
2512
  this._message = void 0;
2474
2513
  this._json = void 0;
2475
- opts && Object.assign(this, opts);
2514
+
2515
+ if (!opts) {
2516
+ return;
2517
+ } else if (Object.prototype.hasOwnProperty.call(opts, 'lastValidBlockHeight')) {
2518
+ const newOpts = opts;
2519
+ Object.assign(this, newOpts);
2520
+ this.recentBlockhash = newOpts.blockhash;
2521
+ this.lastValidBlockHeight = newOpts.lastValidBlockHeight;
2522
+ } else {
2523
+ const oldOpts = opts;
2524
+ Object.assign(this, oldOpts);
2525
+ this.recentBlockhash = oldOpts.recentBlockhash;
2526
+ }
2476
2527
  }
2477
2528
  /**
2478
2529
  * @internal
@@ -3005,8 +3056,7 @@ class Transaction {
3005
3056
  let signatures = [];
3006
3057
 
3007
3058
  for (let i = 0; i < signatureCount; i++) {
3008
- const signature = byteArray.slice(0, SIGNATURE_LENGTH_IN_BYTES);
3009
- byteArray = byteArray.slice(SIGNATURE_LENGTH_IN_BYTES);
3059
+ const signature = guardedSplice(byteArray, 0, SIGNATURE_LENGTH_IN_BYTES);
3010
3060
  signatures.push(bs58__default["default"].encode(buffer.Buffer.from(signature)));
3011
3061
  }
3012
3062
 
@@ -3082,7 +3132,11 @@ async function sendAndConfirmTransaction(connection, transaction, signers, optio
3082
3132
  maxRetries: options.maxRetries
3083
3133
  };
3084
3134
  const signature = await connection.sendTransaction(transaction, signers, sendOptions);
3085
- const status = (await connection.confirmTransaction(signature, options && options.commitment)).value;
3135
+ const status = transaction.recentBlockhash != null && transaction.lastValidBlockHeight != null ? (await connection.confirmTransaction({
3136
+ signature: signature,
3137
+ blockhash: transaction.recentBlockhash,
3138
+ lastValidBlockHeight: transaction.lastValidBlockHeight
3139
+ }, options && options.commitment)).value : (await connection.confirmTransaction(signature, options && options.commitment)).value;
3086
3140
 
3087
3141
  if (status.err) {
3088
3142
  throw new Error(`Transaction ${signature} failed (${JSON.stringify(status)})`);
@@ -4994,16 +5048,28 @@ const NUM_SLOTS_PER_SECOND = NUM_TICKS_PER_SECOND / DEFAULT_TICKS_PER_SLOT;
4994
5048
 
4995
5049
  const MS_PER_SLOT = 1000 / NUM_SLOTS_PER_SECOND;
4996
5050
 
4997
- function promiseTimeout(promise, timeoutMs) {
4998
- let timeoutId;
4999
- const timeoutPromise = new Promise(resolve => {
5000
- timeoutId = setTimeout(() => resolve(null), timeoutMs);
5001
- });
5002
- return Promise.race([promise, timeoutPromise]).then(result => {
5003
- clearTimeout(timeoutId);
5004
- return result;
5005
- });
5051
+ class TransactionExpiredBlockheightExceededError extends Error {
5052
+ constructor(signature) {
5053
+ super(`Signature ${signature} has expired: block height exceeded.`);
5054
+ this.signature = void 0;
5055
+ this.signature = signature;
5056
+ }
5057
+
5006
5058
  }
5059
+ Object.defineProperty(TransactionExpiredBlockheightExceededError.prototype, 'name', {
5060
+ value: 'TransactionExpiredBlockheightExceededError'
5061
+ });
5062
+ class TransactionExpiredTimeoutError extends Error {
5063
+ constructor(signature, timeoutSeconds) {
5064
+ 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.`);
5065
+ this.signature = void 0;
5066
+ this.signature = signature;
5067
+ }
5068
+
5069
+ }
5070
+ Object.defineProperty(TransactionExpiredTimeoutError.prototype, 'name', {
5071
+ value: 'TransactionExpiredTimeoutError'
5072
+ });
5007
5073
 
5008
5074
  function makeWebsocketUrl(endpoint) {
5009
5075
  let url = new URL(endpoint);
@@ -6473,67 +6539,124 @@ class Connection {
6473
6539
 
6474
6540
  return res.result;
6475
6541
  }
6476
- /**
6477
- * Confirm the transaction identified by the specified signature.
6478
- */
6479
6542
 
6543
+ // eslint-disable-next-line no-dupe-class-members
6544
+ async confirmTransaction(strategy, commitment) {
6545
+ let rawSignature;
6546
+
6547
+ if (typeof strategy == 'string') {
6548
+ rawSignature = strategy;
6549
+ } else {
6550
+ const config = strategy;
6551
+ rawSignature = config.signature;
6552
+ }
6480
6553
 
6481
- async confirmTransaction(signature, commitment) {
6482
6554
  let decodedSignature;
6483
6555
 
6484
6556
  try {
6485
- decodedSignature = bs58__default["default"].decode(signature);
6557
+ decodedSignature = bs58__default["default"].decode(rawSignature);
6486
6558
  } catch (err) {
6487
- throw new Error('signature must be base58 encoded: ' + signature);
6559
+ throw new Error('signature must be base58 encoded: ' + rawSignature);
6488
6560
  }
6489
6561
 
6490
6562
  assert(decodedSignature.length === 64, 'signature has invalid length');
6491
- const start = Date.now();
6492
6563
  const subscriptionCommitment = commitment || this.commitment;
6564
+ let timeoutId;
6493
6565
  let subscriptionId;
6494
- let response = null;
6495
- const confirmPromise = new Promise((resolve, reject) => {
6566
+ let done = false;
6567
+ const confirmationPromise = new Promise((resolve, reject) => {
6496
6568
  try {
6497
- subscriptionId = this.onSignature(signature, (result, context) => {
6569
+ subscriptionId = this.onSignature(rawSignature, (result, context) => {
6498
6570
  subscriptionId = undefined;
6499
- response = {
6571
+ const response = {
6500
6572
  context,
6501
6573
  value: result
6502
6574
  };
6503
- resolve(null);
6575
+ done = true;
6576
+ resolve({
6577
+ __type: exports.TransactionStatus.PROCESSED,
6578
+ response
6579
+ });
6504
6580
  }, subscriptionCommitment);
6505
6581
  } catch (err) {
6506
6582
  reject(err);
6507
6583
  }
6508
6584
  });
6509
- let timeoutMs = this._confirmTransactionInitialTimeout || 60 * 1000;
6510
-
6511
- switch (subscriptionCommitment) {
6512
- case 'processed':
6513
- case 'recent':
6514
- case 'single':
6515
- case 'confirmed':
6516
- case 'singleGossip':
6517
- {
6518
- timeoutMs = this._confirmTransactionInitialTimeout || 30 * 1000;
6519
- break;
6585
+
6586
+ const checkBlockHeight = async () => {
6587
+ try {
6588
+ const blockHeight = await this.getBlockHeight(commitment);
6589
+ return blockHeight;
6590
+ } catch (_e) {
6591
+ return -1;
6592
+ }
6593
+ };
6594
+
6595
+ const expiryPromise = new Promise(resolve => {
6596
+ if (typeof strategy === 'string') {
6597
+ let timeoutMs = this._confirmTransactionInitialTimeout || 60 * 1000;
6598
+
6599
+ switch (subscriptionCommitment) {
6600
+ case 'processed':
6601
+ case 'recent':
6602
+ case 'single':
6603
+ case 'confirmed':
6604
+ case 'singleGossip':
6605
+ {
6606
+ timeoutMs = this._confirmTransactionInitialTimeout || 30 * 1000;
6607
+ break;
6608
+ }
6520
6609
  }
6521
- }
6610
+
6611
+ timeoutId = setTimeout(() => resolve({
6612
+ __type: exports.TransactionStatus.TIMED_OUT,
6613
+ timeoutMs
6614
+ }), timeoutMs);
6615
+ } else {
6616
+ let config = strategy;
6617
+
6618
+ (async () => {
6619
+ let currentBlockHeight = await checkBlockHeight();
6620
+ if (done) return;
6621
+
6622
+ while (currentBlockHeight <= config.lastValidBlockHeight) {
6623
+ await sleep(1000);
6624
+ if (done) return;
6625
+ currentBlockHeight = await checkBlockHeight();
6626
+ if (done) return;
6627
+ }
6628
+
6629
+ resolve({
6630
+ __type: exports.TransactionStatus.BLOCKHEIGHT_EXCEEDED
6631
+ });
6632
+ })();
6633
+ }
6634
+ });
6635
+ let result;
6522
6636
 
6523
6637
  try {
6524
- await promiseTimeout(confirmPromise, timeoutMs);
6638
+ const outcome = await Promise.race([confirmationPromise, expiryPromise]);
6639
+
6640
+ switch (outcome.__type) {
6641
+ case exports.TransactionStatus.BLOCKHEIGHT_EXCEEDED:
6642
+ throw new TransactionExpiredBlockheightExceededError(rawSignature);
6643
+
6644
+ case exports.TransactionStatus.PROCESSED:
6645
+ result = outcome.response;
6646
+ break;
6647
+
6648
+ case exports.TransactionStatus.TIMED_OUT:
6649
+ throw new TransactionExpiredTimeoutError(rawSignature, outcome.timeoutMs / 1000);
6650
+ }
6525
6651
  } finally {
6652
+ clearTimeout(timeoutId);
6653
+
6526
6654
  if (subscriptionId) {
6527
6655
  this.removeSignatureListener(subscriptionId);
6528
6656
  }
6529
6657
  }
6530
6658
 
6531
- if (response === null) {
6532
- const duration = (Date.now() - start) / 1000;
6533
- 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.`);
6534
- }
6535
-
6536
- return response;
6659
+ return result;
6537
6660
  }
6538
6661
  /**
6539
6662
  * Return the list of nodes that are currently participating in the cluster
@@ -9650,10 +9773,8 @@ class ValidatorInfo {
9650
9773
  const configKeys = [];
9651
9774
 
9652
9775
  for (let i = 0; i < 2; i++) {
9653
- const publicKey = new PublicKey(byteArray.slice(0, PUBKEY_LENGTH));
9654
- byteArray = byteArray.slice(PUBKEY_LENGTH);
9655
- const isSigner = byteArray.slice(0, 1)[0] === 1;
9656
- byteArray = byteArray.slice(1);
9776
+ const publicKey = new PublicKey(guardedSplice(byteArray, 0, PUBKEY_LENGTH));
9777
+ const isSigner = guardedShift(byteArray) === 1;
9657
9778
  configKeys.push({
9658
9779
  publicKey,
9659
9780
  isSigner