@solana/transactions 2.0.0-experimental.c5061ae → 2.0.0-experimental.c7ef49c

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,5 +1,9 @@
1
1
  import { base58, struct, array, bytes, shortU16, mapSerializer, string, u8 } from '@metaplex-foundation/umi-serializers';
2
- import { getBase58EncodedAddressFromPublicKey, signBytes, getBase58EncodedAddressComparator, getBase58EncodedAddressCodec } from '@solana/keys';
2
+ import { getAddressFromPublicKey, getAddressComparator, getAddressCodec } from '@solana/addresses';
3
+ import { getStructCodec } from '@solana/codecs-data-structures';
4
+ import { getU8Codec } from '@solana/codecs-numbers';
5
+ import { combineCodec } from '@solana/codecs-core';
6
+ import { signBytes } from '@solana/keys';
3
7
 
4
8
  // ../build-scripts/env-shim.ts
5
9
  var __DEV__ = /* @__PURE__ */ (() => process["env"].NODE_ENV === "development")();
@@ -94,6 +98,20 @@ function assertIsDurableNonceTransaction(transaction) {
94
98
  throw new Error("Transaction is not a durable nonce transaction");
95
99
  }
96
100
  }
101
+ function createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress) {
102
+ return {
103
+ accounts: [
104
+ { address: nonceAccountAddress, role: AccountRole.WRITABLE },
105
+ {
106
+ address: RECENT_BLOCKHASHES_SYSVAR_ADDRESS,
107
+ role: AccountRole.READONLY
108
+ },
109
+ { address: nonceAuthorityAddress, role: AccountRole.READONLY_SIGNER }
110
+ ],
111
+ data: new Uint8Array([4, 0, 0, 0]),
112
+ programAddress: SYSTEM_PROGRAM_ADDRESS
113
+ };
114
+ }
97
115
  function isAdvanceNonceAccountInstruction(instruction) {
98
116
  return instruction.programAddress === SYSTEM_PROGRAM_ADDRESS && // Test for `AdvanceNonceAccount` instruction data
99
117
  instruction.data != null && isAdvanceNonceAccountInstructionData(instruction.data) && // Test for exactly 3 accounts
@@ -108,6 +126,28 @@ function isAdvanceNonceAccountInstructionData(data) {
108
126
  function isDurableNonceTransaction(transaction) {
109
127
  return "lifetimeConstraint" in transaction && typeof transaction.lifetimeConstraint.nonce === "string" && transaction.instructions[0] != null && isAdvanceNonceAccountInstruction(transaction.instructions[0]);
110
128
  }
129
+ function setTransactionLifetimeUsingDurableNonce({
130
+ nonce,
131
+ nonceAccountAddress,
132
+ nonceAuthorityAddress
133
+ }, 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;
137
+ }
138
+ const out = {
139
+ ...getUnsignedTransaction(transaction),
140
+ instructions: [
141
+ createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
142
+ ...isAlreadyDurableNonceTransaction ? transaction.instructions.slice(1) : transaction.instructions
143
+ ],
144
+ lifetimeConstraint: {
145
+ nonce
146
+ }
147
+ };
148
+ Object.freeze(out);
149
+ return out;
150
+ }
111
151
 
112
152
  // src/fee-payer.ts
113
153
  function setTransactionFeePayer(feePayer, transaction) {
@@ -191,7 +231,7 @@ function getAddressMapFromInstructions(feePayer, instructions) {
191
231
  const shouldReplaceEntry = (
192
232
  // Consider using the new LOOKUP_TABLE if its address is different...
193
233
  entry.lookupTableAddress !== accountMeta.lookupTableAddress && // ...and sorts before the existing one.
194
- (addressComparator || (addressComparator = getBase58EncodedAddressComparator()))(
234
+ (addressComparator || (addressComparator = getAddressComparator()))(
195
235
  accountMeta.lookupTableAddress,
196
236
  entry.lookupTableAddress
197
237
  ) < 0
@@ -297,7 +337,7 @@ function getOrderedAccountsFromAddressMap(addressMap) {
297
337
  if (leftIsWritable !== isWritableRole(rightEntry.role)) {
298
338
  return leftIsWritable ? -1 : 1;
299
339
  }
300
- addressComparator || (addressComparator = getBase58EncodedAddressComparator());
340
+ addressComparator || (addressComparator = getAddressComparator());
301
341
  if (leftEntry[TYPE] === 1 /* LOOKUP_TABLE */ && rightEntry[TYPE] === 1 /* LOOKUP_TABLE */ && leftEntry.lookupTableAddress !== rightEntry.lookupTableAddress) {
302
342
  return addressComparator(leftEntry.lookupTableAddress, rightEntry.lookupTableAddress);
303
343
  } else {
@@ -326,7 +366,7 @@ function getCompiledAddressTableLookups(orderedAccounts) {
326
366
  entry.readableIndices.push(account.addressIndex);
327
367
  }
328
368
  }
329
- return Object.keys(index).sort(getBase58EncodedAddressComparator()).map((lookupTableAddress) => ({
369
+ return Object.keys(index).sort(getAddressComparator()).map((lookupTableAddress) => ({
330
370
  lookupTableAddress,
331
371
  ...index[lookupTableAddress]
332
372
  }));
@@ -405,12 +445,40 @@ function compileMessage(transaction) {
405
445
  version: transaction.version
406
446
  };
407
447
  }
448
+
449
+ // src/compile-transaction.ts
450
+ function getCompiledTransaction(transaction) {
451
+ const compiledMessage = compileMessage(transaction);
452
+ let signatures;
453
+ if ("signatures" in transaction) {
454
+ signatures = [];
455
+ for (let ii = 0; ii < compiledMessage.header.numSignerAccounts; ii++) {
456
+ signatures[ii] = transaction.signatures[compiledMessage.staticAccounts[ii]] ?? new Uint8Array(Array(64).fill(0));
457
+ }
458
+ } else {
459
+ signatures = Array(compiledMessage.header.numSignerAccounts).fill(new Uint8Array(Array(64).fill(0)));
460
+ }
461
+ return {
462
+ compiledMessage,
463
+ signatures
464
+ };
465
+ }
466
+ function addressSerializerCompat(compat) {
467
+ const codec = getAddressCodec();
468
+ return {
469
+ description: compat?.description ?? codec.description,
470
+ deserialize: codec.decode,
471
+ fixedSize: codec.fixedSize,
472
+ maxSize: codec.maxSize,
473
+ serialize: codec.encode
474
+ };
475
+ }
408
476
  function getAddressTableLookupCodec() {
409
477
  return struct(
410
478
  [
411
479
  [
412
480
  "lookupTableAddress",
413
- getBase58EncodedAddressCodec(
481
+ addressSerializerCompat(
414
482
  __DEV__ ? {
415
483
  description: "The address of the address lookup table account from which instruction addresses should be looked up"
416
484
  } : void 0
@@ -440,37 +508,33 @@ function getAddressTableLookupCodec() {
440
508
  } : void 0
441
509
  );
442
510
  }
511
+ var memoizedU8Codec;
512
+ function getMemoizedU8Codec() {
513
+ if (!memoizedU8Codec)
514
+ memoizedU8Codec = getU8Codec();
515
+ return memoizedU8Codec;
516
+ }
517
+ function getMemoizedU8CodecDescription(description) {
518
+ const codec = getMemoizedU8Codec();
519
+ return {
520
+ ...codec,
521
+ description: description ?? codec.description
522
+ };
523
+ }
524
+ 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;
525
+ 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;
526
+ var numReadonlyNonSignerAccountsDescription = __DEV__ ? "The expected number of addresses in the static address list belonging to accounts that are neither signers, nor writable" : void 0;
527
+ var messageHeaderDescription = __DEV__ ? "The transaction message header containing counts of the signer, readonly-signer, and readonly-nonsigner account addresses" : void 0;
443
528
  function getMessageHeaderCodec() {
444
- return struct(
529
+ return getStructCodec(
445
530
  [
446
- [
447
- "numSignerAccounts",
448
- u8(
449
- __DEV__ ? {
450
- description: "The expected number of addresses in the static address list belonging to accounts that are required to sign this transaction"
451
- } : void 0
452
- )
453
- ],
454
- [
455
- "numReadonlySignerAccounts",
456
- u8(
457
- __DEV__ ? {
458
- description: "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"
459
- } : void 0
460
- )
461
- ],
462
- [
463
- "numReadonlyNonSignerAccounts",
464
- u8(
465
- __DEV__ ? {
466
- description: "The expected number of addresses in the static address list belonging to accounts that are neither signers, nor writable"
467
- } : void 0
468
- )
469
- ]
531
+ ["numSignerAccounts", getMemoizedU8CodecDescription(numSignerAccountsDescription)],
532
+ ["numReadonlySignerAccounts", getMemoizedU8CodecDescription(numReadonlySignerAccountsDescription)],
533
+ ["numReadonlyNonSignerAccounts", getMemoizedU8CodecDescription(numReadonlyNonSignerAccountsDescription)]
470
534
  ],
471
- __DEV__ ? {
472
- description: "The transaction message header containing counts of the signer, readonly-signer, and readonly-nonsigner account addresses"
473
- } : void 0
535
+ {
536
+ description: messageHeaderDescription
537
+ }
474
538
  );
475
539
  }
476
540
  function getInstructionCodec() {
@@ -485,7 +549,7 @@ function getInstructionCodec() {
485
549
  )
486
550
  ],
487
551
  [
488
- "addressIndices",
552
+ "accountIndices",
489
553
  array(
490
554
  u8({
491
555
  description: __DEV__ ? "The index of an account, according to the well-ordered accounts list for this transaction" : ""
@@ -505,50 +569,35 @@ function getInstructionCodec() {
505
569
  ]
506
570
  ]),
507
571
  (value) => {
508
- if (value.addressIndices !== void 0 && value.data !== void 0) {
572
+ if (value.accountIndices !== void 0 && value.data !== void 0) {
509
573
  return value;
510
574
  }
511
575
  return {
512
576
  ...value,
513
- addressIndices: value.addressIndices ?? [],
577
+ accountIndices: value.accountIndices ?? [],
514
578
  data: value.data ?? new Uint8Array(0)
515
579
  };
516
580
  },
517
581
  (value) => {
518
- if (value.addressIndices.length && value.data.byteLength) {
582
+ if (value.accountIndices.length && value.data.byteLength) {
519
583
  return value;
520
584
  }
521
- const { addressIndices, data, ...rest } = value;
585
+ const { accountIndices, data, ...rest } = value;
522
586
  return {
523
587
  ...rest,
524
- ...addressIndices.length ? { addressIndices } : null,
588
+ ...accountIndices.length ? { accountIndices } : null,
525
589
  ...data.byteLength ? { data } : null
526
590
  };
527
591
  }
528
592
  );
529
593
  }
530
-
531
- // src/serializers/unimplemented.ts
532
- function getError(type, name) {
533
- const functionSuffix = name + type[0].toUpperCase() + type.slice(1);
534
- return new Error(
535
- `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}`
536
- );
537
- }
538
- function getUnimplementedDecoder(name) {
539
- return () => {
540
- throw getError("decoder", name);
541
- };
542
- }
543
-
544
- // src/serializers/transaction-version.ts
545
594
  var VERSION_FLAG_MASK = 128;
546
595
  var BASE_CONFIG = {
547
596
  description: __DEV__ ? "A single byte that encodes the version of the transaction" : "",
548
597
  fixedSize: null,
549
598
  maxSize: 1
550
599
  };
551
- function deserialize(bytes3, offset = 0) {
600
+ function decode(bytes3, offset = 0) {
552
601
  const firstByte = bytes3[offset];
553
602
  if ((firstByte & VERSION_FLAG_MASK) === 0) {
554
603
  return ["legacy", offset];
@@ -557,7 +606,7 @@ function deserialize(bytes3, offset = 0) {
557
606
  return [version, offset + 1];
558
607
  }
559
608
  }
560
- function serialize(value) {
609
+ function encode(value) {
561
610
  if (value === "legacy") {
562
611
  return new Uint8Array();
563
612
  }
@@ -566,11 +615,32 @@ function serialize(value) {
566
615
  }
567
616
  return new Uint8Array([value | VERSION_FLAG_MASK]);
568
617
  }
569
- function getTransactionVersionCodec() {
618
+ function getTransactionVersionDecoder() {
570
619
  return {
571
620
  ...BASE_CONFIG,
572
- deserialize,
573
- serialize
621
+ decode
622
+ };
623
+ }
624
+ function getTransactionVersionEncoder() {
625
+ return {
626
+ ...BASE_CONFIG,
627
+ encode
628
+ };
629
+ }
630
+ function getTransactionVersionCodec() {
631
+ return combineCodec(getTransactionVersionEncoder(), getTransactionVersionDecoder());
632
+ }
633
+
634
+ // src/serializers/unimplemented.ts
635
+ function getError(type, name) {
636
+ const functionSuffix = name + type[0].toUpperCase() + type.slice(1);
637
+ return new Error(
638
+ `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}`
639
+ );
640
+ }
641
+ function getUnimplementedDecoder(name) {
642
+ return () => {
643
+ throw getError("decoder", name);
574
644
  };
575
645
  }
576
646
 
@@ -580,7 +650,7 @@ var BASE_CONFIG2 = {
580
650
  fixedSize: null,
581
651
  maxSize: null
582
652
  };
583
- function serialize2(compiledMessage) {
653
+ function serialize(compiledMessage) {
584
654
  if (compiledMessage.version === "legacy") {
585
655
  return struct(getPreludeStructSerializerTuple()).serialize(compiledMessage);
586
656
  } else {
@@ -601,13 +671,22 @@ function serialize2(compiledMessage) {
601
671
  ).serialize(compiledMessage);
602
672
  }
603
673
  }
674
+ function toSerializer(codec) {
675
+ return {
676
+ description: codec.description,
677
+ deserialize: codec.decode,
678
+ fixedSize: codec.fixedSize,
679
+ maxSize: codec.maxSize,
680
+ serialize: codec.encode
681
+ };
682
+ }
604
683
  function getPreludeStructSerializerTuple() {
605
684
  return [
606
- ["version", getTransactionVersionCodec()],
607
- ["header", getMessageHeaderCodec()],
685
+ ["version", toSerializer(getTransactionVersionCodec())],
686
+ ["header", toSerializer(getMessageHeaderCodec())],
608
687
  [
609
688
  "staticAccounts",
610
- array(getBase58EncodedAddressCodec(), {
689
+ array(toSerializer(getAddressCodec()), {
611
690
  description: __DEV__ ? "A compact-array of static account addresses belonging to this transaction" : "",
612
691
  size: shortU16()
613
692
  })
@@ -639,49 +718,7 @@ function getCompiledMessageEncoder() {
639
718
  return {
640
719
  ...BASE_CONFIG2,
641
720
  deserialize: getUnimplementedDecoder("CompiledMessage"),
642
- serialize: serialize2
643
- };
644
- }
645
-
646
- // src/signatures.ts
647
- async function getCompiledMessageSignature(message, secretKey) {
648
- const wireMessageBytes = getCompiledMessageEncoder().serialize(message);
649
- const signature = await signBytes(secretKey, wireMessageBytes);
650
- return signature;
651
- }
652
- async function signTransaction(keyPair, transaction) {
653
- const compiledMessage = compileMessage(transaction);
654
- const [signerPublicKey, signature] = await Promise.all([
655
- getBase58EncodedAddressFromPublicKey(keyPair.publicKey),
656
- getCompiledMessageSignature(compiledMessage, keyPair.privateKey)
657
- ]);
658
- const nextSignatures = {
659
- ..."signatures" in transaction ? transaction.signatures : null,
660
- ...{ [signerPublicKey]: signature }
661
- };
662
- const out = {
663
- ...transaction,
664
- signatures: nextSignatures
665
- };
666
- Object.freeze(out);
667
- return out;
668
- }
669
-
670
- // src/compile-transaction.ts
671
- function getCompiledTransaction(transaction) {
672
- const compiledMessage = compileMessage(transaction);
673
- let signatures;
674
- if ("signatures" in transaction) {
675
- signatures = [];
676
- for (let ii = 0; ii < compiledMessage.header.numSignerAccounts; ii++) {
677
- signatures[ii] = transaction.signatures[compiledMessage.staticAccounts[ii]] ?? new Uint8Array(Array(64).fill(0));
678
- }
679
- } else {
680
- signatures = Array(compiledMessage.header.numSignerAccounts).fill(new Uint8Array(Array(64).fill(0)));
681
- }
682
- return {
683
- compiledMessage,
684
- signatures
721
+ serialize
685
722
  };
686
723
  }
687
724
 
@@ -691,7 +728,7 @@ var BASE_CONFIG3 = {
691
728
  fixedSize: null,
692
729
  maxSize: null
693
730
  };
694
- function serialize3(transaction) {
731
+ function serialize2(transaction) {
695
732
  const compiledTransaction = getCompiledTransaction(transaction);
696
733
  return struct([
697
734
  [
@@ -708,8 +745,82 @@ function getTransactionEncoder() {
708
745
  return {
709
746
  ...BASE_CONFIG3,
710
747
  deserialize: getUnimplementedDecoder("CompiledMessage"),
711
- serialize: serialize3
748
+ serialize: serialize2
749
+ };
750
+ }
751
+ function assertIsTransactionSignature(putativeTransactionSignature) {
752
+ try {
753
+ if (
754
+ // Lowest value (64 bytes of zeroes)
755
+ putativeTransactionSignature.length < 64 || // Highest value (64 bytes of 255)
756
+ putativeTransactionSignature.length > 88
757
+ ) {
758
+ throw new Error("Expected input string to decode to a byte array of length 64.");
759
+ }
760
+ const bytes3 = base58.serialize(putativeTransactionSignature);
761
+ const numBytes = bytes3.byteLength;
762
+ if (numBytes !== 64) {
763
+ throw new Error(`Expected input string to decode to a byte array of length 64. Actual length: ${numBytes}`);
764
+ }
765
+ } catch (e) {
766
+ throw new Error(`\`${putativeTransactionSignature}\` is not a transaction signature`, {
767
+ cause: e
768
+ });
769
+ }
770
+ }
771
+ function isTransactionSignature(putativeTransactionSignature) {
772
+ if (
773
+ // Lowest value (64 bytes of zeroes)
774
+ putativeTransactionSignature.length < 64 || // Highest value (64 bytes of 255)
775
+ putativeTransactionSignature.length > 88
776
+ ) {
777
+ return false;
778
+ }
779
+ const bytes3 = base58.serialize(putativeTransactionSignature);
780
+ const numBytes = bytes3.byteLength;
781
+ if (numBytes !== 64) {
782
+ return false;
783
+ }
784
+ return true;
785
+ }
786
+ async function getCompiledMessageSignature(message, secretKey) {
787
+ const wireMessageBytes = getCompiledMessageEncoder().serialize(message);
788
+ const signature = await signBytes(secretKey, wireMessageBytes);
789
+ return signature;
790
+ }
791
+ function getSignatureFromTransaction(transaction) {
792
+ const signature = transaction.signatures[transaction.feePayer];
793
+ if (!signature) {
794
+ throw new Error(
795
+ "Could not determine this transaction's signature. Make sure that the transaction has been signed by its fee payer."
796
+ );
797
+ }
798
+ return signature;
799
+ }
800
+ async function signTransaction(keyPairs, transaction) {
801
+ const compiledMessage = compileMessage(transaction);
802
+ const nextSignatures = "signatures" in transaction ? { ...transaction.signatures } : {};
803
+ const publicKeySignaturePairs = await Promise.all(
804
+ keyPairs.map(
805
+ (keyPair) => Promise.all([
806
+ getAddressFromPublicKey(keyPair.publicKey),
807
+ getCompiledMessageSignature(compiledMessage, keyPair.privateKey)
808
+ ])
809
+ )
810
+ );
811
+ for (const [signerPublicKey, signature] of publicKeySignaturePairs) {
812
+ nextSignatures[signerPublicKey] = signature;
813
+ }
814
+ const out = {
815
+ ...transaction,
816
+ signatures: nextSignatures
712
817
  };
818
+ Object.freeze(out);
819
+ return out;
820
+ }
821
+ function transactionSignature(putativeTransactionSignature) {
822
+ assertIsTransactionSignature(putativeTransactionSignature);
823
+ return putativeTransactionSignature;
713
824
  }
714
825
 
715
826
  // src/wire-transaction.ts
@@ -720,6 +831,6 @@ function getBase64EncodedWireTransaction(transaction) {
720
831
  }
721
832
  }
722
833
 
723
- export { appendTransactionInstruction, assertIsBlockhash, assertIsDurableNonceTransaction, createTransaction, getBase64EncodedWireTransaction, prependTransactionInstruction, setTransactionFeePayer, setTransactionLifetimeUsingBlockhash, signTransaction };
834
+ export { appendTransactionInstruction, assertIsBlockhash, assertIsDurableNonceTransaction, assertIsTransactionSignature, createTransaction, getBase64EncodedWireTransaction, getSignatureFromTransaction, getTransactionEncoder, isTransactionSignature, prependTransactionInstruction, setTransactionFeePayer, setTransactionLifetimeUsingBlockhash, setTransactionLifetimeUsingDurableNonce, signTransaction, transactionSignature };
724
835
  //# sourceMappingURL=out.js.map
725
836
  //# sourceMappingURL=index.browser.js.map