@solana/transactions 2.0.0-experimental.76ad167 → 2.0.0-experimental.7712fc3

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.
package/README.md CHANGED
@@ -30,7 +30,7 @@ const transferTransaction = pipe(
30
30
  createTransaction({ version: 0 }),
31
31
  tx => setTransactionFeePayer(myAddress, tx),
32
32
  tx => setTransactionLifetimeUsingBlockhash(latestBlockhash, tx),
33
- tx => appendTransactionInstruction(createTransferInstruction(myAddress, toAddress, amountInLamports), tx)
33
+ tx => appendTransactionInstruction(createTransferInstruction(myAddress, toAddress, amountInLamports), tx),
34
34
  );
35
35
  ```
36
36
 
@@ -144,7 +144,7 @@ const nonce =
144
144
 
145
145
  const durableNonceTransaction = setTransactionLifetimeUsingDurableNonce(
146
146
  { nonce, nonceAccountAddress, nonceAuthorityAddress },
147
- tx
147
+ tx,
148
148
  );
149
149
  ```
150
150
 
@@ -210,14 +210,18 @@ const memoTransaction = appendTransactionInstruction(
210
210
  data: new TextEncoder().encode('Hello world!'),
211
211
  programAddress: address('MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'),
212
212
  },
213
- tx
213
+ tx,
214
214
  );
