@solana/transactions 2.0.0-experimental.ffeddf6 → 2.0.0-preview.1

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 (69) hide show
  1. package/README.md +8 -46
  2. package/dist/index.browser.cjs +360 -470
  3. package/dist/index.browser.cjs.map +1 -1
  4. package/dist/index.browser.js +355 -470
  5. package/dist/index.browser.js.map +1 -1
  6. package/dist/index.native.js +353 -470
  7. package/dist/index.native.js.map +1 -1
  8. package/dist/index.node.cjs +360 -470
  9. package/dist/index.node.cjs.map +1 -1
  10. package/dist/index.node.js +353 -470
  11. package/dist/index.node.js.map +1 -1
  12. package/dist/types/accounts.d.ts +3 -3
  13. package/dist/types/accounts.d.ts.map +1 -0
  14. package/dist/types/blockhash.d.ts +7 -9
  15. package/dist/types/blockhash.d.ts.map +1 -0
  16. package/dist/types/compilable-transaction.d.ts +6 -5
  17. package/dist/types/compilable-transaction.d.ts.map +1 -0
  18. package/dist/types/compile-address-table-lookups.d.ts +3 -3
  19. package/dist/types/compile-address-table-lookups.d.ts.map +1 -0
  20. package/dist/types/compile-header.d.ts +1 -1
  21. package/dist/types/compile-header.d.ts.map +1 -0
  22. package/dist/types/compile-instructions.d.ts +1 -1
  23. package/dist/types/compile-instructions.d.ts.map +1 -0
  24. package/dist/types/compile-lifetime-token.d.ts +2 -2
  25. package/dist/types/compile-lifetime-token.d.ts.map +1 -0
  26. package/dist/types/compile-static-accounts.d.ts +3 -3
  27. package/dist/types/compile-static-accounts.d.ts.map +1 -0
  28. package/dist/types/compile-transaction.d.ts +5 -5
  29. package/dist/types/compile-transaction.d.ts.map +1 -0
  30. package/dist/types/create-transaction.d.ts +1 -1
  31. package/dist/types/create-transaction.d.ts.map +1 -0
  32. package/dist/types/decompile-transaction.d.ts +12 -4
  33. package/dist/types/decompile-transaction.d.ts.map +1 -0
  34. package/dist/types/durable-nonce.d.ts +6 -6
  35. package/dist/types/durable-nonce.d.ts.map +1 -0
  36. package/dist/types/fee-payer.d.ts +6 -6
  37. package/dist/types/fee-payer.d.ts.map +1 -0
  38. package/dist/types/index.d.ts +13 -10
  39. package/dist/types/index.d.ts.map +1 -0
  40. package/dist/types/instructions.d.ts +6 -4
  41. package/dist/types/instructions.d.ts.map +1 -0
  42. package/dist/types/message.d.ts +6 -6
  43. package/dist/types/message.d.ts.map +1 -0
  44. package/dist/types/serializers/address-table-lookup.d.ts +5 -5
  45. package/dist/types/serializers/address-table-lookup.d.ts.map +1 -0
  46. package/dist/types/serializers/header.d.ts +5 -5
  47. package/dist/types/serializers/header.d.ts.map +1 -0
  48. package/dist/types/serializers/index.d.ts +2 -1
  49. package/dist/types/serializers/index.d.ts.map +1 -0
  50. package/dist/types/serializers/instruction.d.ts +5 -5
  51. package/dist/types/serializers/instruction.d.ts.map +1 -0
  52. package/dist/types/serializers/message.d.ts +5 -5
  53. package/dist/types/serializers/message.d.ts.map +1 -0
  54. package/dist/types/serializers/transaction-version.d.ts +5 -5
  55. package/dist/types/serializers/transaction-version.d.ts.map +1 -0
  56. package/dist/types/serializers/transaction.d.ts +9 -6
  57. package/dist/types/serializers/transaction.d.ts.map +1 -0
  58. package/dist/types/signatures.d.ts +9 -14
  59. package/dist/types/signatures.d.ts.map +1 -0
  60. package/dist/types/types.d.ts +6 -13
  61. package/dist/types/types.d.ts.map +1 -0
  62. package/dist/types/unsigned-transaction.d.ts +2 -2
  63. package/dist/types/unsigned-transaction.d.ts.map +1 -0
  64. package/dist/types/wire-transaction.d.ts +1 -1
  65. package/dist/types/wire-transaction.d.ts.map +1 -0
  66. package/package.json +18 -39
  67. package/dist/index.development.js +0 -1778
  68. package/dist/index.development.js.map +0 -1
  69. package/dist/index.production.min.js +0 -29
@@ -1,15 +1,36 @@
1
1
  'use strict';
2
2
 
3
+ var errors = require('@solana/errors');
3
4
  var codecsStrings = require('@solana/codecs-strings');
5
+ var addresses = require('@solana/addresses');
6
+ var functional = require('@solana/functional');
4
7
  var codecsCore = require('@solana/codecs-core');
5
8
  var codecsDataStructures = require('@solana/codecs-data-structures');
6
9
  var codecsNumbers = require('@solana/codecs-numbers');
7
- var addresses = require('@solana/addresses');
8
- var functional = require('@solana/functional');
9
10
  var keys = require('@solana/keys');
10
11
 
11
- // ../build-scripts/env-shim.ts
12
- var __DEV__ = /* @__PURE__ */ (() => process["env"].NODE_ENV === "development")();
12
+ // src/blockhash.ts
13
+ var base58Encoder;
14
+ function assertIsBlockhash(putativeBlockhash) {
15
+ if (!base58Encoder)
16
+ base58Encoder = codecsStrings.getBase58Encoder();
17
+ if (
18
+ // Lowest value (32 bytes of zeroes)
19
+ putativeBlockhash.length < 32 || // Highest value (32 bytes of 255)
20
+ putativeBlockhash.length > 44
21
+ ) {
22
+ throw new errors.SolanaError(errors.SOLANA_ERROR__BLOCKHASH_STRING_LENGTH_OUT_OF_RANGE, {
23
+ actualLength: putativeBlockhash.length
24
+ });
25
+ }
26
+ const bytes = base58Encoder.encode(putativeBlockhash);
27
+ const numBytes = bytes.byteLength;
28
+ if (numBytes !== 32) {
29
+ throw new errors.SolanaError(errors.SOLANA_ERROR__INVALID_BLOCKHASH_BYTE_LENGTH, {
30
+ actualLength: numBytes
31
+ });
32
+ }
33
+ }
13
34
 
14
35
  // src/unsigned-transaction.ts
