@solana/transactions 2.0.0-experimental.fc4e943 → 2.0.0-experimental.fd11bd1

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.
@@ -1,10 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var umiSerializers = require('@metaplex-foundation/umi-serializers');
4
- var addresses = require('@solana/addresses');
3
+ var codecsStrings = require('@solana/codecs-strings');
4
+ var codecsCore = require('@solana/codecs-core');
5
5
  var codecsDataStructures = require('@solana/codecs-data-structures');
6
6
  var codecsNumbers = require('@solana/codecs-numbers');
7
- var codecsCore = require('@solana/codecs-core');
7
+ var addresses = require('@solana/addresses');
8
+ var functional = require('@solana/functional');
8
9
  var keys = require('@solana/keys');
9
10
 
10
11
  // ../build-scripts/env-shim.ts
@@ -25,7 +26,10 @@ function getUnsignedTransaction(transaction) {
25
26
  }
26
27
 
27
28
  // src/blockhash.ts
29
+ var base58Encoder;
28
30
  function assertIsBlockhash(putativeBlockhash) {
31
+ if (!base58Encoder)
32
+ base58Encoder = codecsStrings.getBase58Encoder();
29
33
  try {
30
34
  if (
31
35
  // Lowest value (32 bytes of zeroes)
@@ -34,8 +38,8 @@ function assertIsBlockhash(putativeBlockhash) {
34
38
  ) {
35
39
  throw new Error("Expected input string to decode to a byte array of length 32.");
36
40
  }
37
- const bytes3 = umiSerializers.base58.serialize(putativeBlockhash);
38
- const numBytes = bytes3.byteLength;
41
+ const bytes = base58Encoder.encode(putativeBlockhash);
42
+ const numBytes = bytes.byteLength;
39
43
  if (numBytes !== 32) {
40
44
  throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${numBytes}`);
41
45
  }
@@ -120,7 +124,7 @@ function isAdvanceNonceAccountInstruction(instruction) {
120
124
  instruction.accounts?.length === 3 && // First account is nonce account address
121
125
  instruction.accounts[0].address != null && instruction.accounts[0].role === AccountRole.WRITABLE && // Second account is recent blockhashes sysvar
122
126
  instruction.accounts[1].address === RECENT_BLOCKHASHES_SYSVAR_ADDRESS && instruction.accounts[1].role === AccountRole.READONLY && // Third account is nonce authority account
123
- instruction.accounts[2].address != null && instruction.accounts[2].role === AccountRole.READONLY_SIGNER;
127
+ instruction.accounts[2].address != null && isSignerRole(instruction.accounts[2].role);
124
128
  }
125
129
  function isAdvanceNonceAccountInstructionData(data) {
126
130
  return data.byteLength === 4 && data[0] === 4 && data[1] === 0 && data[2] === 0 && data[3] === 0;
@@ -128,21 +132,38 @@ function isAdvanceNonceAccountInstructionData(data) {
128
132
  function isDurableNonceTransaction(transaction) {
129
133
  return "lifetimeConstraint" in transaction && typeof transaction.lifetimeConstraint.nonce === "string" && transaction.instructions[0] != null && isAdvanceNonceAccountInstruction(transaction.instructions[0]);
130
134
  }
135
+ function isAdvanceNonceAccountInstructionForNonce(instruction, nonceAccountAddress, nonceAuthorityAddress) {
136
+ return instruction.accounts[0].address === nonceAccountAddress && instruction.accounts[2].address === nonceAuthorityAddress;
137
+ }
131
138
  function setTransactionLifetimeUsingDurableNonce({
132
139
  nonce,
133
140
  nonceAccountAddress,
134
141
  nonceAuthorityAddress
135
142
  }, transaction) {
136
- const isAlreadyDurableNonceTransaction = isDurableNonceTransaction(transaction);
137
- if (isAlreadyDurableNonceTransaction && transaction.lifetimeConstraint.nonce === nonce && transaction.instructions[0].accounts[0].address === nonceAccountAddress && transaction.instructions[0].accounts[2].address === nonceAuthorityAddress) {
138
- return transaction;
143
+ let newInstructions;
144
+ const firstInstruction = transaction.instructions[0];
145
+ if (firstInstruction && isAdvanceNonceAccountInstruction(firstInstruction)) {
146
+ if (isAdvanceNonceAccountInstructionForNonce(firstInstruction, nonceAccountAddress, nonceAuthorityAddress)) {
147
+ if (isDurableNonceTransaction(transaction) && transaction.lifetimeConstraint.nonce === nonce) {
148
+ return transaction;
149
+ } else {
150
+ newInstructions = [firstInstruction, ...transaction.instructions.slice(1)];
151
+ }
152
+ } else {
153
+ newInstructions = [
154
+ createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
155
+ ...transaction.instructions.slice(1)
156
+ ];
157
+ }
158
+ } else {
159
+ newInstructions = [
160
+ createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
161
+ ...transaction.instructions
162
+ ];
139
163
  }
140
164
  const out = {
141
165
  ...getUnsignedTransaction(transaction),
142
- instructions: [
143
- createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
144
- ...isAlreadyDurableNonceTransaction ? transaction.instructions.slice(1) : transaction.instructions
145
- ],
166
+ instructions: newInstructions,
146
167
  lifetimeConstraint: {
147
168
  nonce
148
169
  }
@@ -465,142 +486,299 @@ function getCompiledTransaction(transaction) {
465
486
  signatures
466
487
  };
467
488
  }
468
- function addressSerializerCompat(compat) {
469
- const codec = addresses.getAddressCodec();
489
+ function getAccountMetas(message) {
490
+ const { header } = message;
491
+ const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
492
+ const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
493
+ const accountMetas = [];
494
+ let accountIndex = 0;
495
+ for (let i = 0; i < numWritableSignerAccounts; i++) {
496
+ accountMetas.push({
497
+ address: message.staticAccounts[accountIndex],
498
+ role: AccountRole.WRITABLE_SIGNER
499
+ });
500
+ accountIndex++;
501
+ }
502
+ for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
503
+ accountMetas.push({
504
+ address: message.staticAccounts[accountIndex],
505
+ role: AccountRole.READONLY_SIGNER
506
+ });
507
+ accountIndex++;
508
+ }
509
+ for (let i = 0; i < numWritableNonSignerAccounts; i++) {
510
+ accountMetas.push({
511
+ address: message.staticAccounts[accountIndex],
512
+ role: AccountRole.WRITABLE
513
+ });
514
+ accountIndex++;
515
+ }
516
+ for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
517
+ accountMetas.push({
518
+ address: message.staticAccounts[accountIndex],
519
+ role: AccountRole.READONLY
520
+ });
521
+ accountIndex++;
522
+ }
523
+ return accountMetas;
524
+ }
525
+ function convertInstruction(instruction, accountMetas) {
526
+ const programAddress = accountMetas[instruction.programAddressIndex]?.address;
527
+ if (!programAddress) {
528
+ throw new Error(`Could not find program address at index ${instruction.programAddressIndex}`);
529
+ }
530
+ const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
531
+ const { data } = instruction;
470
532
  return {
471
- description: compat?.description ?? codec.description,
472
- deserialize: codec.decode,
473
- fixedSize: codec.fixedSize,
474
- maxSize: codec.maxSize,
475
- serialize: codec.encode
533
+ programAddress,
534
+ ...accounts && accounts.length ? { accounts } : {},
535
+ ...data && data.length ? { data } : {}
476
536
  };
477
537
  }
478
- function getAddressTableLookupCodec() {
479
- return umiSerializers.struct(
480
- [
538
+ function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
539
+ if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
540
+ return {
541
+ blockhash: messageLifetimeToken,
542
+ lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
543
+ // U64 MAX
544
+ };
545
+ } else {
546
+ const nonceAccountAddress = firstInstruction.accounts[0].address;
547
+ addresses.assertIsAddress(nonceAccountAddress);
548
+ const nonceAuthorityAddress = firstInstruction.accounts[2].address;
549
+ addresses.assertIsAddress(nonceAuthorityAddress);
550
+ return {
551
+ nonce: messageLifetimeToken,
552
+ nonceAccountAddress,
553
+ nonceAuthorityAddress
554
+ };
555
+ }
556
+ }
557
+ function convertSignatures(compiledTransaction) {
558
+ const {
559
+ compiledMessage: { staticAccounts },
560
+ signatures
561
+ } = compiledTransaction;
562
+ return signatures.reduce((acc, sig, index) => {
563
+ const allZeros = sig.every((byte) => byte === 0);
564
+ if (allZeros)
565
+ return acc;
566
+ const address = staticAccounts[index];
567
+ return { ...acc, [address]: sig };
568
+ }, {});
569
+ }
570
+ function decompileTransaction(compiledTransaction, lastValidBlockHeight) {
571
+ const { compiledMessage } = compiledTransaction;
572
+ if ("addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups.length > 0) {
573
+ throw new Error("Cannot convert transaction with addressTableLookups");
574
+ }
575
+ const feePayer = compiledMessage.staticAccounts[0];
576
+ if (!feePayer)
577
+ throw new Error("No fee payer set in CompiledTransaction");
578
+ const accountMetas = getAccountMetas(compiledMessage);
579
+ const instructions = compiledMessage.instructions.map(
580
+ (compiledInstruction) => convertInstruction(compiledInstruction, accountMetas)
581
+ );
582
+ const firstInstruction = instructions[0];
583
+ const lifetimeConstraint = getLifetimeConstraint(
584
+ compiledMessage.lifetimeToken,
585
+ firstInstruction,
586
+ lastValidBlockHeight
587
+ );
588
+ const signatures = convertSignatures(compiledTransaction);
589
+ return functional.pipe(
590
+ createTransaction({ version: compiledMessage.version }),
591
+ (tx) => setTransactionFeePayer(feePayer, tx),
592
+ (tx) => instructions.reduce((acc, instruction) => {
593
+ return appendTransactionInstruction(instruction, acc);
594
+ }, tx),
595
+ (tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
596
+ (tx) => compiledTransaction.signatures.length ? { ...tx, signatures } : tx
597
+ );
598
+ }
599
+ var lookupTableAddressDescription = __DEV__ ? "The address of the address lookup table account from which instruction addresses should be looked up" : "lookupTableAddress";
600
+ var writableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as writeable" : "writableIndices";
601
+ var readableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as read-only" : "readableIndices";
602
+ var addressTableLookupDescription = __DEV__ ? "A pointer to the address of an address lookup table, along with the readonly/writeable indices of the addresses that should be loaded from it" : "addressTableLookup";
603
+ var memoizedAddressTableLookupEncoder;
604
+ function getAddressTableLookupEncoder() {
605
+ if (!memoizedAddressTableLookupEncoder) {
606
+ memoizedAddressTableLookupEncoder = codecsDataStructures.getStructEncoder(
481
607
  [
482
- "lookupTableAddress",
483
- addressSerializerCompat(
484
- __DEV__ ? {
485
- description: "The address of the address lookup table account from which instruction addresses should be looked up"
486
- } : void 0
487
- )
608
+ ["lookupTableAddress", addresses.getAddressEncoder({ description: lookupTableAddressDescription })],
609
+ [
610
+ "writableIndices",
611
+ codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder(), {
612
+ description: writableIndicesDescription,
613
+ size: codecsNumbers.getShortU16Encoder()
614
+ })
615
+ ],
616
+ [
617
+ "readableIndices",
618
+ codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder(), {
619
+ description: readableIndicesDescription,
620
+ size: codecsNumbers.getShortU16Encoder()
621
+ })
622
+ ]
488
623
  ],
624
+ { description: addressTableLookupDescription }
625
+ );
626
+ }
627
+ return memoizedAddressTableLookupEncoder;
628
+ }
629
+ var memoizedAddressTableLookupDecoder;
630
+ function getAddressTableLookupDecoder() {
631
+ if (!memoizedAddressTableLookupDecoder) {
632
+ memoizedAddressTableLookupDecoder = codecsDataStructures.getStructDecoder(
489
633
  [
490
- "writableIndices",
491
- umiSerializers.array(umiSerializers.u8(), {
492
- ...__DEV__ ? {
493
- description: "The indices of the accounts in the lookup table that should be loaded as writeable"
494
- } : null,
495
- size: umiSerializers.shortU16()
496
- })
634
+ ["lookupTableAddress", addresses.getAddressDecoder({ description: lookupTableAddressDescription })],
635
+ [
636
+ "writableIndices",
637
+ codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), {
638
+ description: writableIndicesDescription,
639
+ size: codecsNumbers.getShortU16Decoder()
640
+ })
641
+ ],
642
+ [
643
+ "readableIndices",
644
+ codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), {
645
+ description: readableIndicesDescription,
646
+ size: codecsNumbers.getShortU16Decoder()
647
+ })
648
+ ]
497
649
  ],
498
- [
499
- "readableIndices",
500
- umiSerializers.array(umiSerializers.u8(), {
501
- ...__DEV__ ? {
502
- description: "The indices of the accounts in the lookup table that should be loaded as read-only"
503
- } : void 0,
504
- size: umiSerializers.shortU16()
505
- })
506
- ]
507
- ],
508
- __DEV__ ? {
509
- 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"
510
- } : void 0
511
- );
650
+ { description: addressTableLookupDescription }
651
+ );
652
+ }
653
+ return memoizedAddressTableLookupDecoder;
512
654
  }
513
- var memoizedU8Codec;
514
- function getMemoizedU8Codec() {
515
- if (!memoizedU8Codec)
516
- memoizedU8Codec = codecsNumbers.getU8Codec();
517
- return memoizedU8Codec;
655
+ var memoizedU8Encoder;
656
+ function getMemoizedU8Encoder() {
657
+ if (!memoizedU8Encoder)
658
+ memoizedU8Encoder = codecsNumbers.getU8Encoder();
659
+ return memoizedU8Encoder;
518
660
  }
519
- function getMemoizedU8CodecDescription(description) {
520
- const codec = getMemoizedU8Codec();
661
+ function getMemoizedU8EncoderDescription(description) {
662
+ const encoder = getMemoizedU8Encoder();
521
663
  return {
522
- ...codec,
523
- description: description ?? codec.description
664
+ ...encoder,
665
+ description: description ?? encoder.description
666
+ };
667
+ }
668
+ var memoizedU8Decoder;
669
+ function getMemoizedU8Decoder() {
670
+ if (!memoizedU8Decoder)
671
+ memoizedU8Decoder = codecsNumbers.getU8Decoder();
672
+ return memoizedU8Decoder;
673
+ }
674
+ function getMemoizedU8DecoderDescription(description) {
675
+ const decoder = getMemoizedU8Decoder();
676
+ return {
677
+ ...decoder,
678
+ description: description ?? decoder.description
524
679
  };
525
680
  }
526
681
  var numSignerAccountsDescription = __DEV__ ? "The expected number of addresses in the static address list belonging to accounts that are required to sign this transaction" : void 0;
527
682
  var numReadonlySignerAccountsDescription = __DEV__ ? "The expected number of addresses in the static address list belonging to accounts that are required to sign this transaction, but may not be writable" : void 0;
528
683
  var numReadonlyNonSignerAccountsDescription = __DEV__ ? "The expected number of addresses in the static address list belonging to accounts that are neither signers, nor writable" : void 0;
529
684
  var messageHeaderDescription = __DEV__ ? "The transaction message header containing counts of the signer, readonly-signer, and readonly-nonsigner account addresses" : void 0;
530
- function getMessageHeaderCodec() {
531
- return codecsDataStructures.getStructCodec(
685
+ function getMessageHeaderEncoder() {
686
+ return codecsDataStructures.getStructEncoder(
532
687
  [
533
- ["numSignerAccounts", getMemoizedU8CodecDescription(numSignerAccountsDescription)],
534
- ["numReadonlySignerAccounts", getMemoizedU8CodecDescription(numReadonlySignerAccountsDescription)],
535
- ["numReadonlyNonSignerAccounts", getMemoizedU8CodecDescription(numReadonlyNonSignerAccountsDescription)]
688
+ ["numSignerAccounts", getMemoizedU8EncoderDescription(numSignerAccountsDescription)],
689
+ ["numReadonlySignerAccounts", getMemoizedU8EncoderDescription(numReadonlySignerAccountsDescription)],
690
+ ["numReadonlyNonSignerAccounts", getMemoizedU8EncoderDescription(numReadonlyNonSignerAccountsDescription)]
536
691
  ],
537
692
  {
538
693
  description: messageHeaderDescription
539
694
  }
540
695
  );
541
696
  }
542
- function getInstructionCodec() {
543
- return umiSerializers.mapSerializer(
544
- umiSerializers.struct([
545
- [
546
- "programAddressIndex",
547
- umiSerializers.u8(
548
- __DEV__ ? {
549
- description: "The index of the program being called, according to the well-ordered accounts list for this transaction"
550
- } : void 0
551
- )
552
- ],
553
- [
554
- "accountIndices",
555
- umiSerializers.array(
556
- umiSerializers.u8({
557
- description: __DEV__ ? "The index of an account, according to the well-ordered accounts list for this transaction" : ""
558
- }),
559
- {
560
- 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" : "",
561
- size: umiSerializers.shortU16()
562
- }
563
- )
564
- ],
565
- [
566
- "data",
567
- umiSerializers.bytes({
568
- description: __DEV__ ? "An optional buffer of data passed to the instruction" : "",
569
- size: umiSerializers.shortU16()
570
- })
571
- ]
572
- ]),
573
- (value) => {
574
- if (value.accountIndices !== void 0 && value.data !== void 0) {
575
- return value;
576
- }
577
- return {
578
- ...value,
579
- accountIndices: value.accountIndices ?? [],
580
- data: value.data ?? new Uint8Array(0)
581
- };
582
- },
583
- (value) => {
584
- if (value.accountIndices.length && value.data.byteLength) {
585
- return value;
586
- }
587
- const { accountIndices, data, ...rest } = value;
588
- return {
589
- ...rest,
590
- ...accountIndices.length ? { accountIndices } : null,
591
- ...data.byteLength ? { data } : null
592
- };
697
+ function getMessageHeaderDecoder() {
698
+ return codecsDataStructures.getStructDecoder(
699
+ [
700
+ ["numSignerAccounts", getMemoizedU8DecoderDescription(numSignerAccountsDescription)],
701
+ ["numReadonlySignerAccounts", getMemoizedU8DecoderDescription(numReadonlySignerAccountsDescription)],
702
+ ["numReadonlyNonSignerAccounts", getMemoizedU8DecoderDescription(numReadonlyNonSignerAccountsDescription)]
703
+ ],
704
+ {
705
+ description: messageHeaderDescription
593
706
  }
594
707
  );
595
708
  }
709
+ var programAddressIndexDescription = __DEV__ ? "The index of the program being called, according to the well-ordered accounts list for this transaction" : "programAddressIndex";
710
+ var accountIndexDescription = __DEV__ ? "The index of an account, according to the well-ordered accounts list for this transaction" : void 0;
711
+ var accountIndicesDescription = __DEV__ ? "An optional list of account indices, according to the well-ordered accounts list for this transaction, in the order in which the program being called expects them" : "accountIndices";
712
+ var dataDescription = __DEV__ ? "An optional buffer of data passed to the instruction" : "data";
713
+ var memoizedGetInstructionEncoder;
714
+ function getInstructionEncoder() {
715
+ if (!memoizedGetInstructionEncoder) {
716
+ memoizedGetInstructionEncoder = codecsCore.mapEncoder(
717
+ codecsDataStructures.getStructEncoder([
718
+ ["programAddressIndex", codecsNumbers.getU8Encoder({ description: programAddressIndexDescription })],
719
+ [
720
+ "accountIndices",
721
+ codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder({ description: accountIndexDescription }), {
722
+ description: accountIndicesDescription,
723
+ size: codecsNumbers.getShortU16Encoder()
724
+ })
725
+ ],
726
+ ["data", codecsDataStructures.getBytesEncoder({ description: dataDescription, size: codecsNumbers.getShortU16Encoder() })]
727
+ ]),
728
+ // Convert an instruction to have all fields defined
729
+ (instruction) => {
730
+ if (instruction.accountIndices !== void 0 && instruction.data !== void 0) {
731
+ return instruction;
732
+ }
733
+ return {
734
+ ...instruction,
735
+ accountIndices: instruction.accountIndices ?? [],
736
+ data: instruction.data ?? new Uint8Array(0)
737
+ };
738
+ }
739
+ );
740
+ }
741
+ return memoizedGetInstructionEncoder;
742
+ }
743
+ var memoizedGetInstructionDecoder;
744
+ function getInstructionDecoder() {
745
+ if (!memoizedGetInstructionDecoder) {
746
+ memoizedGetInstructionDecoder = codecsCore.mapDecoder(
747
+ codecsDataStructures.getStructDecoder([
748
+ ["programAddressIndex", codecsNumbers.getU8Decoder({ description: programAddressIndexDescription })],
749
+ [
750
+ "accountIndices",
751
+ codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder({ description: accountIndexDescription }), {
752
+ description: accountIndicesDescription,
753
+ size: codecsNumbers.getShortU16Decoder()
754
+ })
755
+ ],
756
+ ["data", codecsDataStructures.getBytesDecoder({ description: dataDescription, size: codecsNumbers.getShortU16Decoder() })]
757
+ ]),
758
+ // Convert an instruction to exclude optional fields if they are empty
759
+ (instruction) => {
760
+ if (instruction.accountIndices.length && instruction.data.byteLength) {
761
+ return instruction;
762
+ }
763
+ const { accountIndices, data, ...rest } = instruction;
764
+ return {
765
+ ...rest,
766
+ ...accountIndices.length ? { accountIndices } : null,
767
+ ...data.byteLength ? { data } : null
768
+ };
769
+ }
770
+ );
771
+ }
772
+ return memoizedGetInstructionDecoder;
773
+ }
596
774
  var VERSION_FLAG_MASK = 128;
597
775
  var BASE_CONFIG = {
598
776
  description: __DEV__ ? "A single byte that encodes the version of the transaction" : "",
599
777
  fixedSize: null,
600
778
  maxSize: 1
601
779
  };
602
- function decode(bytes3, offset = 0) {
603
- const firstByte = bytes3[offset];
780
+ function decode(bytes, offset = 0) {
781
+ const firstByte = bytes[offset];
604
782
  if ((firstByte & VERSION_FLAG_MASK) === 0) {
605
783
  return ["legacy", offset];
606
784
  } else {
@@ -629,128 +807,187 @@ function getTransactionVersionEncoder() {
629
807
  encode
630
808
  };
631
809
  }
632
- function getTransactionVersionCodec() {
633
- return codecsCore.combineCodec(getTransactionVersionEncoder(), getTransactionVersionDecoder());
634
- }
635
-
636
- // src/serializers/unimplemented.ts
637
- function getError(type, name) {
638
- const functionSuffix = name + type[0].toUpperCase() + type.slice(1);
639
- return new Error(
640
- `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}`
641
- );
642
- }
643
- function getUnimplementedDecoder(name) {
644
- return () => {
645
- throw getError("decoder", name);
646
- };
647
- }
648
810
 
649
811
  // src/serializers/message.ts
650
- var BASE_CONFIG2 = {
651
- description: __DEV__ ? "The wire format of a Solana transaction message" : "",
652
- fixedSize: null,
653
- maxSize: null
654
- };
655
- function serialize(compiledMessage) {
656
- if (compiledMessage.version === "legacy") {
657
- return umiSerializers.struct(getPreludeStructSerializerTuple()).serialize(compiledMessage);
658
- } else {
659
- return umiSerializers.mapSerializer(
660
- umiSerializers.struct([
661
- ...getPreludeStructSerializerTuple(),
662
- ["addressTableLookups", getAddressTableLookupsSerializer()]
663
- ]),
664
- (value) => {
665
- if (value.version === "legacy") {
666
- return value;
667
- }
668
- return {
669
- ...value,
670
- addressTableLookups: value.addressTableLookups ?? []
671
- };
672
- }
673
- ).serialize(compiledMessage);
674
- }
812
+ var staticAccountsDescription = __DEV__ ? "A compact-array of static account addresses belonging to this transaction" : "staticAccounts";
813
+ var lifetimeTokenDescription = __DEV__ ? "A 32-byte token that specifies the lifetime of this transaction (eg. a recent blockhash, or a durable nonce)" : "lifetimeToken";
814
+ var instructionsDescription = __DEV__ ? "A compact-array of instructions belonging to this transaction" : "instructions";
815
+ var addressTableLookupsDescription = __DEV__ ? "A compact array of address table lookups belonging to this transaction" : "addressTableLookups";
816
+ function getCompiledMessageLegacyEncoder() {
817
+ return codecsDataStructures.getStructEncoder(getPreludeStructEncoderTuple());
675
818
  }
676
- function toSerializer(codec) {
677
- return {
678
- description: codec.description,
679
- deserialize: codec.decode,
680
- fixedSize: codec.fixedSize,
681
- maxSize: codec.maxSize,
682
- serialize: codec.encode
683
- };
819
+ function getCompiledMessageVersionedEncoder() {
820
+ return codecsCore.mapEncoder(
821
+ codecsDataStructures.getStructEncoder([
822
+ ...getPreludeStructEncoderTuple(),
823
+ ["addressTableLookups", getAddressTableLookupArrayEncoder()]
824
+ ]),
825
+ (value) => {
826
+ if (value.version === "legacy") {
827
+ return value;
828
+ }
829
+ return {
830
+ ...value,
831
+ addressTableLookups: value.addressTableLookups ?? []
832
+ };
833
+ }
834
+ );
684
835
  }
685
- function getPreludeStructSerializerTuple() {
836
+ function getPreludeStructEncoderTuple() {
686
837
  return [
687
- ["version", toSerializer(getTransactionVersionCodec())],
688
- ["header", toSerializer(getMessageHeaderCodec())],
838
+ ["version", getTransactionVersionEncoder()],
839
+ ["header", getMessageHeaderEncoder()],
689
840
  [
690
841
  "staticAccounts",
691
- umiSerializers.array(toSerializer(addresses.getAddressCodec()), {
692
- description: __DEV__ ? "A compact-array of static account addresses belonging to this transaction" : "",
693
- size: umiSerializers.shortU16()
842
+ codecsDataStructures.getArrayEncoder(addresses.getAddressEncoder(), {
843
+ description: staticAccountsDescription,
844
+ size: codecsNumbers.getShortU16Encoder()
694
845
  })
695
846
  ],
696
847
  [
697
848
  "lifetimeToken",
698
- umiSerializers.string({
699
- description: __DEV__ ? "A 32-byte token that specifies the lifetime of this transaction (eg. a recent blockhash, or a durable nonce)" : "",
700
- encoding: umiSerializers.base58,
849
+ codecsStrings.getStringEncoder({
850
+ description: lifetimeTokenDescription,
851
+ encoding: codecsStrings.getBase58Encoder(),
701
852
  size: 32
702
853
  })
703
854
  ],
704
855
  [
705
856
  "instructions",
706
- umiSerializers.array(getInstructionCodec(), {
707
- description: __DEV__ ? "A compact-array of instructions belonging to this transaction" : "",
708
- size: umiSerializers.shortU16()
857
+ codecsDataStructures.getArrayEncoder(getInstructionEncoder(), {
858
+ description: instructionsDescription,
859
+ size: codecsNumbers.getShortU16Encoder()
709
860
  })
710
861
  ]
711
862
  ];
712
863
  }
713
- function getAddressTableLookupsSerializer() {
714
- return umiSerializers.array(getAddressTableLookupCodec(), {
715
- ...__DEV__ ? { description: "A compact array of address table lookups belonging to this transaction" } : null,
716
- size: umiSerializers.shortU16()
864
+ function getPreludeStructDecoderTuple() {
865
+ return [
866
+ ["version", getTransactionVersionDecoder()],
867
+ ["header", getMessageHeaderDecoder()],
868
+ [
869
+ "staticAccounts",
870
+ codecsDataStructures.getArrayDecoder(addresses.getAddressDecoder(), {
871
+ description: staticAccountsDescription,
872
+ size: codecsNumbers.getShortU16Decoder()
873
+ })
874
+ ],
875
+ [
876
+ "lifetimeToken",
877
+ codecsStrings.getStringDecoder({
878
+ description: lifetimeTokenDescription,
879
+ encoding: codecsStrings.getBase58Decoder(),
880
+ size: 32
881
+ })
882
+ ],
883
+ [
884
+ "instructions",
885
+ codecsDataStructures.getArrayDecoder(getInstructionDecoder(), {
886
+ description: instructionsDescription,
887
+ size: codecsNumbers.getShortU16Decoder()
888
+ })
889
+ ],
890
+ ["addressTableLookups", getAddressTableLookupArrayDecoder()]
891
+ ];
892
+ }
893
+ function getAddressTableLookupArrayEncoder() {
894
+ return codecsDataStructures.getArrayEncoder(getAddressTableLookupEncoder(), {
895
+ description: addressTableLookupsDescription,
896
+ size: codecsNumbers.getShortU16Encoder()
717
897
  });
718
898
  }
899
+ function getAddressTableLookupArrayDecoder() {
900
+ return codecsDataStructures.getArrayDecoder(getAddressTableLookupDecoder(), {
901
+ description: addressTableLookupsDescription,
902
+ size: codecsNumbers.getShortU16Decoder()
903
+ });
904
+ }
905
+ var messageDescription = __DEV__ ? "The wire format of a Solana transaction message" : "message";
719
906
  function getCompiledMessageEncoder() {
720
907
  return {
721
- ...BASE_CONFIG2,
722
- deserialize: getUnimplementedDecoder("CompiledMessage"),
723
- serialize
908
+ description: messageDescription,
909
+ encode: (compiledMessage) => {
910
+ if (compiledMessage.version === "legacy") {
911
+ return getCompiledMessageLegacyEncoder().encode(compiledMessage);
912
+ } else {
913
+ return getCompiledMessageVersionedEncoder().encode(compiledMessage);
914
+ }
915
+ },
916
+ fixedSize: null,
917
+ maxSize: null
724
918
  };
725
919
  }
920
+ function getCompiledMessageDecoder() {
921
+ return codecsCore.mapDecoder(
922
+ codecsDataStructures.getStructDecoder(getPreludeStructDecoderTuple(), {
923
+ description: messageDescription
924
+ }),
925
+ ({ addressTableLookups, ...restOfMessage }) => {
926
+ if (restOfMessage.version === "legacy" || !addressTableLookups?.length) {
927
+ return restOfMessage;
928
+ }
929
+ return { ...restOfMessage, addressTableLookups };
930
+ }
931
+ );
932
+ }
726
933
 
727
934
  // src/serializers/transaction.ts
728
- var BASE_CONFIG3 = {
729
- description: __DEV__ ? "The wire format of a Solana transaction" : "",
730
- fixedSize: null,
731
- maxSize: null
732
- };
733
- function serialize2(transaction) {
734
- const compiledTransaction = getCompiledTransaction(transaction);
735
- return umiSerializers.struct([
935
+ var signaturesDescription = __DEV__ ? "A compact array of 64-byte, base-64 encoded Ed25519 signatures" : "signatures";
936
+ var transactionDescription = __DEV__ ? "The wire format of a Solana transaction" : "transaction";
937
+ function getCompiledTransactionEncoder() {
938
+ return codecsDataStructures.getStructEncoder(
736
939
  [
737
- "signatures",
738
- umiSerializers.array(umiSerializers.bytes({ size: 64 }), {
739
- ...__DEV__ ? { description: "A compact array of 64-byte, base-64 encoded Ed25519 signatures" } : null,
740
- size: umiSerializers.shortU16()
741
- })
940
+ [
941
+ "signatures",
942
+ codecsDataStructures.getArrayEncoder(codecsDataStructures.getBytesEncoder({ size: 64 }), {
943
+ description: signaturesDescription,
944
+ size: codecsNumbers.getShortU16Encoder()
945
+ })
946
+ ],
947
+ ["compiledMessage", getCompiledMessageEncoder()]
948
+ ],
949
+ {
950
+ description: transactionDescription
951
+ }
952
+ );
953
+ }
954
+ function getSignatureDecoder() {
955
+ return codecsCore.mapDecoder(codecsDataStructures.getBytesDecoder({ size: 64 }), (bytes) => bytes);
956
+ }
957
+ function getCompiledTransactionDecoder() {
958
+ return codecsDataStructures.getStructDecoder(
959
+ [
960
+ [
961
+ "signatures",
962
+ codecsDataStructures.getArrayDecoder(getSignatureDecoder(), {
963
+ description: signaturesDescription,
964
+ size: codecsNumbers.getShortU16Decoder()
965
+ })
966
+ ],
967
+ ["compiledMessage", getCompiledMessageDecoder()]
742
968
  ],
743
- ["compiledMessage", getCompiledMessageEncoder()]
744
- ]).serialize(compiledTransaction);
969
+ {
970
+ description: transactionDescription
971
+ }
972
+ );
745
973
  }
746
974
  function getTransactionEncoder() {
747
- return {
748
- ...BASE_CONFIG3,
749
- deserialize: getUnimplementedDecoder("CompiledMessage"),
750
- serialize: serialize2
751
- };
975
+ return codecsCore.mapEncoder(getCompiledTransactionEncoder(), getCompiledTransaction);
976
+ }
977
+ function getTransactionDecoder(lastValidBlockHeight) {
978
+ return codecsCore.mapDecoder(
979
+ getCompiledTransactionDecoder(),
980
+ (compiledTransaction) => decompileTransaction(compiledTransaction, lastValidBlockHeight)
981
+ );
752
982
  }
983
+ function getTransactionCodec(lastValidBlockHeight) {
984
+ return codecsCore.combineCodec(getTransactionEncoder(), getTransactionDecoder(lastValidBlockHeight));
985
+ }
986
+ var base58Encoder2;
987
+ var base58Decoder;
753
988
  function assertIsTransactionSignature(putativeTransactionSignature) {
989
+ if (!base58Encoder2)
990
+ base58Encoder2 = codecsStrings.getBase58Encoder();
754
991
  try {
755
992
  if (
756
993
  // Lowest value (64 bytes of zeroes)
@@ -759,8 +996,8 @@ function assertIsTransactionSignature(putativeTransactionSignature) {
759
996
  ) {
760
997
  throw new Error("Expected input string to decode to a byte array of length 64.");
761
998
  }
762
- const bytes3 = umiSerializers.base58.serialize(putativeTransactionSignature);
763
- const numBytes = bytes3.byteLength;
999
+ const bytes = base58Encoder2.encode(putativeTransactionSignature);
1000
+ const numBytes = bytes.byteLength;
764
1001
  if (numBytes !== 64) {
765
1002
  throw new Error(`Expected input string to decode to a byte array of length 64. Actual length: ${numBytes}`);
766
1003
  }
@@ -771,6 +1008,8 @@ function assertIsTransactionSignature(putativeTransactionSignature) {
771
1008
  }
772
1009
  }
773
1010
  function isTransactionSignature(putativeTransactionSignature) {
1011
+ if (!base58Encoder2)
1012
+ base58Encoder2 = codecsStrings.getBase58Encoder();
774
1013
  if (
775
1014
  // Lowest value (64 bytes of zeroes)
776
1015
  putativeTransactionSignature.length < 64 || // Highest value (64 bytes of 255)
@@ -778,36 +1017,32 @@ function isTransactionSignature(putativeTransactionSignature) {
778
1017
  ) {
779
1018
  return false;
780
1019
  }
781
- const bytes3 = umiSerializers.base58.serialize(putativeTransactionSignature);
782
- const numBytes = bytes3.byteLength;
1020
+ const bytes = base58Encoder2.encode(putativeTransactionSignature);
1021
+ const numBytes = bytes.byteLength;
783
1022
  if (numBytes !== 64) {
784
1023
  return false;
785
1024
  }
786
1025
  return true;
787
1026
  }
788
- async function getCompiledMessageSignature(message, secretKey) {
789
- const wireMessageBytes = getCompiledMessageEncoder().serialize(message);
790
- const signature = await keys.signBytes(secretKey, wireMessageBytes);
791
- return signature;
792
- }
793
1027
  function getSignatureFromTransaction(transaction) {
794
- const signature = transaction.signatures[transaction.feePayer];
795
- if (!signature) {
1028
+ if (!base58Decoder)
1029
+ base58Decoder = codecsStrings.getBase58Decoder();
1030
+ const signatureBytes = transaction.signatures[transaction.feePayer];
1031
+ if (!signatureBytes) {
796
1032
  throw new Error(
797
1033
  "Could not determine this transaction's signature. Make sure that the transaction has been signed by its fee payer."
798
1034
  );
799
1035
  }
800
- return signature;
1036
+ const transactionSignature2 = base58Decoder.decode(signatureBytes)[0];
1037
+ return transactionSignature2;
801
1038
  }
802
1039
  async function signTransaction(keyPairs, transaction) {
803
1040
  const compiledMessage = compileMessage(transaction);
804
1041
  const nextSignatures = "signatures" in transaction ? { ...transaction.signatures } : {};
1042
+ const wireMessageBytes = getCompiledMessageEncoder().encode(compiledMessage);
805
1043
  const publicKeySignaturePairs = await Promise.all(
806
1044
  keyPairs.map(
807
- (keyPair) => Promise.all([
808
- addresses.getAddressFromPublicKey(keyPair.publicKey),
809
- getCompiledMessageSignature(compiledMessage, keyPair.privateKey)
810
- ])
1045
+ (keyPair) => Promise.all([addresses.getAddressFromPublicKey(keyPair.publicKey), keys.signBytes(keyPair.privateKey, wireMessageBytes)])
811
1046
  )
812
1047
  );
813
1048
  for (const [signerPublicKey, signature] of publicKeySignaturePairs) {
@@ -824,10 +1059,19 @@ function transactionSignature(putativeTransactionSignature) {
824
1059
  assertIsTransactionSignature(putativeTransactionSignature);
825
1060
  return putativeTransactionSignature;
826
1061
  }
1062
+ function assertTransactionIsFullySigned(transaction) {
1063
+ const signerAddressesFromInstructions = transaction.instructions.flatMap((i) => i.accounts?.filter((a) => isSignerRole(a.role)) ?? []).map((a) => a.address);
1064
+ const requiredSigners = /* @__PURE__ */ new Set([transaction.feePayer, ...signerAddressesFromInstructions]);
1065
+ requiredSigners.forEach((address) => {
1066
+ if (!transaction.signatures[address]) {
1067
+ throw new Error(`Transaction is missing signature for address \`${address}\``);
1068
+ }
1069
+ });
1070
+ }
827
1071
 