215
215
  ```
216
216
 
217
+ If you'd like to add multiple instructions to a transaction at once, you may use the `appendTransactionInstructions` function instead which accepts an array of instructions.
218
+
217
219
  #### `prependTransactionInstruction()`
218
220
 
219
221
  Given an instruction, this method will return a new transaction with that instruction having been added to the beginning of the list of existing instructions.
220
222
 
223
+ If you'd like to prepend multiple instructions to a transaction at once, you may use the `prependTransactionInstructions` function instead which accepts an array of instructions.
224
+
221
225
  See [`appendTransactionInstruction()`](#appendtransactioninstruction) for an example of how to use this function.
222
226
 
223
227
  ## Signing transactions
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ var errors = require('@solana/errors');
3
4
  var codecsStrings = require('@solana/codecs-strings');
4
5
  var addresses = require('@solana/addresses');
5
6
  var functional = require('@solana/functional');
@@ -8,7 +9,7 @@ var codecsDataStructures = require('@solana/codecs-data-structures');
8
9
  var codecsNumbers = require('@solana/codecs-numbers');
9
10
  var keys = require('@solana/keys');
10
11
 
11
- // ../rpc-types/dist/index.browser.js
12
+ // src/blockhash.ts
12
13
  var base58Encoder;
13
14
  function assertIsBlockhash(putativeBlockhash) {
14
15
  if (!base58Encoder)
@@ -61,7 +62,7 @@ function isTransactionWithBlockhashLifetime(transaction) {
61
62
  }
62
63
  function assertIsTransactionWithBlockhashLifetime(transaction) {
63
64
  if (!isTransactionWithBlockhashLifetime(transaction)) {
64
- throw new Error("Transaction does not have a blockhash lifetime");
65
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_EXPECTED_BLOCKHASH_LIFETIME);
65
66
  }
66
67
  }
67
68
  function setTransactionLifetimeUsingBlockhash(blockhashLifetimeConstraint, transaction) {
@@ -110,13 +111,11 @@ function isWritableRole(role) {
110
111
  function mergeRoles(roleA, roleB) {
111
112
  return roleA | roleB;
112
113
  }
113
-
114
- // src/durable-nonce.ts
115
114
  var RECENT_BLOCKHASHES_SYSVAR_ADDRESS = "SysvarRecentB1ockHashes11111111111111111111";
116
115
  var SYSTEM_PROGRAM_ADDRESS = "11111111111111111111111111111111";
117
116
  function assertIsDurableNonceTransaction(transaction) {
118
117
  if (!isDurableNonceTransaction(transaction)) {
119
- throw new Error("Transaction is not a durable nonce transaction");
118
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_EXPECTED_NONCE_LIFETIME);
120
119
  }
121
120
  }
122
121
  function createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress) {
@@ -202,17 +201,23 @@ function setTransactionFeePayer(feePayer, transaction) {
202
201
 
203
202
  // src/instructions.ts
204
203
  function appendTransactionInstruction(instruction, transaction) {
204
+ return appendTransactionInstructions([instruction], transaction);
205
+ }
206
+ function appendTransactionInstructions(instructions, transaction) {
205
207
  const out = {
206
208
  ...getUnsignedTransaction(transaction),
207
- instructions: [...transaction.instructions, instruction]
209
+ instructions: [...transaction.instructions, ...instructions]
208
210
  };
209
211
  Object.freeze(out);
210
212
  return out;
211
213
  }
212
214
  function prependTransactionInstruction(instruction, transaction) {
215
+ return prependTransactionInstructions([instruction], transaction);
216
+ }
217
+ function prependTransactionInstructions(instructions, transaction) {
213
218
  const out = {
214
219
  ...getUnsignedTransaction(transaction),
215
- instructions: [instruction, ...transaction.instructions]
220
+ instructions: [...instructions, ...transaction.instructions]
216
221
  };
217
222
  Object.freeze(out);
218
223
  return out;
@@ -259,8 +264,9 @@ function getAddressLookupMetas(compiledAddressTableLookups, addressesByLookupTab
259
264
  const compiledAddressTableLookupAddresses = compiledAddressTableLookups.map((l) => l.lookupTableAddress);
260
265
  const missing = compiledAddressTableLookupAddresses.filter((a) => addressesByLookupTableAddress[a] === void 0);
261
266
  if (missing.length > 0) {
262
- const missingAddresses = missing.join(", ");
263
- throw new Error(`Addresses not provided for lookup tables: [${missingAddresses}]`);
267
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_CONTENTS_MISSING, {
268
+ lookupTableAddresses: missing
269
+ });
264
270
  }
265
271
  const readOnlyMetas = [];
266
272
  const writableMetas = [];
@@ -268,8 +274,13 @@ function getAddressLookupMetas(compiledAddressTableLookups, addressesByLookupTab
268
274
  const addresses = addressesByLookupTableAddress[lookup.lookupTableAddress];
269
275
  const highestIndex = Math.max(...lookup.readableIndices, ...lookup.writableIndices);
270
276
  if (highestIndex >= addresses.length) {
271
- throw new Error(
272
- `Cannot look up index ${highestIndex} in lookup table [${lookup.lookupTableAddress}]. The lookup table may have been extended since the addresses provided were retrieved.`
277
+ throw new errors.SolanaError(
278
+ errors.SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_INDEX_OUT_OF_RANGE,
279
+ {
280
+ highestKnownIndex: addresses.length - 1,
281
+ highestRequestedIndex: highestIndex,
282
+ lookupTableAddress: lookup.lookupTableAddress
283
+ }
273
284
  );
274
285
  }
275
286
  const readOnlyForLookup = lookup.readableIndices.map((r) => ({
@@ -292,7 +303,9 @@ function getAddressLookupMetas(compiledAddressTableLookups, addressesByLookupTab
292
303
  function convertInstruction(instruction, accountMetas) {
293
304
  const programAddress = accountMetas[instruction.programAddressIndex]?.address;
294
305
  if (!programAddress) {
295
- throw new Error(`Could not find program address at index ${instruction.programAddressIndex}`);
306
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_INSTRUCTION_PROGRAM_ADDRESS_NOT_FOUND, {
307
+ index: instruction.programAddressIndex
308
+ });
296
309
  }
297
310
  const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
298
311
  const { data } = instruction;
@@ -337,8 +350,9 @@ function convertSignatures(compiledTransaction) {
337
350
  function decompileTransaction(compiledTransaction, config) {
338
351
  const { compiledMessage } = compiledTransaction;
339
352
  const feePayer = compiledMessage.staticAccounts[0];
340
- if (!feePayer)
341
- throw new Error("No fee payer set in CompiledTransaction");
353
+ if (!feePayer) {
354
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_FEE_PAYER_MISSING);
355
+ }
342
356
  const accountMetas = getAccountMetas(compiledMessage);
343
357
  const accountLookupMetas = "addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups !== void 0 && compiledMessage.addressTableLookups.length > 0 ? getAddressLookupMetas(compiledMessage.addressTableLookups, config?.addressesByLookupTableAddress ?? {}) : [];
344
358
  const transactionMetas = [...accountMetas, ...accountLookupMetas];
@@ -378,13 +392,13 @@ function getAddressMapFromInstructions(feePayer, instructions) {
378
392
  if (isWritableRole(entry.role)) {
379
393
  switch (entry[TYPE]) {
380
394
  case 0 /* FEE_PAYER */:
381
- throw new Error(
382
- `This transaction includes an address (\`${instruction.programAddress}\`) which is both invoked and set as the fee payer. Program addresses may not pay fees.`
383
- );
395
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_CANNOT_PAY_FEES, {
396
+ programAddress: instruction.programAddress
397
+ });
384
398
  default:
385
- throw new Error(
386
- `This transaction includes an address (\`${instruction.programAddress}\`) which is both invoked and marked writable. Program addresses may not be writable.`
387
- );
399
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE, {
400
+ programAddress: instruction.programAddress
401
+ });
388
402
  }
389
403
  }