15
36
  function getUnsignedTransaction(transaction) {
@@ -26,27 +47,20 @@ function getUnsignedTransaction(transaction) {
26
47
  }
27
48
 
28
49
  // src/blockhash.ts
29
- var base58Encoder;
30
- function assertIsBlockhash(putativeBlockhash) {
31
- if (!base58Encoder)
32
- base58Encoder = codecsStrings.getBase58Encoder();
50
+ function isTransactionWithBlockhashLifetime(transaction) {
51
+ const lifetimeConstraintShapeMatches = "lifetimeConstraint" in transaction && typeof transaction.lifetimeConstraint.blockhash === "string" && typeof transaction.lifetimeConstraint.lastValidBlockHeight === "bigint";
52
+ if (!lifetimeConstraintShapeMatches)
53
+ return false;
33
54
  try {
34
- if (
35
- // Lowest value (32 bytes of zeroes)
36
- putativeBlockhash.length < 32 || // Highest value (32 bytes of 255)
37
- putativeBlockhash.length > 44
38
- ) {
39
- throw new Error("Expected input string to decode to a byte array of length 32.");
40
- }
41
- const bytes = base58Encoder.encode(putativeBlockhash);
42
- const numBytes = bytes.byteLength;
43
- if (numBytes !== 32) {
44
- throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${numBytes}`);
45
- }
46
- } catch (e) {
47
- throw new Error(`\`${putativeBlockhash}\` is not a blockhash`, {
48
- cause: e
49
- });
55
+ assertIsBlockhash(transaction.lifetimeConstraint.blockhash);
56
+ return true;
57
+ } catch {
58
+ return false;
59
+ }
60
+ }
61
+ function assertIsTransactionWithBlockhashLifetime(transaction) {
62
+ if (!isTransactionWithBlockhashLifetime(transaction)) {
63
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION__EXPECTED_BLOCKHASH_LIFETIME);
50
64
  }
51
65
  }
52
66
  function setTransactionLifetimeUsingBlockhash(blockhashLifetimeConstraint, transaction) {
@@ -72,8 +86,6 @@ function createTransaction({
72
86
  Object.freeze(out);
73
87
  return out;
74
88
  }
75
-
76
- // ../instructions/dist/index.browser.js
77
89
  var AccountRole = /* @__PURE__ */ ((AccountRole2) => {
78
90
  AccountRole2[AccountRole2["WRITABLE_SIGNER"] = /* 3 */
79
91
  3] = "WRITABLE_SIGNER";
@@ -95,13 +107,11 @@ function isWritableRole(role) {
95
107
  function mergeRoles(roleA, roleB) {
96
108
  return roleA | roleB;
97
109
  }
98
-
99
- // src/durable-nonce.ts
100
110
  var RECENT_BLOCKHASHES_SYSVAR_ADDRESS = "SysvarRecentB1ockHashes11111111111111111111";
101
111
  var SYSTEM_PROGRAM_ADDRESS = "11111111111111111111111111111111";
102
112
  function assertIsDurableNonceTransaction(transaction) {
103
113
  if (!isDurableNonceTransaction(transaction)) {
104
- throw new Error("Transaction is not a durable nonce transaction");
114
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION__EXPECTED_NONCE_LIFETIME);
105
115
  }
106
116
  }
107
117
  function createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress) {
@@ -187,21 +197,181 @@ function setTransactionFeePayer(feePayer, transaction) {
187
197
 
188
198
  // src/instructions.ts
189
199
  function appendTransactionInstruction(instruction, transaction) {
200
+ return appendTransactionInstructions([instruction], transaction);
201
+ }
202
+ function appendTransactionInstructions(instructions, transaction) {
190
203
  const out = {
191
204
  ...getUnsignedTransaction(transaction),
192
- instructions: [...transaction.instructions, instruction]
205
+ instructions: [...transaction.instructions, ...instructions]
193
206
  };
194
207
  Object.freeze(out);
195
208
  return out;
196
209
  }
197
210
  function prependTransactionInstruction(instruction, transaction) {
211
+ return prependTransactionInstructions([instruction], transaction);
212
+ }
213
+ function prependTransactionInstructions(instructions, transaction) {
198
214
  const out = {
199
215
  ...getUnsignedTransaction(transaction),
200
- instructions: [instruction, ...transaction.instructions]
216
+ instructions: [...instructions, ...transaction.instructions]
201
217
  };
202
218
  Object.freeze(out);
203
219
  return out;
204
220
  }
221
+
222
+ // src/decompile-transaction.ts
223
+ function getAccountMetas(message) {
224
+ const { header } = message;
225
+ const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
226
+ const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
227
+ const accountMetas = [];
228
+ let accountIndex = 0;
229
+ for (let i = 0; i < numWritableSignerAccounts; i++) {
230
+ accountMetas.push({
231
+ address: message.staticAccounts[accountIndex],
232
+ role: AccountRole.WRITABLE_SIGNER
233
+ });
234
+ accountIndex++;
235
+ }
236
+ for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
237
+ accountMetas.push({
238
+ address: message.staticAccounts[accountIndex],
239
+ role: AccountRole.READONLY_SIGNER
240
+ });
241
+ accountIndex++;
242
+ }
243
+ for (let i = 0; i < numWritableNonSignerAccounts; i++) {
244
+ accountMetas.push({
245
+ address: message.staticAccounts[accountIndex],
246
+ role: AccountRole.WRITABLE
247
+ });
248
+ accountIndex++;
249
+ }
250
+ for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
251
+ accountMetas.push({
252
+ address: message.staticAccounts[accountIndex],
253
+ role: AccountRole.READONLY
254
+ });
255
+ accountIndex++;
256
+ }
257
+ return accountMetas;
258
+ }
259
+ function getAddressLookupMetas(compiledAddressTableLookups, addressesByLookupTableAddress) {
260
+ const compiledAddressTableLookupAddresses = compiledAddressTableLookups.map((l) => l.lookupTableAddress);
261
+ const missing = compiledAddressTableLookupAddresses.filter((a) => addressesByLookupTableAddress[a] === void 0);
262
+ if (missing.length > 0) {
263
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_CONTENTS_MISSING, {
264
+ lookupTableAddresses: missing
265
+ });
266
+ }
267
+ const readOnlyMetas = [];
268
+ const writableMetas = [];
269
+ for (const lookup of compiledAddressTableLookups) {
270
+ const addresses = addressesByLookupTableAddress[lookup.lookupTableAddress];
271
+ const highestIndex = Math.max(...lookup.readableIndices, ...lookup.writableIndices);
272
+ if (highestIndex >= addresses.length) {
273
+ throw new errors.SolanaError(
274
+ errors.SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_INDEX_OUT_OF_RANGE,
275
+ {
276
+ highestKnownIndex: addresses.length - 1,
277
+ highestRequestedIndex: highestIndex,
278
+ lookupTableAddress: lookup.lookupTableAddress
279
+ }
280
+ );
281
+ }
282
+ const readOnlyForLookup = lookup.readableIndices.map((r) => ({
283
+ address: addresses[r],
284
+ addressIndex: r,
285
+ lookupTableAddress: lookup.lookupTableAddress,
286
+ role: AccountRole.READONLY
287
+ }));
288
+ readOnlyMetas.push(...readOnlyForLookup);
289
+ const writableForLookup = lookup.writableIndices.map((w) => ({
290
+ address: addresses[w],
291
+ addressIndex: w,
292
+ lookupTableAddress: lookup.lookupTableAddress,
293
+ role: AccountRole.WRITABLE
294
+ }));
295
+ writableMetas.push(...writableForLookup);
296
+ }
297
+ return [...writableMetas, ...readOnlyMetas];
298
+ }
299
+ function convertInstruction(instruction, accountMetas) {
300
+ const programAddress = accountMetas[instruction.programAddressIndex]?.address;
301
+ if (!programAddress) {
302
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_INSTRUCTION_PROGRAM_ADDRESS_NOT_FOUND, {
303
+ index: instruction.programAddressIndex
304
+ });
305
+ }
306
+ const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
307
+ const { data } = instruction;
308
+ return {
309
+ programAddress,
310
+ ...accounts && accounts.length ? { accounts } : {},
311
+ ...data && data.length ? { data } : {}
312
+ };
313
+ }
314
+ function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
315
+ if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
316
+ return {
317
+ blockhash: messageLifetimeToken,
318
+ lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
319
+ // U64 MAX
320
+ };
321
+ } else {
322
+ const nonceAccountAddress = firstInstruction.accounts[0].address;
323
+ addresses.assertIsAddress(nonceAccountAddress);
324
+ const nonceAuthorityAddress = firstInstruction.accounts[2].address;
325
+ addresses.assertIsAddress(nonceAuthorityAddress);
326
+ return {
327
+ nonce: messageLifetimeToken,
328
+ nonceAccountAddress,
329
+ nonceAuthorityAddress
330
+ };
331
+ }
332
+ }
333
+ function convertSignatures(compiledTransaction) {
334
+ const {
335
+ compiledMessage: { staticAccounts },
336
+ signatures
337
+ } = compiledTransaction;
338
+ return signatures.reduce((acc, sig, index) => {
339
+ const allZeros = sig.every((byte) => byte === 0);
340
+ if (allZeros)
341
+ return acc;
342
+ const address = staticAccounts[index];
343
+ return { ...acc, [address]: sig };
344
+ }, {});
345
+ }
346
+ function decompileTransaction(compiledTransaction, config) {
347
+ const { compiledMessage } = compiledTransaction;
348
+ const feePayer = compiledMessage.staticAccounts[0];
349
+ if (!feePayer) {
350
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION__FAILED_TO_DECOMPILE_FEE_PAYER_MISSING);
351
+ }
352
+ const accountMetas = getAccountMetas(compiledMessage);
353
+ const accountLookupMetas = "addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups !== void 0 && compiledMessage.addressTableLookups.length > 0 ? getAddressLookupMetas(compiledMessage.addressTableLookups, config?.addressesByLookupTableAddress ?? {}) : [];
354
+ const transactionMetas = [...accountMetas, ...accountLookupMetas];
355
+ const instructions = compiledMessage.instructions.map(
356
+ (compiledInstruction) => convertInstruction(compiledInstruction, transactionMetas)
357
+ );
358
+ const firstInstruction = instructions[0];
359
+ const lifetimeConstraint = getLifetimeConstraint(
360
+ compiledMessage.lifetimeToken,
361
+ firstInstruction,
362
+ config?.lastValidBlockHeight
363
+ );
364
+ const signatures = convertSignatures(compiledTransaction);
365
+ return functional.pipe(
366
+ createTransaction({ version: compiledMessage.version }),
367
+ (tx) => setTransactionFeePayer(feePayer, tx),
368
+ (tx) => instructions.reduce((acc, instruction) => {
369
+ return appendTransactionInstruction(instruction, acc);
370
+ }, tx),
371
+ (tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
372
+ (tx) => Object.keys(signatures).length > 0 ? { ...tx, signatures } : tx
373
+ );
374
+ }
205
375
  function upsert(addressMap, address, update) {
206
376
  addressMap[address] = update(addressMap[address] ?? { role: AccountRole.READONLY });
207
377
  }
