@solana/web3.js 1.78.3 → 2.0.0-experimental.0108bc7

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.
Files changed (106) hide show
  1. package/README.md +56 -112
  2. package/dist/index.browser.cjs +172 -0
  3. package/dist/index.browser.cjs.map +1 -0
  4. package/dist/index.browser.js +139 -0
  5. package/dist/index.browser.js.map +1 -0
  6. package/dist/index.development.js +2287 -0
  7. package/dist/index.development.js.map +1 -0
  8. package/dist/index.native.js +141 -0
  9. package/dist/index.native.js.map +1 -0
  10. package/dist/index.node.cjs +172 -0
  11. package/dist/index.node.cjs.map +1 -0
  12. package/dist/index.node.js +141 -0
  13. package/dist/index.node.js.map +1 -0
  14. package/dist/index.production.min.js +42 -0
  15. package/dist/types/index.d.ts +7 -0
  16. package/dist/types/index.d.ts.map +1 -0
  17. package/dist/types/rpc-default-config.d.ts +3 -0
  18. package/dist/types/rpc-default-config.d.ts.map +1 -0
  19. package/dist/types/rpc-integer-overflow-error.d.ts +8 -0
  20. package/dist/types/rpc-integer-overflow-error.d.ts.map +1 -0
  21. package/dist/types/rpc-request-coalescer.d.ts +5 -0
  22. package/dist/types/rpc-request-coalescer.d.ts.map +1 -0
  23. package/dist/types/rpc-request-deduplication.d.ts +2 -0
  24. package/dist/types/rpc-request-deduplication.d.ts.map +1 -0
  25. package/dist/types/rpc-transport.d.ts +4 -0
  26. package/dist/types/rpc-transport.d.ts.map +1 -0
  27. package/dist/types/rpc.d.ts +5 -0
  28. package/dist/types/rpc.d.ts.map +1 -0
  29. package/package.json +83 -110
  30. package/lib/index.browser.cjs.js +0 -13599
  31. package/lib/index.browser.cjs.js.map +0 -1
  32. package/lib/index.browser.esm.js +0 -13482
  33. package/lib/index.browser.esm.js.map +0 -1
  34. package/lib/index.cjs.js +0 -15910
  35. package/lib/index.cjs.js.map +0 -1
  36. package/lib/index.d.ts +0 -3947
  37. package/lib/index.esm.js +0 -15787
  38. package/lib/index.esm.js.map +0 -1
  39. package/lib/index.iife.js +0 -30621
  40. package/lib/index.iife.js.map +0 -1
  41. package/lib/index.iife.min.js +0 -20
  42. package/lib/index.iife.min.js.map +0 -1
  43. package/lib/index.native.js +0 -13599
  44. package/lib/index.native.js.map +0 -1
  45. package/src/__forks__/browser/fetch-impl.ts +0 -4
  46. package/src/__forks__/browser/rpc-websocket-factory.ts +0 -1
  47. package/src/__forks__/react-native/fetch-impl.ts +0 -4
  48. package/src/__forks__/react-native/rpc-websocket-factory.ts +0 -1
  49. package/src/account-data.ts +0 -39
  50. package/src/account.ts +0 -55
  51. package/src/blockhash.ts +0 -4
  52. package/src/bpf-loader-deprecated.ts +0 -5
  53. package/src/bpf-loader.ts +0 -45
  54. package/src/connection.ts +0 -6796
  55. package/src/epoch-schedule.ts +0 -102
  56. package/src/errors.ts +0 -50
  57. package/src/fee-calculator.ts +0 -18
  58. package/src/fetch-impl.ts +0 -16
  59. package/src/index.ts +0 -24
  60. package/src/instruction.ts +0 -58
  61. package/src/keypair.ts +0 -102
  62. package/src/layout.ts +0 -188
  63. package/src/loader.ts +0 -267
  64. package/src/message/account-keys.ts +0 -79
  65. package/src/message/compiled-keys.ts +0 -165
  66. package/src/message/index.ts +0 -47
  67. package/src/message/legacy.ts +0 -326
  68. package/src/message/v0.ts +0 -496
  69. package/src/message/versioned.ts +0 -36
  70. package/src/nonce-account.ts +0 -82
  71. package/src/programs/address-lookup-table/index.ts +0 -435
  72. package/src/programs/address-lookup-table/state.ts +0 -84
  73. package/src/programs/compute-budget.ts +0 -281
  74. package/src/programs/ed25519.ts +0 -157
  75. package/src/programs/index.ts +0 -7
  76. package/src/programs/secp256k1.ts +0 -228
  77. package/src/programs/stake.ts +0 -935
  78. package/src/programs/system.ts +0 -1048
  79. package/src/programs/vote.ts +0 -543
  80. package/src/publickey.ts +0 -259
  81. package/src/rpc-websocket-factory.ts +0 -4
  82. package/src/rpc-websocket.ts +0 -79
  83. package/src/sysvar.ts +0 -37
  84. package/src/timing.ts +0 -23
  85. package/src/transaction/constants.ts +0 -12
  86. package/src/transaction/expiry-custom-errors.ts +0 -48
  87. package/src/transaction/index.ts +0 -5
  88. package/src/transaction/legacy.ts +0 -948
  89. package/src/transaction/message.ts +0 -140
  90. package/src/transaction/versioned.ts +0 -126
  91. package/src/utils/assert.ts +0 -8
  92. package/src/utils/bigint.ts +0 -43
  93. package/src/utils/borsh-schema.ts +0 -38
  94. package/src/utils/cluster.ts +0 -35
  95. package/src/utils/ed25519.ts +0 -43
  96. package/src/utils/index.ts +0 -5
  97. package/src/utils/makeWebsocketUrl.ts +0 -26
  98. package/src/utils/promise-timeout.ts +0 -14
  99. package/src/utils/secp256k1.ts +0 -11
  100. package/src/utils/send-and-confirm-raw-transaction.ts +0 -102
  101. package/src/utils/send-and-confirm-transaction.ts +0 -98
  102. package/src/utils/shortvec-encoding.ts +0 -28
  103. package/src/utils/sleep.ts +0 -4
  104. package/src/utils/to-buffer.ts +0 -11
  105. package/src/validator-info.ts +0 -104
  106. package/src/vote-account.ts +0 -236
