@solana/transactions 2.0.0-experimental.835e62f → 2.0.0-experimental.85b7dfe

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 (66) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +272 -5
  3. package/dist/index.browser.cjs +543 -236
  4. package/dist/index.browser.cjs.map +1 -1
  5. package/dist/index.browser.js +533 -238
  6. package/dist/index.browser.js.map +1 -1
  7. package/dist/index.development.js +1141 -664
  8. package/dist/index.development.js.map +1 -1
  9. package/dist/index.native.js +533 -238
  10. package/dist/index.native.js.map +1 -1
  11. package/dist/index.node.cjs +543 -236
  12. package/dist/index.node.cjs.map +1 -1
  13. package/dist/index.node.js +535 -238
  14. package/dist/index.node.js.map +1 -1
  15. package/dist/index.production.min.js +23 -11
  16. package/dist/types/accounts.d.ts +3 -3
  17. package/dist/types/accounts.d.ts.map +1 -0
  18. package/dist/types/blockhash.d.ts +2 -1
  19. package/dist/types/blockhash.d.ts.map +1 -0
  20. package/dist/types/compilable-transaction.d.ts +7 -0
  21. package/dist/types/compilable-transaction.d.ts.map +1 -0
  22. package/dist/types/compile-address-table-lookups.d.ts +2 -2
  23. package/dist/types/compile-address-table-lookups.d.ts.map +1 -0
  24. package/dist/types/compile-header.d.ts.map +1 -0
  25. package/dist/types/compile-instructions.d.ts +1 -1
  26. package/dist/types/compile-instructions.d.ts.map +1 -0
  27. package/dist/types/compile-lifetime-token.d.ts.map +1 -0
  28. package/dist/types/compile-static-accounts.d.ts +2 -2
  29. package/dist/types/compile-static-accounts.d.ts.map +1 -0
  30. package/dist/types/compile-transaction.d.ts +5 -6
  31. package/dist/types/compile-transaction.d.ts.map +1 -0
  32. package/dist/types/create-transaction.d.ts.map +1 -0
  33. package/dist/types/decompile-transaction.d.ts +5 -0
  34. package/dist/types/decompile-transaction.d.ts.map +1 -0
  35. package/dist/types/durable-nonce.d.ts +10 -9
  36. package/dist/types/durable-nonce.d.ts.map +1 -0
  37. package/dist/types/fee-payer.d.ts +4 -3
  38. package/dist/types/fee-payer.d.ts.map +1 -0
  39. package/dist/types/index.d.ts +3 -0
  40. package/dist/types/index.d.ts.map +1 -0
  41. package/dist/types/instructions.d.ts.map +1 -0
  42. package/dist/types/message.d.ts +1 -5
  43. package/dist/types/message.d.ts.map +1 -0
  44. package/dist/types/serializers/address-table-lookup.d.ts +5 -3
  45. package/dist/types/serializers/address-table-lookup.d.ts.map +1 -0
  46. package/dist/types/serializers/header.d.ts +4 -2
  47. package/dist/types/serializers/header.d.ts.map +1 -0
  48. package/dist/types/serializers/index.d.ts +3 -0
  49. package/dist/types/serializers/index.d.ts.map +1 -0
  50. package/dist/types/serializers/instruction.d.ts +4 -2
  51. package/dist/types/serializers/instruction.d.ts.map +1 -0
  52. package/dist/types/serializers/message.d.ts +4 -4
  53. package/dist/types/serializers/message.d.ts.map +1 -0
  54. package/dist/types/serializers/transaction-version.d.ts +4 -4
  55. package/dist/types/serializers/transaction-version.d.ts.map +1 -0
  56. package/dist/types/serializers/transaction.d.ts +6 -5
  57. package/dist/types/serializers/transaction.d.ts.map +1 -0
  58. package/dist/types/signatures.d.ts +10 -5
  59. package/dist/types/signatures.d.ts.map +1 -0
  60. package/dist/types/types.d.ts +13 -13
  61. package/dist/types/types.d.ts.map +1 -0
  62. package/dist/types/unsigned-transaction.d.ts.map +1 -0
  63. package/dist/types/wire-transaction.d.ts +2 -2
  64. package/dist/types/wire-transaction.d.ts.map +1 -0
  65. package/package.json +22 -18
  66. package/dist/types/serializers/unimplemented.d.ts +0 -3
@@ -1,5 +1,10 @@
1
- import { base58, struct, array, bytes, shortU16, mapSerializer, string, u8 } from '@metaplex-foundation/umi-serializers';
2
- import { getBase58EncodedAddressFromPublicKey, signBytes, getBase58EncodedAddressComparator, getBase58EncodedAddressCodec } from '@solana/keys';
1
+ import { getBase58Encoder, getBase58Decoder, getBase64Decoder, getStringEncoder, getStringDecoder } from '@solana/codecs-strings';
2
+ import { getAddressFromPublicKey, getAddressComparator, getAddressEncoder, getAddressDecoder, assertIsAddress } from '@solana/addresses';
3
+ import { mapDecoder, combineCodec, mapEncoder } from '@solana/codecs-core';
4
+ import { getStructDecoder, getStructEncoder, getArrayEncoder, getArrayDecoder, getBytesEncoder, getBytesDecoder } from '@solana/codecs-data-structures';
5
+ import { getShortU16Encoder, getShortU16Decoder, getU8Encoder, getU8Decoder } from '@solana/codecs-numbers';
6
+ import { pipe } from '@solana/functional';
7
+ import { signBytes } from '@solana/keys';
3
8
 
4
9
  // ../build-scripts/env-shim.ts
5
10
  var __DEV__ = /* @__PURE__ */ (() => process["env"].NODE_ENV === "development")();
@@ -19,7 +24,10 @@ function getUnsignedTransaction(transaction) {
19
24
  }
