@solana/web3.js 1.66.4 → 1.67.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/lib/index.iife.js CHANGED
@@ -10906,6 +10906,17 @@ var solanaWeb3 = (function (exports) {
10906
10906
  Object.defineProperty(TransactionExpiredTimeoutError.prototype, 'name', {
10907
10907
  value: 'TransactionExpiredTimeoutError'
10908
10908
  });
10909
+ class TransactionExpiredNonceInvalidError extends Error {
10910
+ constructor(signature) {
10911
+ super(`Signature ${signature} has expired: the nonce is no longer valid.`);
10912
+ this.signature = void 0;
10913
+ this.signature = signature;
10914
+ }
10915
+
10916
+ }
10917
+ Object.defineProperty(TransactionExpiredNonceInvalidError.prototype, 'name', {
10918
+ value: 'TransactionExpiredNonceInvalidError'
10919
+ });
10909
10920
 
10910
10921
  class MessageAccountKeys {
10911
10922
  constructor(staticAccountKeys, accountKeysFromLookups) {
@@ -11743,6 +11754,7 @@ var solanaWeb3 = (function (exports) {
11743
11754
  TransactionStatus[TransactionStatus["BLOCKHEIGHT_EXCEEDED"] = 0] = "BLOCKHEIGHT_EXCEEDED";
11744
11755
  TransactionStatus[TransactionStatus["PROCESSED"] = 1] = "PROCESSED";
11745
11756
  TransactionStatus[TransactionStatus["TIMED_OUT"] = 2] = "TIMED_OUT";
11757
+ TransactionStatus[TransactionStatus["NONCE_INVALID"] = 3] = "NONCE_INVALID";
11746
11758
  })(exports.TransactionStatus || (exports.TransactionStatus = {}));
11747
11759
 
11748
11760
  const DEFAULT_SIGNATURE = buffer.Buffer.alloc(SIGNATURE_LENGTH_IN_BYTES).fill(0);
@@ -11837,6 +11849,7 @@ var solanaWeb3 = (function (exports) {
11837
11849
  this.recentBlockhash = void 0;
11838
11850
  this.lastValidBlockHeight = void 0;
11839
11851
  this.nonceInfo = void 0;
11852
+ this.minNonceContextSlot = void 0;
11840
11853
  this._message = void 0;
11841
11854
  this._json = void 0;
11842
11855
 
@@ -11852,7 +11865,14 @@ var solanaWeb3 = (function (exports) {
11852
11865
  this.signatures = opts.signatures;
11853
11866
  }
11854
11867
 
11855
- if (Object.prototype.hasOwnProperty.call(opts, 'lastValidBlockHeight')) {
11868
+ if (Object.prototype.hasOwnProperty.call(opts, 'nonceInfo')) {
11869
+ const {
11870
+ minContextSlot,
11871
+ nonceInfo
11872
+ } = opts;
11873
+ this.minNonceContextSlot = minContextSlot;
11874
+ this.nonceInfo = nonceInfo;
11875
+ } else if (Object.prototype.hasOwnProperty.call(opts, 'lastValidBlockHeight')) {
11856
11876
  const {
11857
11877
  blockhash,
11858
11878
  lastValidBlockHeight
@@ -12669,11 +12689,28 @@ var solanaWeb3 = (function (exports) {
12669
12689
  minContextSlot: options.minContextSlot
12670
12690
  };
12671
12691
  const signature = await connection.sendTransaction(transaction, signers, sendOptions);
12672
- const status = transaction.recentBlockhash != null && transaction.lastValidBlockHeight != null ? (await connection.confirmTransaction({
12673
- signature: signature,
12674
- blockhash: transaction.recentBlockhash,
12675
- lastValidBlockHeight: transaction.lastValidBlockHeight
12676
- }, options && options.commitment)).value : (await connection.confirmTransaction(signature, options && options.commitment)).value;
12692
+ let status;
12693
+
12694
+ if (transaction.recentBlockhash != null && transaction.lastValidBlockHeight != null) {
12695
+ status = (await connection.confirmTransaction({
12696
+ signature: signature,
12697
+ blockhash: transaction.recentBlockhash,
12698
+ lastValidBlockHeight: transaction.lastValidBlockHeight
12699
+ }, options && options.commitment)).value;
12700
+ } else if (transaction.minNonceContextSlot != null && transaction.nonceInfo != null) {
12701
+ const {
12702
+ nonceInstruction
12703
+ } = transaction.nonceInfo;
12704
+ const nonceAccountPubkey = nonceInstruction.keys[0].pubkey;
12705
+ status = (await connection.confirmTransaction({
12706
+ minContextSlot: transaction.minNonceContextSlot,
12707
+ nonceAccountPubkey,
12708
+ nonceValue: transaction.nonceInfo.nonce,
12709
+ signature
12710
+ }, options && options.commitment)).value;
12711
+ } else {
12712
+ status = (await connection.confirmTransaction(signature, options && options.commitment)).value;
12713
+ }
12677
12714
 
12678
12715
  if (status.err) {
12679
12716
  throw new Error(`Transaction ${signature} failed (${JSON.stringify(status)})`);
@@ -12742,6 +12779,9 @@ var solanaWeb3 = (function (exports) {
12742
12779
 
12743
12780
  const NonceAccountLayout = struct([u32('version'), u32('state'), publicKey('authorizedPubkey'), publicKey('nonce'), struct([FeeCalculatorLayout], 'feeCalculator')]);
12744
12781
  const NONCE_ACCOUNT_LENGTH = NonceAccountLayout.span;
12782
+ /**
12783
+ * A durable nonce is a 32 byte value encoded as a base58 string.
12784
+ */
12745
12785
 
12746
12786
  /**
12747
12787
  * NonceAccount class
@@ -17269,10 +17309,13 @@ var solanaWeb3 = (function (exports) {
17269
17309
  };
17270
17310
  }
17271
17311
  /**
17272
- * @internal
17312
+ * A strategy for confirming durable nonce transactions.
17273
17313
  */
17274
17314
 
17275
17315
 
17316
+ /**
17317
+ * @internal
17318
+ */
17276
17319
  function createRpcResult(result) {
17277
17320
  return union([type({
17278
17321
  jsonrpc: literal('2.0'),
@@ -18836,25 +18879,45 @@ var solanaWeb3 = (function (exports) {
18836
18879
  }
18837
18880
 
18838
18881
  assert$1(decodedSignature.length === 64, 'signature has invalid length');
18839
- const subscriptionCommitment = commitment || this.commitment;
18840
- let timeoutId;
18882
+
18883
+ if (typeof strategy === 'string') {
18884
+ return await this.confirmTransactionUsingLegacyTimeoutStrategy({
18885
+ commitment: commitment || this.commitment,
18886
+ signature: rawSignature
18887
+ });
18888
+ } else if ('lastValidBlockHeight' in strategy) {
18889
+ return await this.confirmTransactionUsingBlockHeightExceedanceStrategy({
18890
+ commitment: commitment || this.commitment,
18891
+ strategy
18892
+ });
18893
+ } else {
18894
+ return await this.confirmTransactionUsingDurableNonceStrategy({
18895
+ commitment: commitment || this.commitment,
18896
+ strategy
18897
+ });
18898
+ }
18899
+ }
18900
+
18901
+ getTransactionConfirmationPromise({
18902
+ commitment,
18903
+ signature
18904
+ }) {
18841
18905
  let signatureSubscriptionId;
18842
18906
  let disposeSignatureSubscriptionStateChangeObserver;
18843
18907
  let done = false;
18844
18908
  const confirmationPromise = new Promise((resolve, reject) => {
18845
18909
  try {
18846
- signatureSubscriptionId = this.onSignature(rawSignature, (result, context) => {
18910
+ signatureSubscriptionId = this.onSignature(signature, (result, context) => {
18847
18911
  signatureSubscriptionId = undefined;
18848
18912
  const response = {
18849
18913
  context,
18850
18914
  value: result
18851
18915
  };
18852
- done = true;
18853
18916
  resolve({
18854
18917
  __type: exports.TransactionStatus.PROCESSED,
18855
18918
  response
18856
18919
  });
18857
- }, subscriptionCommitment);
18920
+ }, commitment);
18858
18921
  const subscriptionSetupPromise = new Promise(resolveSubscriptionSetup => {
18859
18922
  if (signatureSubscriptionId == null) {
18860
18923
  resolveSubscriptionSetup();
@@ -18870,7 +18933,7 @@ var solanaWeb3 = (function (exports) {
18870
18933
  (async () => {
18871
18934
  await subscriptionSetupPromise;
18872
18935
  if (done) return;
18873
- const response = await this.getSignatureStatus(rawSignature);
18936
+ const response = await this.getSignatureStatus(signature);
18874
18937
  if (done) return;
18875
18938
 
18876
18939
  if (response == null) {
@@ -18882,11 +18945,41 @@ var solanaWeb3 = (function (exports) {
18882
18945
  value
18883
18946
  } = response;
18884
18947
 
18948
+ if (value == null) {
18949
+ return;
18950
+ }
18951
+
18885
18952
  if (value !== null && value !== void 0 && value.err) {
18886
18953
  reject(value.err);
18887
- }
18954
+ } else {
18955
+ switch (commitment) {
18956
+ case 'confirmed':
18957
+ case 'single':
18958
+ case 'singleGossip':
18959
+ {
18960
+ if (value.confirmationStatus === 'processed') {
18961
+ return;
18962
+ }
18963
+
18964
+ break;
18965
+ }
18966
+
18967
+ case 'finalized':
18968
+ case 'max':
18969
+ case 'root':
18970
+ {
18971
+ if (value.confirmationStatus === 'processed' || value.confirmationStatus === 'confirmed') {
18972
+ return;
18973
+ }
18974
+
18975
+ break;
18976
+ }
18977
+ // exhaust enums to ensure full coverage
18978
+
18979
+ case 'processed':
18980
+ case 'recent':
18981
+ }
18888
18982
 
18889
- if (value) {
18890
18983
  done = true;
18891
18984
  resolve({
18892
18985
  __type: exports.TransactionStatus.PROCESSED,
@@ -18901,81 +18994,279 @@ var solanaWeb3 = (function (exports) {
18901
18994
  reject(err);
18902
18995
  }
18903
18996
  });
18997
+
18998
+ const abortConfirmation = () => {
18999
+ if (disposeSignatureSubscriptionStateChangeObserver) {
19000
+ disposeSignatureSubscriptionStateChangeObserver();
19001
+ disposeSignatureSubscriptionStateChangeObserver = undefined;
19002
+ }
19003
+
19004
+ if (signatureSubscriptionId) {
19005
+ this.removeSignatureListener(signatureSubscriptionId);
19006
+ signatureSubscriptionId = undefined;
19007
+ }
19008
+ };
19009
+
19010
+ return {
19011
+ abortConfirmation,
19012
+ confirmationPromise
19013
+ };
19014
+ }
19015
+
19016
+ async confirmTransactionUsingBlockHeightExceedanceStrategy({
19017
+ commitment,
19018
+ strategy: {
19019
+ lastValidBlockHeight,
19020
+ signature
19021
+ }
19022
+ }) {
19023
+ let done = false;
18904
19024
  const expiryPromise = new Promise(resolve => {
18905
- if (typeof strategy === 'string') {
18906
- let timeoutMs = this._confirmTransactionInitialTimeout || 60 * 1000;
18907
-
18908
- switch (subscriptionCommitment) {
18909
- case 'processed':
18910
- case 'recent':
18911
- case 'single':
18912
- case 'confirmed':
18913
- case 'singleGossip':
18914
- {
18915
- timeoutMs = this._confirmTransactionInitialTimeout || 30 * 1000;
18916
- break;
18917
- }
19025
+ const checkBlockHeight = async () => {
19026
+ try {
19027
+ const blockHeight = await this.getBlockHeight(commitment);
19028
+ return blockHeight;
19029
+ } catch (_e) {
19030
+ return -1;
18918
19031
  }
19032
+ };
18919
19033
 
18920
- timeoutId = setTimeout(() => resolve({
18921
- __type: exports.TransactionStatus.TIMED_OUT,
18922
- timeoutMs
18923
- }), timeoutMs);
19034
+ (async () => {
19035
+ let currentBlockHeight = await checkBlockHeight();
19036
+ if (done) return;
19037
+
19038
+ while (currentBlockHeight <= lastValidBlockHeight) {
19039
+ await sleep(1000);
19040
+ if (done) return;
19041
+ currentBlockHeight = await checkBlockHeight();
19042
+ if (done) return;
19043
+ }
19044
+
19045
+ resolve({
19046
+ __type: exports.TransactionStatus.BLOCKHEIGHT_EXCEEDED
19047
+ });
19048
+ })();
19049
+ });
19050
+ const {
19051
+ abortConfirmation,
19052
+ confirmationPromise
19053
+ } = this.getTransactionConfirmationPromise({
19054
+ commitment,
19055
+ signature
19056
+ });
19057
+ let result;
19058
+
19059
+ try {
19060
+ const outcome = await Promise.race([confirmationPromise, expiryPromise]);
19061
+
19062
+ if (outcome.__type === exports.TransactionStatus.PROCESSED) {
19063
+ result = outcome.response;
18924
19064
  } else {
18925
- let config = strategy;
19065
+ throw new TransactionExpiredBlockheightExceededError(signature);
19066
+ }
19067
+ } finally {
19068
+ done = true;
19069
+ abortConfirmation();
19070
+ }
18926
19071
 
18927
- const checkBlockHeight = async () => {
18928
- try {
18929
- const blockHeight = await this.getBlockHeight(commitment);
18930
- return blockHeight;
18931
- } catch (_e) {
18932
- return -1;
18933
- }
18934
- };
19072
+ return result;
19073
+ }
18935
19074
 
18936
- (async () => {
18937
- let currentBlockHeight = await checkBlockHeight();
18938
- if (done) return;
19075
+ async confirmTransactionUsingDurableNonceStrategy({
19076
+ commitment,
19077
+ strategy: {
19078
+ minContextSlot,
19079
+ nonceAccountPubkey,
19080
+ nonceValue,
19081
+ signature
19082
+ }
19083
+ }) {
19084
+ let done = false;
19085
+ const expiryPromise = new Promise(resolve => {
19086
+ let currentNonceValue = nonceValue;
19087
+ let lastCheckedSlot = null;
18939
19088
 
18940
- while (currentBlockHeight <= config.lastValidBlockHeight) {
18941
- await sleep(1000);
18942
- if (done) return;
18943
- currentBlockHeight = await checkBlockHeight();
18944
- if (done) return;
19089
+ const getCurrentNonceValue = async () => {
19090
+ try {
19091
+ const {
19092
+ context,
19093
+ value: nonceAccount
19094
+ } = await this.getNonceAndContext(nonceAccountPubkey, {
19095
+ commitment,
19096
+ minContextSlot
19097
+ });
19098
+ lastCheckedSlot = context.slot;
19099
+ return nonceAccount === null || nonceAccount === void 0 ? void 0 : nonceAccount.nonce;
19100
+ } catch (e) {
19101
+ // If for whatever reason we can't reach/read the nonce
19102
+ // account, just keep using the last-known value.
19103
+ return currentNonceValue;
19104
+ }
19105
+ };
19106
+
19107
+ (async () => {
19108
+ currentNonceValue = await getCurrentNonceValue();
19109
+ if (done) return;
19110
+
19111
+ while (true // eslint-disable-line no-constant-condition
19112
+ ) {
19113
+ if (nonceValue !== currentNonceValue) {
19114
+ resolve({
19115
+ __type: exports.TransactionStatus.NONCE_INVALID,
19116
+ slotInWhichNonceDidAdvance: lastCheckedSlot
19117
+ });
19118
+ return;
18945
19119
  }
18946
19120
 
18947
- resolve({
18948
- __type: exports.TransactionStatus.BLOCKHEIGHT_EXCEEDED
18949
- });
18950
- })();
18951
- }
19121
+ await sleep(2000);
19122
+ if (done) return;
19123
+ currentNonceValue = await getCurrentNonceValue();
19124
+ if (done) return;
19125
+ }
19126
+ })();
19127
+ });
19128
+ const {
19129
+ abortConfirmation,
19130
+ confirmationPromise
19131
+ } = this.getTransactionConfirmationPromise({
19132
+ commitment,
19133
+ signature
18952
19134
  });
18953
19135
  let result;
18954
19136
 
18955
19137
  try {
18956
19138
  const outcome = await Promise.race([confirmationPromise, expiryPromise]);
18957
19139
 
18958
- switch (outcome.__type) {
18959
- case exports.TransactionStatus.BLOCKHEIGHT_EXCEEDED:
18960
- throw new TransactionExpiredBlockheightExceededError(rawSignature);
19140
+ if (outcome.__type === exports.TransactionStatus.PROCESSED) {
19141
+ result = outcome.response;
19142
+ } else {
19143
+ var _signatureStatus;
19144
+
19145
+ // Double check that the transaction is indeed unconfirmed.
19146
+ let signatureStatus;
18961
19147
 
18962
- case exports.TransactionStatus.PROCESSED:
18963
- result = outcome.response;
19148
+ while (true // eslint-disable-line no-constant-condition
19149
+ ) {
19150
+ var _outcome$slotInWhichN;
19151
+
19152
+ const status = await this.getSignatureStatus(signature);
19153
+
19154
+ if (status == null) {
19155
+ break;
19156
+ }
19157
+
19158
+ if (status.context.slot < ((_outcome$slotInWhichN = outcome.slotInWhichNonceDidAdvance) !== null && _outcome$slotInWhichN !== void 0 ? _outcome$slotInWhichN : minContextSlot)) {
19159
+ await sleep(400);
19160
+ continue;
19161
+ }
19162
+
19163
+ signatureStatus = status;
18964
19164
  break;
19165
+ }
19166
+
19167
+ if ((_signatureStatus = signatureStatus) !== null && _signatureStatus !== void 0 && _signatureStatus.value) {
19168
+ const commitmentForStatus = commitment || 'finalized';
19169
+ const {
19170
+ confirmationStatus
19171
+ } = signatureStatus.value;
19172
+
19173
+ switch (commitmentForStatus) {
19174
+ case 'processed':
19175
+ case 'recent':
19176
+ if (confirmationStatus !== 'processed' && confirmationStatus !== 'confirmed' && confirmationStatus !== 'finalized') {
19177
+ throw new TransactionExpiredNonceInvalidError(signature);
19178
+ }
18965
19179
 
18966
- case exports.TransactionStatus.TIMED_OUT:
18967
- throw new TransactionExpiredTimeoutError(rawSignature, outcome.timeoutMs / 1000);
19180
+ break;
19181
+
19182
+ case 'confirmed':
19183
+ case 'single':
19184
+ case 'singleGossip':
19185
+ if (confirmationStatus !== 'confirmed' && confirmationStatus !== 'finalized') {
19186
+ throw new TransactionExpiredNonceInvalidError(signature);
19187
+ }
19188
+
19189
+ break;
19190
+
19191
+ case 'finalized':
19192
+ case 'max':
19193
+ case 'root':
19194
+ if (confirmationStatus !== 'finalized') {
19195
+ throw new TransactionExpiredNonceInvalidError(signature);
19196
+ }
19197
+
19198
+ break;
19199
+
19200
+ default:
19201
+ // Exhaustive switch.
19202
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
19203
+ (_ => {})(commitmentForStatus);
19204
+
19205
+ }
19206
+
19207
+ result = {
19208
+ context: signatureStatus.context,
19209
+ value: {
19210
+ err: signatureStatus.value.err
19211
+ }
19212
+ };
19213
+ } else {
19214
+ throw new TransactionExpiredNonceInvalidError(signature);
19215
+ }
18968
19216
  }
18969
19217
  } finally {
18970
- clearTimeout(timeoutId);
19218
+ done = true;
19219
+ abortConfirmation();
19220
+ }
18971
19221
 
18972
- if (disposeSignatureSubscriptionStateChangeObserver) {
18973
- disposeSignatureSubscriptionStateChangeObserver();
19222
+ return result;
19223
+ }
19224
+
19225
+ async confirmTransactionUsingLegacyTimeoutStrategy({
19226
+ commitment,
19227
+ signature
19228
+ }) {
19229
+ let timeoutId;
19230
+ const expiryPromise = new Promise(resolve => {
19231
+ let timeoutMs = this._confirmTransactionInitialTimeout || 60 * 1000;
19232
+
19233
+ switch (commitment) {
19234
+ case 'processed':
19235
+ case 'recent':
19236
+ case 'single':
19237
+ case 'confirmed':
19238
+ case 'singleGossip':
19239
+ {
19240
+ timeoutMs = this._confirmTransactionInitialTimeout || 30 * 1000;
19241
+ break;
19242
+ }
18974
19243
  }
18975
19244
 
18976
- if (signatureSubscriptionId) {
18977
- this.removeSignatureListener(signatureSubscriptionId);
19245
+ timeoutId = setTimeout(() => resolve({
19246
+ __type: exports.TransactionStatus.TIMED_OUT,
19247
+ timeoutMs
19248
+ }), timeoutMs);
19249
+ });
19250
+ const {
19251
+ abortConfirmation,
19252
+ confirmationPromise
19253
+ } = this.getTransactionConfirmationPromise({
19254
+ commitment,
19255
+ signature
19256
+ });
19257
+ let result;
19258
+
19259
+ try {
19260
+ const outcome = await Promise.race([confirmationPromise, expiryPromise]);
19261
+
19262
+ if (outcome.__type === exports.TransactionStatus.PROCESSED) {
19263
+ result = outcome.response;
19264
+ } else {
19265
+ throw new TransactionExpiredTimeoutError(signature, outcome.timeoutMs / 1000);
18978
19266
  }
19267
+ } finally {
19268
+ clearTimeout(timeoutId);
19269
+ abortConfirmation();
18979
19270
  }
18980
19271
 
18981
19272
  return result;
@@ -20031,11 +20322,11 @@ var solanaWeb3 = (function (exports) {
20031
20322
  */
20032
20323
 
20033
20324
 
20034
- async getNonceAndContext(nonceAccount, commitment) {
20325
+ async getNonceAndContext(nonceAccount, commitmentOrConfig) {
20035
20326
  const {
20036
20327
  context,
20037
20328
  value: accountInfo
20038
- } = await this.getAccountInfoAndContext(nonceAccount, commitment);
20329
+ } = await this.getAccountInfoAndContext(nonceAccount, commitmentOrConfig);
20039
20330
  let value = null;
20040
20331
 
20041
20332
  if (accountInfo !== null) {
@@ -20052,8 +20343,8 @@ var solanaWeb3 = (function (exports) {
20052
20343
  */
20053
20344
 
20054
20345
 
20055
- async getNonce(nonceAccount, commitment) {
20056
- return await this.getNonceAndContext(nonceAccount, commitment).then(x => x.value).catch(e => {
20346
+ async getNonce(nonceAccount, commitmentOrConfig) {
20347
+ return await this.getNonceAndContext(nonceAccount, commitmentOrConfig).then(x => x.value).catch(e => {
20057
20348
  throw new Error('failed to get nonce for account ' + nonceAccount.toBase58() + ': ' + e);
20058
20349
  });
20059
20350
  }
@@ -24686,6 +24977,9 @@ var solanaWeb3 = (function (exports) {
24686
24977
  if (confirmationStrategyOrConfirmOptions && Object.prototype.hasOwnProperty.call(confirmationStrategyOrConfirmOptions, 'lastValidBlockHeight')) {
24687
24978
  confirmationStrategy = confirmationStrategyOrConfirmOptions;
24688
24979
  options = maybeConfirmOptions;
24980
+ } else if (confirmationStrategyOrConfirmOptions && Object.prototype.hasOwnProperty.call(confirmationStrategyOrConfirmOptions, 'nonceValue')) {
24981
+ confirmationStrategy = confirmationStrategyOrConfirmOptions;
24982
+ options = maybeConfirmOptions;
24689
24983
  } else {
24690
24984
  options = confirmationStrategyOrConfirmOptions;
24691
24985
  }
@@ -24770,6 +25064,7 @@ var solanaWeb3 = (function (exports) {
24770
25064
  exports.SystemProgram = SystemProgram;
24771
25065
  exports.Transaction = Transaction;
24772
25066
  exports.TransactionExpiredBlockheightExceededError = TransactionExpiredBlockheightExceededError;
25067
+ exports.TransactionExpiredNonceInvalidError = TransactionExpiredNonceInvalidError;
24773
25068
  exports.TransactionExpiredTimeoutError = TransactionExpiredTimeoutError;
24774
25069
  exports.TransactionInstruction = TransactionInstruction;
24775
25070
  exports.TransactionMessage = TransactionMessage;