@@ -1,948 +0,0 @@
1
- import bs58 from 'bs58';
2
- import {Buffer} from 'buffer';
3
-
4
- import {PACKET_DATA_SIZE, SIGNATURE_LENGTH_IN_BYTES} from './constants';
5
- import {Connection} from '../connection';
6
- import {Message} from '../message';
7
- import {PublicKey} from '../publickey';
8
- import * as shortvec from '../utils/shortvec-encoding';
9
- import {toBuffer} from '../utils/to-buffer';
10
- import invariant from '../utils/assert';
11
- import type {Signer} from '../keypair';
12
- import type {Blockhash} from '../blockhash';
13
- import type {CompiledInstruction} from '../message';
14
- import {sign, verify} from '../utils/ed25519';
15
-
16
- /**
17
- * Transaction signature as base-58 encoded string
18
- */
19
- export type TransactionSignature = string;
20
-
21
- export const enum TransactionStatus {
22
- BLOCKHEIGHT_EXCEEDED,
23
- PROCESSED,
24
- TIMED_OUT,
25
- NONCE_INVALID,
26
- }
27
-
28
- /**
29
- * Default (empty) signature
30
- */
31
- const DEFAULT_SIGNATURE = Buffer.alloc(SIGNATURE_LENGTH_IN_BYTES).fill(0);
32
-
33
- /**
34
- * Account metadata used to define instructions
35
- */
36
- export type AccountMeta = {
37
- /** An account's public key */
38
- pubkey: PublicKey;
39
- /** True if an instruction requires a transaction signature matching `pubkey` */
40
- isSigner: boolean;
41
- /** True if the `pubkey` can be loaded as a read-write account. */
42
- isWritable: boolean;
43
- };
44
-
45
- /**
46
- * List of TransactionInstruction object fields that may be initialized at construction
47
- */
48
- export type TransactionInstructionCtorFields = {
49
- keys: Array<AccountMeta>;
50
- programId: PublicKey;
51
- data?: Buffer;
52
- };
53
-
54
- /**
55
- * Configuration object for Transaction.serialize()
56
- */
57
- export type SerializeConfig = {
58
- /** Require all transaction signatures be present (default: true) */
59
- requireAllSignatures?: boolean;
60
- /** Verify provided signatures (default: true) */
61
- verifySignatures?: boolean;
62
- };
63
-
64
- /**
65
- * @internal
66
- */
67
- export interface TransactionInstructionJSON {
68
- keys: {
69
- pubkey: string;
70
- isSigner: boolean;
71
- isWritable: boolean;
72
- }[];
73
- programId: string;
74
- data: number[];
75
- }
76
-
77
- /**
78
- * Transaction Instruction class
79
- */
80
- export class TransactionInstruction {
81
- /**
82
- * Public keys to include in this transaction
83
- * Boolean represents whether this pubkey needs to sign the transaction
84
- */
85
- keys: Array<AccountMeta>;
86
-
87
- /**
88
- * Program Id to execute
89
- */
90
- programId: PublicKey;
91
-
92
- /**
93
- * Program input
94
- */
95
- data: Buffer = Buffer.alloc(0);
96
-
97
- constructor(opts: TransactionInstructionCtorFields) {
98
- this.programId = opts.programId;
99
- this.keys = opts.keys;
100
- if (opts.data) {
101
- this.data = opts.data;
102
- }
103
- }
104
-
105
- /**
106
- * @internal
107
- */
108
- toJSON(): TransactionInstructionJSON {
109
- return {
110
- keys: this.keys.map(({pubkey, isSigner, isWritable}) => ({
111
- pubkey: pubkey.toJSON(),
112
- isSigner,
113
- isWritable,
114
- })),
115
- programId: this.programId.toJSON(),
116
- data: [...this.data],
117
- };
118
- }
119
- }
120
-
121
- /**
122
- * Pair of signature and corresponding public key
123
- */
124
- export type SignaturePubkeyPair = {
125
- signature: Buffer | null;
126
- publicKey: PublicKey;
127
- };
128
-
129
- /**
130
- * List of Transaction object fields that may be initialized at construction
131
- */
132
- export type TransactionCtorFields_DEPRECATED = {
133
- /** Optional nonce information used for offline nonce'd transactions */
134
- nonceInfo?: NonceInformation | null;
135
- /** The transaction fee payer */
136
- feePayer?: PublicKey | null;
137
- /** One or more signatures */
138
- signatures?: Array<SignaturePubkeyPair>;
139
- /** A recent blockhash */
140
- recentBlockhash?: Blockhash;
141
- };
142
-
143
- // For backward compatibility; an unfortunate consequence of being
144
- // forced to over-export types by the documentation generator.
145
- // See https://github.com/solana-labs/solana/pull/25820
146
- export type TransactionCtorFields = TransactionCtorFields_DEPRECATED;
147
-
148
- /**
149
- * Blockhash-based transactions have a lifetime that are defined by
150
- * the blockhash they include. Any transaction whose blockhash is
151
- * too old will be rejected.
152
- */
153
- export type TransactionBlockhashCtor = {
154
- /** The transaction fee payer */
155
- feePayer?: PublicKey | null;
156
- /** One or more signatures */
157
- signatures?: Array<SignaturePubkeyPair>;
158
- /** A recent blockhash */
159
- blockhash: Blockhash;
160
- /** the last block chain can advance to before tx is declared expired */
161
- lastValidBlockHeight: number;
162
- };
163
-
164
- /**
165
- * Use these options to construct a durable nonce transaction.
166
- */
167
- export type TransactionNonceCtor = {
168
- /** The transaction fee payer */
169
- feePayer?: PublicKey | null;
170
- minContextSlot: number;
171
- nonceInfo: NonceInformation;
172
- /** One or more signatures */
173
- signatures?: Array<SignaturePubkeyPair>;
174
- };
175
-
176
- /**
177
- * Nonce information to be used to build an offline Transaction.
178
- */
179
- export type NonceInformation = {
180
- /** The current blockhash stored in the nonce */
181
- nonce: Blockhash;
182
- /** AdvanceNonceAccount Instruction */
183
- nonceInstruction: TransactionInstruction;
184
- };
185
-
186
- /**
187
- * @internal
188
- */
189
- export interface TransactionJSON {
190
- recentBlockhash: string | null;
191
- feePayer: string | null;
192
- nonceInfo: {
193
- nonce: string;
194
- nonceInstruction: TransactionInstructionJSON;
195
- } | null;
196
- instructions: TransactionInstructionJSON[];
197
- signers: string[];
198
- }
199
-
200
- /**
201
- * Transaction class
202
- */
203
- export class Transaction {
204
- /**
205
- * Signatures for the transaction. Typically created by invoking the
206
- * `sign()` method
207
- */
208
- signatures: Array<SignaturePubkeyPair> = [];
209
-
210
- /**
211
- * The first (payer) Transaction signature
212
- *
213
- * @returns {Buffer | null} Buffer of payer's signature
214
- */
215
- get signature(): Buffer | null {
216
- if (this.signatures.length > 0) {
217
- return this.signatures[0].signature;
218
- }
219
- return null;
220
- }
221
-
222
- /**
223
- * The transaction fee payer
224
- */
225
- feePayer?: PublicKey;
226
-
227
- /**
228
- * The instructions to atomically execute
229
- */
230
- instructions: Array<TransactionInstruction> = [];
231
-
232
- /**
233
- * A recent transaction id. Must be populated by the caller
234
- */
235
- recentBlockhash?: Blockhash;
236
-
237
- /**
238
- * the last block chain can advance to before tx is declared expired
239
- * */
240
- lastValidBlockHeight?: number;
241
-
242
- /**
243
- * Optional Nonce information. If populated, transaction will use a durable
244
- * Nonce hash instead of a recentBlockhash. Must be populated by the caller
245
- */
246
- nonceInfo?: NonceInformation;
247
-
248
- /**
249
- * If this is a nonce transaction this represents the minimum slot from which
250
- * to evaluate if the nonce has advanced when attempting to confirm the
251
- * transaction. This protects against a case where the transaction confirmation
252
- * logic loads the nonce account from an old slot and assumes the mismatch in
253
- * nonce value implies that the nonce has been advanced.
254
- */
255
- minNonceContextSlot?: number;
256
-
257
- /**
258
- * @internal
259
- */
260
- _message?: Message;
261
-
262
- /**
263
- * @internal
264
- */
265
- _json?: TransactionJSON;
266
-
267
- // Construct a transaction with a blockhash and lastValidBlockHeight
268
- constructor(opts?: TransactionBlockhashCtor);
269
-
270
- // Construct a transaction using a durable nonce
271
- constructor(opts?: TransactionNonceCtor);
272
-
273
- /**
274
- * @deprecated `TransactionCtorFields` has been deprecated and will be removed in a future version.
275
- * Please supply a `TransactionBlockhashCtor` instead.
276
- */
277
- constructor(opts?: TransactionCtorFields_DEPRECATED);
278
-
279
- /**
280
- * Construct an empty Transaction
281
- */
282
- constructor(
283
- opts?:
284
- | TransactionBlockhashCtor
285
- | TransactionNonceCtor
286
- | TransactionCtorFields_DEPRECATED,
287
- ) {
288
- if (!opts) {
289
- return;
290
- }
291
- if (opts.feePayer) {
292
- this.feePayer = opts.feePayer;
293
- }
294
- if (opts.signatures) {
295
- this.signatures = opts.signatures;
296
- }
297
- if (Object.prototype.hasOwnProperty.call(opts, 'nonceInfo')) {
298
- const {minContextSlot, nonceInfo} = opts as TransactionNonceCtor;
299
- this.minNonceContextSlot = minContextSlot;
300
- this.nonceInfo = nonceInfo;
301
- } else if (
302
- Object.prototype.hasOwnProperty.call(opts, 'lastValidBlockHeight')
303
- ) {
304
- const {blockhash, lastValidBlockHeight} =
305
- opts as TransactionBlockhashCtor;
306
- this.recentBlockhash = blockhash;
307
- this.lastValidBlockHeight = lastValidBlockHeight;
308
- } else {
309
- const {recentBlockhash, nonceInfo} =
310
- opts as TransactionCtorFields_DEPRECATED;
311
- if (nonceInfo) {
312
- this.nonceInfo = nonceInfo;
313
- }
314
- this.recentBlockhash = recentBlockhash;
315
- }
316
- }
317
-
318
- /**
319
- * @internal
320
- */
321
- toJSON(): TransactionJSON {
322
- return {
323
- recentBlockhash: this.recentBlockhash || null,
324
- feePayer: this.feePayer ? this.feePayer.toJSON() : null,
325
- nonceInfo: this.nonceInfo
326
- ? {
327
- nonce: this.nonceInfo.nonce,
328
- nonceInstruction: this.nonceInfo.nonceInstruction.toJSON(),
329
- }
330
- : null,
331
- instructions: this.instructions.map(instruction => instruction.toJSON()),
332
- signers: this.signatures.map(({publicKey}) => {
333
- return publicKey.toJSON();
334
- }),
335
- };
336
- }
337
-
338
- /**
339
- * Add one or more instructions to this Transaction
340
- *
341
- * @param {Array< Transaction | TransactionInstruction | TransactionInstructionCtorFields >} items - Instructions to add to the Transaction
342
- */
343
- add(
344
- ...items: Array<
345
- Transaction | TransactionInstruction | TransactionInstructionCtorFields
346
- >
347
- ): Transaction {
348
- if (items.length === 0) {
349
- throw new Error('No instructions');
350
- }
351
-
352
- items.forEach((item: any) => {
353
- if ('instructions' in item) {
354
- this.instructions = this.instructions.concat(item.instructions);
355
- } else if ('data' in item && 'programId' in item && 'keys' in item) {
356
- this.instructions.push(item);
357
- } else {
358
- this.instructions.push(new TransactionInstruction(item));
359
- }
360
- });
361
- return this;
362
- }
363
-
364
- /**
365
- * Compile transaction data
366
- */
367
- compileMessage(): Message {
368
- if (
369
- this._message &&
370
- JSON.stringify(this.toJSON()) === JSON.stringify(this._json)
371
- ) {
372
- return this._message;
373
- }
374
-
375
- let recentBlockhash;
376
- let instructions: TransactionInstruction[];
377
- if (this.nonceInfo) {
378
- recentBlockhash = this.nonceInfo.nonce;
379
- if (this.instructions[0] != this.nonceInfo.nonceInstruction) {
380
- instructions = [this.nonceInfo.nonceInstruction, ...this.instructions];
381
- } else {
382
- instructions = this.instructions;
383
- }
384
- } else {
385
- recentBlockhash = this.recentBlockhash;
386
- instructions = this.instructions;
387
- }
388
- if (!recentBlockhash) {
389
- throw new Error('Transaction recentBlockhash required');
390
- }
391
-
392
- if (instructions.length < 1) {
393
- console.warn('No instructions provided');
394
- }
395
-
396
- let feePayer: PublicKey;
397
- if (this.feePayer) {
398
- feePayer = this.feePayer;
399
- } else if (this.signatures.length > 0 && this.signatures[0].publicKey) {
400
- // Use implicit fee payer
401
- feePayer = this.signatures[0].publicKey;
402
- } else {
403
- throw new Error('Transaction fee payer required');
404
- }
405
-
406
- for (let i = 0; i < instructions.length; i++) {
407
- if (instructions[i].programId === undefined) {
408
- throw new Error(
409
- `Transaction instruction index ${i} has undefined program id`,
410
- );
411
- }
412
- }
413
-
414
- const programIds: string[] = [];
415
- const accountMetas: AccountMeta[] = [];
416
- instructions.forEach(instruction => {
417
- instruction.keys.forEach(accountMeta => {
418
- accountMetas.push({...accountMeta});
419
- });
420
-
421
- const programId = instruction.programId.toString();
422
- if (!programIds.includes(programId)) {
423
- programIds.push(programId);
424
- }
425
- });
426
-
427
- // Append programID account metas
428
- programIds.forEach(programId => {
429
- accountMetas.push({
430
- pubkey: new PublicKey(programId),
431
- isSigner: false,
432
- isWritable: false,
433
- });
434
- });
435
-
436
- // Cull duplicate account metas
437
- const uniqueMetas: AccountMeta[] = [];
438
- accountMetas.forEach(accountMeta => {
439
- const pubkeyString = accountMeta.pubkey.toString();
440
- const uniqueIndex = uniqueMetas.findIndex(x => {
441
- return x.pubkey.toString() === pubkeyString;
442
- });
443
- if (uniqueIndex > -1) {
444
- uniqueMetas[uniqueIndex].isWritable =
445
- uniqueMetas[uniqueIndex].isWritable || accountMeta.isWritable;
446
- uniqueMetas[uniqueIndex].isSigner =
447
- uniqueMetas[uniqueIndex].isSigner || accountMeta.isSigner;
448
- } else {
449
- uniqueMetas.push(accountMeta);
450
- }
451
- });
452
-
453
- // Sort. Prioritizing first by signer, then by writable
454
- uniqueMetas.sort(function (x, y) {
455
- if (x.isSigner !== y.isSigner) {
456
- // Signers always come before non-signers
457
- return x.isSigner ? -1 : 1;
458
- }
459
- if (x.isWritable !== y.isWritable) {
460
- // Writable accounts always come before read-only accounts
461
- return x.isWritable ? -1 : 1;
462
- }
463
- // Otherwise, sort by pubkey, stringwise.
464
- const options = {
465
- localeMatcher: 'best fit',
466
- usage: 'sort',
467
- sensitivity: 'variant',
468
- ignorePunctuation: false,
469
- numeric: false,
470
- caseFirst: 'lower',
471
- } as Intl.CollatorOptions;
472
- return x.pubkey
473
- .toBase58()
474
- .localeCompare(y.pubkey.toBase58(), 'en', options);
475
- });
476
-
477
- // Move fee payer to the front
478
- const feePayerIndex = uniqueMetas.findIndex(x => {
479
- return x.pubkey.equals(feePayer);
480
- });
481
- if (feePayerIndex > -1) {
482
- const [payerMeta] = uniqueMetas.splice(feePayerIndex, 1);
483
- payerMeta.isSigner = true;
484
- payerMeta.isWritable = true;
485
- uniqueMetas.unshift(payerMeta);
486
- } else {
487
- uniqueMetas.unshift({
488
- pubkey: feePayer,
489
- isSigner: true,
490
- isWritable: true,
491
- });
492
- }
493
-
494
- // Disallow unknown signers
495
- for (const signature of this.signatures) {
496
- const uniqueIndex = uniqueMetas.findIndex(x => {
497
- return x.pubkey.equals(signature.publicKey);
498
- });
499
- if (uniqueIndex > -1) {
500
- if (!uniqueMetas[uniqueIndex].isSigner) {
501
- uniqueMetas[uniqueIndex].isSigner = true;
502
- console.warn(
503
- 'Transaction references a signature that is unnecessary, ' +
504
- 'only the fee payer and instruction signer accounts should sign a transaction. ' +
505
- 'This behavior is deprecated and will throw an error in the next major version release.',
506
- );
507
- }
508
- } else {
509
- throw new Error(`unknown signer: ${signature.publicKey.toString()}`);
510
- }
511
- }
512
-
513
- let numRequiredSignatures = 0;
514
- let numReadonlySignedAccounts = 0;
515
- let numReadonlyUnsignedAccounts = 0;
516
-
517
- // Split out signing from non-signing keys and count header values
518
- const signedKeys: string[] = [];
519
- const unsignedKeys: string[] = [];
520
- uniqueMetas.forEach(({pubkey, isSigner, isWritable}) => {
521
- if (isSigner) {
522
- signedKeys.push(pubkey.toString());
523
- numRequiredSignatures += 1;
524
- if (!isWritable) {
525
- numReadonlySignedAccounts += 1;
526
- }
527
- } else {
528
- unsignedKeys.push(pubkey.toString());
529
- if (!isWritable) {
530
- numReadonlyUnsignedAccounts += 1;
531
- }
532
- }
533
- });
534
-
535
- const accountKeys = signedKeys.concat(unsignedKeys);
536
- const compiledInstructions: CompiledInstruction[] = instructions.map(
537
- instruction => {
538
- const {data, programId} = instruction;
539
- return {
540
- programIdIndex: accountKeys.indexOf(programId.toString()),
541
- accounts: instruction.keys.map(meta =>
542
- accountKeys.indexOf(meta.pubkey.toString()),
543
- ),
544
- data: bs58.encode(data),
545
- };
546
- },
547
- );
548
-
549
- compiledInstructions.forEach(instruction => {
550
- invariant(instruction.programIdIndex >= 0);
551
- instruction.accounts.forEach(keyIndex => invariant(keyIndex >= 0));
552
- });
553
-
554
- return new Message({
555
- header: {
556
- numRequiredSignatures,
557
- numReadonlySignedAccounts,
558
- numReadonlyUnsignedAccounts,
559
- },
560
- accountKeys,
561
- recentBlockhash,
562
- instructions: compiledInstructions,
563
- });
564
- }
565
-
566
- /**
567
- * @internal
568
- */
569
- _compile(): Message {
570
- const message = this.compileMessage();
571
- const signedKeys = message.accountKeys.slice(
572
- 0,
573
- message.header.numRequiredSignatures,
574
- );
575
-
576
- if (this.signatures.length === signedKeys.length) {
577
- const valid = this.signatures.every((pair, index) => {
578
- return signedKeys[index].equals(pair.publicKey);
579
- });
580
-
581
- if (valid) return message;
582
- }
583
-
584
- this.signatures = signedKeys.map(publicKey => ({
585
- signature: null,
586
- publicKey,
587
- }));
588
-
589
- return message;
590
- }
591
-
592
- /**
593
- * Get a buffer of the Transaction data that need to be covered by signatures
594
- */
595
- serializeMessage(): Buffer {
596
- return this._compile().serialize();
597
- }
598
-
599
- /**
600
- * Get the estimated fee associated with a transaction
601
- *
602
- * @param {Connection} connection Connection to RPC Endpoint.
603
- *
604
- * @returns {Promise<number | null>} The estimated fee for the transaction
605
- */
606
- async getEstimatedFee(connection: Connection): Promise<number | null> {
607
- return (await connection.getFeeForMessage(this.compileMessage())).value;
608
- }
609
-
610
- /**
611
- * Specify the public keys which will be used to sign the Transaction.
612
- * The first signer will be used as the transaction fee payer account.
613
- *
614
- * Signatures can be added with either `partialSign` or `addSignature`
615
- *
616
- * @deprecated Deprecated since v0.84.0. Only the fee payer needs to be
617
- * specified and it can be set in the Transaction constructor or with the
618
- * `feePayer` property.
619
- */
620
- setSigners(...signers: Array<PublicKey>) {
621
- if (signers.length === 0) {
622
- throw new Error('No signers');
623
- }
624
-
625
- const seen = new Set();
626
- this.signatures = signers
627
- .filter(publicKey => {
628
- const key = publicKey.toString();
629
- if (seen.has(key)) {
630
- return false;
631
- } else {
632
- seen.add(key);
633
- return true;
634
- }
635
- })
636
- .map(publicKey => ({signature: null, publicKey}));
637
- }
638
-
639
- /**
640
- * Sign the Transaction with the specified signers. Multiple signatures may
641
- * be applied to a Transaction. The first signature is considered "primary"
642
- * and is used identify and confirm transactions.
643
- *
644
- * If the Transaction `feePayer` is not set, the first signer will be used
645
- * as the transaction fee payer account.
646
- *
647
- * Transaction fields should not be modified after the first call to `sign`,
648
- * as doing so may invalidate the signature and cause the Transaction to be
649
- * rejected.
650
- *
651
- * The Transaction must be assigned a valid `recentBlockhash` before invoking this method
652
- *
653
- * @param {Array<Signer>} signers Array of signers that will sign the transaction
654
- */
655
- sign(...signers: Array<Signer>) {
656
- if (signers.length === 0) {
657
- throw new Error('No signers');
658
- }
659
-
660
- // Dedupe signers
661
- const seen = new Set();
662
- const uniqueSigners = [];
663
- for (const signer of signers) {
664
- const key = signer.publicKey.toString();
665
- if (seen.has(key)) {
666
- continue;
667
- } else {
668
- seen.add(key);
669
- uniqueSigners.push(signer);
670
- }
671
- }
672
-
673
- this.signatures = uniqueSigners.map(signer => ({
674
- signature: null,
675
- publicKey: signer.publicKey,
676
- }));
677
-
678
- const message = this._compile();
679
- this._partialSign(message, ...uniqueSigners);
680
- }
681
-
682
- /**
683
- * Partially sign a transaction with the specified accounts. All accounts must
684
- * correspond to either the fee payer or a signer account in the transaction
685
- * instructions.
686
- *
687
- * All the caveats from the `sign` method apply to `partialSign`
688
- *
689
- * @param {Array<Signer>} signers Array of signers that will sign the transaction
690
- */
691
- partialSign(...signers: Array<Signer>) {
692
- if (signers.length === 0) {
693
- throw new Error('No signers');
694
- }
695
-
696
- // Dedupe signers
697
- const seen = new Set();
698
- const uniqueSigners = [];
699
- for (const signer of signers) {
700
- const key = signer.publicKey.toString();
701
- if (seen.has(key)) {
702
- continue;
703
- } else {
704
- seen.add(key);
705
- uniqueSigners.push(signer);
706
- }
707
- }
708
-
709
- const message = this._compile();
710
- this._partialSign(message, ...uniqueSigners);
711
- }
712
-
713
- /**
714
- * @internal
715
- */
716
- _partialSign(message: Message, ...signers: Array<Signer>) {
717
- const signData = message.serialize();
718
- signers.forEach(signer => {
719
- const signature = sign(signData, signer.secretKey);
720
- this._addSignature(signer.publicKey, toBuffer(signature));
721
- });
722
- }
723
-
724
- /**
725
- * Add an externally created signature to a transaction. The public key
726
- * must correspond to either the fee payer or a signer account in the transaction
727
- * instructions.
728
- *
729
- * @param {PublicKey} pubkey Public key that will be added to the transaction.
730
- * @param {Buffer} signature An externally created signature to add to the transaction.
731
- */
732
- addSignature(pubkey: PublicKey, signature: Buffer) {
733
- this._compile(); // Ensure signatures array is populated
734
- this._addSignature(pubkey, signature);
735
- }
736
-
737
- /**
738
- * @internal
739
- */
740
- _addSignature(pubkey: PublicKey, signature: Buffer) {
741
- invariant(signature.length === 64);
742
-
743
- const index = this.signatures.findIndex(sigpair =>
744
- pubkey.equals(sigpair.publicKey),
745
- );
746
- if (index < 0) {
747
- throw new Error(`unknown signer: ${pubkey.toString()}`);
748
- }
749
-
750
- this.signatures[index].signature = Buffer.from(signature);
751
- }
752
-
753
- /**
754
- * Verify signatures of a Transaction
755
- * Optional parameter specifies if we're expecting a fully signed Transaction or a partially signed one.
756
- * If no boolean is provided, we expect a fully signed Transaction by default.
757
- *
758
- * @param {boolean} [requireAllSignatures=true] Require a fully signed Transaction
759
- */
760
- verifySignatures(requireAllSignatures?: boolean): boolean {
761
- return this._verifySignatures(
762
- this.serializeMessage(),
763
- requireAllSignatures === undefined ? true : requireAllSignatures,
764
- );
765
- }
766
-
767
- /**
768
- * @internal
769
- */
770
- _verifySignatures(
771
- signData: Uint8Array,
772
- requireAllSignatures: boolean,
773
- ): boolean {
774
- for (const {signature, publicKey} of this.signatures) {
775
- if (signature === null) {
776
- if (requireAllSignatures) {
777
- return false;
778
- }
779
- } else {
780
- if (!verify(signature, signData, publicKey.toBytes())) {
781
- return false;
782
- }
783
- }
784
- }
785
- return true;
786
- }
787
-
788
- /**
789
- * Serialize the Transaction in the wire format.
790
- *
791
- * @param {Buffer} [config] Config of transaction.
792
- *
793
- * @returns {Buffer} Signature of transaction in wire format.
794
- */
795
- serialize(config?: SerializeConfig): Buffer {
796
- const {requireAllSignatures, verifySignatures} = Object.assign(
797
- {requireAllSignatures: true, verifySignatures: true},
798
- config,
799
- );
800
-
801
- const signData = this.serializeMessage();
802
- if (
803
- verifySignatures &&
804
- !this._verifySignatures(signData, requireAllSignatures)
805
- ) {
806
- throw new Error('Signature verification failed');
807
- }
808
-
809
- return this._serialize(signData);
810
- }
811
-
812
- /**
813
- * @internal
814
- */
815
- _serialize(signData: Buffer): Buffer {
816
- const {signatures} = this;
817
- const signatureCount: number[] = [];
818
- shortvec.encodeLength(signatureCount, signatures.length);
819
- const transactionLength =
820
- signatureCount.length + signatures.length * 64 + signData.length;
821
- const wireTransaction = Buffer.alloc(transactionLength);
822
- invariant(signatures.length < 256);
823
- Buffer.from(signatureCount).copy(wireTransaction, 0);
824
- signatures.forEach(({signature}, index) => {
825
- if (signature !== null) {
826
- invariant(signature.length === 64, `signature has invalid length`);
827
- Buffer.from(signature).copy(
828
- wireTransaction,
829
- signatureCount.length + index * 64,
830
- );
831
- }
832
- });
833
- signData.copy(
834
- wireTransaction,
835
- signatureCount.length + signatures.length * 64,
836
- );
837
- invariant(
838
- wireTransaction.length <= PACKET_DATA_SIZE,
839
- `Transaction too large: ${wireTransaction.length} > ${PACKET_DATA_SIZE}`,
840
- );
841
- return wireTransaction;
842
- }
843
-
844
- /**
845
- * Deprecated method
846
- * @internal
847
- */
848
- get keys(): Array<PublicKey> {
849
- invariant(this.instructions.length === 1);
850
- return this.instructions[0].keys.map(keyObj => keyObj.pubkey);
851
- }
852
-
853
- /**
854
- * Deprecated method
855
- * @internal
856
- */
857
- get programId(): PublicKey {
858
- invariant(this.instructions.length === 1);
859
- return this.instructions[0].programId;
860
- }
861
-
862
- /**
863
- * Deprecated method
864
- * @internal
865
- */
866
- get data(): Buffer {
867
- invariant(this.instructions.length === 1);
868
- return this.instructions[0].data;
869
- }
870
-
871
- /**
872
- * Parse a wire transaction into a Transaction object.
873
- *
874
- * @param {Buffer | Uint8Array | Array<number>} buffer Signature of wire Transaction
875
- *
876
- * @returns {Transaction} Transaction associated with the signature
877
- */
878
- static from(buffer: Buffer | Uint8Array | Array<number>): Transaction {
879
- // Slice up wire data
880
- let byteArray = [...buffer];
881
-
882
- const signatureCount = shortvec.decodeLength(byteArray);
883
- let signatures = [];
884
- for (let i = 0; i < signatureCount; i++) {
885
- const signature = byteArray.slice(0, SIGNATURE_LENGTH_IN_BYTES);
886
- byteArray = byteArray.slice(SIGNATURE_LENGTH_IN_BYTES);
887
- signatures.push(bs58.encode(Buffer.from(signature)));
888
- }
889
-
890
- return Transaction.populate(Message.from(byteArray), signatures);
891
- }
892
-
893
- /**
894
- * Populate Transaction object from message and signatures
895
- *
896
- * @param {Message} message Message of transaction
897
- * @param {Array<string>} signatures List of signatures to assign to the transaction
898
- *
899
- * @returns {Transaction} The populated Transaction
900
- */
901
- static populate(
902
- message: Message,
903
- signatures: Array<string> = [],
904
- ): Transaction {
905
- const transaction = new Transaction();
906
- transaction.recentBlockhash = message.recentBlockhash;
907
- if (message.header.numRequiredSignatures > 0) {
908
- transaction.feePayer = message.accountKeys[0];
909
- }
910
- signatures.forEach((signature, index) => {
911
- const sigPubkeyPair = {
912
- signature:
913
- signature == bs58.encode(DEFAULT_SIGNATURE)
914
- ? null
915
- : bs58.decode(signature),
916
- publicKey: message.accountKeys[index],
917
- };
918
- transaction.signatures.push(sigPubkeyPair);
919
- });
920
-
921
- message.instructions.forEach(instruction => {
922
- const keys = instruction.accounts.map(account => {
923
- const pubkey = message.accountKeys[account];
924
- return {
925
- pubkey,
926
- isSigner:
927
- transaction.signatures.some(
928
- keyObj => keyObj.publicKey.toString() === pubkey.toString(),
929
- ) || message.isAccountSigner(account),
930
- isWritable: message.isAccountWritable(account),
931
- };
932
- });
933
-
934
- transaction.instructions.push(
935
- new TransactionInstruction({
936
- keys,
937
- programId: message.accountKeys[instruction.programIdIndex],
938
- data: bs58.decode(instruction.data),
939
- }),
940
- );
941
- });
942
-
943
- transaction._message = message;
944
- transaction._json = transaction.toJSON();
945
-
946
- return transaction;
947
- }
948
- }