828
1072
  // src/wire-transaction.ts
829
1073
  function getBase64EncodedWireTransaction(transaction) {
830
- const wireTransactionBytes = getTransactionEncoder().serialize(transaction);
1074
+ const wireTransactionBytes = getTransactionEncoder().encode(transaction);
831
1075
  {
832
1076
  return btoa(String.fromCharCode(...wireTransactionBytes));
833
1077
  }
@@ -837,10 +1081,14 @@ exports.appendTransactionInstruction = appendTransactionInstruction;
837
1081
  exports.assertIsBlockhash = assertIsBlockhash;
838
1082
  exports.assertIsDurableNonceTransaction = assertIsDurableNonceTransaction;
839
1083
  exports.assertIsTransactionSignature = assertIsTransactionSignature;
1084
+ exports.assertTransactionIsFullySigned = assertTransactionIsFullySigned;
840
1085
  exports.createTransaction = createTransaction;
841
1086
  exports.getBase64EncodedWireTransaction = getBase64EncodedWireTransaction;
842
1087
  exports.getSignatureFromTransaction = getSignatureFromTransaction;
1088
+ exports.getTransactionCodec = getTransactionCodec;
1089
+ exports.getTransactionDecoder = getTransactionDecoder;
843
1090
  exports.getTransactionEncoder = getTransactionEncoder;
1091
+ exports.isAdvanceNonceAccountInstruction = isAdvanceNonceAccountInstruction;
844
1092
  exports.isTransactionSignature = isTransactionSignature;
845
1093
  exports.prependTransactionInstruction = prependTransactionInstruction;
846
1094
  exports.setTransactionFeePayer = setTransactionFeePayer;
@@ -848,5 +1096,3 @@ exports.setTransactionLifetimeUsingBlockhash = setTransactionLifetimeUsingBlockh
848
1096
  exports.setTransactionLifetimeUsingDurableNonce = setTransactionLifetimeUsingDurableNonce;
849
1097
  exports.signTransaction = signTransaction;
850
1098
  exports.transactionSignature = transactionSignature;
851
- //# sourceMappingURL=out.js.map
852
- //# sourceMappingURL=index.browser.cjs.map