@solana/transactions 2.0.0-experimental.6466d76 → 2.0.0-experimental.64d583b

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.
@@ -2,29 +2,14 @@
2
2
 
3
3
  var codecsStrings = require('@solana/codecs-strings');
4
4
  var addresses = require('@solana/addresses');
5
+ var functional = require('@solana/functional');
5
6
  var codecsCore = require('@solana/codecs-core');
6
7
  var codecsDataStructures = require('@solana/codecs-data-structures');
7
8
  var codecsNumbers = require('@solana/codecs-numbers');
8
- var functional = require('@solana/functional');
9
+ var errors = require('@solana/errors');
9
10
  var keys = require('@solana/keys');
10
11
 
11
- // src/blockhash.ts
12
-
13
- // src/unsigned-transaction.ts
14
- function getUnsignedTransaction(transaction) {
15
- if ("signatures" in transaction) {
16
- const {
17
- signatures: _,
18
- // eslint-disable-line @typescript-eslint/no-unused-vars
19
- ...unsignedTransaction
20
- } = transaction;
21
- return unsignedTransaction;
22
- } else {
23
- return transaction;
24
- }
25
- }
26
-
27
- // src/blockhash.ts
12
+ // ../rpc-types/dist/index.browser.js
28
13
  var base58Encoder;
29
14
  function assertIsBlockhash(putativeBlockhash) {
30
15
  if (!base58Encoder)
@@ -48,6 +33,22 @@ function assertIsBlockhash(putativeBlockhash) {
48
33
  });
49
34
  }
50
35
  }