@@ -218,13 +388,13 @@ function getAddressMapFromInstructions(feePayer, instructions) {
218
388
  if (isWritableRole(entry.role)) {
219
389
  switch (entry[TYPE]) {
220
390
  case 0 /* FEE_PAYER */:
221
- throw new Error(
222
- `This transaction includes an address (\`${instruction.programAddress}\`) which is both invoked and set as the fee payer. Program addresses may not pay fees.`
223
- );
391
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION__INVOKED_PROGRAMS_CANNOT_PAY_FEES, {
392
+ programAddress: instruction.programAddress
393
+ });
224
394
  default:
225
- throw new Error(
226
- `This transaction includes an address (\`${instruction.programAddress}\`) which is both invoked and marked writable. Program addresses may not be writable.`
227
- );
395
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION__INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE, {
396
+ programAddress: instruction.programAddress
397
+ });
228
398
  }
229
399
  }
230
400
  if (entry[TYPE] === 2 /* STATIC */) {
@@ -254,7 +424,7 @@ function getAddressMapFromInstructions(feePayer, instructions) {
254
424
  const shouldReplaceEntry = (
255
425
  // Consider using the new LOOKUP_TABLE if its address is different...
256
426
  entry.lookupTableAddress !== accountMeta.lookupTableAddress && // ...and sorts before the existing one.
257
- (addressComparator || (addressComparator = addresses.getAddressComparator()))(
427
+ (addressComparator ||= addresses.getAddressComparator())(
258
428
  accountMeta.lookupTableAddress,
259
429
  entry.lookupTableAddress
260
430
  ) < 0
@@ -289,8 +459,11 @@ function getAddressMapFromInstructions(feePayer, instructions) {
289
459
  addressesOfInvokedPrograms.has(account.address)
290
460
  ) {
291
461
  if (isWritableRole(accountMeta.role)) {
292
- throw new Error(
293
- `This transaction includes an address (\`${account.address}\`) which is both invoked and marked writable. Program addresses may not be writable.`
462
+ throw new errors.SolanaError(
463
+ errors.SOLANA_ERROR__TRANSACTION__INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE,
464
+ {
465
+ programAddress: account.address
466
+ }
294
467
  );
295
468
  }
296
469
  if (entry.role !== nextRole) {
@@ -360,7 +533,7 @@ function getOrderedAccountsFromAddressMap(addressMap) {
360
533
  if (leftIsWritable !== isWritableRole(rightEntry.role)) {
361
534
  return leftIsWritable ? -1 : 1;
362
535
  }
363
- addressComparator || (addressComparator = addresses.getAddressComparator());
536
+ addressComparator ||= addresses.getAddressComparator();
364
537
  if (leftEntry[TYPE] === 1 /* LOOKUP_TABLE */ && rightEntry[TYPE] === 1 /* LOOKUP_TABLE */ && leftEntry.lookupTableAddress !== rightEntry.lookupTableAddress) {
365
538
  return addressComparator(leftEntry.lookupTableAddress, rightEntry.lookupTableAddress);
366
539
  } else {
@@ -373,16 +546,15 @@ function getOrderedAccountsFromAddressMap(addressMap) {
373
546
  return orderedAccounts;
374
547
  }
375
548
  function getCompiledAddressTableLookups(orderedAccounts) {
376
- var _a;
377
549
  const index = {};
378
550
  for (const account of orderedAccounts) {
379
551
  if (!("lookupTableAddress" in account)) {
380
552
  continue;
381
553
  }
382
- const entry = index[_a = account.lookupTableAddress] || (index[_a] = {
554
+ const entry = index[account.lookupTableAddress] ||= {
383
555
  readableIndices: [],
384
556
  writableIndices: []
385
- });
557
+ };
386
558
  if (account.role === AccountRole.WRITABLE) {
387
559
  entry.writableIndices.push(account.addressIndex);
388
560
  } else {
@@ -468,187 +640,31 @@ function compileMessage(transaction) {
468
640
  version: transaction.version
469
641
  };
470
642
  }
471
-
472
- // src/compile-transaction.ts
473
- function getCompiledTransaction(transaction) {
474
- const compiledMessage = compileMessage(transaction);
475
- let signatures;
476
- if ("signatures" in transaction) {
477
- signatures = [];
478
- for (let ii = 0; ii < compiledMessage.header.numSignerAccounts; ii++) {
479
- signatures[ii] = transaction.signatures[compiledMessage.staticAccounts[ii]] ?? new Uint8Array(Array(64).fill(0));
480
- }
481
- } else {
482
- signatures = Array(compiledMessage.header.numSignerAccounts).fill(new Uint8Array(Array(64).fill(0)));
483
- }
484
- return {
485
- compiledMessage,
486
- signatures
487
- };
488
- }
489
- function getAccountMetas(message) {
490
- const { header } = message;
491
- const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
492
- const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
493
- const accountMetas = [];
494
- let accountIndex = 0;
495
- for (let i = 0; i < numWritableSignerAccounts; i++) {
496
- accountMetas.push({
497
- address: message.staticAccounts[accountIndex],
498
- role: AccountRole.WRITABLE_SIGNER
499
- });
500
- accountIndex++;
501
- }
502
- for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
503
- accountMetas.push({
504
- address: message.staticAccounts[accountIndex],
505
- role: AccountRole.READONLY_SIGNER
506
- });
507
- accountIndex++;
508
- }
509
- for (let i = 0; i < numWritableNonSignerAccounts; i++) {
510
- accountMetas.push({
511
- address: message.staticAccounts[accountIndex],
512
- role: AccountRole.WRITABLE
513
- });
514
- accountIndex++;
515
- }
516
- for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
517
- accountMetas.push({
518
- address: message.staticAccounts[accountIndex],
519
- role: AccountRole.READONLY
520
- });
521
- accountIndex++;
522
- }
523
- return accountMetas;
524
- }
525
- function convertInstruction(instruction, accountMetas) {
526
- const programAddress = accountMetas[instruction.programAddressIndex]?.address;
527
- if (!programAddress) {
528
- throw new Error(`Could not find program address at index ${instruction.programAddressIndex}`);
529
- }
530
- const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
531
- const { data } = instruction;
532
- return {
533
- programAddress,
534
- ...accounts && accounts.length ? { accounts } : {},
535
- ...data && data.length ? { data } : {}
536
- };
537
- }
538
- function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
539
- if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
540
- return {
541
- blockhash: messageLifetimeToken,
542
- lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
543
- // U64 MAX
544
- };
545
- } else {
546
- const nonceAccountAddress = firstInstruction.accounts[0].address;
547
- addresses.assertIsAddress(nonceAccountAddress);
548
- const nonceAuthorityAddress = firstInstruction.accounts[2].address;
549
- addresses.assertIsAddress(nonceAuthorityAddress);
550
- return {
551
- nonce: messageLifetimeToken,
552
- nonceAccountAddress,
553
- nonceAuthorityAddress
554
- };
555
- }
556
- }
557
- function convertSignatures(compiledTransaction) {
558
- const {
559
- compiledMessage: { staticAccounts },
560
- signatures
561
- } = compiledTransaction;
562
- return signatures.reduce((acc, sig, index) => {
563
- const allZeros = sig.every((byte) => byte === 0);
564
- if (allZeros)
565
- return acc;
566
- const address = staticAccounts[index];
567
- return { ...acc, [address]: sig };
568
- }, {});
569
- }
570
- function decompileTransaction(compiledTransaction, lastValidBlockHeight) {
571
- const { compiledMessage } = compiledTransaction;
572
- if ("addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups.length > 0) {
573
- throw new Error("Cannot convert transaction with addressTableLookups");
574
- }
575
- const feePayer = compiledMessage.staticAccounts[0];
576
- if (!feePayer)
577
- throw new Error("No fee payer set in CompiledTransaction");
578
- const accountMetas = getAccountMetas(compiledMessage);
579
- const instructions = compiledMessage.instructions.map(
580
- (compiledInstruction) => convertInstruction(compiledInstruction, accountMetas)
581
- );
582
- const firstInstruction = instructions[0];
583
- const lifetimeConstraint = getLifetimeConstraint(
584
- compiledMessage.lifetimeToken,
585
- firstInstruction,
586
- lastValidBlockHeight
587
- );
588
- const signatures = convertSignatures(compiledTransaction);
589
- return functional.pipe(
590
- createTransaction({ version: compiledMessage.version }),
591
- (tx) => setTransactionFeePayer(feePayer, tx),
592
- (tx) => instructions.reduce((acc, instruction) => {
593
- return appendTransactionInstruction(instruction, acc);
594
- }, tx),
595
- (tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
596
- (tx) => compiledTransaction.signatures.length ? { ...tx, signatures } : tx
597
- );
598
- }
599
- var lookupTableAddressDescription = __DEV__ ? "The address of the address lookup table account from which instruction addresses should be looked up" : "lookupTableAddress";
600
- var writableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as writeable" : "writableIndices";
601
- var readableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as read-only" : "readableIndices";
602
- var addressTableLookupDescription = __DEV__ ? "A pointer to the address of an address lookup table, along with the readonly/writeable indices of the addresses that should be loaded from it" : "addressTableLookup";
603
643
  var memoizedAddressTableLookupEncoder;
604
644
  function getAddressTableLookupEncoder() {
605
645
  if (!memoizedAddressTableLookupEncoder) {
606
- memoizedAddressTableLookupEncoder = codecsDataStructures.getStructEncoder(
646
+ memoizedAddressTableLookupEncoder = codecsDataStructures.getStructEncoder([
647
+ ["lookupTableAddress", addresses.getAddressEncoder()],
607
648
  [
608
- ["lookupTableAddress", addresses.getAddressEncoder({ description: lookupTableAddressDescription })],
609
- [
610
- "writableIndices",
611
- codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder(), {
612
- description: writableIndicesDescription,
613
- size: codecsNumbers.getShortU16Encoder()
614
- })
615
- ],
616
- [
617
- "readableIndices",
618
- codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder(), {
619
- description: readableIndicesDescription,
620
- size: codecsNumbers.getShortU16Encoder()
621
- })
622
- ]
649
+ "writableIndices",
650
+ codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder(), { size: codecsNumbers.getShortU16Encoder() })
623
651
  ],
624
- { description: addressTableLookupDescription }
625
- );
652
+ [
653
+ "readableIndices",
654
+ codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder(), { size: codecsNumbers.getShortU16Encoder() })
655
+ ]
656
+ ]);
626
657
  }
627
658
  return memoizedAddressTableLookupEncoder;
628
659
  }
629
660
  var memoizedAddressTableLookupDecoder;
630
661
  function getAddressTableLookupDecoder() {
631
662
  if (!memoizedAddressTableLookupDecoder) {
632
- memoizedAddressTableLookupDecoder = codecsDataStructures.getStructDecoder(
633
- [
634
- ["lookupTableAddress", addresses.getAddressDecoder({ description: lookupTableAddressDescription })],
635
- [
636
- "writableIndices",
637
- codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), {
638
- description: writableIndicesDescription,
639
- size: codecsNumbers.getShortU16Decoder()
640
- })
641
- ],
642
- [
643
- "readableIndices",
644
- codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), {
645
- description: readableIndicesDescription,
646
- size: codecsNumbers.getShortU16Decoder()
647
- })
648
- ]
649
- ],
650
- { description: addressTableLookupDescription }
651
- );
663
+ memoizedAddressTableLookupDecoder = codecsDataStructures.getStructDecoder([
664
+ ["lookupTableAddress", addresses.getAddressDecoder()],
665
+ ["writableIndices", codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), { size: codecsNumbers.getShortU16Decoder() })],
666
+ ["readableIndices", codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), { size: codecsNumbers.getShortU16Decoder() })]
667
+ ]);
652
668
  }
