@solana/transactions 2.0.0-20241006045741

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.
@@ -0,0 +1,192 @@
1
+ import { getAddressDecoder, getAddressFromPublicKey } from '@solana/addresses';
2
+ import { transformDecoder, fixDecoderSize, combineCodec, padRightDecoder, transformEncoder, fixEncoderSize } from '@solana/codecs-core';
3
+ import { getStructEncoder, getBytesEncoder, getStructDecoder, getArrayDecoder, getBytesDecoder, getTupleDecoder, getArrayEncoder } from '@solana/codecs-data-structures';
4
+ import { getShortU16Decoder, getU8Decoder, getShortU16Encoder } from '@solana/codecs-numbers';
5
+ import { SolanaError, SOLANA_ERROR__TRANSACTION__MESSAGE_SIGNATURES_MISMATCH, SOLANA_ERROR__TRANSACTION__FEE_PAYER_SIGNATURE_MISSING, SOLANA_ERROR__TRANSACTION__ADDRESSES_CANNOT_SIGN_TRANSACTION, SOLANA_ERROR__TRANSACTION__SIGNATURES_MISSING, SOLANA_ERROR__TRANSACTION__CANNOT_ENCODE_WITH_EMPTY_SIGNATURES } from '@solana/errors';
6
+ import { getTransactionVersionDecoder, compileTransactionMessage, getCompiledTransactionMessageEncoder, isTransactionMessageWithBlockhashLifetime } from '@solana/transaction-messages';
7
+ import { getBase58Decoder, getBase64Decoder } from '@solana/codecs-strings';
8
+ import { signBytes } from '@solana/keys';
9
+
10
+ // src/codecs/transaction-codec.ts
11
+ function getSignaturesToEncode(signaturesMap) {
12
+ const signatures = Object.values(signaturesMap);
13
+ if (signatures.length === 0) {
14
+ throw new SolanaError(SOLANA_ERROR__TRANSACTION__CANNOT_ENCODE_WITH_EMPTY_SIGNATURES);
15
+ }
16
+ return signatures.map((signature) => {
17
+ if (!signature) {
18
+ return new Uint8Array(64).fill(0);
19
+ }
20
+ return signature;
21
+ });
22
+ }
23
+ function getSignaturesEncoder() {
24
+ return transformEncoder(
25
+ getArrayEncoder(fixEncoderSize(getBytesEncoder(), 64), { size: getShortU16Encoder() }),
26
+ getSignaturesToEncode
27
+ );
28
+ }
29
+
30
+ // src/codecs/transaction-codec.ts
31
+ function getTransactionEncoder() {
32
+ return getStructEncoder([
33
+ ["signatures", getSignaturesEncoder()],
34
+ ["messageBytes", getBytesEncoder()]
35
+ ]);
36
+ }
37
+ function getTransactionDecoder() {
38
+ return transformDecoder(
39
+ getStructDecoder([
40
+ ["signatures", getArrayDecoder(fixDecoderSize(getBytesDecoder(), 64), { size: getShortU16Decoder() })],
41
+ ["messageBytes", getBytesDecoder()]
42
+ ]),
43
+ decodePartiallyDecodedTransaction
44
+ );
45
+ }
46
+ function getTransactionCodec() {
47
+ return combineCodec(getTransactionEncoder(), getTransactionDecoder());
48
+ }
49
+ function decodePartiallyDecodedTransaction(transaction) {
50
+ const { messageBytes, signatures } = transaction;
51
+ const signerAddressesDecoder = getTupleDecoder([
52
+ // read transaction version
53
+ getTransactionVersionDecoder(),
54
+ // read first byte of header, `numSignerAccounts`
55
+ // padRight to skip the next 2 bytes, `numReadOnlySignedAccounts` and `numReadOnlyUnsignedAccounts` which we don't need
56
+ padRightDecoder(getU8Decoder(), 2),
57
+ // read static addresses
58
+ getArrayDecoder(getAddressDecoder(), { size: getShortU16Decoder() })
59
+ ]);
60
+ const [_txVersion, numRequiredSignatures, staticAddresses] = signerAddressesDecoder.decode(messageBytes);
61
+ const signerAddresses = staticAddresses.slice(0, numRequiredSignatures);
62
+ if (signerAddresses.length !== signatures.length) {
63
+ throw new SolanaError(SOLANA_ERROR__TRANSACTION__MESSAGE_SIGNATURES_MISMATCH, {
64
+ numRequiredSignatures,
65
+ signaturesLength: signatures.length,
66
+ signerAddresses
67
+ });
68
+ }
69
+ const signaturesMap = {};
70
+ signerAddresses.forEach((address, index) => {
71
+ const signatureForAddress = signatures[index];
72
+ if (signatureForAddress.every((b) => b === 0)) {
73
+ signaturesMap[address] = null;
74
+ } else {
75
+ signaturesMap[address] = signatureForAddress;
76
+ }
77
+ });
78
+ return {
79
+ messageBytes,
80
+ signatures: Object.freeze(signaturesMap)
81
+ };
82
+ }
83
+ function compileTransaction(transactionMessage) {
84
+ const compiledMessage = compileTransactionMessage(transactionMessage);
85
+ const messageBytes = getCompiledTransactionMessageEncoder().encode(
86
+ compiledMessage
87
+ );
88
+ const transactionSigners = compiledMessage.staticAccounts.slice(0, compiledMessage.header.numSignerAccounts);
89
+ const signatures = {};
90
+ for (const signerAddress of transactionSigners) {
91
+ signatures[signerAddress] = null;
92
+ }
93
+ let lifetimeConstraint;
94
+ if (isTransactionMessageWithBlockhashLifetime(transactionMessage)) {
95
+ lifetimeConstraint = {
96
+ blockhash: transactionMessage.lifetimeConstraint.blockhash,
97
+ lastValidBlockHeight: transactionMessage.lifetimeConstraint.lastValidBlockHeight
98
+ };
99
+ } else {
100
+ lifetimeConstraint = {
101
+ nonce: transactionMessage.lifetimeConstraint.nonce,
102
+ nonceAccountAddress: transactionMessage.instructions[0].accounts[0].address
103
+ };
104
+ }
105
+ const transaction = {
106
+ lifetimeConstraint,
107
+ messageBytes,
108
+ signatures: Object.freeze(signatures)
109
+ };
110
+ return Object.freeze(transaction);
111
+ }
112
+ var base58Decoder;
113
+ function getSignatureFromTransaction(transaction) {
114
+ if (!base58Decoder) base58Decoder = getBase58Decoder();
115
+ const signatureBytes = Object.values(transaction.signatures)[0];
116
+ if (!signatureBytes) {
117
+ throw new SolanaError(SOLANA_ERROR__TRANSACTION__FEE_PAYER_SIGNATURE_MISSING);
118
+ }
119
+ const transactionSignature = base58Decoder.decode(signatureBytes);
120
+ return transactionSignature;
121
+ }
122
+ function uint8ArraysEqual(arr1, arr2) {
123
+ return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]);
124
+ }
125
+ async function partiallySignTransaction(keyPairs, transaction) {
126
+ let newSignatures;
127
+ let unexpectedSigners;
128
+ await Promise.all(
129
+ keyPairs.map(async (keyPair) => {
130
+ const address = await getAddressFromPublicKey(keyPair.publicKey);
131
+ const existingSignature = transaction.signatures[address];
132
+ if (existingSignature === void 0) {
133
+ unexpectedSigners ||= /* @__PURE__ */ new Set();
134
+ unexpectedSigners.add(address);
135
+ return;
136
+ }
137
+ if (unexpectedSigners) {
138
+ return;
139
+ }
140
+ const newSignature = await signBytes(keyPair.privateKey, transaction.messageBytes);
141
+ if (existingSignature !== null && uint8ArraysEqual(newSignature, existingSignature)) {
142
+ return;
143
+ }
144
+ newSignatures ||= {};
145
+ newSignatures[address] = newSignature;
146
+ })
147
+ );
148
+ if (unexpectedSigners && unexpectedSigners.size > 0) {
149
+ const expectedSigners = Object.keys(transaction.signatures);
150
+ throw new SolanaError(SOLANA_ERROR__TRANSACTION__ADDRESSES_CANNOT_SIGN_TRANSACTION, {
151
+ expectedAddresses: expectedSigners,
152
+ unexpectedAddresses: [...unexpectedSigners]
153
+ });
154
+ }
155
+ if (!newSignatures) {
156
+ return transaction;
157
+ }
158
+ return Object.freeze({
159
+ ...transaction,
160
+ signatures: Object.freeze({
161
+ ...transaction.signatures,
162
+ ...newSignatures
163
+ })
164
+ });
165
+ }
166
+ async function signTransaction(keyPairs, transaction) {
167
+ const out = await partiallySignTransaction(keyPairs, transaction);
168
+ assertTransactionIsFullySigned(out);
169
+ Object.freeze(out);
170
+ return out;
171
+ }
172
+ function assertTransactionIsFullySigned(transaction) {
173
+ const missingSigs = [];
174
+ Object.entries(transaction.signatures).forEach(([address, signatureBytes]) => {
175
+ if (!signatureBytes) {
176
+ missingSigs.push(address);
177
+ }
178
+ });
179
+ if (missingSigs.length > 0) {
180
+ throw new SolanaError(SOLANA_ERROR__TRANSACTION__SIGNATURES_MISSING, {
181
+ addresses: missingSigs
182
+ });
183
+ }
184
+ }
185
+ function getBase64EncodedWireTransaction(transaction) {
186
+ const wireTransactionBytes = getTransactionEncoder().encode(transaction);
187
+ return getBase64Decoder().decode(wireTransactionBytes);
188
+ }
189
+
190
+ export { assertTransactionIsFullySigned, compileTransaction, getBase64EncodedWireTransaction, getSignatureFromTransaction, getTransactionCodec, getTransactionDecoder, getTransactionEncoder, partiallySignTransaction, signTransaction };
191
+ //# sourceMappingURL=index.native.mjs.map
192
+ //# sourceMappingURL=index.native.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/codecs/signatures-encoder.ts","../src/codecs/transaction-codec.ts","../src/compile-transaction.ts","../src/signatures.ts","../src/wire-transaction.ts"],"names":["getBytesEncoder","SolanaError"],"mappings":"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","file":"index.native.mjs","sourcesContent":["import { fixEncoderSize, transformEncoder, VariableSizeEncoder } from '@solana/codecs-core';\nimport { getArrayEncoder, getBytesEncoder } from '@solana/codecs-data-structures';\nimport { getShortU16Encoder } from '@solana/codecs-numbers';\nimport { SOLANA_ERROR__TRANSACTION__CANNOT_ENCODE_WITH_EMPTY_SIGNATURES, SolanaError } from '@solana/errors';\nimport { SignatureBytes } from '@solana/keys';\n\nimport { SignaturesMap } from '../transaction';\n\nfunction getSignaturesToEncode(signaturesMap: SignaturesMap): SignatureBytes[] {\n const signatures = Object.values(signaturesMap);\n if (signatures.length === 0) {\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__CANNOT_ENCODE_WITH_EMPTY_SIGNATURES);\n }\n\n return signatures.map(signature => {\n if (!signature) {\n return new Uint8Array(64).fill(0) as SignatureBytes;\n }\n return signature;\n });\n}\n\nexport function getSignaturesEncoder(): VariableSizeEncoder<SignaturesMap> {\n return transformEncoder(\n getArrayEncoder(fixEncoderSize(getBytesEncoder(), 64), { size: getShortU16Encoder() }),\n getSignaturesToEncode,\n );\n}\n","import { getAddressDecoder } from '@solana/addresses';\nimport {\n combineCodec,\n fixDecoderSize,\n padRightDecoder,\n ReadonlyUint8Array,\n transformDecoder,\n VariableSizeCodec,\n VariableSizeDecoder,\n VariableSizeEncoder,\n} from '@solana/codecs-core';\nimport {\n getArrayDecoder,\n getBytesDecoder,\n getBytesEncoder,\n getStructDecoder,\n getStructEncoder,\n getTupleDecoder,\n} from '@solana/codecs-data-structures';\nimport { getShortU16Decoder, getU8Decoder } from '@solana/codecs-numbers';\nimport { SOLANA_ERROR__TRANSACTION__MESSAGE_SIGNATURES_MISMATCH, SolanaError } from '@solana/errors';\nimport { SignatureBytes } from '@solana/keys';\nimport { getTransactionVersionDecoder } from '@solana/transaction-messages';\n\nimport { SignaturesMap, Transaction, TransactionMessageBytes } from '../transaction';\nimport { getSignaturesEncoder } from './signatures-encoder';\n\nexport function getTransactionEncoder(): VariableSizeEncoder<Transaction> {\n return getStructEncoder([\n ['signatures', getSignaturesEncoder()],\n ['messageBytes', getBytesEncoder()],\n ]);\n}\n\nexport function getTransactionDecoder(): VariableSizeDecoder<Transaction> {\n return transformDecoder(\n getStructDecoder([\n ['signatures', getArrayDecoder(fixDecoderSize(getBytesDecoder(), 64), { size: getShortU16Decoder() })],\n ['messageBytes', getBytesDecoder()],\n ]),\n decodePartiallyDecodedTransaction,\n );\n}\n\nexport function getTransactionCodec(): VariableSizeCodec<Transaction> {\n return combineCodec(getTransactionEncoder(), getTransactionDecoder());\n}\n\ntype PartiallyDecodedTransaction = {\n messageBytes: ReadonlyUint8Array;\n signatures: ReadonlyUint8Array[];\n};\n\nfunction decodePartiallyDecodedTransaction(transaction: PartiallyDecodedTransaction): Transaction {\n const { messageBytes, signatures } = transaction;\n\n /*\n Relevant message structure is at the start:\n - transaction version (0 bytes for legacy transactions, 1 byte for versioned transactions)\n - `numRequiredSignatures` (1 byte, we verify this matches the length of signatures)\n - `numReadOnlySignedAccounts` (1 byte, not used here)\n - `numReadOnlyUnsignedAccounts` (1 byte, not used here)\n - static addresses, with signers first. This is an array of addresses, prefixed with a short-u16 length\n */\n\n const signerAddressesDecoder = getTupleDecoder([\n // read transaction version\n getTransactionVersionDecoder(),\n // read first byte of header, `numSignerAccounts`\n // padRight to skip the next 2 bytes, `numReadOnlySignedAccounts` and `numReadOnlyUnsignedAccounts` which we don't need\n padRightDecoder(getU8Decoder(), 2),\n // read static addresses\n getArrayDecoder(getAddressDecoder(), { size: getShortU16Decoder() }),\n ]);\n const [_txVersion, numRequiredSignatures, staticAddresses] = signerAddressesDecoder.decode(messageBytes);\n\n const signerAddresses = staticAddresses.slice(0, numRequiredSignatures);\n\n // signer addresses and signatures must be the same length\n // we encode an all-zero signature when the signature is missing\n if (signerAddresses.length !== signatures.length) {\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__MESSAGE_SIGNATURES_MISMATCH, {\n numRequiredSignatures,\n signaturesLength: signatures.length,\n signerAddresses,\n });\n }\n\n // combine the signer addresses + signatures into the signatures map\n const signaturesMap: SignaturesMap = {};\n signerAddresses.forEach((address, index) => {\n const signatureForAddress = signatures[index];\n if (signatureForAddress.every(b => b === 0)) {\n signaturesMap[address] = null;\n } else {\n signaturesMap[address] = signatureForAddress as SignatureBytes;\n }\n });\n\n return {\n messageBytes: messageBytes as TransactionMessageBytes,\n signatures: Object.freeze(signaturesMap),\n };\n}\n","import { ReadonlyUint8Array } from '@solana/codecs-core';\nimport {\n CompilableTransactionMessage,\n compileTransactionMessage,\n getCompiledTransactionMessageEncoder,\n isTransactionMessageWithBlockhashLifetime,\n TransactionMessageWithBlockhashLifetime,\n TransactionMessageWithDurableNonceLifetime,\n} from '@solana/transaction-messages';\n\nimport {\n TransactionWithBlockhashLifetime,\n TransactionWithDurableNonceLifetime,\n TransactionWithLifetime,\n} from './lifetime';\nimport { SignaturesMap, Transaction, TransactionMessageBytes } from './transaction';\n\nexport function compileTransaction(\n transactionMessage: CompilableTransactionMessage & TransactionMessageWithBlockhashLifetime,\n): Readonly<Transaction & TransactionWithBlockhashLifetime>;\n\nexport function compileTransaction(\n transactionMessage: CompilableTransactionMessage & TransactionMessageWithDurableNonceLifetime,\n): Readonly<Transaction & TransactionWithDurableNonceLifetime>;\n\nexport function compileTransaction(\n transactionMessage: CompilableTransactionMessage,\n): Readonly<Transaction & TransactionWithLifetime>;\n\nexport function compileTransaction(\n transactionMessage: CompilableTransactionMessage,\n): Readonly<Transaction & TransactionWithLifetime> {\n const compiledMessage = compileTransactionMessage(transactionMessage);\n const messageBytes = getCompiledTransactionMessageEncoder().encode(\n compiledMessage,\n ) as ReadonlyUint8Array as TransactionMessageBytes;\n\n const transactionSigners = compiledMessage.staticAccounts.slice(0, compiledMessage.header.numSignerAccounts);\n const signatures: SignaturesMap = {};\n for (const signerAddress of transactionSigners) {\n signatures[signerAddress] = null;\n }\n\n let lifetimeConstraint: TransactionWithLifetime['lifetimeConstraint'];\n if (isTransactionMessageWithBlockhashLifetime(transactionMessage)) {\n lifetimeConstraint = {\n blockhash: transactionMessage.lifetimeConstraint.blockhash,\n lastValidBlockHeight: transactionMessage.lifetimeConstraint.lastValidBlockHeight,\n };\n } else {\n lifetimeConstraint = {\n nonce: transactionMessage.lifetimeConstraint.nonce,\n nonceAccountAddress: transactionMessage.instructions[0].accounts[0].address,\n };\n }\n\n const transaction: Transaction & TransactionWithLifetime = {\n lifetimeConstraint,\n messageBytes: messageBytes as TransactionMessageBytes,\n signatures: Object.freeze(signatures),\n };\n\n return Object.freeze(transaction);\n}\n","import { Address, getAddressFromPublicKey } from '@solana/addresses';\nimport { Decoder } from '@solana/codecs-core';\nimport { getBase58Decoder } from '@solana/codecs-strings';\nimport {\n SOLANA_ERROR__TRANSACTION__ADDRESSES_CANNOT_SIGN_TRANSACTION,\n SOLANA_ERROR__TRANSACTION__FEE_PAYER_SIGNATURE_MISSING,\n SOLANA_ERROR__TRANSACTION__SIGNATURES_MISSING,\n SolanaError,\n} from '@solana/errors';\nimport { Signature, SignatureBytes, signBytes } from '@solana/keys';\n\nimport { Transaction } from './transaction';\n\nexport interface FullySignedTransaction extends Transaction {\n readonly __brand: unique symbol;\n}\n\nlet base58Decoder: Decoder<string> | undefined;\n\nexport function getSignatureFromTransaction(transaction: Transaction): Signature {\n if (!base58Decoder) base58Decoder = getBase58Decoder();\n\n // We have ordered signatures from the compiled message accounts\n // first signature is the fee payer\n const signatureBytes = Object.values(transaction.signatures)[0];\n if (!signatureBytes) {\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__FEE_PAYER_SIGNATURE_MISSING);\n }\n const transactionSignature = base58Decoder.decode(signatureBytes);\n return transactionSignature as Signature;\n}\n\nfunction uint8ArraysEqual(arr1: Uint8Array, arr2: Uint8Array) {\n return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]);\n}\n\nexport async function partiallySignTransaction<T extends Transaction>(\n keyPairs: CryptoKeyPair[],\n transaction: T,\n): Promise<T> {\n let newSignatures: Record<Address, SignatureBytes> | undefined;\n let unexpectedSigners: Set<Address> | undefined;\n\n await Promise.all(\n keyPairs.map(async keyPair => {\n const address = await getAddressFromPublicKey(keyPair.publicKey);\n const existingSignature = transaction.signatures[address];\n\n // Check if the address is expected to sign the transaction\n if (existingSignature === undefined) {\n // address is not an expected signer for this transaction\n unexpectedSigners ||= new Set();\n unexpectedSigners.add(address);\n return;\n }\n\n // Return if there are any unexpected signers already since we won't be using signatures\n if (unexpectedSigners) {\n return;\n }\n\n const newSignature = await signBytes(keyPair.privateKey, transaction.messageBytes);\n\n if (existingSignature !== null && uint8ArraysEqual(newSignature, existingSignature)) {\n // already have the same signature set\n return;\n }\n\n newSignatures ||= {};\n newSignatures[address] = newSignature;\n }),\n );\n\n if (unexpectedSigners && unexpectedSigners.size > 0) {\n const expectedSigners = Object.keys(transaction.signatures);\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__ADDRESSES_CANNOT_SIGN_TRANSACTION, {\n expectedAddresses: expectedSigners,\n unexpectedAddresses: [...unexpectedSigners],\n });\n }\n\n if (!newSignatures) {\n return transaction;\n }\n\n return Object.freeze({\n ...transaction,\n signatures: Object.freeze({\n ...transaction.signatures,\n ...newSignatures,\n }),\n });\n}\n\nexport async function signTransaction<T extends Transaction>(\n keyPairs: CryptoKeyPair[],\n transaction: T,\n): Promise<FullySignedTransaction & T> {\n const out = await partiallySignTransaction(keyPairs, transaction);\n assertTransactionIsFullySigned(out);\n Object.freeze(out);\n return out;\n}\n\nexport function assertTransactionIsFullySigned(\n transaction: Transaction,\n): asserts transaction is FullySignedTransaction {\n const missingSigs: Address[] = [];\n Object.entries(transaction.signatures).forEach(([address, signatureBytes]) => {\n if (!signatureBytes) {\n missingSigs.push(address as Address);\n }\n });\n\n if (missingSigs.length > 0) {\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__SIGNATURES_MISSING, {\n addresses: missingSigs,\n });\n }\n}\n","import { getBase64Decoder } from '@solana/codecs-strings';\n\nimport { getTransactionEncoder } from './codecs';\nimport { Transaction } from './transaction';\n\nexport type Base64EncodedWireTransaction = string & {\n readonly __brand: unique symbol;\n};\n\nexport function getBase64EncodedWireTransaction(transaction: Transaction): Base64EncodedWireTransaction {\n const wireTransactionBytes = getTransactionEncoder().encode(transaction);\n return getBase64Decoder().decode(wireTransactionBytes) as Base64EncodedWireTransaction;\n}\n"]}
@@ -0,0 +1,202 @@
1
+ 'use strict';
2
+
3
+ var addresses = require('@solana/addresses');
4
+ var codecsCore = require('@solana/codecs-core');
5
+ var codecsDataStructures = require('@solana/codecs-data-structures');
6
+ var codecsNumbers = require('@solana/codecs-numbers');
7
+ var errors = require('@solana/errors');
8
+ var transactionMessages = require('@solana/transaction-messages');
9
+ var codecsStrings = require('@solana/codecs-strings');
10
+ var keys = require('@solana/keys');
11
+
12
+ // src/codecs/transaction-codec.ts
13
+ function getSignaturesToEncode(signaturesMap) {
14
+ const signatures = Object.values(signaturesMap);
15
+ if (signatures.length === 0) {
16
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION__CANNOT_ENCODE_WITH_EMPTY_SIGNATURES);
17
+ }
18
+ return signatures.map((signature) => {
19
+ if (!signature) {
20
+ return new Uint8Array(64).fill(0);
21
+ }
22
+ return signature;
23
+ });
24
+ }
25
+ function getSignaturesEncoder() {
26
+ return codecsCore.transformEncoder(
27
+ codecsDataStructures.getArrayEncoder(codecsCore.fixEncoderSize(codecsDataStructures.getBytesEncoder(), 64), { size: codecsNumbers.getShortU16Encoder() }),
28
+ getSignaturesToEncode
29
+ );
30
+ }
31
+
32
+ // src/codecs/transaction-codec.ts
33
+ function getTransactionEncoder() {
34
+ return codecsDataStructures.getStructEncoder([
35
+ ["signatures", getSignaturesEncoder()],
36
+ ["messageBytes", codecsDataStructures.getBytesEncoder()]
37
+ ]);
38
+ }
39
+ function getTransactionDecoder() {
40
+ return codecsCore.transformDecoder(
41
+ codecsDataStructures.getStructDecoder([
42
+ ["signatures", codecsDataStructures.getArrayDecoder(codecsCore.fixDecoderSize(codecsDataStructures.getBytesDecoder(), 64), { size: codecsNumbers.getShortU16Decoder() })],
43
+ ["messageBytes", codecsDataStructures.getBytesDecoder()]
44
+ ]),
45
+ decodePartiallyDecodedTransaction
46
+ );
47
+ }
48
+ function getTransactionCodec() {
49
+ return codecsCore.combineCodec(getTransactionEncoder(), getTransactionDecoder());
50
+ }
51
+ function decodePartiallyDecodedTransaction(transaction) {
52
+ const { messageBytes, signatures } = transaction;
53
+ const signerAddressesDecoder = codecsDataStructures.getTupleDecoder([
54
+ // read transaction version
55
+ transactionMessages.getTransactionVersionDecoder(),
56
+ // read first byte of header, `numSignerAccounts`
57
+ // padRight to skip the next 2 bytes, `numReadOnlySignedAccounts` and `numReadOnlyUnsignedAccounts` which we don't need
58
+ codecsCore.padRightDecoder(codecsNumbers.getU8Decoder(), 2),
59
+ // read static addresses
60
+ codecsDataStructures.getArrayDecoder(addresses.getAddressDecoder(), { size: codecsNumbers.getShortU16Decoder() })
61
+ ]);
62
+ const [_txVersion, numRequiredSignatures, staticAddresses] = signerAddressesDecoder.decode(messageBytes);
63
+ const signerAddresses = staticAddresses.slice(0, numRequiredSignatures);
64
+ if (signerAddresses.length !== signatures.length) {
65
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION__MESSAGE_SIGNATURES_MISMATCH, {
66
+ numRequiredSignatures,
67
+ signaturesLength: signatures.length,
68
+ signerAddresses
69
+ });
70
+ }
71
+ const signaturesMap = {};
72
+ signerAddresses.forEach((address, index) => {
73
+ const signatureForAddress = signatures[index];
74
+ if (signatureForAddress.every((b) => b === 0)) {
75
+ signaturesMap[address] = null;
76
+ } else {
77
+ signaturesMap[address] = signatureForAddress;
78
+ }
79
+ });
80
+ return {
81
+ messageBytes,
82
+ signatures: Object.freeze(signaturesMap)
83
+ };
84
+ }
85
+ function compileTransaction(transactionMessage) {
86
+ const compiledMessage = transactionMessages.compileTransactionMessage(transactionMessage);
87
+ const messageBytes = transactionMessages.getCompiledTransactionMessageEncoder().encode(
88
+ compiledMessage
89
+ );
90
+ const transactionSigners = compiledMessage.staticAccounts.slice(0, compiledMessage.header.numSignerAccounts);
91
+ const signatures = {};
92
+ for (const signerAddress of transactionSigners) {
93
+ signatures[signerAddress] = null;
94
+ }
95
+ let lifetimeConstraint;
96
+ if (transactionMessages.isTransactionMessageWithBlockhashLifetime(transactionMessage)) {
97
+ lifetimeConstraint = {
98
+ blockhash: transactionMessage.lifetimeConstraint.blockhash,
99
+ lastValidBlockHeight: transactionMessage.lifetimeConstraint.lastValidBlockHeight
100
+ };
101
+ } else {
102
+ lifetimeConstraint = {
103
+ nonce: transactionMessage.lifetimeConstraint.nonce,
104
+ nonceAccountAddress: transactionMessage.instructions[0].accounts[0].address
105
+ };
106
+ }
107
+ const transaction = {
108
+ lifetimeConstraint,
109
+ messageBytes,
110
+ signatures: Object.freeze(signatures)
111
+ };
112
+ return Object.freeze(transaction);
113
+ }
114
+ var base58Decoder;
115
+ function getSignatureFromTransaction(transaction) {
116
+ if (!base58Decoder) base58Decoder = codecsStrings.getBase58Decoder();
117
+ const signatureBytes = Object.values(transaction.signatures)[0];
118
+ if (!signatureBytes) {
119
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION__FEE_PAYER_SIGNATURE_MISSING);
120
+ }
121
+ const transactionSignature = base58Decoder.decode(signatureBytes);
122
+ return transactionSignature;
123
+ }
124
+ function uint8ArraysEqual(arr1, arr2) {
125
+ return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]);
126
+ }
127
+ async function partiallySignTransaction(keyPairs, transaction) {
128
+ let newSignatures;
129
+ let unexpectedSigners;
130
+ await Promise.all(
131
+ keyPairs.map(async (keyPair) => {
132
+ const address = await addresses.getAddressFromPublicKey(keyPair.publicKey);
133
+ const existingSignature = transaction.signatures[address];
134
+ if (existingSignature === void 0) {
135
+ unexpectedSigners ||= /* @__PURE__ */ new Set();
136
+ unexpectedSigners.add(address);
137
+ return;
138
+ }
139
+ if (unexpectedSigners) {
140
+ return;
141
+ }
142
+ const newSignature = await keys.signBytes(keyPair.privateKey, transaction.messageBytes);
143
+ if (existingSignature !== null && uint8ArraysEqual(newSignature, existingSignature)) {
144
+ return;
145
+ }
146
+ newSignatures ||= {};
147
+ newSignatures[address] = newSignature;
148
+ })
149
+ );
150
+ if (unexpectedSigners && unexpectedSigners.size > 0) {
151
+ const expectedSigners = Object.keys(transaction.signatures);
152
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION__ADDRESSES_CANNOT_SIGN_TRANSACTION, {
153
+ expectedAddresses: expectedSigners,
154
+ unexpectedAddresses: [...unexpectedSigners]
155
+ });
156
+ }
157
+ if (!newSignatures) {
158
+ return transaction;
159
+ }
160
+ return Object.freeze({
161
+ ...transaction,
162
+ signatures: Object.freeze({
163
+ ...transaction.signatures,
164
+ ...newSignatures
165
+ })
166
+ });
167
+ }
168
+ async function signTransaction(keyPairs, transaction) {
169
+ const out = await partiallySignTransaction(keyPairs, transaction);
170
+ assertTransactionIsFullySigned(out);
171
+ Object.freeze(out);
172
+ return out;
173
+ }
174
+ function assertTransactionIsFullySigned(transaction) {
175
+ const missingSigs = [];
176
+ Object.entries(transaction.signatures).forEach(([address, signatureBytes]) => {
177
+ if (!signatureBytes) {
178
+ missingSigs.push(address);
179
+ }
180
+ });
181
+ if (missingSigs.length > 0) {
182
+ throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION__SIGNATURES_MISSING, {
183
+ addresses: missingSigs
184
+ });
185
+ }
186
+ }
187
+ function getBase64EncodedWireTransaction(transaction) {
188
+ const wireTransactionBytes = getTransactionEncoder().encode(transaction);
189
+ return codecsStrings.getBase64Decoder().decode(wireTransactionBytes);
190
+ }
191
+
192
+ exports.assertTransactionIsFullySigned = assertTransactionIsFullySigned;
193
+ exports.compileTransaction = compileTransaction;
194
+ exports.getBase64EncodedWireTransaction = getBase64EncodedWireTransaction;
195
+ exports.getSignatureFromTransaction = getSignatureFromTransaction;
196
+ exports.getTransactionCodec = getTransactionCodec;
197
+ exports.getTransactionDecoder = getTransactionDecoder;
198
+ exports.getTransactionEncoder = getTransactionEncoder;
199
+ exports.partiallySignTransaction = partiallySignTransaction;
200
+ exports.signTransaction = signTransaction;
201
+ //# sourceMappingURL=index.node.cjs.map
202
+ //# sourceMappingURL=index.node.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/codecs/signatures-encoder.ts","../src/codecs/transaction-codec.ts","../src/compile-transaction.ts","../src/signatures.ts","../src/wire-transaction.ts"],"names":["SolanaError","SOLANA_ERROR__TRANSACTION__CANNOT_ENCODE_WITH_EMPTY_SIGNATURES","transformEncoder","getArrayEncoder","fixEncoderSize","getBytesEncoder","getShortU16Encoder","getStructEncoder","transformDecoder","getStructDecoder","getArrayDecoder","fixDecoderSize","getBytesDecoder","getShortU16Decoder","combineCodec","getTupleDecoder","getTransactionVersionDecoder","padRightDecoder","getU8Decoder","getAddressDecoder","SOLANA_ERROR__TRANSACTION__MESSAGE_SIGNATURES_MISMATCH","compileTransactionMessage","getCompiledTransactionMessageEncoder","isTransactionMessageWithBlockhashLifetime","getBase58Decoder","SOLANA_ERROR__TRANSACTION__FEE_PAYER_SIGNATURE_MISSING","getAddressFromPublicKey","signBytes","SOLANA_ERROR__TRANSACTION__ADDRESSES_CANNOT_SIGN_TRANSACTION","SOLANA_ERROR__TRANSACTION__SIGNATURES_MISSING","getBase64Decoder"],"mappings":"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","file":"index.node.cjs","sourcesContent":["import { fixEncoderSize, transformEncoder, VariableSizeEncoder } from '@solana/codecs-core';\nimport { getArrayEncoder, getBytesEncoder } from '@solana/codecs-data-structures';\nimport { getShortU16Encoder } from '@solana/codecs-numbers';\nimport { SOLANA_ERROR__TRANSACTION__CANNOT_ENCODE_WITH_EMPTY_SIGNATURES, SolanaError } from '@solana/errors';\nimport { SignatureBytes } from '@solana/keys';\n\nimport { SignaturesMap } from '../transaction';\n\nfunction getSignaturesToEncode(signaturesMap: SignaturesMap): SignatureBytes[] {\n const signatures = Object.values(signaturesMap);\n if (signatures.length === 0) {\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__CANNOT_ENCODE_WITH_EMPTY_SIGNATURES);\n }\n\n return signatures.map(signature => {\n if (!signature) {\n return new Uint8Array(64).fill(0) as SignatureBytes;\n }\n return signature;\n });\n}\n\nexport function getSignaturesEncoder(): VariableSizeEncoder<SignaturesMap> {\n return transformEncoder(\n getArrayEncoder(fixEncoderSize(getBytesEncoder(), 64), { size: getShortU16Encoder() }),\n getSignaturesToEncode,\n );\n}\n","import { getAddressDecoder } from '@solana/addresses';\nimport {\n combineCodec,\n fixDecoderSize,\n padRightDecoder,\n ReadonlyUint8Array,\n transformDecoder,\n VariableSizeCodec,\n VariableSizeDecoder,\n VariableSizeEncoder,\n} from '@solana/codecs-core';\nimport {\n getArrayDecoder,\n getBytesDecoder,\n getBytesEncoder,\n getStructDecoder,\n getStructEncoder,\n getTupleDecoder,\n} from '@solana/codecs-data-structures';\nimport { getShortU16Decoder, getU8Decoder } from '@solana/codecs-numbers';\nimport { SOLANA_ERROR__TRANSACTION__MESSAGE_SIGNATURES_MISMATCH, SolanaError } from '@solana/errors';\nimport { SignatureBytes } from '@solana/keys';\nimport { getTransactionVersionDecoder } from '@solana/transaction-messages';\n\nimport { SignaturesMap, Transaction, TransactionMessageBytes } from '../transaction';\nimport { getSignaturesEncoder } from './signatures-encoder';\n\nexport function getTransactionEncoder(): VariableSizeEncoder<Transaction> {\n return getStructEncoder([\n ['signatures', getSignaturesEncoder()],\n ['messageBytes', getBytesEncoder()],\n ]);\n}\n\nexport function getTransactionDecoder(): VariableSizeDecoder<Transaction> {\n return transformDecoder(\n getStructDecoder([\n ['signatures', getArrayDecoder(fixDecoderSize(getBytesDecoder(), 64), { size: getShortU16Decoder() })],\n ['messageBytes', getBytesDecoder()],\n ]),\n decodePartiallyDecodedTransaction,\n );\n}\n\nexport function getTransactionCodec(): VariableSizeCodec<Transaction> {\n return combineCodec(getTransactionEncoder(), getTransactionDecoder());\n}\n\ntype PartiallyDecodedTransaction = {\n messageBytes: ReadonlyUint8Array;\n signatures: ReadonlyUint8Array[];\n};\n\nfunction decodePartiallyDecodedTransaction(transaction: PartiallyDecodedTransaction): Transaction {\n const { messageBytes, signatures } = transaction;\n\n /*\n Relevant message structure is at the start:\n - transaction version (0 bytes for legacy transactions, 1 byte for versioned transactions)\n - `numRequiredSignatures` (1 byte, we verify this matches the length of signatures)\n - `numReadOnlySignedAccounts` (1 byte, not used here)\n - `numReadOnlyUnsignedAccounts` (1 byte, not used here)\n - static addresses, with signers first. This is an array of addresses, prefixed with a short-u16 length\n */\n\n const signerAddressesDecoder = getTupleDecoder([\n // read transaction version\n getTransactionVersionDecoder(),\n // read first byte of header, `numSignerAccounts`\n // padRight to skip the next 2 bytes, `numReadOnlySignedAccounts` and `numReadOnlyUnsignedAccounts` which we don't need\n padRightDecoder(getU8Decoder(), 2),\n // read static addresses\n getArrayDecoder(getAddressDecoder(), { size: getShortU16Decoder() }),\n ]);\n const [_txVersion, numRequiredSignatures, staticAddresses] = signerAddressesDecoder.decode(messageBytes);\n\n const signerAddresses = staticAddresses.slice(0, numRequiredSignatures);\n\n // signer addresses and signatures must be the same length\n // we encode an all-zero signature when the signature is missing\n if (signerAddresses.length !== signatures.length) {\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__MESSAGE_SIGNATURES_MISMATCH, {\n numRequiredSignatures,\n signaturesLength: signatures.length,\n signerAddresses,\n });\n }\n\n // combine the signer addresses + signatures into the signatures map\n const signaturesMap: SignaturesMap = {};\n signerAddresses.forEach((address, index) => {\n const signatureForAddress = signatures[index];\n if (signatureForAddress.every(b => b === 0)) {\n signaturesMap[address] = null;\n } else {\n signaturesMap[address] = signatureForAddress as SignatureBytes;\n }\n });\n\n return {\n messageBytes: messageBytes as TransactionMessageBytes,\n signatures: Object.freeze(signaturesMap),\n };\n}\n","import { ReadonlyUint8Array } from '@solana/codecs-core';\nimport {\n CompilableTransactionMessage,\n compileTransactionMessage,\n getCompiledTransactionMessageEncoder,\n isTransactionMessageWithBlockhashLifetime,\n TransactionMessageWithBlockhashLifetime,\n TransactionMessageWithDurableNonceLifetime,\n} from '@solana/transaction-messages';\n\nimport {\n TransactionWithBlockhashLifetime,\n TransactionWithDurableNonceLifetime,\n TransactionWithLifetime,\n} from './lifetime';\nimport { SignaturesMap, Transaction, TransactionMessageBytes } from './transaction';\n\nexport function compileTransaction(\n transactionMessage: CompilableTransactionMessage & TransactionMessageWithBlockhashLifetime,\n): Readonly<Transaction & TransactionWithBlockhashLifetime>;\n\nexport function compileTransaction(\n transactionMessage: CompilableTransactionMessage & TransactionMessageWithDurableNonceLifetime,\n): Readonly<Transaction & TransactionWithDurableNonceLifetime>;\n\nexport function compileTransaction(\n transactionMessage: CompilableTransactionMessage,\n): Readonly<Transaction & TransactionWithLifetime>;\n\nexport function compileTransaction(\n transactionMessage: CompilableTransactionMessage,\n): Readonly<Transaction & TransactionWithLifetime> {\n const compiledMessage = compileTransactionMessage(transactionMessage);\n const messageBytes = getCompiledTransactionMessageEncoder().encode(\n compiledMessage,\n ) as ReadonlyUint8Array as TransactionMessageBytes;\n\n const transactionSigners = compiledMessage.staticAccounts.slice(0, compiledMessage.header.numSignerAccounts);\n const signatures: SignaturesMap = {};\n for (const signerAddress of transactionSigners) {\n signatures[signerAddress] = null;\n }\n\n let lifetimeConstraint: TransactionWithLifetime['lifetimeConstraint'];\n if (isTransactionMessageWithBlockhashLifetime(transactionMessage)) {\n lifetimeConstraint = {\n blockhash: transactionMessage.lifetimeConstraint.blockhash,\n lastValidBlockHeight: transactionMessage.lifetimeConstraint.lastValidBlockHeight,\n };\n } else {\n lifetimeConstraint = {\n nonce: transactionMessage.lifetimeConstraint.nonce,\n nonceAccountAddress: transactionMessage.instructions[0].accounts[0].address,\n };\n }\n\n const transaction: Transaction & TransactionWithLifetime = {\n lifetimeConstraint,\n messageBytes: messageBytes as TransactionMessageBytes,\n signatures: Object.freeze(signatures),\n };\n\n return Object.freeze(transaction);\n}\n","import { Address, getAddressFromPublicKey } from '@solana/addresses';\nimport { Decoder } from '@solana/codecs-core';\nimport { getBase58Decoder } from '@solana/codecs-strings';\nimport {\n SOLANA_ERROR__TRANSACTION__ADDRESSES_CANNOT_SIGN_TRANSACTION,\n SOLANA_ERROR__TRANSACTION__FEE_PAYER_SIGNATURE_MISSING,\n SOLANA_ERROR__TRANSACTION__SIGNATURES_MISSING,\n SolanaError,\n} from '@solana/errors';\nimport { Signature, SignatureBytes, signBytes } from '@solana/keys';\n\nimport { Transaction } from './transaction';\n\nexport interface FullySignedTransaction extends Transaction {\n readonly __brand: unique symbol;\n}\n\nlet base58Decoder: Decoder<string> | undefined;\n\nexport function getSignatureFromTransaction(transaction: Transaction): Signature {\n if (!base58Decoder) base58Decoder = getBase58Decoder();\n\n // We have ordered signatures from the compiled message accounts\n // first signature is the fee payer\n const signatureBytes = Object.values(transaction.signatures)[0];\n if (!signatureBytes) {\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__FEE_PAYER_SIGNATURE_MISSING);\n }\n const transactionSignature = base58Decoder.decode(signatureBytes);\n return transactionSignature as Signature;\n}\n\nfunction uint8ArraysEqual(arr1: Uint8Array, arr2: Uint8Array) {\n return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]);\n}\n\nexport async function partiallySignTransaction<T extends Transaction>(\n keyPairs: CryptoKeyPair[],\n transaction: T,\n): Promise<T> {\n let newSignatures: Record<Address, SignatureBytes> | undefined;\n let unexpectedSigners: Set<Address> | undefined;\n\n await Promise.all(\n keyPairs.map(async keyPair => {\n const address = await getAddressFromPublicKey(keyPair.publicKey);\n const existingSignature = transaction.signatures[address];\n\n // Check if the address is expected to sign the transaction\n if (existingSignature === undefined) {\n // address is not an expected signer for this transaction\n unexpectedSigners ||= new Set();\n unexpectedSigners.add(address);\n return;\n }\n\n // Return if there are any unexpected signers already since we won't be using signatures\n if (unexpectedSigners) {\n return;\n }\n\n const newSignature = await signBytes(keyPair.privateKey, transaction.messageBytes);\n\n if (existingSignature !== null && uint8ArraysEqual(newSignature, existingSignature)) {\n // already have the same signature set\n return;\n }\n\n newSignatures ||= {};\n newSignatures[address] = newSignature;\n }),\n );\n\n if (unexpectedSigners && unexpectedSigners.size > 0) {\n const expectedSigners = Object.keys(transaction.signatures);\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__ADDRESSES_CANNOT_SIGN_TRANSACTION, {\n expectedAddresses: expectedSigners,\n unexpectedAddresses: [...unexpectedSigners],\n });\n }\n\n if (!newSignatures) {\n return transaction;\n }\n\n return Object.freeze({\n ...transaction,\n signatures: Object.freeze({\n ...transaction.signatures,\n ...newSignatures,\n }),\n });\n}\n\nexport async function signTransaction<T extends Transaction>(\n keyPairs: CryptoKeyPair[],\n transaction: T,\n): Promise<FullySignedTransaction & T> {\n const out = await partiallySignTransaction(keyPairs, transaction);\n assertTransactionIsFullySigned(out);\n Object.freeze(out);\n return out;\n}\n\nexport function assertTransactionIsFullySigned(\n transaction: Transaction,\n): asserts transaction is FullySignedTransaction {\n const missingSigs: Address[] = [];\n Object.entries(transaction.signatures).forEach(([address, signatureBytes]) => {\n if (!signatureBytes) {\n missingSigs.push(address as Address);\n }\n });\n\n if (missingSigs.length > 0) {\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__SIGNATURES_MISSING, {\n addresses: missingSigs,\n });\n }\n}\n","import { getBase64Decoder } from '@solana/codecs-strings';\n\nimport { getTransactionEncoder } from './codecs';\nimport { Transaction } from './transaction';\n\nexport type Base64EncodedWireTransaction = string & {\n readonly __brand: unique symbol;\n};\n\nexport function getBase64EncodedWireTransaction(transaction: Transaction): Base64EncodedWireTransaction {\n const wireTransactionBytes = getTransactionEncoder().encode(transaction);\n return getBase64Decoder().decode(wireTransactionBytes) as Base64EncodedWireTransaction;\n}\n"]}