36
+
37
+ // src/unsigned-transaction.ts
38
+ function getUnsignedTransaction(transaction) {
39
+ if ("signatures" in transaction) {
40
+ const {
41
+ signatures: _,
42
+ // eslint-disable-line @typescript-eslint/no-unused-vars
43
+ ...unsignedTransaction
44
+ } = transaction;
45
+ return unsignedTransaction;
46
+ } else {
47
+ return transaction;
48
+ }
49
+ }
50
+
51
+ // src/blockhash.ts
51
52
  function isTransactionWithBlockhashLifetime(transaction) {
52
53
  const lifetimeConstraintShapeMatches = "lifetimeConstraint" in transaction && typeof transaction.lifetimeConstraint.blockhash === "string" && typeof transaction.lifetimeConstraint.lastValidBlockHeight === "bigint";
53
54
  if (!lifetimeConstraintShapeMatches)
@@ -217,6 +218,151 @@ function prependTransactionInstruction(instruction, transaction) {
217
218
  Object.freeze(out);
218
219
  return out;
219
220
  }
221
+
222
+ // src/decompile-transaction.ts
223
+ function getAccountMetas(message) {
224
+ const { header } = message;
225
+ const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
226
+ const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
227
+ const accountMetas = [];
228
+ let accountIndex = 0;
229
+ for (let i = 0; i < numWritableSignerAccounts; i++) {
230
+ accountMetas.push({
231
+ address: message.staticAccounts[accountIndex],
232
+ role: AccountRole.WRITABLE_SIGNER
233
+ });
234
+ accountIndex++;
235
+ }
236
+ for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
237
+ accountMetas.push({
238
+ address: message.staticAccounts[accountIndex],
239
+ role: AccountRole.READONLY_SIGNER
240
+ });
241
+ accountIndex++;
242
+ }
243
+ for (let i = 0; i < numWritableNonSignerAccounts; i++) {
244
+ accountMetas.push({
245
+ address: message.staticAccounts[accountIndex],
246
+ role: AccountRole.WRITABLE
247
+ });
248
+ accountIndex++;
249
+ }
250
+ for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
251
+ accountMetas.push({
252
+ address: message.staticAccounts[accountIndex],
253
+ role: AccountRole.READONLY
254
+ });
255
+ accountIndex++;
256
+ }
257
+ return accountMetas;
258
+ }
259
+ function getAddressLookupMetas(compiledAddressTableLookups, addressesByLookupTableAddress) {
260
+ const compiledAddressTableLookupAddresses = compiledAddressTableLookups.map((l) => l.lookupTableAddress);
261
+ const missing = compiledAddressTableLookupAddresses.filter((a) => addressesByLookupTableAddress[a] === void 0);
262
+ if (missing.length > 0) {
263
+ const missingAddresses = missing.join(", ");
264
+ throw new Error(`Addresses not provided for lookup tables: [${missingAddresses}]`);
265
+ }
266
+ const readOnlyMetas = [];
267
+ const writableMetas = [];
268
+ for (const lookup of compiledAddressTableLookups) {
269
+ const addresses = addressesByLookupTableAddress[lookup.lookupTableAddress];
270
+ const highestIndex = Math.max(...lookup.readableIndices, ...lookup.writableIndices);
271
+ if (highestIndex >= addresses.length) {
272
+ throw new Error(
273
+ `Cannot look up index ${highestIndex} in lookup table [${lookup.lookupTableAddress}]. The lookup table may have been extended since the addresses provided were retrieved.`
274
+ );
275
+ }
276
+ const readOnlyForLookup = lookup.readableIndices.map((r) => ({
277
+ address: addresses[r],
278
+ addressIndex: r,
279
+ lookupTableAddress: lookup.lookupTableAddress,
280
+ role: AccountRole.READONLY
281
+ }));
282
+ readOnlyMetas.push(...readOnlyForLookup);
283
+ const writableForLookup = lookup.writableIndices.map((w) => ({
284
+ address: addresses[w],
285
+ addressIndex: w,
286
+ lookupTableAddress: lookup.lookupTableAddress,
287
+ role: AccountRole.WRITABLE
288
+ }));
289
+ writableMetas.push(...writableForLookup);
290
+ }
291
+ return [...writableMetas, ...readOnlyMetas];
292
+ }
293
+ function convertInstruction(instruction, accountMetas) {
294
+ const programAddress = accountMetas[instruction.programAddressIndex]?.address;
295
+ if (!programAddress) {
296
+ throw new Error(`Could not find program address at index ${instruction.programAddressIndex}`);
297
+ }
298
+ const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
299
+ const { data } = instruction;
300
+ return {
301
+ programAddress,
302
+ ...accounts && accounts.length ? { accounts } : {},
303
+ ...data && data.length ? { data } : {}
304
+ };
305
+ }
306
+ function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
307
+ if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
308
+ return {
309
+ blockhash: messageLifetimeToken,
310
+ lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
311
+ // U64 MAX
312
+ };
313
+ } else {
314
+ const nonceAccountAddress = firstInstruction.accounts[0].address;
315
+ addresses.assertIsAddress(nonceAccountAddress);
316
+ const nonceAuthorityAddress = firstInstruction.accounts[2].address;
317
+ addresses.assertIsAddress(nonceAuthorityAddress);
318
+ return {
319
+ nonce: messageLifetimeToken,
320
+ nonceAccountAddress,
321
+ nonceAuthorityAddress
322
+ };
323
+ }
324
+ }
325
+ function convertSignatures(compiledTransaction) {
326
+ const {
327
+ compiledMessage: { staticAccounts },
328
+ signatures
329
+ } = compiledTransaction;
330
+ return signatures.reduce((acc, sig, index) => {
331
+ const allZeros = sig.every((byte) => byte === 0);
332
+ if (allZeros)
333
+ return acc;
334
+ const address = staticAccounts[index];
335
+ return { ...acc, [address]: sig };
336
+ }, {});
337
+ }
338
+ function decompileTransaction(compiledTransaction, config) {
339
+ const { compiledMessage } = compiledTransaction;
340
+ const feePayer = compiledMessage.staticAccounts[0];
341
+ if (!feePayer)
342
+ throw new Error("No fee payer set in CompiledTransaction");
343
+ const accountMetas = getAccountMetas(compiledMessage);
344
+ const accountLookupMetas = "addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups !== void 0 && compiledMessage.addressTableLookups.length > 0 ? getAddressLookupMetas(compiledMessage.addressTableLookups, config?.addressesByLookupTableAddress ?? {}) : [];
345
+ const transactionMetas = [...accountMetas, ...accountLookupMetas];
346
+ const instructions = compiledMessage.instructions.map(
347
+ (compiledInstruction) => convertInstruction(compiledInstruction, transactionMetas)
348
+ );
349
+ const firstInstruction = instructions[0];
350
+ const lifetimeConstraint = getLifetimeConstraint(
351
+ compiledMessage.lifetimeToken,
352
+ firstInstruction,
353
+ config?.lastValidBlockHeight
354
+ );
355
+ const signatures = convertSignatures(compiledTransaction);
356
+ return functional.pipe(
357
+ createTransaction({ version: compiledMessage.version }),
358
+ (tx) => setTransactionFeePayer(feePayer, tx),
359
+ (tx) => instructions.reduce((acc, instruction) => {
360
+ return appendTransactionInstruction(instruction, acc);
361
+ }, tx),
362
+ (tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
363
+ (tx) => Object.keys(signatures).length > 0 ? { ...tx, signatures } : tx
364
+ );
365
+ }
220
366
  function upsert(addressMap, address, update) {
221
367
  addressMap[address] = update(addressMap[address] ?? { role: AccountRole.READONLY });
222
368
  }
@@ -710,149 +856,6 @@ function getCompiledTransaction(transaction) {
710
856
  signatures
711
857
  };
712
858
  }
