@solana/web3.js 1.57.0 → 1.58.0

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.
@@ -639,6 +639,129 @@ function encodeLength(bytes, len) {
639
639
  }
640
640
  }
641
641
 
642
+ function assert (condition, message) {
643
+ if (!condition) {
644
+ throw new Error(message || 'Assertion failed');
645
+ }
646
+ }
647
+
648
+ class CompiledKeys {
649
+ constructor(payer, keyMetaMap) {
650
+ this.payer = void 0;
651
+ this.keyMetaMap = void 0;
652
+ this.payer = payer;
653
+ this.keyMetaMap = keyMetaMap;
654
+ }
655
+
656
+ static compile(instructions, payer) {
657
+ const keyMetaMap = new Map();
658
+
659
+ const getOrInsertDefault = pubkey => {
660
+ const address = pubkey.toBase58();
661
+ let keyMeta = keyMetaMap.get(address);
662
+
663
+ if (keyMeta === undefined) {
664
+ keyMeta = {
665
+ isSigner: false,
666
+ isWritable: false,
667
+ isInvoked: false
668
+ };
669
+ keyMetaMap.set(address, keyMeta);
670
+ }
671
+
672
+ return keyMeta;
673
+ };
674
+
675
+ const payerKeyMeta = getOrInsertDefault(payer);
676
+ payerKeyMeta.isSigner = true;
677
+ payerKeyMeta.isWritable = true;
678
+
679
+ for (const ix of instructions) {
680
+ getOrInsertDefault(ix.programId).isInvoked = true;
681
+
682
+ for (const accountMeta of ix.keys) {
683
+ const keyMeta = getOrInsertDefault(accountMeta.pubkey);
684
+ keyMeta.isSigner || (keyMeta.isSigner = accountMeta.isSigner);
685
+ keyMeta.isWritable || (keyMeta.isWritable = accountMeta.isWritable);
686
+ }
687
+ }
688
+
689
+ return new CompiledKeys(payer, keyMetaMap);
690
+ }
691
+
692
+ getMessageComponents() {
693
+ const mapEntries = [...this.keyMetaMap.entries()];
694
+ assert(mapEntries.length <= 256, 'Max static account keys length exceeded');
695
+ const writableSigners = mapEntries.filter(([, meta]) => meta.isSigner && meta.isWritable);
696
+ const readonlySigners = mapEntries.filter(([, meta]) => meta.isSigner && !meta.isWritable);
697
+ const writableNonSigners = mapEntries.filter(([, meta]) => !meta.isSigner && meta.isWritable);
698
+ const readonlyNonSigners = mapEntries.filter(([, meta]) => !meta.isSigner && !meta.isWritable);
699
+ const header = {
700
+ numRequiredSignatures: writableSigners.length + readonlySigners.length,
701
+ numReadonlySignedAccounts: readonlySigners.length,
702
+ numReadonlyUnsignedAccounts: readonlyNonSigners.length
703
+ }; // sanity checks
704
+
705
+ {
706
+ assert(writableSigners.length > 0, 'Expected at least one writable signer key');
707
+ const [payerAddress] = writableSigners[0];
708
+ assert(payerAddress === this.payer.toBase58(), 'Expected first writable signer key to be the fee payer');
709
+ }
710
+ const staticAccountKeys = [...writableSigners.map(([address]) => new PublicKey(address)), ...readonlySigners.map(([address]) => new PublicKey(address)), ...writableNonSigners.map(([address]) => new PublicKey(address)), ...readonlyNonSigners.map(([address]) => new PublicKey(address))];
711
+ return [header, staticAccountKeys];
712
+ }
713
+
714
+ extractTableLookup(lookupTable) {
715
+ const [writableIndexes, drainedWritableKeys] = this.drainKeysFoundInLookupTable(lookupTable.state.addresses, keyMeta => !keyMeta.isSigner && !keyMeta.isInvoked && keyMeta.isWritable);
716
+ const [readonlyIndexes, drainedReadonlyKeys] = this.drainKeysFoundInLookupTable(lookupTable.state.addresses, keyMeta => !keyMeta.isSigner && !keyMeta.isInvoked && !keyMeta.isWritable); // Don't extract lookup if no keys were found
717
+
718
+ if (writableIndexes.length === 0 && readonlyIndexes.length === 0) {
719
+ return;
720
+ }
721
+
722
+ return [{
723
+ accountKey: lookupTable.key,
724
+ writableIndexes,
725
+ readonlyIndexes
726
+ }, {
727
+ writable: drainedWritableKeys,
728
+ readonly: drainedReadonlyKeys
729
+ }];
730
+ }
731
+ /** @internal */
732
+
733
+
734
+ drainKeysFoundInLookupTable(lookupTableEntries, keyMetaFilter) {
735
+ const lookupTableIndexes = new Array();
736
+ const drainedKeys = new Array();
737
+
738
+ for (const [address, keyMeta] of this.keyMetaMap.entries()) {
739
+ if (keyMetaFilter(keyMeta)) {
740
+ const key = new PublicKey(address);
741
+ const lookupTableIndex = lookupTableEntries.findIndex(entry => entry.equals(key));
742
+
743
+ if (lookupTableIndex >= 0) {
744
+ assert(lookupTableIndex < 256, 'Max lookup table index exceeded');
745
+ lookupTableIndexes.push(lookupTableIndex);
746
+ drainedKeys.push(key);
747
+ this.keyMetaMap.delete(address);
748
+ }
749
+ }
750
+ }
751
+
752
+ return [lookupTableIndexes, drainedKeys];
753
+ }
754
+
755
+ }
756
+
757
+ /**
758
+ * An instruction to execute by a program
759
+ *
760
+ * @property {number} programIdIndex
761
+ * @property {number[]} accounts
762
+ * @property {string} data
763
+ */
764
+
642
765
  /**
643
766
  * List of instructions to be processed atomically
644
767
  */
