@solana/web3.js 1.53.0 → 1.54.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.d.ts CHANGED
@@ -19,6 +19,10 @@ declare module '@solana/web3.js' {
19
19
  * Maximum length of derived pubkey seed
20
20
  */
21
21
  export const MAX_SEED_LENGTH = 32;
22
+ /**
23
+ * Size of public key in bytes
24
+ */
25
+ export const PUBLIC_KEY_LENGTH = 32;
22
26
  /**
23
27
  * Value to be converted into public key
24
28
  */
@@ -285,6 +289,7 @@ declare module '@solana/web3.js' {
285
289
  * 8 bytes is the size of the fragment header
286
290
  */
287
291
  export const PACKET_DATA_SIZE: number;
292
+ export const VERSION_PREFIX_MASK = 127;
288
293
  export const SIGNATURE_LENGTH_IN_BYTES = 64;
289
294
 
290
295
  export class TransactionExpiredBlockheightExceededError extends Error {
@@ -296,6 +301,21 @@ declare module '@solana/web3.js' {
296
301
  constructor(signature: string, timeoutSeconds: number);
297
302
  }
298
303
 
304
+ /**
305
+ * An instruction to execute by a program
306
+ *
307
+ * @property {number} programIdIndex
308
+ * @property {number[]} accounts
309
+ * @property {string} data
310
+ */
311
+ export type CompiledInstruction = {
312
+ /** Index into the transaction keys array indicating the program account that executes this instruction */
313
+ programIdIndex: number;
314
+ /** Ordered indices into the transaction keys array indicating which accounts to pass to the program */
315
+ accounts: number[];
316
+ /** The program input data encoded as base 58 */
317
+ data: string;
318
+ };
299
319
  /**
300
320
  * Message constructor arguments
301
321
  */
@@ -319,6 +339,10 @@ declare module '@solana/web3.js' {
319
339
  instructions: CompiledInstruction[];
320
340
  private indexToProgramIds;
321
341
  constructor(args: MessageArgs);
342
+ get version(): 'legacy';
343
+ get staticAccountKeys(): Array<PublicKey>;
344
+ get compiledInstructions(): Array<MessageCompiledInstruction>;
345
+ get addressTableLookups(): Array<MessageAddressTableLookup>;
322
346
  isAccountSigner(index: number): boolean;
323
347
  isAccountWritable(index: number): boolean;
324
348
  isProgramId(index: number): boolean;
@@ -331,6 +355,40 @@ declare module '@solana/web3.js' {
331
355
  static from(buffer: Buffer | Uint8Array | Array<number>): Message;
332
356
  }
333
357
 
358
+ /**
359
+ * Message constructor arguments
360
+ */
361
+ export type MessageV0Args = {
362
+ /** The message header, identifying signed and read-only `accountKeys` */
363
+ header: MessageHeader;
364
+ /** The static account keys used by this transaction */
365
+ staticAccountKeys: PublicKey[];
366
+ /** The hash of a recent ledger block */
367
+ recentBlockhash: Blockhash;
368
+ /** Instructions that will be executed in sequence and committed in one atomic transaction if all succeed. */
369
+ compiledInstructions: MessageCompiledInstruction[];
370
+ /** Instructions that will be executed in sequence and committed in one atomic transaction if all succeed. */
371
+ addressTableLookups: MessageAddressTableLookup[];
372
+ };
373
+ export class MessageV0 {
374
+ header: MessageHeader;
375
+ staticAccountKeys: Array<PublicKey>;
376
+ recentBlockhash: Blockhash;
377
+ compiledInstructions: Array<MessageCompiledInstruction>;
378
+ addressTableLookups: Array<MessageAddressTableLookup>;
379
+ constructor(args: MessageV0Args);
380
+ get version(): 0;
381
+ serialize(): Uint8Array;
382
+ private serializeInstructions;
383
+ private serializeAddressTableLookups;
384
+ static deserialize(serializedMessage: Uint8Array): MessageV0;
385
+ }
386
+
387
+ export type VersionedMessage = Message | MessageV0;
388
+ export const VersionedMessage: {
389
+ deserialize: (serializedMessage: Uint8Array) => VersionedMessage;
390
+ };
391
+
334
392
  /**
335
393
  * The message header, identifying signed and read-only account
336
394
  */
@@ -345,20 +403,28 @@ declare module '@solana/web3.js' {
345
403
  /** The last `numReadonlySignedAccounts` of the unsigned keys are read-only accounts */
346
404
  numReadonlyUnsignedAccounts: number;
347
405
  };
406
+ /**
407
+ * An address table lookup used to load additional accounts
408
+ */
409
+ export type MessageAddressTableLookup = {
410
+ accountKey: PublicKey;
411
+ writableIndexes: Array<number>;
412
+ readonlyIndexes: Array<number>;
413
+ };
348
414
  /**
349
415
  * An instruction to execute by a program
350
416
  *
351
417
  * @property {number} programIdIndex
352
- * @property {number[]} accounts
353
- * @property {string} data
418
+ * @property {number[]} accountKeyIndexes
419
+ * @property {Uint8Array} data
354
420
  */
355
- export type CompiledInstruction = {
421
+ export type MessageCompiledInstruction = {
356
422
  /** Index into the transaction keys array indicating the program account that executes this instruction */
357
423
  programIdIndex: number;
358
424
  /** Ordered indices into the transaction keys array indicating which accounts to pass to the program */
359
- accounts: number[];
360
- /** The program input data encoded as base 58 */
361
- data: string;
425
+ accountKeyIndexes: number[];
426
+ /** The program input data */
427
+ data: Uint8Array;
362
428
  };
363
429
 
364
430
  /**
@@ -578,6 +644,19 @@ declare module '@solana/web3.js' {
578
644
  static populate(message: Message, signatures?: Array<string>): Transaction;
579
645
  }
580
646
 
647
+ export type TransactionVersion = 'legacy' | 0;
648
+ /**
649
+ * Versioned transaction class
650
+ */
651
+ export class VersionedTransaction {
652
+ signatures: Array<Uint8Array>;
653
+ message: VersionedMessage;
654
+ constructor(message: VersionedMessage, signatures?: Array<Uint8Array>);
655
+ serialize(): Uint8Array;
656
+ static deserialize(serializedTransaction: Uint8Array): VersionedTransaction;
657
+ sign(signers: Array<Signer>): void;
658
+ }
659
+
581
660
  export type AddressLookupTableState = {
582
661
  deactivationSlot: bigint;
583
662
  lastExtendedSlot: number;
@@ -3595,6 +3674,19 @@ declare module '@solana/web3.js' {
3595
3674
  * Generate a transaction to withdraw from a Vote account.
3596
3675
  */
3597
3676
  static withdraw(params: WithdrawFromVoteAccountParams): Transaction;
3677
+ /**
3678
+ * Generate a transaction to withdraw safely from a Vote account.
3679
+ *
3680
+ * This function was created as a safeguard for vote accounts running validators, `safeWithdraw`
3681
+ * checks that the withdraw amount will not exceed the specified balance while leaving enough left
3682
+ * to cover rent. If you wish to close the vote account by withdrawing the full amount, call the
3683
+ * `withdraw` method directly.
3684
+ */
3685
+ static safeWithdraw(
3686
+ params: WithdrawFromVoteAccountParams,
3687
+ currentVoteAccountBalance: number,
3688
+ rentExemptMinimum: number,
3689
+ ): Transaction;
3598
3690
  }
3599
3691
 
3600
3692
  export const VALIDATOR_INFO_KEY: PublicKey;
package/lib/index.esm.js CHANGED
@@ -1793,6 +1793,11 @@ const SOLANA_SCHEMA = new Map();
1793
1793
  */
1794
1794
 
1795
1795
  const MAX_SEED_LENGTH = 32;
1796
+ /**
1797
+ * Size of public key in bytes
1798
+ */
1799
+
1800
+ const PUBLIC_KEY_LENGTH = 32;
1796
1801
  /**
1797
1802
  * Value to be converted into public key
1798
1803
  */
@@ -1823,7 +1828,7 @@ class PublicKey extends Struct {
1823
1828
  // assume base 58 encoding by default
1824
1829
  const decoded = bs58.decode(value);
1825
1830
 
1826
- if (decoded.length != 32) {
1831
+ if (decoded.length != PUBLIC_KEY_LENGTH) {
1827
1832
  throw new Error(`Invalid public key input`);
1828
1833
  }
1829
1834
 
@@ -1876,7 +1881,7 @@ class PublicKey extends Struct {
1876
1881
  toBuffer() {
1877
1882
  const b = this._bn.toArrayLike(Buffer);
1878
1883
 
1879
- if (b.length === 32) {
1884
+ if (b.length === PUBLIC_KEY_LENGTH) {
1880
1885
  return b;
1881
1886
  }
1882
1887
 
@@ -2104,6 +2109,7 @@ const BPF_LOADER_DEPRECATED_PROGRAM_ID = new PublicKey('BPFLoader111111111111111
2104
2109
  * 8 bytes is the size of the fragment header
2105
2110
  */
2106
2111
  const PACKET_DATA_SIZE = 1280 - 40 - 8;
2112
+ const VERSION_PREFIX_MASK = 0x7f;
2107
2113
  const SIGNATURE_LENGTH_IN_BYTES = 64;
2108
2114
 
2109
2115
  class TransactionExpiredBlockheightExceededError extends Error {
@@ -2136,6 +2142,13 @@ Object.defineProperty(TransactionExpiredTimeoutError.prototype, 'name', {
2136
2142
  const publicKey = (property = 'publicKey') => {
2137
2143
  return BufferLayout.blob(32, property);
2138
2144
  };
2145
+ /**
2146
+ * Layout for a signature
2147
+ */
2148
+
2149
+ const signature = (property = 'signature') => {
2150
+ return BufferLayout.blob(64, property);
2151
+ };
2139
2152
 
2140
2153
  /**
2141
2154
  * Layout for a Rust String type
@@ -2247,11 +2260,9 @@ function encodeLength(bytes, len) {
2247
2260
  }
2248
2261
  }
2249
2262
 
2250
- const PUBKEY_LENGTH = 32;
2251
2263
  /**
2252
2264
  * List of instructions to be processed atomically
2253
2265
  */
2254
-
2255
2266
  class Message {
2256
2267
  constructor(args) {
2257
2268
  this.header = void 0;
@@ -2266,6 +2277,26 @@ class Message {
2266
2277
  this.instructions.forEach(ix => this.indexToProgramIds.set(ix.programIdIndex, this.accountKeys[ix.programIdIndex]));
2267
2278
  }
2268
2279
 
2280
+ get version() {
2281
+ return 'legacy';
2282
+ }
2283
+
2284
+ get staticAccountKeys() {
2285
+ return this.accountKeys;
2286
+ }
2287
+
2288
+ get compiledInstructions() {
2289
+ return this.instructions.map(ix => ({
2290
+ programIdIndex: ix.programIdIndex,
2291
+ accountKeyIndexes: ix.accounts,
2292
+ data: bs58.decode(ix.data)
2293
+ }));
2294
+ }
2295
+
2296
+ get addressTableLookups() {
2297
+ return [];
2298
+ }
2299
+
2269
2300
  isAccountSigner(index) {
2270
2301
  return index < this.header.numRequiredSignatures;
2271
2302
  }
@@ -2342,19 +2373,24 @@ class Message {
2342
2373
  // Slice up wire data
2343
2374
  let byteArray = [...buffer];
2344
2375
  const numRequiredSignatures = byteArray.shift();
2376
+
2377
+ if (numRequiredSignatures !== (numRequiredSignatures & VERSION_PREFIX_MASK)) {
2378
+ throw new Error('Versioned messages must be deserialized with VersionedMessage.deserialize()');
2379
+ }
2380
+
2345
2381
  const numReadonlySignedAccounts = byteArray.shift();
2346
2382
  const numReadonlyUnsignedAccounts = byteArray.shift();
2347
2383
  const accountCount = decodeLength(byteArray);
2348
2384
  let accountKeys = [];
2349
2385
 
2350
2386
  for (let i = 0; i < accountCount; i++) {
2351
- const account = byteArray.slice(0, PUBKEY_LENGTH);
2352
- byteArray = byteArray.slice(PUBKEY_LENGTH);
2387
+ const account = byteArray.slice(0, PUBLIC_KEY_LENGTH);
2388
+ byteArray = byteArray.slice(PUBLIC_KEY_LENGTH);
2353
2389
  accountKeys.push(bs58.encode(Buffer.from(account)));
2354
2390
  }
2355
2391
 
2356
- const recentBlockhash = byteArray.slice(0, PUBKEY_LENGTH);
2357
- byteArray = byteArray.slice(PUBKEY_LENGTH);
2392
+ const recentBlockhash = byteArray.slice(0, PUBLIC_KEY_LENGTH);
2393
+ byteArray = byteArray.slice(PUBLIC_KEY_LENGTH);
2358
2394
  const instructionCount = decodeLength(byteArray);
2359
2395
  let instructions = [];
2360
2396
 
@@ -2395,6 +2431,182 @@ function assert (condition, message) {
2395
2431
  }
2396
2432
  }
2397
2433
 
2434
+ /**
2435
+ * Message constructor arguments
2436
+ */
2437
+
2438
+ class MessageV0 {
2439
+ constructor(args) {
2440
+ this.header = void 0;
2441
+ this.staticAccountKeys = void 0;
2442
+ this.recentBlockhash = void 0;
2443
+ this.compiledInstructions = void 0;
2444
+ this.addressTableLookups = void 0;
2445
+ this.header = args.header;
2446
+ this.staticAccountKeys = args.staticAccountKeys;
2447
+ this.recentBlockhash = args.recentBlockhash;
2448
+ this.compiledInstructions = args.compiledInstructions;
2449
+ this.addressTableLookups = args.addressTableLookups;
2450
+ }
2451
+
2452
+ get version() {
2453
+ return 0;
2454
+ }
2455
+
2456
+ serialize() {
2457
+ const encodedStaticAccountKeysLength = Array();
2458
+ encodeLength(encodedStaticAccountKeysLength, this.staticAccountKeys.length);
2459
+ const serializedInstructions = this.serializeInstructions();
2460
+ const encodedInstructionsLength = Array();
2461
+ encodeLength(encodedInstructionsLength, this.compiledInstructions.length);
2462
+ const serializedAddressTableLookups = this.serializeAddressTableLookups();
2463
+ const encodedAddressTableLookupsLength = Array();
2464
+ encodeLength(encodedAddressTableLookupsLength, this.addressTableLookups.length);
2465
+ const messageLayout = BufferLayout.struct([BufferLayout.u8('prefix'), BufferLayout.struct([BufferLayout.u8('numRequiredSignatures'), BufferLayout.u8('numReadonlySignedAccounts'), BufferLayout.u8('numReadonlyUnsignedAccounts')], 'header'), BufferLayout.blob(encodedStaticAccountKeysLength.length, 'staticAccountKeysLength'), BufferLayout.seq(publicKey(), this.staticAccountKeys.length, 'staticAccountKeys'), publicKey('recentBlockhash'), BufferLayout.blob(encodedInstructionsLength.length, 'instructionsLength'), BufferLayout.blob(serializedInstructions.length, 'serializedInstructions'), BufferLayout.blob(encodedAddressTableLookupsLength.length, 'addressTableLookupsLength'), BufferLayout.blob(serializedAddressTableLookups.length, 'serializedAddressTableLookups')]);
2466
+ const serializedMessage = new Uint8Array(PACKET_DATA_SIZE);
2467
+ const MESSAGE_VERSION_0_PREFIX = 1 << 7;
2468
+ const serializedMessageLength = messageLayout.encode({
2469
+ prefix: MESSAGE_VERSION_0_PREFIX,
2470
+ header: this.header,
2471
+ staticAccountKeysLength: new Uint8Array(encodedStaticAccountKeysLength),
2472
+ staticAccountKeys: this.staticAccountKeys.map(key => key.toBytes()),
2473
+ recentBlockhash: bs58.decode(this.recentBlockhash),
2474
+ instructionsLength: new Uint8Array(encodedInstructionsLength),
2475
+ serializedInstructions,
2476
+ addressTableLookupsLength: new Uint8Array(encodedAddressTableLookupsLength),
2477
+ serializedAddressTableLookups
2478
+ }, serializedMessage);
2479
+ return serializedMessage.slice(0, serializedMessageLength);
2480
+ }
2481
+
2482
+ serializeInstructions() {
2483
+ let serializedLength = 0;
2484
+ const serializedInstructions = new Uint8Array(PACKET_DATA_SIZE);
2485
+
2486
+ for (const instruction of this.compiledInstructions) {
2487
+ const encodedAccountKeyIndexesLength = Array();
2488
+ encodeLength(encodedAccountKeyIndexesLength, instruction.accountKeyIndexes.length);
2489
+ const encodedDataLength = Array();
2490
+ encodeLength(encodedDataLength, instruction.data.length);
2491
+ const instructionLayout = BufferLayout.struct([BufferLayout.u8('programIdIndex'), BufferLayout.blob(encodedAccountKeyIndexesLength.length, 'encodedAccountKeyIndexesLength'), BufferLayout.seq(BufferLayout.u8(), instruction.accountKeyIndexes.length, 'accountKeyIndexes'), BufferLayout.blob(encodedDataLength.length, 'encodedDataLength'), BufferLayout.blob(instruction.data.length, 'data')]);
2492
+ serializedLength += instructionLayout.encode({
2493
+ programIdIndex: instruction.programIdIndex,
2494
+ encodedAccountKeyIndexesLength: new Uint8Array(encodedAccountKeyIndexesLength),
2495
+ accountKeyIndexes: instruction.accountKeyIndexes,
2496
+ encodedDataLength: new Uint8Array(encodedDataLength),
2497
+ data: instruction.data
2498
+ }, serializedInstructions, serializedLength);
2499
+ }
2500
+
2501
+ return serializedInstructions.slice(0, serializedLength);
2502
+ }
2503
+
2504
+ serializeAddressTableLookups() {
2505
+ let serializedLength = 0;
2506
+ const serializedAddressTableLookups = new Uint8Array(PACKET_DATA_SIZE);
2507
+
2508
+ for (const lookup of this.addressTableLookups) {
2509
+ const encodedWritableIndexesLength = Array();
2510
+ encodeLength(encodedWritableIndexesLength, lookup.writableIndexes.length);
2511
+ const encodedReadonlyIndexesLength = Array();
2512
+ encodeLength(encodedReadonlyIndexesLength, lookup.readonlyIndexes.length);
2513
+ const addressTableLookupLayout = BufferLayout.struct([publicKey('accountKey'), BufferLayout.blob(encodedWritableIndexesLength.length, 'encodedWritableIndexesLength'), BufferLayout.seq(BufferLayout.u8(), lookup.writableIndexes.length, 'writableIndexes'), BufferLayout.blob(encodedReadonlyIndexesLength.length, 'encodedReadonlyIndexesLength'), BufferLayout.seq(BufferLayout.u8(), lookup.readonlyIndexes.length, 'readonlyIndexes')]);
2514
+ serializedLength += addressTableLookupLayout.encode({
2515
+ accountKey: lookup.accountKey.toBytes(),
2516
+ encodedWritableIndexesLength: new Uint8Array(encodedWritableIndexesLength),
2517
+ writableIndexes: lookup.writableIndexes,
2518
+ encodedReadonlyIndexesLength: new Uint8Array(encodedReadonlyIndexesLength),
2519
+ readonlyIndexes: lookup.readonlyIndexes
2520
+ }, serializedAddressTableLookups, serializedLength);
2521
+ }
2522
+
2523
+ return serializedAddressTableLookups.slice(0, serializedLength);
2524
+ }
2525
+
2526
+ static deserialize(serializedMessage) {
2527
+ let byteArray = [...serializedMessage];
2528
+ const prefix = byteArray.shift();
2529
+ const maskedPrefix = prefix & VERSION_PREFIX_MASK;
2530
+ assert(prefix !== maskedPrefix, `Expected versioned message but received legacy message`);
2531
+ const version = maskedPrefix;
2532
+ assert(version === 0, `Expected versioned message with version 0 but found version ${version}`);
2533
+ const header = {
2534
+ numRequiredSignatures: byteArray.shift(),
2535
+ numReadonlySignedAccounts: byteArray.shift(),
2536
+ numReadonlyUnsignedAccounts: byteArray.shift()
2537
+ };
2538
+ const staticAccountKeys = [];
2539
+ const staticAccountKeysLength = decodeLength(byteArray);
2540
+
2541
+ for (let i = 0; i < staticAccountKeysLength; i++) {
2542
+ staticAccountKeys.push(new PublicKey(byteArray.splice(0, PUBLIC_KEY_LENGTH)));
2543
+ }
2544
+
2545
+ const recentBlockhash = bs58.encode(byteArray.splice(0, PUBLIC_KEY_LENGTH));
2546
+ const instructionCount = decodeLength(byteArray);
2547
+ const compiledInstructions = [];
2548
+
2549
+ for (let i = 0; i < instructionCount; i++) {
2550
+ const programIdIndex = byteArray.shift();
2551
+ const accountKeyIndexesLength = decodeLength(byteArray);
2552
+ const accountKeyIndexes = byteArray.splice(0, accountKeyIndexesLength);
2553
+ const dataLength = decodeLength(byteArray);
2554
+ const data = new Uint8Array(byteArray.splice(0, dataLength));
2555
+ compiledInstructions.push({
2556
+ programIdIndex,
2557
+ accountKeyIndexes,
2558
+ data
2559
+ });
2560
+ }
2561
+
2562
+ const addressTableLookupsCount = decodeLength(byteArray);
2563
+ const addressTableLookups = [];
2564
+
2565
+ for (let i = 0; i < addressTableLookupsCount; i++) {
2566
+ const accountKey = new PublicKey(byteArray.splice(0, PUBLIC_KEY_LENGTH));
2567
+ const writableIndexesLength = decodeLength(byteArray);
2568
+ const writableIndexes = byteArray.splice(0, writableIndexesLength);
2569
+ const readonlyIndexesLength = decodeLength(byteArray);
2570
+ const readonlyIndexes = byteArray.splice(0, readonlyIndexesLength);
2571
+ addressTableLookups.push({
2572
+ accountKey,
2573
+ writableIndexes,
2574
+ readonlyIndexes
2575
+ });
2576
+ }
2577
+
2578
+ return new MessageV0({
2579
+ header,
2580
+ staticAccountKeys,
2581
+ recentBlockhash,
2582
+ compiledInstructions,
2583
+ addressTableLookups
2584
+ });
2585
+ }
2586
+
2587
+ }
2588
+
2589
+ // eslint-disable-next-line no-redeclare
2590
+ const VersionedMessage = {
2591
+ deserialize: serializedMessage => {
2592
+ const prefix = serializedMessage[0];
2593
+ const maskedPrefix = prefix & VERSION_PREFIX_MASK; // if the highest bit of the prefix is not set, the message is not versioned
2594
+
2595
+ if (maskedPrefix === prefix) {
2596
+ return Message.from(serializedMessage);
2597
+ } // the lower 7 bits of the prefix indicate the message version
2598
+
2599
+
2600
+ const version = maskedPrefix;
2601
+
2602
+ if (version === 0) {
2603
+ return MessageV0.deserialize(serializedMessage);
2604
+ } else {
2605
+ throw new Error(`Transaction message version ${version} deserialization is not supported`);
2606
+ }
2607
+ }
2608
+ };
2609
+
2398
2610
  let TransactionStatus;
2399
2611
  /**
2400
2612
  * Default (empty) signature
@@ -3123,6 +3335,70 @@ class Transaction {
3123
3335
 
3124
3336
  }
3125
3337
 
3338
+ /**
3339
+ * Versioned transaction class
3340
+ */
3341
+ class VersionedTransaction {
3342
+ constructor(message, signatures) {
3343
+ this.signatures = void 0;
3344
+ this.message = void 0;
3345
+
3346
+ if (signatures !== undefined) {
3347
+ assert(signatures.length === message.header.numRequiredSignatures, 'Expected signatures length to be equal to the number of required signatures');
3348
+ this.signatures = signatures;
3349
+ } else {
3350
+ const defaultSignatures = [];
3351
+
3352
+ for (let i = 0; i < message.header.numRequiredSignatures; i++) {
3353
+ defaultSignatures.push(new Uint8Array(SIGNATURE_LENGTH_IN_BYTES));
3354
+ }
3355
+
3356
+ this.signatures = defaultSignatures;
3357
+ }
3358
+
3359
+ this.message = message;
3360
+ }
3361
+
3362
+ serialize() {
3363
+ const serializedMessage = this.message.serialize();
3364
+ const encodedSignaturesLength = Array();
3365
+ encodeLength(encodedSignaturesLength, this.signatures.length);
3366
+ const transactionLayout = BufferLayout.struct([BufferLayout.blob(encodedSignaturesLength.length, 'encodedSignaturesLength'), BufferLayout.seq(signature(), this.signatures.length, 'signatures'), BufferLayout.blob(serializedMessage.length, 'serializedMessage')]);
3367
+ const serializedTransaction = new Uint8Array(2048);
3368
+ const serializedTransactionLength = transactionLayout.encode({
3369
+ encodedSignaturesLength: new Uint8Array(encodedSignaturesLength),
3370
+ signatures: this.signatures,
3371
+ serializedMessage
3372
+ }, serializedTransaction);
3373
+ return serializedTransaction.slice(0, serializedTransactionLength);
3374
+ }
3375
+
3376
+ static deserialize(serializedTransaction) {
3377
+ let byteArray = [...serializedTransaction];
3378
+ const signatures = [];
3379
+ const signaturesLength = decodeLength(byteArray);
3380
+
3381
+ for (let i = 0; i < signaturesLength; i++) {
3382
+ signatures.push(new Uint8Array(byteArray.splice(0, SIGNATURE_LENGTH_IN_BYTES)));
3383
+ }
3384
+
3385
+ const message = VersionedMessage.deserialize(new Uint8Array(byteArray));
3386
+ return new VersionedTransaction(message, signatures);
3387
+ }
3388
+
3389
+ sign(signers) {
3390
+ const messageData = this.message.serialize();
3391
+ const signerPubkeys = this.message.staticAccountKeys.slice(0, this.message.header.numRequiredSignatures);
3392
+
3393
+ for (const signer of signers) {
3394
+ const signerIndex = signerPubkeys.findIndex(pubkey => pubkey.equals(signer.publicKey));
3395
+ assert(signerIndex >= 0, `Cannot sign with non signer key ${signer.publicKey.toBase58()}`);
3396
+ this.signatures[signerIndex] = nacl.sign.detached(messageData, signer.secretKey);
3397
+ }
3398
+ }
3399
+
3400
+ }
3401
+
3126
3402
  const SYSVAR_CLOCK_PUBKEY = new PublicKey('SysvarC1ock11111111111111111111111111111111');
3127
3403
  const SYSVAR_EPOCH_SCHEDULE_PUBKEY = new PublicKey('SysvarEpochSchedu1e111111111111111111111111');
3128
3404
  const SYSVAR_INSTRUCTIONS_PUBKEY = new PublicKey('Sysvar1nstructions1111111111111111111111111');
@@ -4568,24 +4844,26 @@ const LookupTableMetaLayout = {
4568
4844
  BufferLayout.seq(publicKey(), BufferLayout.offset(BufferLayout.u8(), -1), 'authority')])
4569
4845
  };
4570
4846
 
4571
- const URL = globalThis.URL;
4572
-
4847
+ const URL_RE = /^[^:]+:\/\/([^:[]+|\[[^\]]+\])(:\d+)?(.*)/i;
4573
4848
  function makeWebsocketUrl(endpoint) {
4574
- let url = new URL(endpoint);
4575
- const useHttps = url.protocol === 'https:';
4576
- url.protocol = useHttps ? 'wss:' : 'ws:';
4577
- url.host = ''; // Only shift the port by +1 as a convention for ws(s) only if given endpoint
4849
+ const matches = endpoint.match(URL_RE);
4850
+
4851
+ if (matches == null) {
4852
+ throw TypeError(`Failed to validate endpoint URL \`${endpoint}\``);
4853
+ }
4854
+
4855
+ const [_, // eslint-disable-line @typescript-eslint/no-unused-vars
4856
+ hostish, portWithColon, rest] = matches;
4857
+ const protocol = endpoint.startsWith('https:') ? 'wss:' : 'ws:';
4858
+ const startPort = portWithColon == null ? null : parseInt(portWithColon.slice(1), 10);
4859
+ const websocketPort = // Only shift the port by +1 as a convention for ws(s) only if given endpoint
4578
4860
  // is explictly specifying the endpoint port (HTTP-based RPC), assuming
4579
4861
  // we're directly trying to connect to solana-validator's ws listening port.
4580
4862
  // When the endpoint omits the port, we're connecting to the protocol
4581
4863
  // default ports: http(80) or https(443) and it's assumed we're behind a reverse
4582
4864
  // proxy which manages WebSocket upgrade and backend port redirection.
4583
-
4584
- if (url.port !== '') {
4585
- url.port = String(Number(url.port) + 1);
4586
- }
4587
-
4588
- return url.toString();
4865
+ startPort == null ? '' : `:${startPort + 1}`;
4866
+ return `${protocol}//${hostish}${websocketPort}${rest}`;
4589
4867
  }
4590
4868
 
4591
4869
  var _process$env$npm_pack;
@@ -4605,7 +4883,17 @@ const BLOCKHASH_CACHE_TIMEOUT_MS = 30 * 1000;
4605
4883
  * https://gist.github.com/steveluscher/c057eca81d479ef705cdb53162f9971d
4606
4884
  */
4607
4885
 
4886
+ /* @internal */
4887
+ function assertEndpointUrl(putativeUrl) {
4888
+ if (/^https?:/.test(putativeUrl) === false) {
4889
+ throw new TypeError('Endpoint URL must start with `http:` or `https:`.');
4890
+ }
4891
+
4892
+ return putativeUrl;
4893
+ }
4608
4894
  /** @internal */
4895
+
4896
+
4609
4897
  function extractCommitmentFromConfig(commitmentOrConfig) {
4610
4898
  let commitment;
4611
4899
  let config;
@@ -4800,12 +5088,14 @@ const BlockProductionResponseStruct = jsonRpcResultAndContext(type({
4800
5088
  * A performance sample
4801
5089
  */
4802
5090
 
4803
- function createRpcClient(url, useHttps, httpHeaders, customFetch, fetchMiddleware, disableRetryOnRateLimit) {
5091
+ function createRpcClient(url, httpHeaders, customFetch, fetchMiddleware, disableRetryOnRateLimit) {
4804
5092
  const fetch = customFetch ? customFetch : fetchImpl;
4805
5093
  let agentManager;
4806
5094
 
4807
5095
  {
4808
- agentManager = new AgentManager(useHttps);
5096
+ agentManager = new AgentManager(url.startsWith('https:')
5097
+ /* useHttps */
5098
+ );
4809
5099
  }
4810
5100
 
4811
5101
  let fetchWithMiddleware;
@@ -5612,8 +5902,6 @@ class Connection {
5612
5902
  this._subscriptionCallbacksByServerSubscriptionId = {};
5613
5903
  this._subscriptionsByHash = {};
5614
5904
  this._subscriptionsAutoDisposedByRpc = new Set();
5615
- let url = new URL(endpoint);
5616
- const useHttps = url.protocol === 'https:';
5617
5905
  let wsEndpoint;
5618
5906
  let httpHeaders;
5619
5907
  let fetch;
@@ -5632,9 +5920,9 @@ class Connection {
5632
5920
  disableRetryOnRateLimit = commitmentOrConfig.disableRetryOnRateLimit;
5633
5921
  }
5634
5922
 
5635
- this._rpcEndpoint = endpoint;
5923
+ this._rpcEndpoint = assertEndpointUrl(endpoint);
5636
5924
  this._rpcWsEndpoint = wsEndpoint || makeWebsocketUrl(endpoint);
5637
- this._rpcClient = createRpcClient(url.toString(), useHttps, httpHeaders, fetch, fetchMiddleware, disableRetryOnRateLimit);
5925
+ this._rpcClient = createRpcClient(endpoint, httpHeaders, fetch, fetchMiddleware, disableRetryOnRateLimit);
5638
5926
  this._rpcRequest = createRpcRequest(this._rpcClient);
5639
5927
  this._rpcBatchRequest = createRpcBatchRequest(this._rpcClient);
5640
5928
  this._rpcWebSocket = new Client(this._rpcWsEndpoint, {
@@ -10175,6 +10463,23 @@ class VoteProgram {
10175
10463
  data
10176
10464
  });
10177
10465
  }
10466
+ /**
10467
+ * Generate a transaction to withdraw safely from a Vote account.
10468
+ *
10469
+ * This function was created as a safeguard for vote accounts running validators, `safeWithdraw`
10470
+ * checks that the withdraw amount will not exceed the specified balance while leaving enough left
10471
+ * to cover rent. If you wish to close the vote account by withdrawing the full amount, call the
10472
+ * `withdraw` method directly.
10473
+ */
10474
+
10475
+
10476
+ static safeWithdraw(params, currentVoteAccountBalance, rentExemptMinimum) {
10477
+ if (params.lamports > currentVoteAccountBalance - rentExemptMinimum) {
10478
+ throw new Error('Withdraw will leave vote account with insuffcient funds.');
10479
+ }
10480
+
10481
+ return VoteProgram.withdraw(params);
10482
+ }
10178
10483
 
10179
10484
  }
10180
10485
  VoteProgram.programId = new PublicKey('Vote111111111111111111111111111111111111111');
@@ -10226,15 +10531,14 @@ class ValidatorInfo {
10226
10531
 
10227
10532
 
10228
10533
  static fromConfigData(buffer) {
10229
- const PUBKEY_LENGTH = 32;
10230
10534
  let byteArray = [...buffer];
10231
10535
  const configKeyCount = decodeLength(byteArray);
10232
10536
  if (configKeyCount !== 2) return null;
10233
10537
  const configKeys = [];
10234
10538
 
10235
10539
  for (let i = 0; i < 2; i++) {
10236
- const publicKey = new PublicKey(byteArray.slice(0, PUBKEY_LENGTH));
10237
- byteArray = byteArray.slice(PUBKEY_LENGTH);
10540
+ const publicKey = new PublicKey(byteArray.slice(0, PUBLIC_KEY_LENGTH));
10541
+ byteArray = byteArray.slice(PUBLIC_KEY_LENGTH);
10238
10542
  const isSigner = byteArray.slice(0, 1)[0] === 1;
10239
10543
  byteArray = byteArray.slice(1);
10240
10544
  configKeys.push({
@@ -10446,5 +10750,5 @@ async function sendAndConfirmRawTransaction(connection, rawTransaction, confirma
10446
10750
 
10447
10751
  const LAMPORTS_PER_SOL = 1000000000;
10448
10752
 
10449
- export { Account, AddressLookupTableAccount, AddressLookupTableInstruction, AddressLookupTableProgram, Authorized, BLOCKHASH_CACHE_TIMEOUT_MS, BPF_LOADER_DEPRECATED_PROGRAM_ID, BPF_LOADER_PROGRAM_ID, BpfLoader, COMPUTE_BUDGET_INSTRUCTION_LAYOUTS, ComputeBudgetInstruction, ComputeBudgetProgram, Connection, Ed25519Program, Enum, EpochSchedule, FeeCalculatorLayout, Keypair, LAMPORTS_PER_SOL, LOOKUP_TABLE_INSTRUCTION_LAYOUTS, Loader, Lockup, MAX_SEED_LENGTH, Message, NONCE_ACCOUNT_LENGTH, NonceAccount, PACKET_DATA_SIZE, PublicKey, SIGNATURE_LENGTH_IN_BYTES, SOLANA_SCHEMA, STAKE_CONFIG_ID, STAKE_INSTRUCTION_LAYOUTS, SYSTEM_INSTRUCTION_LAYOUTS, SYSVAR_CLOCK_PUBKEY, SYSVAR_EPOCH_SCHEDULE_PUBKEY, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_RECENT_BLOCKHASHES_PUBKEY, SYSVAR_RENT_PUBKEY, SYSVAR_REWARDS_PUBKEY, SYSVAR_SLOT_HASHES_PUBKEY, SYSVAR_SLOT_HISTORY_PUBKEY, SYSVAR_STAKE_HISTORY_PUBKEY, Secp256k1Program, SendTransactionError, SolanaJSONRPCError, SolanaJSONRPCErrorCode, StakeAuthorizationLayout, StakeInstruction, StakeProgram, Struct, SystemInstruction, SystemProgram, Transaction, TransactionExpiredBlockheightExceededError, TransactionExpiredTimeoutError, TransactionInstruction, TransactionStatus, VALIDATOR_INFO_KEY, VOTE_PROGRAM_ID, ValidatorInfo, VoteAccount, VoteAuthorizationLayout, VoteInit, VoteInstruction, VoteProgram, clusterApiUrl, sendAndConfirmRawTransaction, sendAndConfirmTransaction };
10753
+ export { Account, AddressLookupTableAccount, AddressLookupTableInstruction, AddressLookupTableProgram, Authorized, BLOCKHASH_CACHE_TIMEOUT_MS, BPF_LOADER_DEPRECATED_PROGRAM_ID, BPF_LOADER_PROGRAM_ID, BpfLoader, COMPUTE_BUDGET_INSTRUCTION_LAYOUTS, ComputeBudgetInstruction, ComputeBudgetProgram, Connection, Ed25519Program, Enum, EpochSchedule, FeeCalculatorLayout, Keypair, LAMPORTS_PER_SOL, LOOKUP_TABLE_INSTRUCTION_LAYOUTS, Loader, Lockup, MAX_SEED_LENGTH, Message, MessageV0, NONCE_ACCOUNT_LENGTH, NonceAccount, PACKET_DATA_SIZE, PUBLIC_KEY_LENGTH, PublicKey, SIGNATURE_LENGTH_IN_BYTES, SOLANA_SCHEMA, STAKE_CONFIG_ID, STAKE_INSTRUCTION_LAYOUTS, SYSTEM_INSTRUCTION_LAYOUTS, SYSVAR_CLOCK_PUBKEY, SYSVAR_EPOCH_SCHEDULE_PUBKEY, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_RECENT_BLOCKHASHES_PUBKEY, SYSVAR_RENT_PUBKEY, SYSVAR_REWARDS_PUBKEY, SYSVAR_SLOT_HASHES_PUBKEY, SYSVAR_SLOT_HISTORY_PUBKEY, SYSVAR_STAKE_HISTORY_PUBKEY, Secp256k1Program, SendTransactionError, SolanaJSONRPCError, SolanaJSONRPCErrorCode, StakeAuthorizationLayout, StakeInstruction, StakeProgram, Struct, SystemInstruction, SystemProgram, Transaction, TransactionExpiredBlockheightExceededError, TransactionExpiredTimeoutError, TransactionInstruction, TransactionStatus, VALIDATOR_INFO_KEY, VERSION_PREFIX_MASK, VOTE_PROGRAM_ID, ValidatorInfo, VersionedMessage, VersionedTransaction, VoteAccount, VoteAuthorizationLayout, VoteInit, VoteInstruction, VoteProgram, clusterApiUrl, sendAndConfirmRawTransaction, sendAndConfirmTransaction };
10450
10754
  //# sourceMappingURL=index.esm.js.map