653
669
  return memoizedAddressTableLookupDecoder;
654
670
  }
@@ -658,72 +674,34 @@ function getMemoizedU8Encoder() {
658
674
  memoizedU8Encoder = codecsNumbers.getU8Encoder();
659
675
  return memoizedU8Encoder;
660
676
  }
661
- function getMemoizedU8EncoderDescription(description) {
662
- const encoder = getMemoizedU8Encoder();
663
- return {
664
- ...encoder,
665
- description: description ?? encoder.description
666
- };
667
- }
668
677
  var memoizedU8Decoder;
669
678
  function getMemoizedU8Decoder() {
670
679
  if (!memoizedU8Decoder)
671
680
  memoizedU8Decoder = codecsNumbers.getU8Decoder();
672
681
  return memoizedU8Decoder;
673
682
  }
674
- function getMemoizedU8DecoderDescription(description) {
675
- const decoder = getMemoizedU8Decoder();
676
- return {
677
- ...decoder,
678
- description: description ?? decoder.description
679
- };
680
- }
681
- var numSignerAccountsDescription = __DEV__ ? "The expected number of addresses in the static address list belonging to accounts that are required to sign this transaction" : void 0;
682
- var numReadonlySignerAccountsDescription = __DEV__ ? "The expected number of addresses in the static address list belonging to accounts that are required to sign this transaction, but may not be writable" : void 0;
683
- var numReadonlyNonSignerAccountsDescription = __DEV__ ? "The expected number of addresses in the static address list belonging to accounts that are neither signers, nor writable" : void 0;
684
- var messageHeaderDescription = __DEV__ ? "The transaction message header containing counts of the signer, readonly-signer, and readonly-nonsigner account addresses" : void 0;
685
683
  function getMessageHeaderEncoder() {
686
- return codecsDataStructures.getStructEncoder(
687
- [
688
- ["numSignerAccounts", getMemoizedU8EncoderDescription(numSignerAccountsDescription)],
689
- ["numReadonlySignerAccounts", getMemoizedU8EncoderDescription(numReadonlySignerAccountsDescription)],
690
- ["numReadonlyNonSignerAccounts", getMemoizedU8EncoderDescription(numReadonlyNonSignerAccountsDescription)]
691
- ],
692
- {
693
- description: messageHeaderDescription
694
- }
695
- );
684
+ return codecsDataStructures.getStructEncoder([
685
+ ["numSignerAccounts", getMemoizedU8Encoder()],
686
+ ["numReadonlySignerAccounts", getMemoizedU8Encoder()],
687
+ ["numReadonlyNonSignerAccounts", getMemoizedU8Encoder()]
688
+ ]);
696
689
  }