20
25
 
21
26
  // src/blockhash.ts
27
+ var base58Encoder;
22
28
  function assertIsBlockhash(putativeBlockhash) {
29
+ if (!base58Encoder)
30
+ base58Encoder = getBase58Encoder();
23
31
  try {
24
32
  if (
25
33
  // Lowest value (32 bytes of zeroes)
@@ -28,8 +36,8 @@ function assertIsBlockhash(putativeBlockhash) {
28
36
  ) {
29
37
  throw new Error("Expected input string to decode to a byte array of length 32.");
30
38
  }
31
- const bytes3 = base58.serialize(putativeBlockhash);
32
- const numBytes = bytes3.byteLength;
39
+ const bytes = base58Encoder.encode(putativeBlockhash);
40
+ const numBytes = bytes.byteLength;
33
41
  if (numBytes !== 32) {
34
42
  throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${numBytes}`);
35
43
  }
@@ -39,6 +47,22 @@ function assertIsBlockhash(putativeBlockhash) {
39
47
  });
40
48
  }
41
49
  }
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;
54
+ try {
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 Error("Transaction does not have a blockhash lifetime");
64
+ }
65
+ }
42
66
  function setTransactionLifetimeUsingBlockhash(blockhashLifetimeConstraint, transaction) {
43
67
  if ("lifetimeConstraint" in transaction && transaction.lifetimeConstraint.blockhash === blockhashLifetimeConstraint.blockhash && transaction.lifetimeConstraint.lastValidBlockHeight === blockhashLifetimeConstraint.lastValidBlockHeight) {
44
68
  return transaction;
@@ -114,7 +138,7 @@ function isAdvanceNonceAccountInstruction(instruction) {
114
138
  instruction.accounts?.length === 3 && // First account is nonce account address
115
139
  instruction.accounts[0].address != null && instruction.accounts[0].role === AccountRole.WRITABLE && // Second account is recent blockhashes sysvar
116
140
  instruction.accounts[1].address === RECENT_BLOCKHASHES_SYSVAR_ADDRESS && instruction.accounts[1].role === AccountRole.READONLY && // Third account is nonce authority account
117
- instruction.accounts[2].address != null && instruction.accounts[2].role === AccountRole.READONLY_SIGNER;
141
+ instruction.accounts[2].address != null && isSignerRole(instruction.accounts[2].role);
118
142
  }
119
143
  function isAdvanceNonceAccountInstructionData(data) {
120
144
  return data.byteLength === 4 && data[0] === 4 && data[1] === 0 && data[2] === 0 && data[3] === 0;
@@ -122,21 +146,38 @@ function isAdvanceNonceAccountInstructionData(data) {
122
146
  function isDurableNonceTransaction(transaction) {
123
147
  return "lifetimeConstraint" in transaction && typeof transaction.lifetimeConstraint.nonce === "string" && transaction.instructions[0] != null && isAdvanceNonceAccountInstruction(transaction.instructions[0]);
124
148
  }
149
+ function isAdvanceNonceAccountInstructionForNonce(instruction, nonceAccountAddress, nonceAuthorityAddress) {
150
+ return instruction.accounts[0].address === nonceAccountAddress && instruction.accounts[2].address === nonceAuthorityAddress;
151
+ }
125
152
  function setTransactionLifetimeUsingDurableNonce({
126
153
  nonce,
127
154
  nonceAccountAddress,
128
155
  nonceAuthorityAddress
129
156
  }, transaction) {
130
- const isAlreadyDurableNonceTransaction = isDurableNonceTransaction(transaction);
131
- if (isAlreadyDurableNonceTransaction && transaction.lifetimeConstraint.nonce === nonce && transaction.instructions[0].accounts[0].address === nonceAccountAddress && transaction.instructions[0].accounts[2].address === nonceAuthorityAddress) {
132
- return transaction;
157
+ let newInstructions;
158
+ const firstInstruction = transaction.instructions[0];
159
+ if (firstInstruction && isAdvanceNonceAccountInstruction(firstInstruction)) {
160
+ if (isAdvanceNonceAccountInstructionForNonce(firstInstruction, nonceAccountAddress, nonceAuthorityAddress)) {
161
+ if (isDurableNonceTransaction(transaction) && transaction.lifetimeConstraint.nonce === nonce) {
162
+ return transaction;
163
+ } else {
164
+ newInstructions = [firstInstruction, ...transaction.instructions.slice(1)];
165
+ }
166
+ } else {
167
+ newInstructions = [
168
+ createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
169
+ ...transaction.instructions.slice(1)
170
+ ];
171
+ }
172
+ } else {
173
+ newInstructions = [
174
+ createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
175
+ ...transaction.instructions
176
+ ];
133
177
  }
134
178
  const out = {
135
179
  ...getUnsignedTransaction(transaction),
136
- instructions: [
137
- createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
138
- ...isAlreadyDurableNonceTransaction ? transaction.instructions.slice(1) : transaction.instructions
139
- ],
180
+ instructions: newInstructions,
140
181
  lifetimeConstraint: {
141
182
  nonce
142
183
  }
@@ -227,7 +268,7 @@ function getAddressMapFromInstructions(feePayer, instructions) {
227
268
  const shouldReplaceEntry = (
228
269
  // Consider using the new LOOKUP_TABLE if its address is different...
229
270
  entry.lookupTableAddress !== accountMeta.lookupTableAddress && // ...and sorts before the existing one.
230
- (addressComparator || (addressComparator = getBase58EncodedAddressComparator()))(
271
+ (addressComparator ||= getAddressComparator())(
231
272
  accountMeta.lookupTableAddress,
232
273
  entry.lookupTableAddress
233
274
  ) < 0
@@ -333,7 +374,7 @@ function getOrderedAccountsFromAddressMap(addressMap) {
333
374
  if (leftIsWritable !== isWritableRole(rightEntry.role)) {
334
375
  return leftIsWritable ? -1 : 1;
335
376
  }
336
- addressComparator || (addressComparator = getBase58EncodedAddressComparator());
377
+ addressComparator ||= getAddressComparator();
337
378
  if (leftEntry[TYPE] === 1 /* LOOKUP_TABLE */ && rightEntry[TYPE] === 1 /* LOOKUP_TABLE */ && leftEntry.lookupTableAddress !== rightEntry.lookupTableAddress) {
338
379
  return addressComparator(leftEntry.lookupTableAddress, rightEntry.lookupTableAddress);
339
380
  } else {
@@ -346,23 +387,22 @@ function getOrderedAccountsFromAddressMap(addressMap) {
346
387
  return orderedAccounts;
347
388
  }
348
389
  function getCompiledAddressTableLookups(orderedAccounts) {
349
- var _a;
350
390
  const index = {};
351
391
  for (const account of orderedAccounts) {
352
392
  if (!("lookupTableAddress" in account)) {
353
393
  continue;
354
394
  }
355
- const entry = index[_a = account.lookupTableAddress] || (index[_a] = {
395
+ const entry = index[account.lookupTableAddress] ||= {
356
396
  readableIndices: [],
357
397
  writableIndices: []
358
- });
398
+ };
359
399
  if (account.role === AccountRole.WRITABLE) {
360
400
  entry.writableIndices.push(account.addressIndex);
361
401
  } else {
362
402
  entry.readableIndices.push(account.addressIndex);
363
403
  }
364
404
  }
365
- return Object.keys(index).sort(getBase58EncodedAddressComparator()).map((lookupTableAddress) => ({
405
+ return Object.keys(index).sort(getAddressComparator()).map((lookupTableAddress) => ({
366
406
  lookupTableAddress,
367
407
  ...index[lookupTableAddress]
368
408
  }));
@@ -441,151 +481,189 @@ function compileMessage(transaction) {
441
481
  version: transaction.version
442
482
  };
443
483
  }
444
- function getAddressTableLookupCodec() {
445
- return struct(
446
- [
484
+ var lookupTableAddressDescription = __DEV__ ? "The address of the address lookup table account from which instruction addresses should be looked up" : "lookupTableAddress";
485
+ var writableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as writeable" : "writableIndices";
486
+ var readableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as read-only" : "readableIndices";
487
+ 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";
488
+ var memoizedAddressTableLookupEncoder;
489
+ function getAddressTableLookupEncoder() {
490
+ if (!memoizedAddressTableLookupEncoder) {
491
+ memoizedAddressTableLookupEncoder = getStructEncoder(
447
492
  [
448
- "lookupTableAddress",
449
- getBase58EncodedAddressCodec(
450
- __DEV__ ? {
451
- description: "The address of the address lookup table account from which instruction addresses should be looked up"
452
- } : void 0
453
- )
493
+ ["lookupTableAddress", getAddressEncoder({ description: lookupTableAddressDescription })],
494
+ [
495
+ "writableIndices",
496
+ getArrayEncoder(getU8Encoder(), {
497
+ description: writableIndicesDescription,
498
+ size: getShortU16Encoder()
499
+ })
500
+ ],
501
+ [
502
+ "readableIndices",
503
+ getArrayEncoder(getU8Encoder(), {
504
+ description: readableIndicesDescription,
505
+ size: getShortU16Encoder()
506
+ })
507
+ ]
454
508
  ],
509
+ { description: addressTableLookupDescription }
510
+ );
511
+ }
512
+ return memoizedAddressTableLookupEncoder;
513
+ }
514
+ var memoizedAddressTableLookupDecoder;
515
+ function getAddressTableLookupDecoder() {
516
+ if (!memoizedAddressTableLookupDecoder) {
517
+ memoizedAddressTableLookupDecoder = getStructDecoder(
455
518
  [
456
- "writableIndices",
457
- array(u8(), {
458
- ...__DEV__ ? {
459
- description: "The indices of the accounts in the lookup table that should be loaded as writeable"
460
- } : null,
461
- size: shortU16()
462
- })
519
+ ["lookupTableAddress", getAddressDecoder({ description: lookupTableAddressDescription })],
520
+ [
521
+ "writableIndices",
522
+ getArrayDecoder(getU8Decoder(), {
523
+ description: writableIndicesDescription,
524
+ size: getShortU16Decoder()
525
+ })
526
+ ],
527
+ [
528
+ "readableIndices",
529
+ getArrayDecoder(getU8Decoder(), {
530
+ description: readableIndicesDescription,
531
+ size: getShortU16Decoder()
532
+ })
533
+ ]
463
534
  ],
464
- [
465
- "readableIndices",
466
- array(u8(), {
467
- ...__DEV__ ? {
468
- description: "The indices of the accounts in the lookup table that should be loaded as read-only"
469
- } : void 0,
470
- size: shortU16()
471
- })
472
- ]
473
- ],
474
- __DEV__ ? {
475
- description: "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"
476
- } : void 0
477
- );
535
+ { description: addressTableLookupDescription }
536
+ );
537
+ }
538
+ return memoizedAddressTableLookupDecoder;
478
539
  }
479
- function getMessageHeaderCodec() {
480
- return struct(
540
+ var memoizedU8Encoder;
541
+ function getMemoizedU8Encoder() {
542
+ if (!memoizedU8Encoder)
543
+ memoizedU8Encoder = getU8Encoder();
544
+ return memoizedU8Encoder;
545
+ }
546
+ function getMemoizedU8EncoderDescription(description) {
547
+ const encoder = getMemoizedU8Encoder();
548
+ return {
549
+ ...encoder,
550
+ description: description ?? encoder.description
551
+ };
552
+ }
553
+ var memoizedU8Decoder;
554
+ function getMemoizedU8Decoder() {
555
+ if (!memoizedU8Decoder)
556
+ memoizedU8Decoder = getU8Decoder();
557
+ return memoizedU8Decoder;
558
+ }
559
+ function getMemoizedU8DecoderDescription(description) {
560
+ const decoder = getMemoizedU8Decoder();
561
+ return {
562
+ ...decoder,
563
+ description: description ?? decoder.description
564
+ };
565
+ }
566
+ 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;
567
+ 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;
568
+ var numReadonlyNonSignerAccountsDescription = __DEV__ ? "The expected number of addresses in the static address list belonging to accounts that are neither signers, nor writable" : void 0;
569
+ var messageHeaderDescription = __DEV__ ? "The transaction message header containing counts of the signer, readonly-signer, and readonly-nonsigner account addresses" : void 0;
570
+ function getMessageHeaderEncoder() {
571
+ return getStructEncoder(
481
572
  [
482
- [
483
- "numSignerAccounts",
484
- u8(
485
- __DEV__ ? {
486
- description: "The expected number of addresses in the static address list belonging to accounts that are required to sign this transaction"
487
- } : void 0
488
- )
489
- ],
490
- [
491
- "numReadonlySignerAccounts",
492
- u8(
493
- __DEV__ ? {
494
- description: "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"
495
- } : void 0
496
- )
497
- ],
498
- [
499
- "numReadonlyNonSignerAccounts",
500
- u8(
501
- __DEV__ ? {
502
- description: "The expected number of addresses in the static address list belonging to accounts that are neither signers, nor writable"
503
- } : void 0
504
- )
505
- ]
573
+ ["numSignerAccounts", getMemoizedU8EncoderDescription(numSignerAccountsDescription)],
574
+ ["numReadonlySignerAccounts", getMemoizedU8EncoderDescription(numReadonlySignerAccountsDescription)],
575
+ ["numReadonlyNonSignerAccounts", getMemoizedU8EncoderDescription(numReadonlyNonSignerAccountsDescription)]
506
576
  ],
507
- __DEV__ ? {
508
- description: "The transaction message header containing counts of the signer, readonly-signer, and readonly-nonsigner account addresses"
509
- } : void 0
577
+ {
578
+ description: messageHeaderDescription
579
+ }
510
580
  );
511
581
  }
512
- function getInstructionCodec() {
513
- return mapSerializer(
514
- struct([
515
- [
516
- "programAddressIndex",
517
- u8(
518
- __DEV__ ? {
519
- description: "The index of the program being called, according to the well-ordered accounts list for this transaction"
520
- } : void 0
521
- )
522
- ],
523
- [
524
- "addressIndices",
525
- array(
526
- u8({
527
- description: __DEV__ ? "The index of an account, according to the well-ordered accounts list for this transaction" : ""
528
- }),
529
- {
530
- description: __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" : "",
531
- size: shortU16()
532
- }
533
- )
534
- ],
535
- [
536
- "data",
537
- bytes({
538
- description: __DEV__ ? "An optional buffer of data passed to the instruction" : "",
539
- size: shortU16()
540
- })
541
- ]
542
- ]),
543
- (value) => {
544
- if (value.addressIndices !== void 0 && value.data !== void 0) {
545
- return value;
546
- }
547
- return {
548
- ...value,
549
- addressIndices: value.addressIndices ?? [],
550
- data: value.data ?? new Uint8Array(0)
551
- };
552
- },
553
- (value) => {
554
- if (value.addressIndices.length && value.data.byteLength) {
555
- return value;
556
- }
557
- const { addressIndices, data, ...rest } = value;
558
- return {
559
- ...rest,
560
- ...addressIndices.length ? { addressIndices } : null,
561
- ...data.byteLength ? { data } : null
562
- };
582
+ function getMessageHeaderDecoder() {
583
+ return getStructDecoder(
584
+ [
585
+ ["numSignerAccounts", getMemoizedU8DecoderDescription(numSignerAccountsDescription)],
586
+ ["numReadonlySignerAccounts", getMemoizedU8DecoderDescription(numReadonlySignerAccountsDescription)],
587
+ ["numReadonlyNonSignerAccounts", getMemoizedU8DecoderDescription(numReadonlyNonSignerAccountsDescription)]
588
+ ],
589
+ {
590
+ description: messageHeaderDescription
563
591
  }
564
592
  );
565
593
  }
566
-
567
- // src/serializers/unimplemented.ts
568
- function getError(type, name) {
569
- const functionSuffix = name + type[0].toUpperCase() + type.slice(1);
570
- return new Error(
571
- `No ${type} exists for ${name}. Use \`get${functionSuffix}()\` if you need a ${type}, and \`get${name}Codec()\` if you need to both encode and decode ${name}`
572
- );
594
+ var programAddressIndexDescription = __DEV__ ? "The index of the program being called, according to the well-ordered accounts list for this transaction" : "programAddressIndex";
595
+ var accountIndexDescription = __DEV__ ? "The index of an account, according to the well-ordered accounts list for this transaction" : void 0;
596
+ 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";
597
+ var dataDescription = __DEV__ ? "An optional buffer of data passed to the instruction" : "data";
598
+ var memoizedGetInstructionEncoder;
599
+ function getInstructionEncoder() {
600
+ if (!memoizedGetInstructionEncoder) {
601
+ memoizedGetInstructionEncoder = mapEncoder(
602
+ getStructEncoder([
603
+ ["programAddressIndex", getU8Encoder({ description: programAddressIndexDescription })],
604
+ [
605
+ "accountIndices",
606
+ getArrayEncoder(getU8Encoder({ description: accountIndexDescription }), {
607
+ description: accountIndicesDescription,
608
+ size: getShortU16Encoder()
609
+ })
610
+ ],
611
+ ["data", getBytesEncoder({ description: dataDescription, size: getShortU16Encoder() })]
612
+ ]),
613
+ // Convert an instruction to have all fields defined
614
+ (instruction) => {
615
+ if (instruction.accountIndices !== void 0 && instruction.data !== void 0) {
616
+ return instruction;
617
+ }
618
+ return {
619
+ ...instruction,
620
+ accountIndices: instruction.accountIndices ?? [],
621
+ data: instruction.data ?? new Uint8Array(0)
622
+ };
623
+ }
624
+ );
625
+ }
626
+ return memoizedGetInstructionEncoder;
573
627
  }
574
- function getUnimplementedDecoder(name) {
575
- return () => {
576
- throw getError("decoder", name);
577
- };
628
+ var memoizedGetInstructionDecoder;
629
+ function getInstructionDecoder() {
630
+ if (!memoizedGetInstructionDecoder) {
631
+ memoizedGetInstructionDecoder = mapDecoder(
632
+ getStructDecoder([
633
+ ["programAddressIndex", getU8Decoder({ description: programAddressIndexDescription })],
634
+ [
635
+ "accountIndices",
636
+ getArrayDecoder(getU8Decoder({ description: accountIndexDescription }), {
637
+ description: accountIndicesDescription,
638
+ size: getShortU16Decoder()
639
+ })
640
+ ],
641
+ ["data", getBytesDecoder({ description: dataDescription, size: getShortU16Decoder() })]
642
+ ]),
643
+ // Convert an instruction to exclude optional fields if they are empty
644
+ (instruction) => {
645
+ if (instruction.accountIndices.length && instruction.data.byteLength) {
646
+ return instruction;
647
+ }
648
+ const { accountIndices, data, ...rest } = instruction;
649
+ return {
650
+ ...rest,
651
+ ...accountIndices.length ? { accountIndices } : null,
652
+ ...data.byteLength ? { data } : null
653
+ };
654
+ }
655
+ );
656
+ }
657
+ return memoizedGetInstructionDecoder;
578
658
  }
579
-
580
- // src/serializers/transaction-version.ts
581
659
  var VERSION_FLAG_MASK = 128;
582
660
  var BASE_CONFIG = {
583
661
  description: __DEV__ ? "A single byte that encodes the version of the transaction" : "",
584
662
  fixedSize: null,
585
663
  maxSize: 1
586
664
  };
587
- function deserialize(bytes3, offset = 0) {
588
- const firstByte = bytes3[offset];
665
+ function decode(bytes, offset = 0) {
666
+ const firstByte = bytes[offset];
589
667
  if ((firstByte & VERSION_FLAG_MASK) === 0) {
590
668
  return ["legacy", offset];
591
669
  } else {
@@ -593,7 +671,7 @@ function deserialize(bytes3, offset = 0) {
593
671
  return [version, offset + 1];
594
672
  }
595
673
  }
596
- function serialize(value) {
674
+ function encode(value) {
597
675
  if (value === "legacy") {
598
676
  return new Uint8Array();
599
677
  }
@@ -602,105 +680,143 @@ function serialize(value) {
602
680
  }
603
681
  return new Uint8Array([value | VERSION_FLAG_MASK]);
604
682
  }
605
- function getTransactionVersionCodec() {
683
+ function getTransactionVersionDecoder() {
684
+ return {
685
+ ...BASE_CONFIG,
686
+ decode
687
+ };
688
+ }
689
+ function getTransactionVersionEncoder() {
606
690
  return {
607
691
  ...BASE_CONFIG,
608
- deserialize,
609
- serialize
692
+ encode
610
693
  };
611
694
  }
612
695
 
613
696
  // src/serializers/message.ts
614
- var BASE_CONFIG2 = {
615
- description: __DEV__ ? "The wire format of a Solana transaction message" : "",
616
- fixedSize: null,
617
- maxSize: null
618
- };
619
- function serialize2(compiledMessage) {
620
- if (compiledMessage.version === "legacy") {
621
- return struct(getPreludeStructSerializerTuple()).serialize(compiledMessage);
622
- } else {
623
- return mapSerializer(
624
- struct([
625
- ...getPreludeStructSerializerTuple(),
626
- ["addressTableLookups", getAddressTableLookupsSerializer()]
627
- ]),
628
- (value) => {
629
- if (value.version === "legacy") {
630
- return value;
631
- }
632
- return {
633
- ...value,
634
- addressTableLookups: value.addressTableLookups ?? []
635
- };
697
+ var staticAccountsDescription = __DEV__ ? "A compact-array of static account addresses belonging to this transaction" : "staticAccounts";
698
+ var lifetimeTokenDescription = __DEV__ ? "A 32-byte token that specifies the lifetime of this transaction (eg. a recent blockhash, or a durable nonce)" : "lifetimeToken";
699
+ var instructionsDescription = __DEV__ ? "A compact-array of instructions belonging to this transaction" : "instructions";
700
+ var addressTableLookupsDescription = __DEV__ ? "A compact array of address table lookups belonging to this transaction" : "addressTableLookups";
701
+ function getCompiledMessageLegacyEncoder() {
702
+ return getStructEncoder(getPreludeStructEncoderTuple());
703
+ }
704
+ function getCompiledMessageVersionedEncoder() {
705
+ return mapEncoder(
706
+ getStructEncoder([
707
+ ...getPreludeStructEncoderTuple(),
708
+ ["addressTableLookups", getAddressTableLookupArrayEncoder()]
709
+ ]),
710
+ (value) => {
711
+ if (value.version === "legacy") {
712
+ return value;
636
713
  }
637
- ).serialize(compiledMessage);
638
- }
714
+ return {
715
+ ...value,
716
+ addressTableLookups: value.addressTableLookups ?? []
717
+ };
718
+ }
719
+ );
639
720
  }
640
- function getPreludeStructSerializerTuple() {
721
+ function getPreludeStructEncoderTuple() {
641
722
  return [
642
- ["version", getTransactionVersionCodec()],
643
- ["header", getMessageHeaderCodec()],
723
+ ["version", getTransactionVersionEncoder()],
724
+ ["header", getMessageHeaderEncoder()],
644
725
  [
645
726
  "staticAccounts",
646
- array(getBase58EncodedAddressCodec(), {
647
- description: __DEV__ ? "A compact-array of static account addresses belonging to this transaction" : "",
648
- size: shortU16()
727
+ getArrayEncoder(getAddressEncoder(), {
728
+ description: staticAccountsDescription,
729
+ size: getShortU16Encoder()
649
730
  })
650
731
  ],
651
732
  [
652
733
  "lifetimeToken",
653
- string({
654
- description: __DEV__ ? "A 32-byte token that specifies the lifetime of this transaction (eg. a recent blockhash, or a durable nonce)" : "",
655
- encoding: base58,
734
+ getStringEncoder({
735
+ description: lifetimeTokenDescription,
736
+ encoding: getBase58Encoder(),
656
737
  size: 32
657
738
  })
658
739
  ],
659
740
  [
660
741
  "instructions",
661
- array(getInstructionCodec(), {
662
- description: __DEV__ ? "A compact-array of instructions belonging to this transaction" : "",
663
- size: shortU16()
742
+ getArrayEncoder(getInstructionEncoder(), {
743
+ description: instructionsDescription,
744
+ size: getShortU16Encoder()
664
745
  })
665
746
  ]
666
747
  ];
667
748
  }
668
- function getAddressTableLookupsSerializer() {
669
- return array(getAddressTableLookupCodec(), {
670
- ...__DEV__ ? { description: "A compact array of address table lookups belonging to this transaction" } : null,
671
- size: shortU16()
749
+ function getPreludeStructDecoderTuple() {
750
+ return [
751
+ ["version", getTransactionVersionDecoder()],
752
+ ["header", getMessageHeaderDecoder()],
753
+ [
754
+ "staticAccounts",
755
+ getArrayDecoder(getAddressDecoder(), {
756
+ description: staticAccountsDescription,
757
+ size: getShortU16Decoder()
758
+ })
759
+ ],
760
+ [
761
+ "lifetimeToken",
762
+ getStringDecoder({
763
+ description: lifetimeTokenDescription,
764
+ encoding: getBase58Decoder(),
765
+ size: 32
766
+ })
767
+ ],
768
+ [
769
+ "instructions",
770
+ getArrayDecoder(getInstructionDecoder(), {
771
+ description: instructionsDescription,
772
+ size: getShortU16Decoder()
773
+ })
774
+ ],
775
+ ["addressTableLookups", getAddressTableLookupArrayDecoder()]
776
+ ];
777
+ }
778
+ function getAddressTableLookupArrayEncoder() {
779
+ return getArrayEncoder(getAddressTableLookupEncoder(), {
780
+ description: addressTableLookupsDescription,
781
+ size: getShortU16Encoder()
782
+ });
783
+ }
784
+ function getAddressTableLookupArrayDecoder() {
785
+ return getArrayDecoder(getAddressTableLookupDecoder(), {
786
+ description: addressTableLookupsDescription,
787
+ size: getShortU16Decoder()
672
788
  });
673
789
  }
790
+ var messageDescription = __DEV__ ? "The wire format of a Solana transaction message" : "message";
674
791
  function getCompiledMessageEncoder() {
675
792
  return {
676
- ...BASE_CONFIG2,
677
- deserialize: getUnimplementedDecoder("CompiledMessage"),
678
- serialize: serialize2
793
+ description: messageDescription,
794
+ encode: (compiledMessage) => {
795
+ if (compiledMessage.version === "legacy") {
796
+ return getCompiledMessageLegacyEncoder().encode(compiledMessage);
797
+ } else {
798
+ return getCompiledMessageVersionedEncoder().encode(compiledMessage);
799
+ }
800
+ },
801
+ fixedSize: null,
802
+ maxSize: null
679
803
  };
680
804
  }
681
-
682
- // src/signatures.ts
683
- async function getCompiledMessageSignature(message, secretKey) {
684
- const wireMessageBytes = getCompiledMessageEncoder().serialize(message);
685
- const signature = await signBytes(secretKey, wireMessageBytes);
686
- return signature;
805
+ function getCompiledMessageDecoder() {
806
+ return mapDecoder(
807
+ getStructDecoder(getPreludeStructDecoderTuple(), {
808
+ description: messageDescription
809
+ }),
810
+ ({ addressTableLookups, ...restOfMessage }) => {
811
+ if (restOfMessage.version === "legacy" || !addressTableLookups?.length) {
812
+ return restOfMessage;
813
+ }
814
+ return { ...restOfMessage, addressTableLookups };
815
+ }
816
+ );
687
817
  }
688
- async function signTransaction(keyPair, transaction) {
689
- const compiledMessage = compileMessage(transaction);
690
- const [signerPublicKey, signature] = await Promise.all([
691
- getBase58EncodedAddressFromPublicKey(keyPair.publicKey),
692
- getCompiledMessageSignature(compiledMessage, keyPair.privateKey)
693
- ]);
694
- const nextSignatures = {
695
- ..."signatures" in transaction ? transaction.signatures : null,
696
- ...{ [signerPublicKey]: signature }
697
- };
698
- const out = {
699
- ...transaction,
700
- signatures: nextSignatures
701
- };
702
- Object.freeze(out);
703
- return out;
818
+ function getCompiledMessageCodec() {
819
+ return combineCodec(getCompiledMessageEncoder(), getCompiledMessageDecoder());
704
820
  }
705
821
 
706
822
  // src/compile-transaction.ts
@@ -720,42 +836,221 @@ function getCompiledTransaction(transaction) {
720
836
  signatures
721
837
  };
722
838
  }
839
+ function getAccountMetas(message) {
840
+ const { header } = message;
841
+ const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
842
+ const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
843
+ const accountMetas = [];
844
+ let accountIndex = 0;
845
+ for (let i = 0; i < numWritableSignerAccounts; i++) {
846
+ accountMetas.push({
847
+ address: message.staticAccounts[accountIndex],
848
+ role: AccountRole.WRITABLE_SIGNER
849
+ });
850
+ accountIndex++;
851
+ }
852
+ for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
853
+ accountMetas.push({
854
+ address: message.staticAccounts[accountIndex],
855
+ role: AccountRole.READONLY_SIGNER
856
+ });
857
+ accountIndex++;
858
+ }
859
+ for (let i = 0; i < numWritableNonSignerAccounts; i++) {
860
+ accountMetas.push({
861
+ address: message.staticAccounts[accountIndex],
862
+ role: AccountRole.WRITABLE
863
+ });
864
+ accountIndex++;
865
+ }
866
+ for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
867
+ accountMetas.push({
868
+ address: message.staticAccounts[accountIndex],
869
+ role: AccountRole.READONLY
870
+ });
871
+ accountIndex++;
872
+ }
873
+ return accountMetas;
874
+ }
875
+ function convertInstruction(instruction, accountMetas) {
876
+ const programAddress = accountMetas[instruction.programAddressIndex]?.address;
877
+ if (!programAddress) {
878
+ throw new Error(`Could not find program address at index ${instruction.programAddressIndex}`);
879
+ }
880
+ const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
881
+ const { data } = instruction;
882
+ return {
883
+ programAddress,
884
+ ...accounts && accounts.length ? { accounts } : {},
885
+ ...data && data.length ? { data } : {}
886
+ };
887
+ }
888
+ function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
889
+ if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
890
+ return {
891
+ blockhash: messageLifetimeToken,
892
+ lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
893
+ // U64 MAX
894
+ };
895
+ } else {
896
+ const nonceAccountAddress = firstInstruction.accounts[0].address;
897
+ assertIsAddress(nonceAccountAddress);
898
+ const nonceAuthorityAddress = firstInstruction.accounts[2].address;
899
+ assertIsAddress(nonceAuthorityAddress);
900
+ return {
901
+ nonce: messageLifetimeToken,
902
+ nonceAccountAddress,
903
+ nonceAuthorityAddress
904
+ };
905
+ }
906
+ }
907
+ function convertSignatures(compiledTransaction) {
908
+ const {
909
+ compiledMessage: { staticAccounts },
910
+ signatures
911
+ } = compiledTransaction;
912
+ return signatures.reduce((acc, sig, index) => {
913
+ const allZeros = sig.every((byte) => byte === 0);
914
+ if (allZeros)
915
+ return acc;
916
+ const address = staticAccounts[index];
917
+ return { ...acc, [address]: sig };
918
+ }, {});
919
+ }
920
+ function decompileTransaction(compiledTransaction, lastValidBlockHeight) {
921
+ const { compiledMessage } = compiledTransaction;
922
+ if ("addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups.length > 0) {
923
+ throw new Error("Cannot convert transaction with addressTableLookups");
924
+ }
925
+ const feePayer = compiledMessage.staticAccounts[0];
926
+ if (!feePayer)
927
+ throw new Error("No fee payer set in CompiledTransaction");
928
+ const accountMetas = getAccountMetas(compiledMessage);
929
+ const instructions = compiledMessage.instructions.map(
930
+ (compiledInstruction) => convertInstruction(compiledInstruction, accountMetas)
931
+ );
932
+ const firstInstruction = instructions[0];
933
+ const lifetimeConstraint = getLifetimeConstraint(
934
+ compiledMessage.lifetimeToken,
935
+ firstInstruction,
936
+ lastValidBlockHeight
937
+ );
938
+ const signatures = convertSignatures(compiledTransaction);
939
+ return pipe(
940
+ createTransaction({ version: compiledMessage.version }),
941
+ (tx) => setTransactionFeePayer(feePayer, tx),
942
+ (tx) => instructions.reduce((acc, instruction) => {
943
+ return appendTransactionInstruction(instruction, acc);
944
+ }, tx),
945
+ (tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
946
+ (tx) => compiledTransaction.signatures.length ? { ...tx, signatures } : tx
947
+ );
948
+ }
723
949
 
724
950
  // src/serializers/transaction.ts
725
- var BASE_CONFIG3 = {
726
- description: __DEV__ ? "The wire format of a Solana transaction" : "",
727
- fixedSize: null,
728
- maxSize: null
729
- };
730
- function serialize3(transaction) {
731
- const compiledTransaction = getCompiledTransaction(transaction);
732
- return struct([
951
+ var signaturesDescription = __DEV__ ? "A compact array of 64-byte, base-64 encoded Ed25519 signatures" : "signatures";
952
+ var transactionDescription = __DEV__ ? "The wire format of a Solana transaction" : "transaction";
953
+ function getCompiledTransactionEncoder() {
954
+ return getStructEncoder(
733
955
  [
734
- "signatures",
735
- array(bytes({ size: 64 }), {
736
- ...__DEV__ ? { description: "A compact array of 64-byte, base-64 encoded Ed25519 signatures" } : null,
737
- size: shortU16()
738
- })
956
+ [
957
+ "signatures",
958
+ getArrayEncoder(getBytesEncoder({ size: 64 }), {
959
+ description: signaturesDescription,
960
+ size: getShortU16Encoder()
961
+ })
962
+ ],
963
+ ["compiledMessage", getCompiledMessageEncoder()]
739
964
  ],
740
- ["compiledMessage", getCompiledMessageEncoder()]
741
- ]).serialize(compiledTransaction);
965
+ {
966
+ description: transactionDescription
967
+ }
968
+ );
969
+ }
970
+ function getSignatureDecoder() {
971
+ return mapDecoder(getBytesDecoder({ size: 64 }), (bytes) => bytes);
972
+ }
973
+ function getCompiledTransactionDecoder() {
974
+ return getStructDecoder(
975
+ [
976
+ [
977
+ "signatures",
978
+ getArrayDecoder(getSignatureDecoder(), {
979
+ description: signaturesDescription,
980
+ size: getShortU16Decoder()
981
+ })
982
+ ],
983
+ ["compiledMessage", getCompiledMessageDecoder()]
984
+ ],
985
+ {
986
+ description: transactionDescription
987
+ }
988
+ );
742
989
  }
743
990
  function getTransactionEncoder() {
744
- return {
745
- ...BASE_CONFIG3,
746
- deserialize: getUnimplementedDecoder("CompiledMessage"),
747
- serialize: serialize3
991
+ return mapEncoder(getCompiledTransactionEncoder(), getCompiledTransaction);
992
+ }
993
+ function getTransactionDecoder(lastValidBlockHeight) {
994
+ return mapDecoder(
995
+ getCompiledTransactionDecoder(),
996
+ (compiledTransaction) => decompileTransaction(compiledTransaction, lastValidBlockHeight)
997
+ );
998
+ }
999
+ function getTransactionCodec(lastValidBlockHeight) {
1000
+ return combineCodec(getTransactionEncoder(), getTransactionDecoder(lastValidBlockHeight));
1001
+ }
1002
+ var base58Decoder;
1003
+ function getSignatureFromTransaction(transaction) {
1004
+ if (!base58Decoder)
1005
+ base58Decoder = getBase58Decoder();
1006
+ const signatureBytes = transaction.signatures[transaction.feePayer];
1007
+ if (!signatureBytes) {
1008
+ throw new Error(
1009
+ "Could not determine this transaction's signature. Make sure that the transaction has been signed by its fee payer."
1010
+ );
1011
+ }
1012
+ const transactionSignature = base58Decoder.decode(signatureBytes)[0];
1013
+ return transactionSignature;
1014
+ }
1015
+ async function partiallySignTransaction(keyPairs, transaction) {
1016
+ const compiledMessage = compileMessage(transaction);
1017
+ const nextSignatures = "signatures" in transaction ? { ...transaction.signatures } : {};
1018
+ const wireMessageBytes = getCompiledMessageEncoder().encode(compiledMessage);
1019
+ const publicKeySignaturePairs = await Promise.all(
1020
+ keyPairs.map(
1021
+ (keyPair) => Promise.all([getAddressFromPublicKey(keyPair.publicKey), signBytes(keyPair.privateKey, wireMessageBytes)])
1022
+ )
1023
+ );
1024
+ for (const [signerPublicKey, signature] of publicKeySignaturePairs) {
1025
+ nextSignatures[signerPublicKey] = signature;
1026
+ }
1027
+ const out = {
1028
+ ...transaction,
1029
+ signatures: nextSignatures
748
1030
  };
1031
+ Object.freeze(out);
1032
+ return out;
1033
+ }
1034
+ async function signTransaction(keyPairs, transaction) {
1035
+ const out = await partiallySignTransaction(keyPairs, transaction);
1036
+ assertTransactionIsFullySigned(out);
1037
+ Object.freeze(out);
1038
+ return out;
1039
+ }
1040
+ function assertTransactionIsFullySigned(transaction) {
1041
+ const signerAddressesFromInstructions = transaction.instructions.flatMap((i) => i.accounts?.filter((a) => isSignerRole(a.role)) ?? []).map((a) => a.address);
1042
+ const requiredSigners = /* @__PURE__ */ new Set([transaction.feePayer, ...signerAddressesFromInstructions]);
1043
+ requiredSigners.forEach((address) => {
1044
+ if (!transaction.signatures[address]) {
1045
+ throw new Error(`Transaction is missing signature for address \`${address}\``);
1046
+ }
1047
+ });
749
1048
  }
750
-
751
- // src/wire-transaction.ts
752
1049
  function getBase64EncodedWireTransaction(transaction) {
753
- const wireTransactionBytes = getTransactionEncoder().serialize(transaction);
754
- {
755
- return btoa(String.fromCharCode(...wireTransactionBytes));
756
- }
1050
+ const wireTransactionBytes = getTransactionEncoder().encode(transaction);
1051
+ return getBase64Decoder().decode(wireTransactionBytes)[0];
757
1052
  }
758
1053
 
759
- export { appendTransactionInstruction, assertIsBlockhash, assertIsDurableNonceTransaction, createTransaction, getBase64EncodedWireTransaction, prependTransactionInstruction, setTransactionFeePayer, setTransactionLifetimeUsingBlockhash, setTransactionLifetimeUsingDurableNonce, signTransaction };
1054
+ export { appendTransactionInstruction, assertIsBlockhash, assertIsDurableNonceTransaction, assertIsTransactionWithBlockhashLifetime, assertTransactionIsFullySigned, compileMessage, createTransaction, getBase64EncodedWireTransaction, getCompiledMessageCodec, getCompiledMessageDecoder, getCompiledMessageEncoder, getSignatureFromTransaction, getTransactionCodec, getTransactionDecoder, getTransactionEncoder, isAdvanceNonceAccountInstruction, partiallySignTransaction, prependTransactionInstruction, setTransactionFeePayer, setTransactionLifetimeUsingBlockhash, setTransactionLifetimeUsingDurableNonce, signTransaction };
760
1055
  //# sourceMappingURL=out.js.map
761
1056
  //# sourceMappingURL=index.browser.js.map