@@ -676,6 +799,27 @@ class Message {
676
799
  return [];
677
800
  }
678
801
 
802
+ getAccountKeys() {
803
+ return new MessageAccountKeys(this.staticAccountKeys);
804
+ }
805
+
806
+ static compile(args) {
807
+ const compiledKeys = CompiledKeys.compile(args.instructions, args.payerKey);
808
+ const [header, staticAccountKeys] = compiledKeys.getMessageComponents();
809
+ const accountKeys = new MessageAccountKeys(staticAccountKeys);
810
+ const instructions = accountKeys.compileInstructions(args.instructions).map(ix => ({
811
+ programIdIndex: ix.programIdIndex,
812
+ accounts: ix.accountKeyIndexes,
813
+ data: bs58__default["default"].encode(ix.data)
814
+ }));
815
+ return new Message({
816
+ header,
817
+ accountKeys: staticAccountKeys,
818
+ recentBlockhash: args.recentBlockhash,
819
+ instructions
820
+ });
821
+ }
822
+
679
823
  isAccountSigner(index) {
680
824
  return index < this.header.numRequiredSignatures;
681
825
  }
@@ -765,7 +909,7 @@ class Message {
765
909
  for (let i = 0; i < accountCount; i++) {
766
910
  const account = byteArray.slice(0, PUBLIC_KEY_LENGTH);
767
911
  byteArray = byteArray.slice(PUBLIC_KEY_LENGTH);
768
- accountKeys.push(bs58__default["default"].encode(buffer.Buffer.from(account)));
912
+ accountKeys.push(new PublicKey(buffer.Buffer.from(account)));
769
913
  }
770
914
 
771
915
  const recentBlockhash = byteArray.slice(0, PUBLIC_KEY_LENGTH);
@@ -804,141 +948,87 @@ class Message {
804
948
 
805
949
  }
806
950
 
807
- function assert (condition, message) {
808
- if (!condition) {
809
- throw new Error(message || 'Assertion failed');
810
- }
811
- }
951
+ /**
952
+ * Message constructor arguments
953
+ */
812
954
 
813
- class CompiledKeys {
814
- constructor(payer, keyMetaMap) {
815
- this.payer = void 0;
816
- this.keyMetaMap = void 0;
817
- this.payer = payer;
818
- this.keyMetaMap = keyMetaMap;
955
+ class MessageV0 {
956
+ constructor(args) {
957
+ this.header = void 0;
958
+ this.staticAccountKeys = void 0;
959
+ this.recentBlockhash = void 0;
960
+ this.compiledInstructions = void 0;
961
+ this.addressTableLookups = void 0;
962
+ this.header = args.header;
963
+ this.staticAccountKeys = args.staticAccountKeys;
964
+ this.recentBlockhash = args.recentBlockhash;
965
+ this.compiledInstructions = args.compiledInstructions;
966
+ this.addressTableLookups = args.addressTableLookups;
819
967
  }
820
968
 
821
- static compile(instructions, payer) {
822
- const keyMetaMap = new Map();
823
-
824
- const getOrInsertDefault = pubkey => {
825
- const address = pubkey.toBase58();
826
- let keyMeta = keyMetaMap.get(address);
827
-
828
- if (keyMeta === undefined) {
829
- keyMeta = {
830
- isSigner: false,
831
- isWritable: false,
832
- isInvoked: false
833
- };
834
- keyMetaMap.set(address, keyMeta);
835
- }
836
-
837
- return keyMeta;
838
- };
839
-
840
- const payerKeyMeta = getOrInsertDefault(payer);
841
- payerKeyMeta.isSigner = true;
842
- payerKeyMeta.isWritable = true;
969
+ get version() {
970
+ return 0;
971
+ }
843
972
 
844
- for (const ix of instructions) {
845
- getOrInsertDefault(ix.programId).isInvoked = true;
973
+ get numAccountKeysFromLookups() {
974
+ let count = 0;
846
975
 
847
- for (const accountMeta of ix.keys) {
848
- const keyMeta = getOrInsertDefault(accountMeta.pubkey);
849
- keyMeta.isSigner || (keyMeta.isSigner = accountMeta.isSigner);
850
- keyMeta.isWritable || (keyMeta.isWritable = accountMeta.isWritable);
851
- }
976
+ for (const lookup of this.addressTableLookups) {
977
+ count += lookup.readonlyIndexes.length + lookup.writableIndexes.length;
852
978
  }
853
979
 
854
- return new CompiledKeys(payer, keyMetaMap);
980
+ return count;
855
981
  }
856
982
 
857
- getMessageComponents() {
858
- const mapEntries = [...this.keyMetaMap.entries()];
859
- assert(mapEntries.length <= 256, 'Max static account keys length exceeded');
860
- const writableSigners = mapEntries.filter(([, meta]) => meta.isSigner && meta.isWritable);
861
- const readonlySigners = mapEntries.filter(([, meta]) => meta.isSigner && !meta.isWritable);
862
- const writableNonSigners = mapEntries.filter(([, meta]) => !meta.isSigner && meta.isWritable);
863
- const readonlyNonSigners = mapEntries.filter(([, meta]) => !meta.isSigner && !meta.isWritable);
864
- const header = {
865
- numRequiredSignatures: writableSigners.length + readonlySigners.length,
866
- numReadonlySignedAccounts: readonlySigners.length,
867
- numReadonlyUnsignedAccounts: readonlyNonSigners.length
868
- }; // sanity checks
869
-
870
- {
871
- assert(writableSigners.length > 0, 'Expected at least one writable signer key');
872
- const [payerAddress] = writableSigners[0];
873
- assert(payerAddress === this.payer.toBase58(), 'Expected first writable signer key to be the fee payer');
874
- }
875
- const staticAccountKeys = [...writableSigners.map(([address]) => new PublicKey(address)), ...readonlySigners.map(([address]) => new PublicKey(address)), ...writableNonSigners.map(([address]) => new PublicKey(address)), ...readonlyNonSigners.map(([address]) => new PublicKey(address))];
876
- return [header, staticAccountKeys];
877
- }
983
+ getAccountKeys(args) {
984
+ let accountKeysFromLookups;
878
985
 
879
- extractTableLookup(lookupTable) {
880
- const [writableIndexes, drainedWritableKeys] = this.drainKeysFoundInLookupTable(lookupTable.state.addresses, keyMeta => !keyMeta.isSigner && !keyMeta.isInvoked && keyMeta.isWritable);
881
- const [readonlyIndexes, drainedReadonlyKeys] = this.drainKeysFoundInLookupTable(lookupTable.state.addresses, keyMeta => !keyMeta.isSigner && !keyMeta.isInvoked && !keyMeta.isWritable); // Don't extract lookup if no keys were found
986
+ if (args && 'accountKeysFromLookups' in args) {
987
+ if (this.numAccountKeysFromLookups != args.accountKeysFromLookups.writable.length + args.accountKeysFromLookups.readonly.length) {
988
+ throw new Error('Failed to get account keys because of a mismatch in the number of account keys from lookups');
989
+ }
882
990
 
883
- if (writableIndexes.length === 0 && readonlyIndexes.length === 0) {
884
- return;
991
+ accountKeysFromLookups = args.accountKeysFromLookups;
992
+ } else if (args && 'addressLookupTableAccounts' in args) {
993
+ accountKeysFromLookups = this.resolveAddressTableLookups(args.addressLookupTableAccounts);
994
+ } else if (this.addressTableLookups.length > 0) {
995
+ throw new Error('Failed to get account keys because address table lookups were not resolved');
885
996
  }
886
997
 
887
- return [{
888
- accountKey: lookupTable.key,
889
- writableIndexes,
890
- readonlyIndexes
891
- }, {
892
- writable: drainedWritableKeys,
893
- readonly: drainedReadonlyKeys
894
- }];
998
+ return new MessageAccountKeys(this.staticAccountKeys, accountKeysFromLookups);
895
999
  }
896
- /** @internal */
897
1000
 
1001
+ resolveAddressTableLookups(addressLookupTableAccounts) {
1002
+ const accountKeysFromLookups = {
1003
+ writable: [],
1004
+ readonly: []
1005
+ };
898
1006
 
899
- drainKeysFoundInLookupTable(lookupTableEntries, keyMetaFilter) {
900
- const lookupTableIndexes = new Array();
901
- const drainedKeys = new Array();
1007
+ for (const tableLookup of this.addressTableLookups) {
1008
+ const tableAccount = addressLookupTableAccounts.find(account => account.key.equals(tableLookup.accountKey));
902
1009
 
903
- for (const [address, keyMeta] of this.keyMetaMap.entries()) {
904
- if (keyMetaFilter(keyMeta)) {
905
- const key = new PublicKey(address);
906
- const lookupTableIndex = lookupTableEntries.findIndex(entry => entry.equals(key));
1010
+ if (!tableAccount) {
1011
+ throw new Error(`Failed to find address lookup table account for table key ${tableLookup.accountKey.toBase58()}`);
1012
+ }
907
1013
 
908
- if (lookupTableIndex >= 0) {
909
- assert(lookupTableIndex < 256, 'Max lookup table index exceeded');
910
- lookupTableIndexes.push(lookupTableIndex);
911
- drainedKeys.push(key);
912
- this.keyMetaMap.delete(address);
1014
+ for (const index of tableLookup.writableIndexes) {
1015
+ if (index < tableAccount.state.addresses.length) {
1016
+ accountKeysFromLookups.writable.push(tableAccount.state.addresses[index]);
1017
+ } else {
1018
+ throw new Error(`Failed to find address for index ${index} in address lookup table ${tableLookup.accountKey.toBase58()}`);
913
1019
  }
914
1020
  }
915
- }
916
-
917
- return [lookupTableIndexes, drainedKeys];
918
- }
919
-
920
- }
921
-
922
- /**
923
- * Message constructor arguments
924
- */
925
1021
 
926
- class MessageV0 {
927
- constructor(args) {
928
- this.header = void 0;
929
- this.staticAccountKeys = void 0;
930
- this.recentBlockhash = void 0;
931
- this.compiledInstructions = void 0;
932
- this.addressTableLookups = void 0;
933
- this.header = args.header;
934
- this.staticAccountKeys = args.staticAccountKeys;
935
- this.recentBlockhash = args.recentBlockhash;
936
- this.compiledInstructions = args.compiledInstructions;
937
- this.addressTableLookups = args.addressTableLookups;
938
- }
1022
+ for (const index of tableLookup.readonlyIndexes) {
1023
+ if (index < tableAccount.state.addresses.length) {
1024
+ accountKeysFromLookups.readonly.push(tableAccount.state.addresses[index]);
1025
+ } else {
1026
+ throw new Error(`Failed to find address for index ${index} in address lookup table ${tableLookup.accountKey.toBase58()}`);
1027
+ }
1028
+ }
1029
+ }
939
1030
 
940
- get version() {
941
- return 0;
1031
+ return accountKeysFromLookups;
942
1032
  }
943
1033
 
944
1034
  static compile(args) {
@@ -1870,6 +1960,114 @@ class Transaction {
1870
1960
 
1871
1961
  }
1872
1962
 
1963
+ class TransactionMessage {
1964
+ constructor(args) {
1965
+ this.accountKeys = void 0;
1966
+ this.instructions = void 0;
1967
+ this.recentBlockhash = void 0;
1968
+ this.accountKeys = args.accountKeys;
1969
+ this.instructions = args.instructions;
1970
+ this.recentBlockhash = args.recentBlockhash;
1971
+ }
1972
+
1973
+ static decompile(message, args) {
1974
+ const {
1975
+ header,
1976
+ compiledInstructions,
1977
+ recentBlockhash
1978
+ } = message;
1979
+ const {
1980
+ numRequiredSignatures,
1981
+ numReadonlySignedAccounts,
1982
+ numReadonlyUnsignedAccounts
1983
+ } = header;
1984
+ const numWritableSignedAccounts = numRequiredSignatures - numReadonlySignedAccounts;
1985
+ assert(numWritableSignedAccounts > 0, 'Message header is invalid');
1986
+ const numWritableUnsignedAccounts = message.staticAccountKeys.length - numReadonlyUnsignedAccounts;
1987
+ assert(numWritableUnsignedAccounts >= 0, 'Message header is invalid');
1988
+ const accountKeys = message.getAccountKeys(args);
1989
+ const instructions = [];
1990
+
1991
+ for (const compiledIx of compiledInstructions) {
1992
+ const keys = [];
1993
+
1994
+ for (const keyIndex of compiledIx.accountKeyIndexes) {
1995
+ const pubkey = accountKeys.get(keyIndex);
1996
+
1997
+ if (pubkey === undefined) {
1998
+ throw new Error(`Failed to find key for account key index ${keyIndex}`);
1999
+ }
2000
+
2001
+ const isSigner = keyIndex < numRequiredSignatures;
2002
+ let isWritable;
2003
+
2004
+ if (isSigner) {
2005
+ isWritable = keyIndex < numWritableSignedAccounts;
2006
+ } else if (keyIndex < accountKeys.staticAccountKeys.length) {
2007
+ isWritable = keyIndex - numRequiredSignatures < numWritableUnsignedAccounts;
2008
+ } else {
2009
+ isWritable = keyIndex - accountKeys.staticAccountKeys.length < // accountKeysFromLookups cannot be undefined because we already found a pubkey for this index above
2010
+ accountKeys.accountKeysFromLookups.writable.length;
2011
+ }
2012
+
2013
+ keys.push({
2014
+ pubkey,
2015
+ isSigner: keyIndex < header.numRequiredSignatures,
2016
+ isWritable
2017
+ });
2018
+ }
2019
+
2020
+ const programId = accountKeys.get(compiledIx.programIdIndex);
2021
+
2022
+ if (programId === undefined) {
2023
+ throw new Error(`Failed to find program id for program id index ${compiledIx.programIdIndex}`);
2024
+ }
2025
+
2026
+ instructions.push(new TransactionInstruction({
2027
+ programId,
2028
+ data: toBuffer(compiledIx.data),
2029
+ keys
2030
+ }));
2031
+ }
2032
+
2033
+ return new TransactionMessage({
2034
+ accountKeys,
2035
+ instructions,
2036
+ recentBlockhash
2037
+ });
2038
+ }
2039
+
2040
+ compileToLegacyMessage() {
2041
+ const payerKey = this.accountKeys.get(0);
2042
+
2043
+ if (payerKey === undefined) {
2044
+ throw new Error('Failed to compile message because no account keys were found');
2045
+ }
2046
+
2047
+ return Message.compile({
2048
+ payerKey,
2049
+ recentBlockhash: this.recentBlockhash,
2050
+ instructions: this.instructions
2051
+ });
2052
+ }
2053
+
2054
+ compileToV0Message(addressLookupTableAccounts) {
2055
+ const payerKey = this.accountKeys.get(0);
2056
+
2057
+ if (payerKey === undefined) {
2058
+ throw new Error('Failed to compile message because no account keys were found');
2059
+ }
2060
+
2061
+ return MessageV0.compile({
2062
+ payerKey,
2063
+ recentBlockhash: this.recentBlockhash,
2064
+ instructions: this.instructions,
2065
+ addressLookupTableAccounts
2066
+ });
2067
+ }
2068
+
2069
+ }
2070
+
1873
2071
  /**
1874
2072
  * Versioned transaction class
1875
2073
  */
@@ -6173,10 +6371,44 @@ class Connection {
6173
6371
  }
6174
6372
  /**
6175
6373
  * Simulate a transaction
6374
+ *
6375
+ * @deprecated Instead, call {@link simulateTransaction} with {@link
6376
+ * VersionedTransaction} and {@link SimulateTransactionConfig} parameters
6176
6377
  */
6177
6378
 
6178
6379
 
6179
- async simulateTransaction(transactionOrMessage, signers, includeAccounts) {
6380
+ /**
6381
+ * Simulate a transaction
6382
+ */
6383
+ // eslint-disable-next-line no-dupe-class-members
6384
+ async simulateTransaction(transactionOrMessage, configOrSigners, includeAccounts) {
6385
+ if ('message' in transactionOrMessage) {
6386
+ const versionedTx = transactionOrMessage;
6387
+ const wireTransaction = versionedTx.serialize();
6388
+ const encodedTransaction = buffer.Buffer.from(wireTransaction).toString('base64');
6389
+
6390
+ if (Array.isArray(configOrSigners) || includeAccounts !== undefined) {
6391
+ throw new Error('Invalid arguments');
6392
+ }
6393
+
6394
+ const config = configOrSigners || {};
6395
+ config.encoding = 'base64';
6396
+
6397
+ if (!('commitment' in config)) {
6398
+ config.commitment = this.commitment;
6399
+ }
6400
+
6401
+ const args = [encodedTransaction, config];
6402
+ const unsafeRes = await this._rpcRequest('simulateTransaction', args);
6403
+ const res = superstruct.create(unsafeRes, SimulatedTransactionResponseStruct);
6404
+
6405
+ if ('error' in res) {
6406
+ throw new Error('failed to simulate transaction: ' + res.error.message);
6407
+ }
6408
+
6409
+ return res.result;
6410
+ }
6411
+
6180
6412
  let transaction;
6181
6413
 
6182
6414
  if (transactionOrMessage instanceof Transaction) {
@@ -6192,6 +6424,12 @@ class Connection {
6192
6424
  transaction._message = transaction._json = undefined;
6193
6425
  }
6194
6426
 
6427
+ if (configOrSigners !== undefined && !Array.isArray(configOrSigners)) {
6428
+ throw new Error('Invalid arguments');
6429
+ }
6430
+
6431
+ const signers = configOrSigners;
6432
+
6195
6433
  if (transaction.nonceInfo && signers) {
6196
6434
  transaction.sign(...signers);
6197
6435
  } else {
@@ -6272,12 +6510,34 @@ class Connection {
6272
6510
 
6273
6511
  return res.result;
6274
6512
  }
6513
+ /**
6514
+ * Sign and send a transaction
6515
+ *
6516
+ * @deprecated Instead, call {@link sendTransaction} with a {@link
6517
+ * VersionedTransaction}
6518
+ */
6519
+
6520
+
6275
6521
  /**
6276
6522
  * Sign and send a transaction
6277
6523
  */
6524
+ // eslint-disable-next-line no-dupe-class-members
6525
+ async sendTransaction(transaction, signersOrOptions, options) {
6526
+ if ('message' in transaction) {
6527
+ if (signersOrOptions && Array.isArray(signersOrOptions)) {
6528
+ throw new Error('Invalid arguments');
6529
+ }
6530
+
6531
+ const wireTransaction = transaction.serialize();
6532
+ return await this.sendRawTransaction(wireTransaction, options);
6533
+ }
6534
+
6535
+ if (signersOrOptions === undefined || !Array.isArray(signersOrOptions)) {
6536
+ throw new Error('Invalid arguments');
6537
+ }
6278
6538
 
6539
+ const signers = signersOrOptions;
6279
6540
 
6280
- async sendTransaction(transaction, signers, options) {
6281
6541
  if (transaction.nonceInfo) {
6282
6542
  transaction.sign(...signers);
6283
6543
  } else {
@@ -9363,6 +9623,7 @@ exports.Transaction = Transaction;
9363
9623
  exports.TransactionExpiredBlockheightExceededError = TransactionExpiredBlockheightExceededError;
9364
9624
  exports.TransactionExpiredTimeoutError = TransactionExpiredTimeoutError;
9365
9625
  exports.TransactionInstruction = TransactionInstruction;
9626
+ exports.TransactionMessage = TransactionMessage;
9366
9627
  exports.VALIDATOR_INFO_KEY = VALIDATOR_INFO_KEY;
9367
9628
  exports.VERSION_PREFIX_MASK = VERSION_PREFIX_MASK;
9368
9629
  exports.VOTE_PROGRAM_ID = VOTE_PROGRAM_ID;