697
690
  function getMessageHeaderDecoder() {
698
- return codecsDataStructures.getStructDecoder(
699
- [
700
- ["numSignerAccounts", getMemoizedU8DecoderDescription(numSignerAccountsDescription)],
701
- ["numReadonlySignerAccounts", getMemoizedU8DecoderDescription(numReadonlySignerAccountsDescription)],
702
- ["numReadonlyNonSignerAccounts", getMemoizedU8DecoderDescription(numReadonlyNonSignerAccountsDescription)]
703
- ],
704
- {
705
- description: messageHeaderDescription
706
- }
707
- );
691
+ return codecsDataStructures.getStructDecoder([
692
+ ["numSignerAccounts", getMemoizedU8Decoder()],
693
+ ["numReadonlySignerAccounts", getMemoizedU8Decoder()],
694
+ ["numReadonlyNonSignerAccounts", getMemoizedU8Decoder()]
695
+ ]);
708
696
  }
709
- var programAddressIndexDescription = __DEV__ ? "The index of the program being called, according to the well-ordered accounts list for this transaction" : "programAddressIndex";
710
- var accountIndexDescription = __DEV__ ? "The index of an account, according to the well-ordered accounts list for this transaction" : void 0;
711
- var accountIndicesDescription = __DEV__ ? "An optional list of account indices, according to the well-ordered accounts list for this transaction, in the order in which the program being called expects them" : "accountIndices";
712
- var dataDescription = __DEV__ ? "An optional buffer of data passed to the instruction" : "data";
713
697
  var memoizedGetInstructionEncoder;
