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