390
404
  if (entry[TYPE] === 2 /* STATIC */) {
@@ -449,8 +463,11 @@ function getAddressMapFromInstructions(feePayer, instructions) {
449
463
  addressesOfInvokedPrograms.has(account.address)
450
464
  ) {
451
465
  if (isWritableRole(accountMeta.role)) {
452
- throw new Error(
453
- `This transaction includes an address (\`${account.address}\`) which is both invoked and marked writable. Program addresses may not be writable.`
466
+ throw new errors.SolanaError(
467
+ errors.SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE,
468
+ {
469
+ programAddress: account.address
470
+ }
454
471
  );
455
472
  }
456
473
  if (entry.role !== nextRole) {
@@ -740,7 +757,9 @@ function getTransactionVersionEncoder() {
740
757
  return offset;
741
758
  }
742
759
  if (value < 0 || value > 127) {
743
- throw new Error(`Transaction version must be in the range [0, 127]. \`${value}\` given.`);
760
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_VERSION_NUMBER_OUT_OF_RANGE, {
761
+ actualVersion: value
762
+ });
744
763
  }
745
764
  bytes.set([value | VERSION_FLAG_MASK], offset);
746
765
  return offset + 1;
@@ -827,12 +846,15 @@ function getCompiledMessageEncoder() {
827
846
  });
828
847
  }
829
848
  function getCompiledMessageDecoder() {
830
- return codecsCore.mapDecoder(codecsDataStructures.getStructDecoder(getPreludeStructDecoderTuple()), ({ addressTableLookups, ...restOfMessage }) => {
831
- if (restOfMessage.version === "legacy" || !addressTableLookups?.length) {
832
- return restOfMessage;
849
+ return codecsCore.mapDecoder(
850
+ codecsDataStructures.getStructDecoder(getPreludeStructDecoderTuple()),
851
+ ({ addressTableLookups, ...restOfMessage }) => {
852
+ if (restOfMessage.version === "legacy" || !addressTableLookups?.length) {
853
+ return restOfMessage;
854
+ }
855
+ return { ...restOfMessage, addressTableLookups };
833
856
  }
834
- return { ...restOfMessage, addressTableLookups };
835
- });
857
+ );
836
858
  }
837
859
  function getCompiledMessageCodec() {
838
860
  return codecsCore.combineCodec(getCompiledMessageEncoder(), getCompiledMessageDecoder());
@@ -892,9 +914,7 @@ function getSignatureFromTransaction(transaction) {
892
914
  base58Decoder = codecsStrings.getBase58Decoder();
893
915
  const signatureBytes = transaction.signatures[transaction.feePayer];
894
916
  if (!signatureBytes) {
895
- throw new Error(
896
- "Could not determine this transaction's signature. Make sure that the transaction has been signed by its fee payer."
897
- );
917
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_SIGNATURE_NOT_COMPUTABLE);
898
918
  }
899
919
  const transactionSignature = base58Decoder.decode(signatureBytes);
900
920
  return transactionSignature;
@@ -934,7 +954,9 @@ function assertTransactionIsFullySigned(transaction) {
934
954
  }
935
955
  });
936
956
  if (missingSigs.length > 0) {
937
- throw new Error("Transaction is missing signatures for addresses: " + missingSigs.join(", "));
957
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_MISSING_SIGNATURES, {
958
+ addresses: missingSigs
959
+ });
938
960
  }
939
961
  }
940
962
  function getBase64EncodedWireTransaction(transaction) {
@@ -943,6 +965,7 @@ function getBase64EncodedWireTransaction(transaction) {
943
965
  }
944
966
 
945
967
  exports.appendTransactionInstruction = appendTransactionInstruction;
968
+ exports.appendTransactionInstructions = appendTransactionInstructions;
946
969
  exports.assertIsDurableNonceTransaction = assertIsDurableNonceTransaction;
947
970
  exports.assertIsTransactionWithBlockhashLifetime = assertIsTransactionWithBlockhashLifetime;
948
971
  exports.assertTransactionIsFullySigned = assertTransactionIsFullySigned;
@@ -958,9 +981,11 @@ exports.getSignatureFromTransaction = getSignatureFromTransaction;
958
981
  exports.getTransactionCodec = getTransactionCodec;
959
982
  exports.getTransactionDecoder = getTransactionDecoder;
960
983
  exports.getTransactionEncoder = getTransactionEncoder;
984
+ exports.getUnsignedTransaction = getUnsignedTransaction;
961
985
  exports.isAdvanceNonceAccountInstruction = isAdvanceNonceAccountInstruction;
962
986
  exports.partiallySignTransaction = partiallySignTransaction;
963
987
  exports.prependTransactionInstruction = prependTransactionInstruction;
988
+ exports.prependTransactionInstructions = prependTransactionInstructions;
964
989
  exports.setTransactionFeePayer = setTransactionFeePayer;
965
990
  exports.setTransactionLifetimeUsingBlockhash = setTransactionLifetimeUsingBlockhash;
966
991
  exports.setTransactionLifetimeUsingDurableNonce = setTransactionLifetimeUsingDurableNonce;