714
698
  function getInstructionEncoder() {
715
699
  if (!memoizedGetInstructionEncoder) {
716
700
  memoizedGetInstructionEncoder = codecsCore.mapEncoder(
717
701
  codecsDataStructures.getStructEncoder([
718
- ["programAddressIndex", codecsNumbers.getU8Encoder({ description: programAddressIndexDescription })],
719
- [
720
- "accountIndices",
721
- codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder({ description: accountIndexDescription }), {
722
- description: accountIndicesDescription,
723
- size: codecsNumbers.getShortU16Encoder()
724
- })
725
- ],
726
- ["data", codecsDataStructures.getBytesEncoder({ description: dataDescription, size: codecsNumbers.getShortU16Encoder() })]
702
+ ["programAddressIndex", codecsNumbers.getU8Encoder()],
703
+ ["accountIndices", codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder(), { size: codecsNumbers.getShortU16Encoder() })],
704
+ ["data", codecsDataStructures.getBytesEncoder({ size: codecsNumbers.getShortU16Encoder() })]
727
705
  ]),
728
706
  // Convert an instruction to have all fields defined
729
707
  (instruction) => {
@@ -745,15 +723,9 @@ function getInstructionDecoder() {
745
723
  if (!memoizedGetInstructionDecoder) {
746
724
  memoizedGetInstructionDecoder = codecsCore.mapDecoder(
747
725
  codecsDataStructures.getStructDecoder([
748
- ["programAddressIndex", codecsNumbers.getU8Decoder({ description: programAddressIndexDescription })],
749
- [
750
- "accountIndices",
751
- codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder({ description: accountIndexDescription }), {
752
- description: accountIndicesDescription,
753
- size: codecsNumbers.getShortU16Decoder()
754
- })
755
- ],
756
- ["data", codecsDataStructures.getBytesDecoder({ description: dataDescription, size: codecsNumbers.getShortU16Decoder() })]
726
+ ["programAddressIndex", codecsNumbers.getU8Decoder()],
727
+ ["accountIndices", codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), { size: codecsNumbers.getShortU16Decoder() })],
728
+ ["data", codecsDataStructures.getBytesDecoder({ size: codecsNumbers.getShortU16Decoder() })]
757
729
  ]),
758
730
  // Convert an instruction to exclude optional fields if they are empty
759
731
  (instruction) => {
@@ -772,47 +744,40 @@ function getInstructionDecoder() {
772
744
  return memoizedGetInstructionDecoder;
773
745
  }
774
746
  var VERSION_FLAG_MASK = 128;
775
- var BASE_CONFIG = {
776
- description: __DEV__ ? "A single byte that encodes the version of the transaction" : "",
777
- fixedSize: null,
778
- maxSize: 1
779
- };
780
- function decode(bytes, offset = 0) {
781
- const firstByte = bytes[offset];
782
- if ((firstByte & VERSION_FLAG_MASK) === 0) {
783
- return ["legacy", offset];
784
- } else {
785
- const version = firstByte ^ VERSION_FLAG_MASK;
786
- return [version, offset + 1];
787
- }
788
- }
789
- function encode(value) {
790
- if (value === "legacy") {
791
- return new Uint8Array();
792
- }
793
- if (value < 0 || value > 127) {
794
- throw new Error(`Transaction version must be in the range [0, 127]. \`${value}\` given.`);
795
- }
796
- return new Uint8Array([value | VERSION_FLAG_MASK]);
747
+ function getTransactionVersionEncoder() {
748
+ return codecsCore.createEncoder({
749
+ getSizeFromValue: (value) => value === "legacy" ? 0 : 1,
750
+ maxSize: 1,
751
+ write: (value, bytes, offset) => {
752
+ if (value === "legacy") {
753
+ return offset;
754
+ }
755
+ if (value < 0 || value > 127) {
756
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION__VERSION_NUMBER_OUT_OF_RANGE, {
757
+ actualVersion: value
758
+ });
759
+ }
760
+ bytes.set([value | VERSION_FLAG_MASK], offset);
761
+ return offset + 1;
762
+ }
763
+ });
797
764
  }
798
765
  function getTransactionVersionDecoder() {
799
- return {
800
- ...BASE_CONFIG,
801
- decode
802
- };
803
- }
804
- function getTransactionVersionEncoder() {
805
- return {
806
- ...BASE_CONFIG,
807
- encode
808
- };
766
+ return codecsCore.createDecoder({
767
+ maxSize: 1,
768
+ read: (bytes, offset) => {
769
+ const firstByte = bytes[offset];
770
+ if ((firstByte & VERSION_FLAG_MASK) === 0) {
771
+ return ["legacy", offset];
772
+ } else {
773
+ const version = firstByte ^ VERSION_FLAG_MASK;
774
+ return [version, offset + 1];
775
+ }
776
+ }
777
+ });
809
778
  }
810
779
 
811
780
  // src/serializers/message.ts
812
- var staticAccountsDescription = __DEV__ ? "A compact-array of static account addresses belonging to this transaction" : "staticAccounts";
813
- var lifetimeTokenDescription = __DEV__ ? "A 32-byte token that specifies the lifetime of this transaction (eg. a recent blockhash, or a durable nonce)" : "lifetimeToken";
814
- var instructionsDescription = __DEV__ ? "A compact-array of instructions belonging to this transaction" : "instructions";
815
- var addressTableLookupsDescription = __DEV__ ? "A compact array of address table lookups belonging to this transaction" : "addressTableLookups";
816
781
  function getCompiledMessageLegacyEncoder() {
817
782
  return codecsDataStructures.getStructEncoder(getPreludeStructEncoderTuple());
818
783
  }
@@ -837,91 +802,48 @@ function getPreludeStructEncoderTuple() {
837
802
  return [
838
803
  ["version", getTransactionVersionEncoder()],
839
804
  ["header", getMessageHeaderEncoder()],
840
- [
841
- "staticAccounts",
842
- codecsDataStructures.getArrayEncoder(addresses.getAddressEncoder(), {
843
- description: staticAccountsDescription,
844
- size: codecsNumbers.getShortU16Encoder()
845
- })
846
- ],
847
- [
848
- "lifetimeToken",
849
- codecsStrings.getStringEncoder({
850
- description: lifetimeTokenDescription,
851
- encoding: codecsStrings.getBase58Encoder(),
852
- size: 32
853
- })
854
- ],
855
- [
856
- "instructions",
857
- codecsDataStructures.getArrayEncoder(getInstructionEncoder(), {
858
- description: instructionsDescription,
859
- size: codecsNumbers.getShortU16Encoder()
860
- })
861
- ]
805
+ ["staticAccounts", codecsDataStructures.getArrayEncoder(addresses.getAddressEncoder(), { size: codecsNumbers.getShortU16Encoder() })],
806
+ ["lifetimeToken", codecsStrings.getStringEncoder({ encoding: codecsStrings.getBase58Encoder(), size: 32 })],
807
+ ["instructions", codecsDataStructures.getArrayEncoder(getInstructionEncoder(), { size: codecsNumbers.getShortU16Encoder() })]
862
808
  ];
863
809
  }
864
810
  function getPreludeStructDecoderTuple() {
865
811
  return [
866
812
  ["version", getTransactionVersionDecoder()],
867
813
  ["header", getMessageHeaderDecoder()],
868
- [
869
- "staticAccounts",
870
- codecsDataStructures.getArrayDecoder(addresses.getAddressDecoder(), {
871
- description: staticAccountsDescription,
872
- size: codecsNumbers.getShortU16Decoder()
873
- })
874
- ],
875
- [
876
- "lifetimeToken",
877
- codecsStrings.getStringDecoder({
878
- description: lifetimeTokenDescription,
879
- encoding: codecsStrings.getBase58Decoder(),
880
- size: 32
881
- })
882
- ],
883
- [
884
- "instructions",
885
- codecsDataStructures.getArrayDecoder(getInstructionDecoder(), {
886
- description: instructionsDescription,
887
- size: codecsNumbers.getShortU16Decoder()
888
- })
889
- ],
814
+ ["staticAccounts", codecsDataStructures.getArrayDecoder(addresses.getAddressDecoder(), { size: codecsNumbers.getShortU16Decoder() })],
815
+ ["lifetimeToken", codecsStrings.getStringDecoder({ encoding: codecsStrings.getBase58Decoder(), size: 32 })],
816
+ ["instructions", codecsDataStructures.getArrayDecoder(getInstructionDecoder(), { size: codecsNumbers.getShortU16Decoder() })],
890
817
  ["addressTableLookups", getAddressTableLookupArrayDecoder()]
891
818
  ];
892
819
  }
893
820
  function getAddressTableLookupArrayEncoder() {
894
- return codecsDataStructures.getArrayEncoder(getAddressTableLookupEncoder(), {
895
- description: addressTableLookupsDescription,
896
- size: codecsNumbers.getShortU16Encoder()
897
- });
821
+ return codecsDataStructures.getArrayEncoder(getAddressTableLookupEncoder(), { size: codecsNumbers.getShortU16Encoder() });
898
822
  }
899
823
  function getAddressTableLookupArrayDecoder() {
900
- return codecsDataStructures.getArrayDecoder(getAddressTableLookupDecoder(), {
901
- description: addressTableLookupsDescription,
902
- size: codecsNumbers.getShortU16Decoder()
903
- });
824
+ return codecsDataStructures.getArrayDecoder(getAddressTableLookupDecoder(), { size: codecsNumbers.getShortU16Decoder() });
904
825
  }
905
- var messageDescription = __DEV__ ? "The wire format of a Solana transaction message" : "message";
906
826
  function getCompiledMessageEncoder() {
907
- return {
908
- description: messageDescription,
909
- encode: (compiledMessage) => {
827
+ return codecsCore.createEncoder({
828
+ getSizeFromValue: (compiledMessage) => {
910
829
  if (compiledMessage.version === "legacy") {
911
- return getCompiledMessageLegacyEncoder().encode(compiledMessage);
830
+ return getCompiledMessageLegacyEncoder().getSizeFromValue(compiledMessage);
912
831
  } else {
913
- return getCompiledMessageVersionedEncoder().encode(compiledMessage);
832
+ return getCompiledMessageVersionedEncoder().getSizeFromValue(compiledMessage);
914
833
  }
915
834
  },
916
- fixedSize: null,
917
- maxSize: null
918
- };
835
+ write: (compiledMessage, bytes, offset) => {
836
+ if (compiledMessage.version === "legacy") {
837
+ return getCompiledMessageLegacyEncoder().write(compiledMessage, bytes, offset);
838
+ } else {
839
+ return getCompiledMessageVersionedEncoder().write(compiledMessage, bytes, offset);
840
+ }
841
+ }
842
+ });
919
843
  }
920
844
  function getCompiledMessageDecoder() {
921
845
  return codecsCore.mapDecoder(
922
- codecsDataStructures.getStructDecoder(getPreludeStructDecoderTuple(), {
923
- description: messageDescription
924
- }),
846
+ codecsDataStructures.getStructDecoder(getPreludeStructDecoderTuple()),
925
847
  ({ addressTableLookups, ...restOfMessage }) => {
926
848
  if (restOfMessage.version === "legacy" || !addressTableLookups?.length) {
927
849
  return restOfMessage;
@@ -930,113 +852,70 @@ function getCompiledMessageDecoder() {
930
852
  }
931
853
  );
932
854
  }
855
+ function getCompiledMessageCodec() {
856
+ return codecsCore.combineCodec(getCompiledMessageEncoder(), getCompiledMessageDecoder());
857
+ }
933
858
 
934
- // src/serializers/transaction.ts
935
- var signaturesDescription = __DEV__ ? "A compact array of 64-byte, base-64 encoded Ed25519 signatures" : "signatures";
936
- var transactionDescription = __DEV__ ? "The wire format of a Solana transaction" : "transaction";
937
- function getCompiledTransactionEncoder() {
938
- return codecsDataStructures.getStructEncoder(
939
- [
940
- [
941
- "signatures",
942
- codecsDataStructures.getArrayEncoder(codecsDataStructures.getBytesEncoder({ size: 64 }), {
943
- description: signaturesDescription,
944
- size: codecsNumbers.getShortU16Encoder()
945
- })
946
- ],
947
- ["compiledMessage", getCompiledMessageEncoder()]
948
- ],
949
- {
950
- description: transactionDescription
859
+ // src/compile-transaction.ts
860
+ function getCompiledTransaction(transaction) {
861
+ const compiledMessage = compileMessage(transaction);
862
+ let signatures;
863
+ if ("signatures" in transaction) {
864
+ signatures = [];
865
+ for (let ii = 0; ii < compiledMessage.header.numSignerAccounts; ii++) {
866
+ signatures[ii] = transaction.signatures[compiledMessage.staticAccounts[ii]] ?? new Uint8Array(Array(64).fill(0));
951
867
  }
952
- );
868
+ } else {
869
+ signatures = Array(compiledMessage.header.numSignerAccounts).fill(new Uint8Array(Array(64).fill(0)));
870
+ }
871
+ return {
872
+ compiledMessage,
873
+ signatures
874
+ };
953
875
  }
954
- function getSignatureDecoder() {
955
- return codecsCore.mapDecoder(codecsDataStructures.getBytesDecoder({ size: 64 }), (bytes) => bytes);
876
+
877
+ // src/serializers/transaction.ts
878
+ function getCompiledTransactionEncoder() {
879
+ return codecsDataStructures.getStructEncoder([
880
+ ["signatures", codecsDataStructures.getArrayEncoder(codecsDataStructures.getBytesEncoder({ size: 64 }), { size: codecsNumbers.getShortU16Encoder() })],
881
+ ["compiledMessage", getCompiledMessageEncoder()]
882
+ ]);
956
883
  }
957
884
  function getCompiledTransactionDecoder() {
958
- return codecsDataStructures.getStructDecoder(
885
+ return codecsDataStructures.getStructDecoder([
959
886
  [
960
- [
961
- "signatures",
962
- codecsDataStructures.getArrayDecoder(getSignatureDecoder(), {
963
- description: signaturesDescription,
964
- size: codecsNumbers.getShortU16Decoder()
965
- })
966
- ],
967
- ["compiledMessage", getCompiledMessageDecoder()]
887
+ "signatures",
888
+ codecsDataStructures.getArrayDecoder(codecsDataStructures.getBytesDecoder({ size: 64 }), {
889
+ size: codecsNumbers.getShortU16Decoder()
890
+ })
968
891
  ],
969
- {
970
- description: transactionDescription
971
- }
972
- );
892
+ ["compiledMessage", getCompiledMessageDecoder()]
893
+ ]);
973
894
  }
974
895
  function getTransactionEncoder() {
975
896
  return codecsCore.mapEncoder(getCompiledTransactionEncoder(), getCompiledTransaction);
976
897
  }
977
- function getTransactionDecoder(lastValidBlockHeight) {
898
+ function getTransactionDecoder(config) {
978
899
  return codecsCore.mapDecoder(
979
900
  getCompiledTransactionDecoder(),
980
- (compiledTransaction) => decompileTransaction(compiledTransaction, lastValidBlockHeight)
901
+ (compiledTransaction) => decompileTransaction(compiledTransaction, config)
981
902
  );
982
903
  }
983
- function getTransactionCodec(lastValidBlockHeight) {
984
- return codecsCore.combineCodec(getTransactionEncoder(), getTransactionDecoder(lastValidBlockHeight));
904
+ function getTransactionCodec(config) {
905
+ return codecsCore.combineCodec(getTransactionEncoder(), getTransactionDecoder(config));
985
906
  }
986
- var base58Encoder2;
987
907
  var base58Decoder;
988
- function assertIsTransactionSignature(putativeTransactionSignature) {
989
- if (!base58Encoder2)
990
- base58Encoder2 = codecsStrings.getBase58Encoder();
991
- try {
992
- if (
993
- // Lowest value (64 bytes of zeroes)
994
- putativeTransactionSignature.length < 64 || // Highest value (64 bytes of 255)
995
- putativeTransactionSignature.length > 88
996
- ) {
997
- throw new Error("Expected input string to decode to a byte array of length 64.");
998
- }
999
- const bytes = base58Encoder2.encode(putativeTransactionSignature);
1000
- const numBytes = bytes.byteLength;
1001
- if (numBytes !== 64) {
1002
- throw new Error(`Expected input string to decode to a byte array of length 64. Actual length: ${numBytes}`);
1003
- }
1004
- } catch (e) {
1005
- throw new Error(`\`${putativeTransactionSignature}\` is not a transaction signature`, {
1006
- cause: e
1007
- });
1008
- }
1009
- }
1010
- function isTransactionSignature(putativeTransactionSignature) {
1011
- if (!base58Encoder2)
1012
- base58Encoder2 = codecsStrings.getBase58Encoder();
1013
- if (
1014
- // Lowest value (64 bytes of zeroes)
1015
- putativeTransactionSignature.length < 64 || // Highest value (64 bytes of 255)
1016
- putativeTransactionSignature.length > 88
1017
- ) {
1018
- return false;
1019
- }
1020
- const bytes = base58Encoder2.encode(putativeTransactionSignature);
1021
- const numBytes = bytes.byteLength;
1022
- if (numBytes !== 64) {
1023
- return false;
1024
- }
1025
- return true;
1026
- }
1027
908
  function getSignatureFromTransaction(transaction) {
1028
909
  if (!base58Decoder)
1029
910
  base58Decoder = codecsStrings.getBase58Decoder();
1030
911
  const signatureBytes = transaction.signatures[transaction.feePayer];
1031
912
  if (!signatureBytes) {
1032
- throw new Error(
1033
- "Could not determine this transaction's signature. Make sure that the transaction has been signed by its fee payer."
1034
- );
913
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION__FEE_PAYER_SIGNATURE_MISSING);
1035
914
  }
1036
- const transactionSignature2 = base58Decoder.decode(signatureBytes)[0];
1037
- return transactionSignature2;
915
+ const transactionSignature = base58Decoder.decode(signatureBytes);
916
+ return transactionSignature;
1038
917
  }
1039
- async function signTransaction(keyPairs, transaction) {
918
+ async function partiallySignTransaction(keyPairs, transaction) {
1040
919
  const compiledMessage = compileMessage(transaction);
1041
920
  const nextSignatures = "signatures" in transaction ? { ...transaction.signatures } : {};
1042
921
  const wireMessageBytes = getCompiledMessageEncoder().encode(compiledMessage);
@@ -1055,46 +934,57 @@ async function signTransaction(keyPairs, transaction) {
1055
934
  Object.freeze(out);
1056
935
  return out;
1057
936
  }
1058
- function transactionSignature(putativeTransactionSignature) {
1059
- assertIsTransactionSignature(putativeTransactionSignature);
1060
- return putativeTransactionSignature;
937
+ async function signTransaction(keyPairs, transaction) {
938
+ const out = await partiallySignTransaction(keyPairs, transaction);
939
+ assertTransactionIsFullySigned(out);
940
+ Object.freeze(out);
941
+ return out;
1061
942
  }
1062
943
  function assertTransactionIsFullySigned(transaction) {
1063
944
  const signerAddressesFromInstructions = transaction.instructions.flatMap((i) => i.accounts?.filter((a) => isSignerRole(a.role)) ?? []).map((a) => a.address);
1064
945
  const requiredSigners = /* @__PURE__ */ new Set([transaction.feePayer, ...signerAddressesFromInstructions]);
946
+ const missingSigs = [];
1065
947
  requiredSigners.forEach((address) => {
1066
948
  if (!transaction.signatures[address]) {
1067
- throw new Error(`Transaction is missing signature for address \`${address}\``);
949
+ missingSigs.push(address);
1068
950
  }
1069
951
  });
952
+ if (missingSigs.length > 0) {
953
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION__SIGNATURES_MISSING, {
954
+ addresses: missingSigs
955
+ });
956
+ }
1070
957
  }
1071
-
1072
- // src/wire-transaction.ts
1073
958
  function getBase64EncodedWireTransaction(transaction) {
1074
959
  const wireTransactionBytes = getTransactionEncoder().encode(transaction);
1075
- {
1076
- return btoa(String.fromCharCode(...wireTransactionBytes));
1077
- }
960
+ return codecsStrings.getBase64Decoder().decode(wireTransactionBytes);
1078
961
  }
1079
962
 
1080
963
  exports.appendTransactionInstruction = appendTransactionInstruction;
1081
- exports.assertIsBlockhash = assertIsBlockhash;
964
+ exports.appendTransactionInstructions = appendTransactionInstructions;
1082
965
  exports.assertIsDurableNonceTransaction = assertIsDurableNonceTransaction;
1083
- exports.assertIsTransactionSignature = assertIsTransactionSignature;
966
+ exports.assertIsTransactionWithBlockhashLifetime = assertIsTransactionWithBlockhashLifetime;
1084
967
  exports.assertTransactionIsFullySigned = assertTransactionIsFullySigned;
968
+ exports.compileMessage = compileMessage;
1085
969
  exports.createTransaction = createTransaction;
970
+ exports.decompileTransaction = decompileTransaction;
1086
971
  exports.getBase64EncodedWireTransaction = getBase64EncodedWireTransaction;
972
+ exports.getCompiledMessageCodec = getCompiledMessageCodec;
973
+ exports.getCompiledMessageDecoder = getCompiledMessageDecoder;
974
+ exports.getCompiledMessageEncoder = getCompiledMessageEncoder;
975
+ exports.getCompiledTransactionDecoder = getCompiledTransactionDecoder;
1087
976
  exports.getSignatureFromTransaction = getSignatureFromTransaction;
1088
977
  exports.getTransactionCodec = getTransactionCodec;
1089
978
  exports.getTransactionDecoder = getTransactionDecoder;
1090
979
  exports.getTransactionEncoder = getTransactionEncoder;
980
+ exports.getUnsignedTransaction = getUnsignedTransaction;
1091
981
  exports.isAdvanceNonceAccountInstruction = isAdvanceNonceAccountInstruction;
1092
- exports.isTransactionSignature = isTransactionSignature;
982
+ exports.partiallySignTransaction = partiallySignTransaction;
1093
983
  exports.prependTransactionInstruction = prependTransactionInstruction;
984
+ exports.prependTransactionInstructions = prependTransactionInstructions;
1094
985
  exports.setTransactionFeePayer = setTransactionFeePayer;
1095
986
  exports.setTransactionLifetimeUsingBlockhash = setTransactionLifetimeUsingBlockhash;
1096
987
  exports.setTransactionLifetimeUsingDurableNonce = setTransactionLifetimeUsingDurableNonce;
1097
988
  exports.signTransaction = signTransaction;
1098
- exports.transactionSignature = transactionSignature;
1099
989
  //# sourceMappingURL=out.js.map
1100
990
  //# sourceMappingURL=index.browser.cjs.map