@solana/transactions 2.0.0-experimental.e1ca396 → 2.0.0-experimental.e58bb22

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.
Files changed (44) hide show
  1. package/dist/index.browser.cjs +178 -137
  2. package/dist/index.browser.cjs.map +1 -1
  3. package/dist/index.browser.js +181 -141
  4. package/dist/index.browser.js.map +1 -1
  5. package/dist/index.native.js +181 -141
  6. package/dist/index.native.js.map +1 -1
  7. package/dist/index.node.cjs +178 -137
  8. package/dist/index.node.cjs.map +1 -1
  9. package/dist/index.node.js +183 -141
  10. package/dist/index.node.js.map +1 -1
  11. package/dist/types/blockhash.d.ts +4 -7
  12. package/dist/types/blockhash.d.ts.map +1 -1
  13. package/dist/types/compilable-transaction.d.ts +4 -4
  14. package/dist/types/compile-address-table-lookups.d.ts +1 -1
  15. package/dist/types/compile-header.d.ts +1 -1
  16. package/dist/types/compile-instructions.d.ts +1 -1
  17. package/dist/types/compile-lifetime-token.d.ts +1 -1
  18. package/dist/types/compile-static-accounts.d.ts +1 -1
  19. package/dist/types/compile-transaction.d.ts +3 -3
  20. package/dist/types/create-transaction.d.ts +1 -1
  21. package/dist/types/decompile-transaction.d.ts +12 -4
  22. package/dist/types/decompile-transaction.d.ts.map +1 -1
  23. package/dist/types/durable-nonce.d.ts +2 -2
  24. package/dist/types/fee-payer.d.ts +2 -2
  25. package/dist/types/index.d.ts +12 -11
  26. package/dist/types/index.d.ts.map +1 -1
  27. package/dist/types/instructions.d.ts +2 -2
  28. package/dist/types/message.d.ts +6 -6
  29. package/dist/types/serializers/address-table-lookup.d.ts +1 -1
  30. package/dist/types/serializers/header.d.ts +1 -1
  31. package/dist/types/serializers/index.d.ts +2 -2
  32. package/dist/types/serializers/instruction.d.ts +1 -1
  33. package/dist/types/serializers/message.d.ts +1 -1
  34. package/dist/types/serializers/transaction-version.d.ts +1 -1
  35. package/dist/types/serializers/transaction.d.ts +7 -4
  36. package/dist/types/serializers/transaction.d.ts.map +1 -1
  37. package/dist/types/signatures.d.ts +2 -2
  38. package/dist/types/signatures.d.ts.map +1 -1
  39. package/dist/types/unsigned-transaction.d.ts +1 -1
  40. package/dist/types/wire-transaction.d.ts +1 -1
  41. package/package.json +17 -15
  42. package/dist/index.development.js +0 -1628
  43. package/dist/index.development.js.map +0 -1
  44. package/dist/index.production.min.js +0 -32