713
- function getAccountMetas(message) {
714
- const { header } = message;
715
- const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
716
- const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
717
- const accountMetas = [];
718
- let accountIndex = 0;
719
- for (let i = 0; i < numWritableSignerAccounts; i++) {
720
- accountMetas.push({
721
- address: message.staticAccounts[accountIndex],
722
- role: AccountRole.WRITABLE_SIGNER
723
- });
724
- accountIndex++;
725
- }
726
- for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
727
- accountMetas.push({
728
- address: message.staticAccounts[accountIndex],
729
- role: AccountRole.READONLY_SIGNER
730
- });
731
- accountIndex++;
732
- }
733
- for (let i = 0; i < numWritableNonSignerAccounts; i++) {
734
- accountMetas.push({
735
- address: message.staticAccounts[accountIndex],
736
- role: AccountRole.WRITABLE
737
- });
738
- accountIndex++;
739
- }
740
- for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
741
- accountMetas.push({
742
- address: message.staticAccounts[accountIndex],
743
- role: AccountRole.READONLY
744
- });
745
- accountIndex++;
746
- }
747
- return accountMetas;
748
- }
749
- function getAddressLookupMetas(compiledAddressTableLookups, addressesByLookupTableAddress) {
750
- const compiledAddressTableLookupAddresses = compiledAddressTableLookups.map((l) => l.lookupTableAddress);
751
- const missing = compiledAddressTableLookupAddresses.filter((a) => addressesByLookupTableAddress[a] === void 0);
752
- if (missing.length > 0) {
753
- const missingAddresses = missing.join(", ");
754
- throw new Error(`Addresses not provided for lookup tables: [${missingAddresses}]`);
755
- }
756
- const readOnlyMetas = [];
757
- const writableMetas = [];
758
- for (const lookup of compiledAddressTableLookups) {
759
- const addresses = addressesByLookupTableAddress[lookup.lookupTableAddress];
760
- const highestIndex = Math.max(...lookup.readableIndices, ...lookup.writableIndices);
761
- if (highestIndex >= addresses.length) {
762
- throw new Error(
763
- `Cannot look up index ${highestIndex} in lookup table [${lookup.lookupTableAddress}]. The lookup table may have been extended since the addresses provided were retrieved.`
764
- );
765
- }
766
- const readOnlyForLookup = lookup.readableIndices.map((r) => ({
767
- address: addresses[r],
768
- addressIndex: r,
769
- lookupTableAddress: lookup.lookupTableAddress,
770
- role: AccountRole.READONLY
771
- }));
772
- readOnlyMetas.push(...readOnlyForLookup);
773
- const writableForLookup = lookup.writableIndices.map((w) => ({
774
- address: addresses[w],
775
- addressIndex: w,
776
- lookupTableAddress: lookup.lookupTableAddress,
777
- role: AccountRole.WRITABLE
778
- }));
779
- writableMetas.push(...writableForLookup);
780
- }
781
- return [...writableMetas, ...readOnlyMetas];
782
- }
783
- function convertInstruction(instruction, accountMetas) {
784
- const programAddress = accountMetas[instruction.programAddressIndex]?.address;
785
- if (!programAddress) {
786
- throw new Error(`Could not find program address at index ${instruction.programAddressIndex}`);
787
- }
788
- const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
789
- const { data } = instruction;
790
- return {
791
- programAddress,
792
- ...accounts && accounts.length ? { accounts } : {},
793
- ...data && data.length ? { data } : {}
794
- };
795
- }
796
- function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
797
- if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
798
- return {
799
- blockhash: messageLifetimeToken,
800
- lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
801
- // U64 MAX
802
- };
803
- } else {
804
- const nonceAccountAddress = firstInstruction.accounts[0].address;
805
- addresses.assertIsAddress(nonceAccountAddress);
806
- const nonceAuthorityAddress = firstInstruction.accounts[2].address;
807
- addresses.assertIsAddress(nonceAuthorityAddress);
808
- return {
809
- nonce: messageLifetimeToken,
810
- nonceAccountAddress,
811
- nonceAuthorityAddress
812
- };
813
- }
814
- }
815
- function convertSignatures(compiledTransaction) {
816
- const {
817
- compiledMessage: { staticAccounts },
818
- signatures
819
- } = compiledTransaction;
820
- return signatures.reduce((acc, sig, index) => {
821
- const allZeros = sig.every((byte) => byte === 0);
822
- if (allZeros)
823
- return acc;
824
- const address = staticAccounts[index];
825
- return { ...acc, [address]: sig };
826
- }, {});
827
- }
828
- function decompileTransaction(compiledTransaction, config) {
829
- const { compiledMessage } = compiledTransaction;
830
- const feePayer = compiledMessage.staticAccounts[0];
831
- if (!feePayer)
832
- throw new Error("No fee payer set in CompiledTransaction");
833
- const accountMetas = getAccountMetas(compiledMessage);
834
- const accountLookupMetas = "addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups !== void 0 && compiledMessage.addressTableLookups.length > 0 ? getAddressLookupMetas(compiledMessage.addressTableLookups, config?.addressesByLookupTableAddress ?? {}) : [];
835
- const transactionMetas = [...accountMetas, ...accountLookupMetas];
836
- const instructions = compiledMessage.instructions.map(
837
- (compiledInstruction) => convertInstruction(compiledInstruction, transactionMetas)
838
- );
839
- const firstInstruction = instructions[0];
840
- const lifetimeConstraint = getLifetimeConstraint(
841
- compiledMessage.lifetimeToken,
842
- firstInstruction,
843
- config?.lastValidBlockHeight
844
- );
845
- const signatures = convertSignatures(compiledTransaction);
846
- return functional.pipe(
847
- createTransaction({ version: compiledMessage.version }),
848
- (tx) => setTransactionFeePayer(feePayer, tx),
849
- (tx) => instructions.reduce((acc, instruction) => {
850
- return appendTransactionInstruction(instruction, acc);
851
- }, tx),
852
- (tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
853
- (tx) => compiledTransaction.signatures.length ? { ...tx, signatures } : tx
854
- );
855
- }
856
859
 
857
860
  // src/serializers/transaction.ts
858
861
  function getCompiledTransactionEncoder() {
@@ -890,9 +893,7 @@ function getSignatureFromTransaction(transaction) {
890
893
  base58Decoder = codecsStrings.getBase58Decoder();
891
894
  const signatureBytes = transaction.signatures[transaction.feePayer];
892
895
  if (!signatureBytes) {
893
- throw new Error(
894
- "Could not determine this transaction's signature. Make sure that the transaction has been signed by its fee payer."
895
- );
896
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_SIGNATURE_NOT_COMPUTABLE);
896
897
  }
897
898
  const transactionSignature = base58Decoder.decode(signatureBytes);
898
899
  return transactionSignature;
@@ -932,7 +933,9 @@ function assertTransactionIsFullySigned(transaction) {
932
933
  }
933
934
  });
