@solana/transactions 2.0.0-experimental.68e85dc → 2.0.0-experimental.699bde0
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 +1 -43
- package/dist/index.browser.cjs +345 -75
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +348 -75
- package/dist/index.browser.js.map +1 -1
- package/dist/index.development.js +888 -490
- package/dist/index.development.js.map +1 -1
- package/dist/index.native.js +346 -75
- package/dist/index.native.js.map +1 -1
- package/dist/index.node.cjs +347 -73
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +348 -75
- package/dist/index.node.js.map +1 -1
- package/dist/index.production.min.js +18 -17
- package/dist/types/accounts.d.ts +2 -2
- package/dist/types/compilable-transaction.d.ts +7 -0
- package/dist/types/compile-address-table-lookups.d.ts +2 -2
- package/dist/types/compile-static-accounts.d.ts +2 -2
- package/dist/types/compile-transaction.d.ts +5 -6
- package/dist/types/decompile-transaction.d.ts +5 -0
- package/dist/types/durable-nonce.d.ts +5 -6
- package/dist/types/fee-payer.d.ts +4 -4
- package/dist/types/index.d.ts +1 -0
- package/dist/types/message.d.ts +1 -5
- package/dist/types/serializers/transaction.d.ts +5 -5
- package/dist/types/signatures.d.ts +8 -12
- package/dist/types/types.d.ts +6 -13
- package/package.json +13 -14
package/README.md
CHANGED
|
@@ -244,21 +244,11 @@ This type represents a transaction that is signed by all of its required signers
|
|
|
244
244
|
|
|
245
245
|
Expect any function that modifies a transaction (eg. `setTransactionFeePayer`, `appendTransactionInstruction`, et cetera) to delete a transaction's `signatures` property and unset this type.
|
|
246
246
|
|
|
247
|
-
#### `TransactionSignature`
|
|
248
|
-
|
|
249
|
-
This type represents the base58-encoded signature of a transactions fee payer. This value uniquely identifies the transaction on the network.
|
|
250
|
-
|
|
251
247
|
### Functions
|
|
252
248
|
|
|
253
|
-
#### `assertIsTransactionSignature()`
|
|
254
|
-
|
|
255
|
-
From time to time you might acquire a string that you expect to be the base58-encoded signature of a transaction, from an untrusted network API or user input. To assert that such an arbitrary string is in fact a transaction signature, use the `assertIsTransactionSignature` function.
|
|
256
|
-
|
|
257
|
-
See [`assertIsBlockhash()`](#assertisblockhash) for an example of how to use an assertion function.
|
|
258
|
-
|
|
259
249
|
#### `getSignatureFromTransaction()`
|
|
260
250
|
|
|
261
|
-
Given a transaction signed by its fee payer, this method will return the `
|
|
251
|
+
Given a transaction signed by its fee payer, this method will return the `Signature` that uniquely identifies it. This string can be used to look up transactions at a later date, for example on a Solana block explorer.
|
|
262
252
|
|
|
263
253
|
```ts
|
|
264
254
|
import { getSignatureFromTransaction } from '@solana/transactions';
|
|
@@ -267,25 +257,6 @@ const signature = getSignatureFromTransaction(tx);
|
|
|
267
257
|
console.debug(`Inspect this transaction at https://explorer.solana.com/tx/${signature}`);
|
|
268
258
|
```
|
|
269
259
|
|
|
270
|
-
#### `isTransactionSignature()`
|
|
271
|
-
|
|
272
|
-
This is a type guard that accepts a string as input. It will both return `true` if the string conforms to the `TransactionSignature` type and will refine the type for use in your program.
|
|
273
|
-
|
|
274
|
-
```ts
|
|
275
|
-
import { isTransactionSignature } from '@solana/transactions';
|
|
276
|
-
|
|
277
|
-
if (isTransactionSignature(signature)) {
|
|
278
|
-
// At this point, `signature` has been refined to a
|
|
279
|
-
// `TransactionSignature` that can be used with the RPC.
|
|
280
|
-
const {
|
|
281
|
-
value: [status],
|
|
282
|
-
} = await rpc.getSignatureStatuses([signature]).send();
|
|
283
|
-
setSignatureStatus(status);
|
|
284
|
-
} else {
|
|
285
|
-
setError(`${signature} is not a transaction signature`);
|
|
286
|
-
}
|
|
287
|
-
```
|
|
288
|
-
|
|
289
260
|
#### `signTransaction()`
|
|
290
261
|
|
|
291
262
|
Given an array of `CryptoKey` objects which are private keys pertaining to addresses that are required to sign a transaction, this method will return a new signed transaction having the same type as the one supplied plus the `ITransactionWithSignatures` type.
|
|
@@ -297,19 +268,6 @@ import { signTransaction } from '@solana/transactions';
|
|
|
297
268
|
const signedTransaction = await signTransaction([myPrivateKey], tx);
|
|
298
269
|
```
|
|
299
270
|
|
|
300
|
-
#### `transactionSignature()`
|
|
301
|
-
|
|
302
|
-
This helper combines _asserting_ that a string is a transaction signature with _coercing_ it to the `TransactionSignature` type. It's best used with untrusted input.
|
|
303
|
-
|
|
304
|
-
```ts
|
|
305
|
-
import { transactionSignature } from '@solana/transactions';
|
|
306
|
-
|
|
307
|
-
const signature = transactionSignature(userSuppliedSignature);
|
|
308
|
-
const {
|
|
309
|
-
value: [status],
|
|
310
|
-
} = await rpc.getSignatureStatuses([signature]).send();
|
|
311
|
-
```
|
|
312
|
-
|
|
313
271
|
## Serializing transactions
|
|
314
272
|
|
|
315
273
|
Before sending a transaction to be landed on the network, you must serialize it in a particular way. You can use these types and functions to serialize a signed transaction into a binary format suitable for transit over the wire.
|
package/dist/index.browser.cjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var codecsStrings = require('@solana/codecs-strings');
|
|
4
4
|
var codecsCore = require('@solana/codecs-core');
|
|
5
5
|
var codecsDataStructures = require('@solana/codecs-data-structures');
|
|
6
6
|
var codecsNumbers = require('@solana/codecs-numbers');
|
|
7
7
|
var addresses = require('@solana/addresses');
|
|
8
|
-
var
|
|
8
|
+
var functional = require('@solana/functional');
|
|
9
9
|
var keys = require('@solana/keys');
|
|
10
10
|
|
|
11
11
|
// ../build-scripts/env-shim.ts
|
|
@@ -26,7 +26,10 @@ function getUnsignedTransaction(transaction) {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// src/blockhash.ts
|
|
29
|
+
var base58Encoder;
|
|
29
30
|
function assertIsBlockhash(putativeBlockhash) {
|
|
31
|
+
if (!base58Encoder)
|
|
32
|
+
base58Encoder = codecsStrings.getBase58Encoder();
|
|
30
33
|
try {
|
|
31
34
|
if (
|
|
32
35
|
// Lowest value (32 bytes of zeroes)
|
|
@@ -35,7 +38,7 @@ function assertIsBlockhash(putativeBlockhash) {
|
|
|
35
38
|
) {
|
|
36
39
|
throw new Error("Expected input string to decode to a byte array of length 32.");
|
|
37
40
|
}
|
|
38
|
-
const bytes =
|
|
41
|
+
const bytes = base58Encoder.encode(putativeBlockhash);
|
|
39
42
|
const numBytes = bytes.byteLength;
|
|
40
43
|
if (numBytes !== 32) {
|
|
41
44
|
throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${numBytes}`);
|
|
@@ -121,7 +124,7 @@ function isAdvanceNonceAccountInstruction(instruction) {
|
|
|
121
124
|
instruction.accounts?.length === 3 && // First account is nonce account address
|
|
122
125
|
instruction.accounts[0].address != null && instruction.accounts[0].role === AccountRole.WRITABLE && // Second account is recent blockhashes sysvar
|
|
123
126
|
instruction.accounts[1].address === RECENT_BLOCKHASHES_SYSVAR_ADDRESS && instruction.accounts[1].role === AccountRole.READONLY && // Third account is nonce authority account
|
|
124
|
-
instruction.accounts[2].address != null && instruction.accounts[2].role
|
|
127
|
+
instruction.accounts[2].address != null && isSignerRole(instruction.accounts[2].role);
|
|
125
128
|
}
|
|
126
129
|
function isAdvanceNonceAccountInstructionData(data) {
|
|
127
130
|
return data.byteLength === 4 && data[0] === 4 && data[1] === 0 && data[2] === 0 && data[3] === 0;
|
|
@@ -129,21 +132,38 @@ function isAdvanceNonceAccountInstructionData(data) {
|
|
|
129
132
|
function isDurableNonceTransaction(transaction) {
|
|
130
133
|
return "lifetimeConstraint" in transaction && typeof transaction.lifetimeConstraint.nonce === "string" && transaction.instructions[0] != null && isAdvanceNonceAccountInstruction(transaction.instructions[0]);
|
|
131
134
|
}
|
|
135
|
+
function isAdvanceNonceAccountInstructionForNonce(instruction, nonceAccountAddress, nonceAuthorityAddress) {
|
|
136
|
+
return instruction.accounts[0].address === nonceAccountAddress && instruction.accounts[2].address === nonceAuthorityAddress;
|
|
137
|
+
}
|
|
132
138
|
function setTransactionLifetimeUsingDurableNonce({
|
|
133
139
|
nonce,
|
|
134
140
|
nonceAccountAddress,
|
|
135
141
|
nonceAuthorityAddress
|
|
136
142
|
}, transaction) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
143
|
+
let newInstructions;
|
|
144
|
+
const firstInstruction = transaction.instructions[0];
|
|
145
|
+
if (firstInstruction && isAdvanceNonceAccountInstruction(firstInstruction)) {
|
|
146
|
+
if (isAdvanceNonceAccountInstructionForNonce(firstInstruction, nonceAccountAddress, nonceAuthorityAddress)) {
|
|
147
|
+
if (isDurableNonceTransaction(transaction) && transaction.lifetimeConstraint.nonce === nonce) {
|
|
148
|
+
return transaction;
|
|
149
|
+
} else {
|
|
150
|
+
newInstructions = [firstInstruction, ...transaction.instructions.slice(1)];
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
newInstructions = [
|
|
154
|
+
createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
|
|
155
|
+
...transaction.instructions.slice(1)
|
|
156
|
+
];
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
newInstructions = [
|
|
160
|
+
createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
|
|
161
|
+
...transaction.instructions
|
|
162
|
+
];
|
|
140
163
|
}
|
|
141
164
|
const out = {
|
|
142
165
|
...getUnsignedTransaction(transaction),
|
|
143
|
-
instructions:
|
|
144
|
-
createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
|
|
145
|
-
...isAlreadyDurableNonceTransaction ? transaction.instructions.slice(1) : transaction.instructions
|
|
146
|
-
],
|
|
166
|
+
instructions: newInstructions,
|
|
147
167
|
lifetimeConstraint: {
|
|
148
168
|
nonce
|
|
149
169
|
}
|
|
@@ -234,7 +254,7 @@ function getAddressMapFromInstructions(feePayer, instructions) {
|
|
|
234
254
|
const shouldReplaceEntry = (
|
|
235
255
|
// Consider using the new LOOKUP_TABLE if its address is different...
|
|
236
256
|
entry.lookupTableAddress !== accountMeta.lookupTableAddress && // ...and sorts before the existing one.
|
|
237
|
-
(addressComparator
|
|
257
|
+
(addressComparator ||= addresses.getAddressComparator())(
|
|
238
258
|
accountMeta.lookupTableAddress,
|
|
239
259
|
entry.lookupTableAddress
|
|
240
260
|
) < 0
|
|
@@ -340,7 +360,7 @@ function getOrderedAccountsFromAddressMap(addressMap) {
|
|
|
340
360
|
if (leftIsWritable !== isWritableRole(rightEntry.role)) {
|
|
341
361
|
return leftIsWritable ? -1 : 1;
|
|
342
362
|
}
|
|
343
|
-
addressComparator
|
|
363
|
+
addressComparator ||= addresses.getAddressComparator();
|
|
344
364
|
if (leftEntry[TYPE] === 1 /* LOOKUP_TABLE */ && rightEntry[TYPE] === 1 /* LOOKUP_TABLE */ && leftEntry.lookupTableAddress !== rightEntry.lookupTableAddress) {
|
|
345
365
|
return addressComparator(leftEntry.lookupTableAddress, rightEntry.lookupTableAddress);
|
|
346
366
|
} else {
|
|
@@ -353,16 +373,15 @@ function getOrderedAccountsFromAddressMap(addressMap) {
|
|
|
353
373
|
return orderedAccounts;
|
|
354
374
|
}
|
|
355
375
|
function getCompiledAddressTableLookups(orderedAccounts) {
|
|
356
|
-
var _a;
|
|
357
376
|
const index = {};
|
|
358
377
|
for (const account of orderedAccounts) {
|
|
359
378
|
if (!("lookupTableAddress" in account)) {
|
|
360
379
|
continue;
|
|
361
380
|
}
|
|
362
|
-
const entry = index[
|
|
381
|
+
const entry = index[account.lookupTableAddress] ||= {
|
|
363
382
|
readableIndices: [],
|
|
364
383
|
writableIndices: []
|
|
365
|
-
}
|
|
384
|
+
};
|
|
366
385
|
if (account.role === AccountRole.WRITABLE) {
|
|
367
386
|
entry.writableIndices.push(account.addressIndex);
|
|
368
387
|
} else {
|
|
@@ -466,6 +485,116 @@ function getCompiledTransaction(transaction) {
|
|
|
466
485
|
signatures
|
|
467
486
|
};
|
|
468
487
|
}
|
|
488
|
+
function getAccountMetas(message) {
|
|
489
|
+
const { header } = message;
|
|
490
|
+
const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
|
|
491
|
+
const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
|
|
492
|
+
const accountMetas = [];
|
|
493
|
+
let accountIndex = 0;
|
|
494
|
+
for (let i = 0; i < numWritableSignerAccounts; i++) {
|
|
495
|
+
accountMetas.push({
|
|
496
|
+
address: message.staticAccounts[accountIndex],
|
|
497
|
+
role: AccountRole.WRITABLE_SIGNER
|
|
498
|
+
});
|
|
499
|
+
accountIndex++;
|
|
500
|
+
}
|
|
501
|
+
for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
|
|
502
|
+
accountMetas.push({
|
|
503
|
+
address: message.staticAccounts[accountIndex],
|
|
504
|
+
role: AccountRole.READONLY_SIGNER
|
|
505
|
+
});
|
|
506
|
+
accountIndex++;
|
|
507
|
+
}
|
|
508
|
+
for (let i = 0; i < numWritableNonSignerAccounts; i++) {
|
|
509
|
+
accountMetas.push({
|
|
510
|
+
address: message.staticAccounts[accountIndex],
|
|
511
|
+
role: AccountRole.WRITABLE
|
|
512
|
+
});
|
|
513
|
+
accountIndex++;
|
|
514
|
+
}
|
|
515
|
+
for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
|
|
516
|
+
accountMetas.push({
|
|
517
|
+
address: message.staticAccounts[accountIndex],
|
|
518
|
+
role: AccountRole.READONLY
|
|
519
|
+
});
|
|
520
|
+
accountIndex++;
|
|
521
|
+
}
|
|
522
|
+
return accountMetas;
|
|
523
|
+
}
|
|
524
|
+
function convertInstruction(instruction, accountMetas) {
|
|
525
|
+
const programAddress = accountMetas[instruction.programAddressIndex]?.address;
|
|
526
|
+
if (!programAddress) {
|
|
527
|
+
throw new Error(`Could not find program address at index ${instruction.programAddressIndex}`);
|
|
528
|
+
}
|
|
529
|
+
const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
|
|
530
|
+
const { data } = instruction;
|
|
531
|
+
return {
|
|
532
|
+
programAddress,
|
|
533
|
+
...accounts && accounts.length ? { accounts } : {},
|
|
534
|
+
...data && data.length ? { data } : {}
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
|
|
538
|
+
if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
|
|
539
|
+
return {
|
|
540
|
+
blockhash: messageLifetimeToken,
|
|
541
|
+
lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
|
|
542
|
+
// U64 MAX
|
|
543
|
+
};
|
|
544
|
+
} else {
|
|
545
|
+
const nonceAccountAddress = firstInstruction.accounts[0].address;
|
|
546
|
+
addresses.assertIsAddress(nonceAccountAddress);
|
|
547
|
+
const nonceAuthorityAddress = firstInstruction.accounts[2].address;
|
|
548
|
+
addresses.assertIsAddress(nonceAuthorityAddress);
|
|
549
|
+
return {
|
|
550
|
+
nonce: messageLifetimeToken,
|
|
551
|
+
nonceAccountAddress,
|
|
552
|
+
nonceAuthorityAddress
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
function convertSignatures(compiledTransaction) {
|
|
557
|
+
const {
|
|
558
|
+
compiledMessage: { staticAccounts },
|
|
559
|
+
signatures
|
|
560
|
+
} = compiledTransaction;
|
|
561
|
+
return signatures.reduce((acc, sig, index) => {
|
|
562
|
+
const allZeros = sig.every((byte) => byte === 0);
|
|
563
|
+
if (allZeros)
|
|
564
|
+
return acc;
|
|
565
|
+
const address = staticAccounts[index];
|
|
566
|
+
return { ...acc, [address]: sig };
|
|
567
|
+
}, {});
|
|
568
|
+
}
|
|
569
|
+
function decompileTransaction(compiledTransaction, lastValidBlockHeight) {
|
|
570
|
+
const { compiledMessage } = compiledTransaction;
|
|
571
|
+
if ("addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups.length > 0) {
|
|
572
|
+
throw new Error("Cannot convert transaction with addressTableLookups");
|
|
573
|
+
}
|
|
574
|
+
const feePayer = compiledMessage.staticAccounts[0];
|
|
575
|
+
if (!feePayer)
|
|
576
|
+
throw new Error("No fee payer set in CompiledTransaction");
|
|
577
|
+
const accountMetas = getAccountMetas(compiledMessage);
|
|
578
|
+
const instructions = compiledMessage.instructions.map(
|
|
579
|
+
(compiledInstruction) => convertInstruction(compiledInstruction, accountMetas)
|
|
580
|
+
);
|
|
581
|
+
const firstInstruction = instructions[0];
|
|
582
|
+
const lifetimeConstraint = getLifetimeConstraint(
|
|
583
|
+
compiledMessage.lifetimeToken,
|
|
584
|
+
firstInstruction,
|
|
585
|
+
lastValidBlockHeight
|
|
586
|
+
);
|
|
587
|
+
const signatures = convertSignatures(compiledTransaction);
|
|
588
|
+
return functional.pipe(
|
|
589
|
+
createTransaction({ version: compiledMessage.version }),
|
|
590
|
+
(tx) => setTransactionFeePayer(feePayer, tx),
|
|
591
|
+
(tx) => instructions.reduce((acc, instruction) => {
|
|
592
|
+
return appendTransactionInstruction(instruction, acc);
|
|
593
|
+
}, tx),
|
|
594
|
+
(tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
|
|
595
|
+
(tx) => compiledTransaction.signatures.length ? { ...tx, signatures } : tx
|
|
596
|
+
);
|
|
597
|
+
}
|
|
469
598
|
var lookupTableAddressDescription = __DEV__ ? "The address of the address lookup table account from which instruction addresses should be looked up" : "lookupTableAddress";
|
|
470
599
|
var writableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as writeable" : "writableIndices";
|
|
471
600
|
var readableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as read-only" : "readableIndices";
|
|
@@ -496,6 +625,32 @@ function getAddressTableLookupEncoder() {
|
|
|
496
625
|
}
|
|
497
626
|
return memoizedAddressTableLookupEncoder;
|
|
498
627
|
}
|
|
628
|
+
var memoizedAddressTableLookupDecoder;
|
|
629
|
+
function getAddressTableLookupDecoder() {
|
|
630
|
+
if (!memoizedAddressTableLookupDecoder) {
|
|
631
|
+
memoizedAddressTableLookupDecoder = codecsDataStructures.getStructDecoder(
|
|
632
|
+
[
|
|
633
|
+
["lookupTableAddress", addresses.getAddressDecoder({ description: lookupTableAddressDescription })],
|
|
634
|
+
[
|
|
635
|
+
"writableIndices",
|
|
636
|
+
codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), {
|
|
637
|
+
description: writableIndicesDescription,
|
|
638
|
+
size: codecsNumbers.getShortU16Decoder()
|
|
639
|
+
})
|
|
640
|
+
],
|
|
641
|
+
[
|
|
642
|
+
"readableIndices",
|
|
643
|
+
codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), {
|
|
644
|
+
description: readableIndicesDescription,
|
|
645
|
+
size: codecsNumbers.getShortU16Decoder()
|
|
646
|
+
})
|
|
647
|
+
]
|
|
648
|
+
],
|
|
649
|
+
{ description: addressTableLookupDescription }
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
return memoizedAddressTableLookupDecoder;
|
|
653
|
+
}
|
|
499
654
|
var memoizedU8Encoder;
|
|
500
655
|
function getMemoizedU8Encoder() {
|
|
501
656
|
if (!memoizedU8Encoder)
|
|
@@ -509,6 +664,19 @@ function getMemoizedU8EncoderDescription(description) {
|
|
|
509
664
|
description: description ?? encoder.description
|
|
510
665
|
};
|
|
511
666
|
}
|
|
667
|
+
var memoizedU8Decoder;
|
|
668
|
+
function getMemoizedU8Decoder() {
|
|
669
|
+
if (!memoizedU8Decoder)
|
|
670
|
+
memoizedU8Decoder = codecsNumbers.getU8Decoder();
|
|
671
|
+
return memoizedU8Decoder;
|
|
672
|
+
}
|
|
673
|
+
function getMemoizedU8DecoderDescription(description) {
|
|
674
|
+
const decoder = getMemoizedU8Decoder();
|
|
675
|
+
return {
|
|
676
|
+
...decoder,
|
|
677
|
+
description: description ?? decoder.description
|
|
678
|
+
};
|
|
679
|
+
}
|
|
512
680
|
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;
|
|
513
681
|
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;
|
|
514
682
|
var numReadonlyNonSignerAccountsDescription = __DEV__ ? "The expected number of addresses in the static address list belonging to accounts that are neither signers, nor writable" : void 0;
|
|
@@ -525,6 +693,18 @@ function getMessageHeaderEncoder() {
|
|
|
525
693
|
}
|
|
526
694
|
);
|
|
527
695
|
}
|
|
696
|
+
function getMessageHeaderDecoder() {
|
|
697
|
+
return codecsDataStructures.getStructDecoder(
|
|
698
|
+
[
|
|
699
|
+
["numSignerAccounts", getMemoizedU8DecoderDescription(numSignerAccountsDescription)],
|
|
700
|
+
["numReadonlySignerAccounts", getMemoizedU8DecoderDescription(numReadonlySignerAccountsDescription)],
|
|
701
|
+
["numReadonlyNonSignerAccounts", getMemoizedU8DecoderDescription(numReadonlyNonSignerAccountsDescription)]
|
|
702
|
+
],
|
|
703
|
+
{
|
|
704
|
+
description: messageHeaderDescription
|
|
705
|
+
}
|
|
706
|
+
);
|
|
707
|
+
}
|
|
528
708
|
var programAddressIndexDescription = __DEV__ ? "The index of the program being called, according to the well-ordered accounts list for this transaction" : "programAddressIndex";
|
|
529
709
|
var accountIndexDescription = __DEV__ ? "The index of an account, according to the well-ordered accounts list for this transaction" : void 0;
|
|
530
710
|
var accountIndicesDescription = __DEV__ ? "An optional list of account indices, according to the well-ordered accounts list for this transaction, in the order in which the program being called expects them" : "accountIndices";
|
|
@@ -559,12 +739,52 @@ function getInstructionEncoder() {
|
|
|
559
739
|
}
|
|
560
740
|
return memoizedGetInstructionEncoder;
|
|
561
741
|
}
|
|
742
|
+
var memoizedGetInstructionDecoder;
|
|
743
|
+
function getInstructionDecoder() {
|
|
744
|
+
if (!memoizedGetInstructionDecoder) {
|
|
745
|
+
memoizedGetInstructionDecoder = codecsCore.mapDecoder(
|
|
746
|
+
codecsDataStructures.getStructDecoder([
|
|
747
|
+
["programAddressIndex", codecsNumbers.getU8Decoder({ description: programAddressIndexDescription })],
|
|
748
|
+
[
|
|
749
|
+
"accountIndices",
|
|
750
|
+
codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder({ description: accountIndexDescription }), {
|
|
751
|
+
description: accountIndicesDescription,
|
|
752
|
+
size: codecsNumbers.getShortU16Decoder()
|
|
753
|
+
})
|
|
754
|
+
],
|
|
755
|
+
["data", codecsDataStructures.getBytesDecoder({ description: dataDescription, size: codecsNumbers.getShortU16Decoder() })]
|
|
756
|
+
]),
|
|
757
|
+
// Convert an instruction to exclude optional fields if they are empty
|
|
758
|
+
(instruction) => {
|
|
759
|
+
if (instruction.accountIndices.length && instruction.data.byteLength) {
|
|
760
|
+
return instruction;
|
|
761
|
+
}
|
|
762
|
+
const { accountIndices, data, ...rest } = instruction;
|
|
763
|
+
return {
|
|
764
|
+
...rest,
|
|
765
|
+
...accountIndices.length ? { accountIndices } : null,
|
|
766
|
+
...data.byteLength ? { data } : null
|
|
767
|
+
};
|
|
768
|
+
}
|
|
769
|
+
);
|
|
770
|
+
}
|
|
771
|
+
return memoizedGetInstructionDecoder;
|
|
772
|
+
}
|
|
562
773
|
var VERSION_FLAG_MASK = 128;
|
|
563
774
|
var BASE_CONFIG = {
|
|
564
775
|
description: __DEV__ ? "A single byte that encodes the version of the transaction" : "",
|
|
565
776
|
fixedSize: null,
|
|
566
777
|
maxSize: 1
|
|
567
778
|
};
|
|
779
|
+
function decode(bytes, offset = 0) {
|
|
780
|
+
const firstByte = bytes[offset];
|
|
781
|
+
if ((firstByte & VERSION_FLAG_MASK) === 0) {
|
|
782
|
+
return ["legacy", offset];
|
|
783
|
+
} else {
|
|
784
|
+
const version = firstByte ^ VERSION_FLAG_MASK;
|
|
785
|
+
return [version, offset + 1];
|
|
786
|
+
}
|
|
787
|
+
}
|
|
568
788
|
function encode(value) {
|
|
569
789
|
if (value === "legacy") {
|
|
570
790
|
return new Uint8Array();
|
|
@@ -574,6 +794,12 @@ function encode(value) {
|
|
|
574
794
|
}
|
|
575
795
|
return new Uint8Array([value | VERSION_FLAG_MASK]);
|
|
576
796
|
}
|
|
797
|
+
function getTransactionVersionDecoder() {
|
|
798
|
+
return {
|
|
799
|
+
...BASE_CONFIG,
|
|
800
|
+
decode
|
|
801
|
+
};
|
|
802
|
+
}
|
|
577
803
|
function getTransactionVersionEncoder() {
|
|
578
804
|
return {
|
|
579
805
|
...BASE_CONFIG,
|
|
@@ -634,12 +860,47 @@ function getPreludeStructEncoderTuple() {
|
|
|
634
860
|
]
|
|
635
861
|
];
|
|
636
862
|
}
|
|
863
|
+
function getPreludeStructDecoderTuple() {
|
|
864
|
+
return [
|
|
865
|
+
["version", getTransactionVersionDecoder()],
|
|
866
|
+
["header", getMessageHeaderDecoder()],
|
|
867
|
+
[
|
|
868
|
+
"staticAccounts",
|
|
869
|
+
codecsDataStructures.getArrayDecoder(addresses.getAddressDecoder(), {
|
|
870
|
+
description: staticAccountsDescription,
|
|
871
|
+
size: codecsNumbers.getShortU16Decoder()
|
|
872
|
+
})
|
|
873
|
+
],
|
|
874
|
+
[
|
|
875
|
+
"lifetimeToken",
|
|
876
|
+
codecsStrings.getStringDecoder({
|
|
877
|
+
description: lifetimeTokenDescription,
|
|
878
|
+
encoding: codecsStrings.getBase58Decoder(),
|
|
879
|
+
size: 32
|
|
880
|
+
})
|
|
881
|
+
],
|
|
882
|
+
[
|
|
883
|
+
"instructions",
|
|
884
|
+
codecsDataStructures.getArrayDecoder(getInstructionDecoder(), {
|
|
885
|
+
description: instructionsDescription,
|
|
886
|
+
size: codecsNumbers.getShortU16Decoder()
|
|
887
|
+
})
|
|
888
|
+
],
|
|
889
|
+
["addressTableLookups", getAddressTableLookupArrayDecoder()]
|
|
890
|
+
];
|
|
891
|
+
}
|
|
637
892
|
function getAddressTableLookupArrayEncoder() {
|
|
638
893
|
return codecsDataStructures.getArrayEncoder(getAddressTableLookupEncoder(), {
|
|
639
894
|
description: addressTableLookupsDescription,
|
|
640
895
|
size: codecsNumbers.getShortU16Encoder()
|
|
641
896
|
});
|
|
642
897
|
}
|
|
898
|
+
function getAddressTableLookupArrayDecoder() {
|
|
899
|
+
return codecsDataStructures.getArrayDecoder(getAddressTableLookupDecoder(), {
|
|
900
|
+
description: addressTableLookupsDescription,
|
|
901
|
+
size: codecsNumbers.getShortU16Decoder()
|
|
902
|
+
});
|
|
903
|
+
}
|
|
643
904
|
var messageDescription = __DEV__ ? "The wire format of a Solana transaction message" : "message";
|
|
644
905
|
function getCompiledMessageEncoder() {
|
|
645
906
|
return {
|
|
@@ -655,10 +916,23 @@ function getCompiledMessageEncoder() {
|
|
|
655
916
|
maxSize: null
|
|
656
917
|
};
|
|
657
918
|
}
|
|
919
|
+
function getCompiledMessageDecoder() {
|
|
920
|
+
return codecsCore.mapDecoder(
|
|
921
|
+
codecsDataStructures.getStructDecoder(getPreludeStructDecoderTuple(), {
|
|
922
|
+
description: messageDescription
|
|
923
|
+
}),
|
|
924
|
+
({ addressTableLookups, ...restOfMessage }) => {
|
|
925
|
+
if (restOfMessage.version === "legacy" || !addressTableLookups?.length) {
|
|
926
|
+
return restOfMessage;
|
|
927
|
+
}
|
|
928
|
+
return { ...restOfMessage, addressTableLookups };
|
|
929
|
+
}
|
|
930
|
+
);
|
|
931
|
+
}
|
|
658
932
|
|
|
659
933
|
// src/serializers/transaction.ts
|
|
660
|
-
var transactionDescription = __DEV__ ? "The wire format of a Solana transaction" : "transaction";
|
|
661
934
|
var signaturesDescription = __DEV__ ? "A compact array of 64-byte, base-64 encoded Ed25519 signatures" : "signatures";
|
|
935
|
+
var transactionDescription = __DEV__ ? "The wire format of a Solana transaction" : "transaction";
|
|
662
936
|
function getCompiledTransactionEncoder() {
|
|
663
937
|
return codecsDataStructures.getStructEncoder(
|
|
664
938
|
[
|
|
@@ -676,68 +950,58 @@ function getCompiledTransactionEncoder() {
|
|
|
676
950
|
}
|
|
677
951
|
);
|
|
678
952
|
}
|
|
679
|
-
function
|
|
680
|
-
return codecsCore.
|
|
953
|
+
function getSignatureDecoder() {
|
|
954
|
+
return codecsCore.mapDecoder(codecsDataStructures.getBytesDecoder({ size: 64 }), (bytes) => bytes);
|
|
681
955
|
}
|
|
682
|
-
function
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
956
|
+
function getCompiledTransactionDecoder() {
|
|
957
|
+
return codecsDataStructures.getStructDecoder(
|
|
958
|
+
[
|
|
959
|
+
[
|
|
960
|
+
"signatures",
|
|
961
|
+
codecsDataStructures.getArrayDecoder(getSignatureDecoder(), {
|
|
962
|
+
description: signaturesDescription,
|
|
963
|
+
size: codecsNumbers.getShortU16Decoder()
|
|
964
|
+
})
|
|
965
|
+
],
|
|
966
|
+
["compiledMessage", getCompiledMessageDecoder()]
|
|
967
|
+
],
|
|
968
|
+
{
|
|
969
|
+
description: transactionDescription
|
|
695
970
|
}
|
|
696
|
-
|
|
697
|
-
throw new Error(`\`${putativeTransactionSignature}\` is not a transaction signature`, {
|
|
698
|
-
cause: e
|
|
699
|
-
});
|
|
700
|
-
}
|
|
971
|
+
);
|
|
701
972
|
}
|
|
702
|
-
function
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
const bytes = umiSerializers.base58.serialize(putativeTransactionSignature);
|
|
711
|
-
const numBytes = bytes.byteLength;
|
|
712
|
-
if (numBytes !== 64) {
|
|
713
|
-
return false;
|
|
714
|
-
}
|
|
715
|
-
return true;
|
|
973
|
+
function getTransactionEncoder() {
|
|
974
|
+
return codecsCore.mapEncoder(getCompiledTransactionEncoder(), getCompiledTransaction);
|
|
975
|
+
}
|
|
976
|
+
function getTransactionDecoder(lastValidBlockHeight) {
|
|
977
|
+
return codecsCore.mapDecoder(
|
|
978
|
+
getCompiledTransactionDecoder(),
|
|
979
|
+
(compiledTransaction) => decompileTransaction(compiledTransaction, lastValidBlockHeight)
|
|
980
|
+
);
|
|
716
981
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
const signature = await keys.signBytes(secretKey, wireMessageBytes);
|
|
720
|
-
return signature;
|
|
982
|
+
function getTransactionCodec(lastValidBlockHeight) {
|
|
983
|
+
return codecsCore.combineCodec(getTransactionEncoder(), getTransactionDecoder(lastValidBlockHeight));
|
|
721
984
|
}
|
|
985
|
+
var base58Decoder;
|
|
722
986
|
function getSignatureFromTransaction(transaction) {
|
|
987
|
+
if (!base58Decoder)
|
|
988
|
+
base58Decoder = codecsStrings.getBase58Decoder();
|
|
723
989
|
const signatureBytes = transaction.signatures[transaction.feePayer];
|
|
724
990
|
if (!signatureBytes) {
|
|
725
991
|
throw new Error(
|
|
726
992
|
"Could not determine this transaction's signature. Make sure that the transaction has been signed by its fee payer."
|
|
727
993
|
);
|
|
728
994
|
}
|
|
729
|
-
const
|
|
730
|
-
return
|
|
995
|
+
const transactionSignature = base58Decoder.decode(signatureBytes)[0];
|
|
996
|
+
return transactionSignature;
|
|
731
997
|
}
|
|
732
|
-
async function
|
|
998
|
+
async function partiallySignTransaction(keyPairs, transaction) {
|
|
733
999
|
const compiledMessage = compileMessage(transaction);
|
|
734
1000
|
const nextSignatures = "signatures" in transaction ? { ...transaction.signatures } : {};
|
|
1001
|
+
const wireMessageBytes = getCompiledMessageEncoder().encode(compiledMessage);
|
|
735
1002
|
const publicKeySignaturePairs = await Promise.all(
|
|
736
1003
|
keyPairs.map(
|
|
737
|
-
(keyPair) => Promise.all([
|
|
738
|
-
addresses.getAddressFromPublicKey(keyPair.publicKey),
|
|
739
|
-
getCompiledMessageSignature(compiledMessage, keyPair.privateKey)
|
|
740
|
-
])
|
|
1004
|
+
(keyPair) => Promise.all([addresses.getAddressFromPublicKey(keyPair.publicKey), keys.signBytes(keyPair.privateKey, wireMessageBytes)])
|
|
741
1005
|
)
|
|
742
1006
|
);
|
|
743
1007
|
for (const [signerPublicKey, signature] of publicKeySignaturePairs) {
|
|
@@ -750,34 +1014,40 @@ async function signTransaction(keyPairs, transaction) {
|
|
|
750
1014
|
Object.freeze(out);
|
|
751
1015
|
return out;
|
|
752
1016
|
}
|
|
753
|
-
function
|
|
754
|
-
|
|
755
|
-
|
|
1017
|
+
async function signTransaction(keyPairs, transaction) {
|
|
1018
|
+
const out = await partiallySignTransaction(keyPairs, transaction);
|
|
1019
|
+
assertTransactionIsFullySigned(out);
|
|
1020
|
+
Object.freeze(out);
|
|
1021
|
+
return out;
|
|
1022
|
+
}
|
|
1023
|
+
function assertTransactionIsFullySigned(transaction) {
|
|
1024
|
+
const signerAddressesFromInstructions = transaction.instructions.flatMap((i) => i.accounts?.filter((a) => isSignerRole(a.role)) ?? []).map((a) => a.address);
|
|
1025
|
+
const requiredSigners = /* @__PURE__ */ new Set([transaction.feePayer, ...signerAddressesFromInstructions]);
|
|
1026
|
+
requiredSigners.forEach((address) => {
|
|
1027
|
+
if (!transaction.signatures[address]) {
|
|
1028
|
+
throw new Error(`Transaction is missing signature for address \`${address}\``);
|
|
1029
|
+
}
|
|
1030
|
+
});
|
|
756
1031
|
}
|
|
757
|
-
|
|
758
|
-
// src/wire-transaction.ts
|
|
759
1032
|
function getBase64EncodedWireTransaction(transaction) {
|
|
760
1033
|
const wireTransactionBytes = getTransactionEncoder().encode(transaction);
|
|
761
|
-
|
|
762
|
-
return btoa(String.fromCharCode(...wireTransactionBytes));
|
|
763
|
-
}
|
|
1034
|
+
return codecsStrings.getBase64Decoder().decode(wireTransactionBytes)[0];
|
|
764
1035
|
}
|
|
765
1036
|
|
|
766
1037
|
exports.appendTransactionInstruction = appendTransactionInstruction;
|
|
767
1038
|
exports.assertIsBlockhash = assertIsBlockhash;
|
|
768
1039
|
exports.assertIsDurableNonceTransaction = assertIsDurableNonceTransaction;
|
|
769
|
-
exports.
|
|
1040
|
+
exports.assertTransactionIsFullySigned = assertTransactionIsFullySigned;
|
|
770
1041
|
exports.createTransaction = createTransaction;
|
|
771
1042
|
exports.getBase64EncodedWireTransaction = getBase64EncodedWireTransaction;
|
|
772
1043
|
exports.getSignatureFromTransaction = getSignatureFromTransaction;
|
|
1044
|
+
exports.getTransactionCodec = getTransactionCodec;
|
|
1045
|
+
exports.getTransactionDecoder = getTransactionDecoder;
|
|
773
1046
|
exports.getTransactionEncoder = getTransactionEncoder;
|
|
774
1047
|
exports.isAdvanceNonceAccountInstruction = isAdvanceNonceAccountInstruction;
|
|
775
|
-
exports.
|
|
1048
|
+
exports.partiallySignTransaction = partiallySignTransaction;
|
|
776
1049
|
exports.prependTransactionInstruction = prependTransactionInstruction;
|
|
777
1050
|
exports.setTransactionFeePayer = setTransactionFeePayer;
|
|
778
1051
|
exports.setTransactionLifetimeUsingBlockhash = setTransactionLifetimeUsingBlockhash;
|
|
779
1052
|
exports.setTransactionLifetimeUsingDurableNonce = setTransactionLifetimeUsingDurableNonce;
|
|
780
1053
|
exports.signTransaction = signTransaction;
|
|
781
|
-
exports.transactionSignature = transactionSignature;
|
|
782
|
-
//# sourceMappingURL=out.js.map
|
|
783
|
-
//# sourceMappingURL=index.browser.cjs.map
|