@@ -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,116 +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 convertInstruction(instruction, accountMetas) {
750
- const programAddress = accountMetas[instruction.programAddressIndex]?.address;
751
- if (!programAddress) {
752
- throw new Error(`Could not find program address at index ${instruction.programAddressIndex}`);
753
- }
754
- const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
755
- const { data } = instruction;
756
- return {
757
- programAddress,
758
- ...accounts && accounts.length ? { accounts } : {},
759
- ...data && data.length ? { data } : {}
760
- };
761
- }
762
- function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
763
- if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
764
- return {
765
- blockhash: messageLifetimeToken,
766
- lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
767
- // U64 MAX
768
- };
769
- } else {
770
- const nonceAccountAddress = firstInstruction.accounts[0].address;
771
- addresses.assertIsAddress(nonceAccountAddress);
772
- const nonceAuthorityAddress = firstInstruction.accounts[2].address;
773
- addresses.assertIsAddress(nonceAuthorityAddress);
774
- return {
775
- nonce: messageLifetimeToken,
776
- nonceAccountAddress,
777
- nonceAuthorityAddress
778
- };
779
- }
780
- }
781
- function convertSignatures(compiledTransaction) {
782
- const {
783
- compiledMessage: { staticAccounts },
784
- signatures
785
- } = compiledTransaction;
786
- return signatures.reduce((acc, sig, index) => {
787
- const allZeros = sig.every((byte) => byte === 0);
788
- if (allZeros)
789
- return acc;
790
- const address = staticAccounts[index];
791
- return { ...acc, [address]: sig };
792
- }, {});
793
- }
794
- function decompileTransaction(compiledTransaction, lastValidBlockHeight) {
795
- const { compiledMessage } = compiledTransaction;
796
- if ("addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups.length > 0) {
797
- throw new Error("Cannot convert transaction with addressTableLookups");
798
- }
799
- const feePayer = compiledMessage.staticAccounts[0];
800
- if (!feePayer)
801
- throw new Error("No fee payer set in CompiledTransaction");
802
- const accountMetas = getAccountMetas(compiledMessage);
803
- const instructions = compiledMessage.instructions.map(
804
- (compiledInstruction) => convertInstruction(compiledInstruction, accountMetas)
805
- );
806
- const firstInstruction = instructions[0];
807
- const lifetimeConstraint = getLifetimeConstraint(
808
- compiledMessage.lifetimeToken,
809
- firstInstruction,
810
- lastValidBlockHeight
811
- );
812
- const signatures = convertSignatures(compiledTransaction);
813
- return functional.pipe(
814
- createTransaction({ version: compiledMessage.version }),
815
- (tx) => setTransactionFeePayer(feePayer, tx),
816
- (tx) => instructions.reduce((acc, instruction) => {
817
- return appendTransactionInstruction(instruction, acc);
818
- }, tx),
819
- (tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
820
- (tx) => compiledTransaction.signatures.length ? { ...tx, signatures } : tx
821
- );
822
- }
823
859
 
824
860
  // src/serializers/transaction.ts
825
861
  function getCompiledTransactionEncoder() {
@@ -842,14 +878,14 @@ function getCompiledTransactionDecoder() {
842
878
  function getTransactionEncoder() {
843
879
  return codecsCore.mapEncoder(getCompiledTransactionEncoder(), getCompiledTransaction);
844
880
  }
845
- function getTransactionDecoder(lastValidBlockHeight) {
881
+ function getTransactionDecoder(config) {
846
882
  return codecsCore.mapDecoder(
847
883
  getCompiledTransactionDecoder(),
848
- (compiledTransaction) => decompileTransaction(compiledTransaction, lastValidBlockHeight)
884
+ (compiledTransaction) => decompileTransaction(compiledTransaction, config)
849
885
  );
850
886
  }
851
- function getTransactionCodec(lastValidBlockHeight) {
852
- return codecsCore.combineCodec(getTransactionEncoder(), getTransactionDecoder(lastValidBlockHeight));
887
+ function getTransactionCodec(config) {
888
+ return codecsCore.combineCodec(getTransactionEncoder(), getTransactionDecoder(config));
853
889
  }
854
890
  var base58Decoder;
855
891
  function getSignatureFromTransaction(transaction) {
@@ -857,9 +893,7 @@ function getSignatureFromTransaction(transaction) {
857
893
  base58Decoder = codecsStrings.getBase58Decoder();
858
894
  const signatureBytes = transaction.signatures[transaction.feePayer];
859
895
  if (!signatureBytes) {
860
- throw new Error(
861
- "Could not determine this transaction's signature. Make sure that the transaction has been signed by its fee payer."
862
- );
896
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_SIGNATURE_NOT_COMPUTABLE);
863
897
  }
864
898
  const transactionSignature = base58Decoder.decode(signatureBytes);
865
899
  return transactionSignature;
@@ -892,11 +926,17 @@ async function signTransaction(keyPairs, transaction) {
892
926
  function assertTransactionIsFullySigned(transaction) {
893
927
  const signerAddressesFromInstructions = transaction.instructions.flatMap((i) => i.accounts?.filter((a) => isSignerRole(a.role)) ?? []).map((a) => a.address);
894
928
  const requiredSigners = /* @__PURE__ */ new Set([transaction.feePayer, ...signerAddressesFromInstructions]);
929
+ const missingSigs = [];
895
930
  requiredSigners.forEach((address) => {
896
931
  if (!transaction.signatures[address]) {
897
- throw new Error(`Transaction is missing signature for address \`${address}\``);
932
+ missingSigs.push(address);
898
933
  }
899
934
  });
935
+ if (missingSigs.length > 0) {
936
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_MISSING_SIGNATURES, {
937
+ addresses: missingSigs
938
+ });
939
+ }
900
940
  }
901
941
  function getBase64EncodedWireTransaction(transaction) {
902
942
  const wireTransactionBytes = getTransactionEncoder().encode(transaction);
@@ -904,16 +944,17 @@ function getBase64EncodedWireTransaction(transaction) {
904
944
  }
905
945
 
906
946
  exports.appendTransactionInstruction = appendTransactionInstruction;
907
- exports.assertIsBlockhash = assertIsBlockhash;
908
947
  exports.assertIsDurableNonceTransaction = assertIsDurableNonceTransaction;
909
948
  exports.assertIsTransactionWithBlockhashLifetime = assertIsTransactionWithBlockhashLifetime;
910
949
  exports.assertTransactionIsFullySigned = assertTransactionIsFullySigned;
911
950
  exports.compileMessage = compileMessage;
912
951
  exports.createTransaction = createTransaction;
952
+ exports.decompileTransaction = decompileTransaction;
913
953
  exports.getBase64EncodedWireTransaction = getBase64EncodedWireTransaction;
914
954
  exports.getCompiledMessageCodec = getCompiledMessageCodec;
915
955
  exports.getCompiledMessageDecoder = getCompiledMessageDecoder;
916
956
  exports.getCompiledMessageEncoder = getCompiledMessageEncoder;
957
+ exports.getCompiledTransactionDecoder = getCompiledTransactionDecoder;
917
958
  exports.getSignatureFromTransaction = getSignatureFromTransaction;
918
959
  exports.getTransactionCodec = getTransactionCodec;
919
960
  exports.getTransactionDecoder = getTransactionDecoder;