@solana/transactions 2.0.0-experimental.ce179f2 → 2.0.0-experimental.cf6ca9d

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