@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.browser.cjs.js
CHANGED
|
@@ -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
|
|
2326
|
-
const numReadonlySignedAccounts = byteArray
|
|
2327
|
-
const numReadonlyUnsignedAccounts = byteArray
|
|
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
|
|
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
|
|
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
|
|
2371
|
+
const programIdIndex = guardedShift(byteArray);
|
|
2344
2372
|
const accountCount = decodeLength(byteArray);
|
|
2345
|
-
const accounts = byteArray
|
|
2346
|
-
byteArray = byteArray.slice(accountCount);
|
|
2373
|
+
const accounts = guardedSplice(byteArray, 0, accountCount);
|
|
2347
2374
|
const dataLength = decodeLength(byteArray);
|
|
2348
|
-
const dataSlice = byteArray
|
|
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
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
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(
|
|
6557
|
+
decodedSignature = bs58__default["default"].decode(rawSignature);
|
|
6486
6558
|
} catch (err) {
|
|
6487
|
-
throw new Error('signature must be base58 encoded: ' +
|
|
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
|
|
6495
|
-
const
|
|
6566
|
+
let done = false;
|
|
6567
|
+
const confirmationPromise = new Promise((resolve, reject) => {
|
|
6496
6568
|
try {
|
|
6497
|
-
subscriptionId = this.onSignature(
|
|
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
|
-
|
|
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
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
9654
|
-
|
|
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
|