@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.browser.cjs.js +181 -60
- package/lib/index.browser.cjs.js.map +1 -1
- package/lib/index.browser.esm.js +182 -61
- package/lib/index.browser.esm.js.map +1 -1
- package/lib/index.cjs.js +181 -60
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +44 -10
- package/lib/index.esm.js +182 -61
- package/lib/index.esm.js.map +1 -1
- package/lib/index.iife.js +181 -60
- package/lib/index.iife.js.map +1 -1
- package/lib/index.iife.min.js +2 -2
- package/lib/index.iife.min.js.map +1 -1
- package/package.json +22 -22
- package/src/connection.ts +118 -41
- package/src/message.ts +9 -12
- package/src/transaction.ts +56 -8
- package/src/util/guarded-array-utils.ts +34 -0
- package/src/util/send-and-confirm-transaction.ts +19 -6
- package/src/util/tx-expiry-custom-errors.ts +35 -0
- package/src/validator-info.ts +5 -4
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
|
|
2338
|
-
const numReadonlySignedAccounts = byteArray
|
|
2339
|
-
const numReadonlyUnsignedAccounts = byteArray
|
|
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
|
|
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
|
|
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
|
|
2383
|
+
const programIdIndex = guardedShift(byteArray);
|
|
2356
2384
|
const accountCount = decodeLength(byteArray);
|
|
2357
|
-
const accounts = byteArray
|
|
2358
|
-
byteArray = byteArray.slice(accountCount);
|
|
2385
|
+
const accounts = guardedSplice(byteArray, 0, accountCount);
|
|
2359
2386
|
const dataLength = decodeLength(byteArray);
|
|
2360
|
-
const dataSlice = byteArray
|
|
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
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
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(
|
|
6063
|
+
decodedSignature = bs58__default["default"].decode(rawSignature);
|
|
5992
6064
|
} catch (err) {
|
|
5993
|
-
throw new Error('signature must be base58 encoded: ' +
|
|
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
|
|
6001
|
-
const
|
|
6072
|
+
let done = false;
|
|
6073
|
+
const confirmationPromise = new Promise((resolve, reject) => {
|
|
6002
6074
|
try {
|
|
6003
|
-
subscriptionId = this.onSignature(
|
|
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
|
-
|
|
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
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
9160
|
-
|
|
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
|