934
935
  if (missingSigs.length > 0) {
935
- throw new Error("Transaction is missing signatures for addresses: " + missingSigs.join(", "));
936
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_MISSING_SIGNATURES, {
937
+ addresses: missingSigs
938
+ });
936
939
  }
937
940
  }
938
941
  function getBase64EncodedWireTransaction(transaction) {
@@ -941,16 +944,17 @@ function getBase64EncodedWireTransaction(transaction) {
941
944
  }
942
945
 
943
946
  exports.appendTransactionInstruction = appendTransactionInstruction;
944
- exports.assertIsBlockhash = assertIsBlockhash;
945
947
  exports.assertIsDurableNonceTransaction = assertIsDurableNonceTransaction;
946
948
  exports.assertIsTransactionWithBlockhashLifetime = assertIsTransactionWithBlockhashLifetime;
947
949
  exports.assertTransactionIsFullySigned = assertTransactionIsFullySigned;
948
950
  exports.compileMessage = compileMessage;
949
951
  exports.createTransaction = createTransaction;
952
+ exports.decompileTransaction = decompileTransaction;
950
953
  exports.getBase64EncodedWireTransaction = getBase64EncodedWireTransaction;
951
954
  exports.getCompiledMessageCodec = getCompiledMessageCodec;
952
955
  exports.getCompiledMessageDecoder = getCompiledMessageDecoder;
953
956
  exports.getCompiledMessageEncoder = getCompiledMessageEncoder;
957
+ exports.getCompiledTransactionDecoder = getCompiledTransactionDecoder;
954
958
  exports.getSignatureFromTransaction = getSignatureFromTransaction;
955
959
  exports.getTransactionCodec = getTransactionCodec;
956
960
  exports.getTransactionDecoder = getTransactionDecoder;