@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/dist/index.browser.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { mapEncoder } from '@solana/codecs-core';
|
|
3
|
-
import { getStructEncoder, getArrayEncoder, getBytesEncoder } from '@solana/codecs-data-structures';
|
|
4
|
-
import { getShortU16Encoder, getU8Encoder } from '@solana/codecs-numbers';
|
|
5
|
-
import { getAddressFromPublicKey, getAddressComparator, getAddressEncoder } from '@solana/addresses';
|
|
6
|
-
import {
|
|
1
|
+
import { getBase58Encoder, getBase58Decoder, getBase64Decoder, getStringEncoder, getStringDecoder } from '@solana/codecs-strings';
|
|
2
|
+
import { mapEncoder, mapDecoder, combineCodec } from '@solana/codecs-core';
|
|
3
|
+
import { getStructEncoder, getArrayEncoder, getBytesEncoder, getStructDecoder, getArrayDecoder, getBytesDecoder } from '@solana/codecs-data-structures';
|
|
4
|
+
import { getShortU16Encoder, getShortU16Decoder, getU8Encoder, getU8Decoder } from '@solana/codecs-numbers';
|
|
5
|
+
import { getAddressFromPublicKey, getAddressComparator, assertIsAddress, getAddressEncoder, getAddressDecoder } from '@solana/addresses';
|
|
6
|
+
import { pipe } from '@solana/functional';
|
|
7
7
|
import { signBytes } from '@solana/keys';
|
|
8
8
|
|
|
9
9
|
// ../build-scripts/env-shim.ts
|
|
@@ -24,7 +24,10 @@ function getUnsignedTransaction(transaction) {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// src/blockhash.ts
|
|
27
|
+
var base58Encoder;
|
|
27
28
|
function assertIsBlockhash(putativeBlockhash) {
|
|
29
|
+
if (!base58Encoder)
|
|
30
|
+
base58Encoder = getBase58Encoder();
|
|
28
31
|
try {
|
|
29
32
|
if (
|
|
30
33
|
// Lowest value (32 bytes of zeroes)
|
|
@@ -33,7 +36,7 @@ function assertIsBlockhash(putativeBlockhash) {
|
|
|
33
36
|
) {
|
|
34
37
|
throw new Error("Expected input string to decode to a byte array of length 32.");
|
|
35
38
|
}
|
|
36
|
-
const bytes =
|
|
39
|
+
const bytes = base58Encoder.encode(putativeBlockhash);
|
|
37
40
|
const numBytes = bytes.byteLength;
|
|
38
41
|
if (numBytes !== 32) {
|
|
39
42
|
throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${numBytes}`);
|
|
@@ -119,7 +122,7 @@ function isAdvanceNonceAccountInstruction(instruction) {
|
|
|
119
122
|
instruction.accounts?.length === 3 && // First account is nonce account address
|
|
120
123
|
instruction.accounts[0].address != null && instruction.accounts[0].role === AccountRole.WRITABLE && // Second account is recent blockhashes sysvar
|
|
121
124
|
instruction.accounts[1].address === RECENT_BLOCKHASHES_SYSVAR_ADDRESS && instruction.accounts[1].role === AccountRole.READONLY && // Third account is nonce authority account
|
|
122
|
-
instruction.accounts[2].address != null && instruction.accounts[2].role
|
|
125
|
+
instruction.accounts[2].address != null && isSignerRole(instruction.accounts[2].role);
|
|
123
126
|
}
|
|
124
127
|
function isAdvanceNonceAccountInstructionData(data) {
|
|
125
128
|
return data.byteLength === 4 && data[0] === 4 && data[1] === 0 && data[2] === 0 && data[3] === 0;
|
|
@@ -127,21 +130,38 @@ function isAdvanceNonceAccountInstructionData(data) {
|
|
|
127
130
|
function isDurableNonceTransaction(transaction) {
|
|
128
131
|
return "lifetimeConstraint" in transaction && typeof transaction.lifetimeConstraint.nonce === "string" && transaction.instructions[0] != null && isAdvanceNonceAccountInstruction(transaction.instructions[0]);
|
|
129
132
|
}
|
|
133
|
+
function isAdvanceNonceAccountInstructionForNonce(instruction, nonceAccountAddress, nonceAuthorityAddress) {
|
|
134
|
+
return instruction.accounts[0].address === nonceAccountAddress && instruction.accounts[2].address === nonceAuthorityAddress;
|
|
135
|
+
}
|
|
130
136
|
function setTransactionLifetimeUsingDurableNonce({
|
|
131
137
|
nonce,
|
|
132
138
|
nonceAccountAddress,
|
|
133
139
|
nonceAuthorityAddress
|
|
134
140
|
}, transaction) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
141
|
+
let newInstructions;
|
|
142
|
+
const firstInstruction = transaction.instructions[0];
|
|
143
|
+
if (firstInstruction && isAdvanceNonceAccountInstruction(firstInstruction)) {
|
|
144
|
+
if (isAdvanceNonceAccountInstructionForNonce(firstInstruction, nonceAccountAddress, nonceAuthorityAddress)) {
|
|
145
|
+
if (isDurableNonceTransaction(transaction) && transaction.lifetimeConstraint.nonce === nonce) {
|
|
146
|
+
return transaction;
|
|
147
|
+
} else {
|
|
148
|
+
newInstructions = [firstInstruction, ...transaction.instructions.slice(1)];
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
newInstructions = [
|
|
152
|
+
createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
|
|
153
|
+
...transaction.instructions.slice(1)
|
|
154
|
+
];
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
newInstructions = [
|
|
158
|
+
createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
|
|
159
|
+
...transaction.instructions
|
|
160
|
+
];
|
|
138
161
|
}
|
|
139
162
|
const out = {
|
|
140
163
|
...getUnsignedTransaction(transaction),
|
|
141
|
-
instructions:
|
|
142
|
-
createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
|
|
143
|
-
...isAlreadyDurableNonceTransaction ? transaction.instructions.slice(1) : transaction.instructions
|
|
144
|
-
],
|
|
164
|
+
instructions: newInstructions,
|
|
145
165
|
lifetimeConstraint: {
|
|
146
166
|
nonce
|
|
147
167
|
}
|
|
@@ -232,7 +252,7 @@ function getAddressMapFromInstructions(feePayer, instructions) {
|
|
|
232
252
|
const shouldReplaceEntry = (
|
|
233
253
|
// Consider using the new LOOKUP_TABLE if its address is different...
|
|
234
254
|
entry.lookupTableAddress !== accountMeta.lookupTableAddress && // ...and sorts before the existing one.
|
|
235
|
-
(addressComparator
|
|
255
|
+
(addressComparator ||= getAddressComparator())(
|
|
236
256
|
accountMeta.lookupTableAddress,
|
|
237
257
|
entry.lookupTableAddress
|
|
238
258
|
) < 0
|
|
@@ -338,7 +358,7 @@ function getOrderedAccountsFromAddressMap(addressMap) {
|
|
|
338
358
|
if (leftIsWritable !== isWritableRole(rightEntry.role)) {
|
|
339
359
|
return leftIsWritable ? -1 : 1;
|
|
340
360
|
}
|
|
341
|
-
addressComparator
|
|
361
|
+
addressComparator ||= getAddressComparator();
|
|
342
362
|
if (leftEntry[TYPE] === 1 /* LOOKUP_TABLE */ && rightEntry[TYPE] === 1 /* LOOKUP_TABLE */ && leftEntry.lookupTableAddress !== rightEntry.lookupTableAddress) {
|
|
343
363
|
return addressComparator(leftEntry.lookupTableAddress, rightEntry.lookupTableAddress);
|
|
344
364
|
} else {
|
|
@@ -351,16 +371,15 @@ function getOrderedAccountsFromAddressMap(addressMap) {
|
|
|
351
371
|
return orderedAccounts;
|
|
352
372
|
}
|
|
353
373
|
function getCompiledAddressTableLookups(orderedAccounts) {
|
|
354
|
-
var _a;
|
|
355
374
|
const index = {};
|
|
356
375
|
for (const account of orderedAccounts) {
|
|
357
376
|
if (!("lookupTableAddress" in account)) {
|
|
358
377
|
continue;
|
|
359
378
|
}
|
|
360
|
-
const entry = index[
|
|
379
|
+
const entry = index[account.lookupTableAddress] ||= {
|
|
361
380
|
readableIndices: [],
|
|
362
381
|
writableIndices: []
|
|
363
|
-
}
|
|
382
|
+
};
|
|
364
383
|
if (account.role === AccountRole.WRITABLE) {
|
|
365
384
|
entry.writableIndices.push(account.addressIndex);
|
|
366
385
|
} else {
|
|
@@ -464,6 +483,116 @@ function getCompiledTransaction(transaction) {
|
|
|
464
483
|
signatures
|
|
465
484
|
};
|
|
466
485
|
}
|
|
486
|
+
function getAccountMetas(message) {
|
|
487
|
+
const { header } = message;
|
|
488
|
+
const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
|
|
489
|
+
const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
|
|
490
|
+
const accountMetas = [];
|
|
491
|
+
let accountIndex = 0;
|
|
492
|
+
for (let i = 0; i < numWritableSignerAccounts; i++) {
|
|
493
|
+
accountMetas.push({
|
|
494
|
+
address: message.staticAccounts[accountIndex],
|
|
495
|
+
role: AccountRole.WRITABLE_SIGNER
|
|
496
|
+
});
|
|
497
|
+
accountIndex++;
|
|
498
|
+
}
|
|
499
|
+
for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
|
|
500
|
+
accountMetas.push({
|
|
501
|
+
address: message.staticAccounts[accountIndex],
|
|
502
|
+
role: AccountRole.READONLY_SIGNER
|
|
503
|
+
});
|
|
504
|
+
accountIndex++;
|
|
505
|
+
}
|
|
506
|
+
for (let i = 0; i < numWritableNonSignerAccounts; i++) {
|
|
507
|
+
accountMetas.push({
|
|
508
|
+
address: message.staticAccounts[accountIndex],
|
|
509
|
+
role: AccountRole.WRITABLE
|
|
510
|
+
});
|
|
511
|
+
accountIndex++;
|
|
512
|
+
}
|
|
513
|
+
for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
|
|
514
|
+
accountMetas.push({
|
|
515
|
+
address: message.staticAccounts[accountIndex],
|
|
516
|
+
role: AccountRole.READONLY
|
|
517
|
+
});
|
|
518
|
+
accountIndex++;
|
|
519
|
+
}
|
|
520
|
+
return accountMetas;
|
|
521
|
+
}
|
|
522
|
+
function convertInstruction(instruction, accountMetas) {
|
|
523
|
+
const programAddress = accountMetas[instruction.programAddressIndex]?.address;
|
|
524
|
+
if (!programAddress) {
|
|
525
|
+
throw new Error(`Could not find program address at index ${instruction.programAddressIndex}`);
|
|
526
|
+
}
|
|
527
|
+
const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
|
|
528
|
+
const { data } = instruction;
|
|
529
|
+
return {
|
|
530
|
+
programAddress,
|
|
531
|
+
...accounts && accounts.length ? { accounts } : {},
|
|
532
|
+
...data && data.length ? { data } : {}
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
|
|
536
|
+
if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
|
|
537
|
+
return {
|
|
538
|
+
blockhash: messageLifetimeToken,
|
|
539
|
+
lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
|
|
540
|
+
// U64 MAX
|
|
541
|
+
};
|
|
542
|
+
} else {
|
|
543
|
+
const nonceAccountAddress = firstInstruction.accounts[0].address;
|
|
544
|
+
assertIsAddress(nonceAccountAddress);
|
|
545
|
+
const nonceAuthorityAddress = firstInstruction.accounts[2].address;
|
|
546
|
+
assertIsAddress(nonceAuthorityAddress);
|
|
547
|
+
return {
|
|
548
|
+
nonce: messageLifetimeToken,
|
|
549
|
+
nonceAccountAddress,
|
|
550
|
+
nonceAuthorityAddress
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
function convertSignatures(compiledTransaction) {
|
|
555
|
+
const {
|
|
556
|
+
compiledMessage: { staticAccounts },
|
|
557
|
+
signatures
|
|
558
|
+
} = compiledTransaction;
|
|
559
|
+
return signatures.reduce((acc, sig, index) => {
|
|
560
|
+
const allZeros = sig.every((byte) => byte === 0);
|
|
561
|
+
if (allZeros)
|
|
562
|
+
return acc;
|
|
563
|
+
const address = staticAccounts[index];
|
|
564
|
+
return { ...acc, [address]: sig };
|
|
565
|
+
}, {});
|
|
566
|
+
}
|
|
567
|
+
function decompileTransaction(compiledTransaction, lastValidBlockHeight) {
|
|
568
|
+
const { compiledMessage } = compiledTransaction;
|
|
569
|
+
if ("addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups.length > 0) {
|
|
570
|
+
throw new Error("Cannot convert transaction with addressTableLookups");
|
|
571
|
+
}
|
|
572
|
+
const feePayer = compiledMessage.staticAccounts[0];
|
|
573
|
+
if (!feePayer)
|
|
574
|
+
throw new Error("No fee payer set in CompiledTransaction");
|
|
575
|
+
const accountMetas = getAccountMetas(compiledMessage);
|
|
576
|
+
const instructions = compiledMessage.instructions.map(
|
|
577
|
+
(compiledInstruction) => convertInstruction(compiledInstruction, accountMetas)
|
|
578
|
+
);
|
|
579
|
+
const firstInstruction = instructions[0];
|
|
580
|
+
const lifetimeConstraint = getLifetimeConstraint(
|
|
581
|
+
compiledMessage.lifetimeToken,
|
|
582
|
+
firstInstruction,
|
|
583
|
+
lastValidBlockHeight
|
|
584
|
+
);
|
|
585
|
+
const signatures = convertSignatures(compiledTransaction);
|
|
586
|
+
return pipe(
|
|
587
|
+
createTransaction({ version: compiledMessage.version }),
|
|
588
|
+
(tx) => setTransactionFeePayer(feePayer, tx),
|
|
589
|
+
(tx) => instructions.reduce((acc, instruction) => {
|
|
590
|
+
return appendTransactionInstruction(instruction, acc);
|
|
591
|
+
}, tx),
|
|
592
|
+
(tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
|
|
593
|
+
(tx) => compiledTransaction.signatures.length ? { ...tx, signatures } : tx
|
|
594
|
+
);
|
|
595
|
+
}
|
|
467
596
|
var lookupTableAddressDescription = __DEV__ ? "The address of the address lookup table account from which instruction addresses should be looked up" : "lookupTableAddress";
|
|
468
597
|
var writableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as writeable" : "writableIndices";
|
|
469
598
|
var readableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as read-only" : "readableIndices";
|
|
@@ -494,6 +623,32 @@ function getAddressTableLookupEncoder() {
|
|
|
494
623
|
}
|
|
495
624
|
return memoizedAddressTableLookupEncoder;
|
|
496
625
|
}
|
|
626
|
+
var memoizedAddressTableLookupDecoder;
|
|
627
|
+
function getAddressTableLookupDecoder() {
|
|
628
|
+
if (!memoizedAddressTableLookupDecoder) {
|
|
629
|
+
memoizedAddressTableLookupDecoder = getStructDecoder(
|
|
630
|
+
[
|
|
631
|
+
["lookupTableAddress", getAddressDecoder({ description: lookupTableAddressDescription })],
|
|
632
|
+
[
|
|
633
|
+
"writableIndices",
|
|
634
|
+
getArrayDecoder(getU8Decoder(), {
|
|
635
|
+
description: writableIndicesDescription,
|
|
636
|
+
size: getShortU16Decoder()
|
|
637
|
+
})
|
|
638
|
+
],
|
|
639
|
+
[
|
|
640
|
+
"readableIndices",
|
|
641
|
+
getArrayDecoder(getU8Decoder(), {
|
|
642
|
+
description: readableIndicesDescription,
|
|
643
|
+
size: getShortU16Decoder()
|
|
644
|
+
})
|
|
645
|
+
]
|
|
646
|
+
],
|
|
647
|
+
{ description: addressTableLookupDescription }
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
return memoizedAddressTableLookupDecoder;
|
|
651
|
+
}
|
|
497
652
|
var memoizedU8Encoder;
|
|
498
653
|
function getMemoizedU8Encoder() {
|
|
499
654
|
if (!memoizedU8Encoder)
|
|
@@ -507,6 +662,19 @@ function getMemoizedU8EncoderDescription(description) {
|
|
|
507
662
|
description: description ?? encoder.description
|
|
508
663
|
};
|
|
509
664
|
}
|
|
665
|
+
var memoizedU8Decoder;
|
|
666
|
+
function getMemoizedU8Decoder() {
|
|
667
|
+
if (!memoizedU8Decoder)
|
|
668
|
+
memoizedU8Decoder = getU8Decoder();
|
|
669
|
+
return memoizedU8Decoder;
|
|
670
|
+
}
|
|
671
|
+
function getMemoizedU8DecoderDescription(description) {
|
|
672
|
+
const decoder = getMemoizedU8Decoder();
|
|
673
|
+
return {
|
|
674
|
+
...decoder,
|
|
675
|
+
description: description ?? decoder.description
|
|
676
|
+
};
|
|
677
|
+
}
|
|
510
678
|
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;
|
|
511
679
|
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;
|
|
512
680
|
var numReadonlyNonSignerAccountsDescription = __DEV__ ? "The expected number of addresses in the static address list belonging to accounts that are neither signers, nor writable" : void 0;
|
|
@@ -523,6 +691,18 @@ function getMessageHeaderEncoder() {
|
|
|
523
691
|
}
|
|
524
692
|
);
|
|
525
693
|
}
|
|
694
|
+
function getMessageHeaderDecoder() {
|
|
695
|
+
return getStructDecoder(
|
|
696
|
+
[
|
|
697
|
+
["numSignerAccounts", getMemoizedU8DecoderDescription(numSignerAccountsDescription)],
|
|
698
|
+
["numReadonlySignerAccounts", getMemoizedU8DecoderDescription(numReadonlySignerAccountsDescription)],
|
|
699
|
+
["numReadonlyNonSignerAccounts", getMemoizedU8DecoderDescription(numReadonlyNonSignerAccountsDescription)]
|
|
700
|
+
],
|
|
701
|
+
{
|
|
702
|
+
description: messageHeaderDescription
|
|
703
|
+
}
|
|
704
|
+
);
|
|
705
|
+
}
|
|
526
706
|
var programAddressIndexDescription = __DEV__ ? "The index of the program being called, according to the well-ordered accounts list for this transaction" : "programAddressIndex";
|
|
527
707
|
var accountIndexDescription = __DEV__ ? "The index of an account, according to the well-ordered accounts list for this transaction" : void 0;
|
|
528
708
|
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";
|
|
@@ -557,12 +737,52 @@ function getInstructionEncoder() {
|
|
|
557
737
|
}
|
|
558
738
|
return memoizedGetInstructionEncoder;
|
|
559
739
|
}
|
|
740
|
+
var memoizedGetInstructionDecoder;
|
|
741
|
+
function getInstructionDecoder() {
|
|
742
|
+
if (!memoizedGetInstructionDecoder) {
|
|
743
|
+
memoizedGetInstructionDecoder = mapDecoder(
|
|
744
|
+
getStructDecoder([
|
|
745
|
+
["programAddressIndex", getU8Decoder({ description: programAddressIndexDescription })],
|
|
746
|
+
[
|
|
747
|
+
"accountIndices",
|
|
748
|
+
getArrayDecoder(getU8Decoder({ description: accountIndexDescription }), {
|
|
749
|
+
description: accountIndicesDescription,
|
|
750
|
+
size: getShortU16Decoder()
|
|
751
|
+
})
|
|
752
|
+
],
|
|
753
|
+
["data", getBytesDecoder({ description: dataDescription, size: getShortU16Decoder() })]
|
|
754
|
+
]),
|
|
755
|
+
// Convert an instruction to exclude optional fields if they are empty
|
|
756
|
+
(instruction) => {
|
|
757
|
+
if (instruction.accountIndices.length && instruction.data.byteLength) {
|
|
758
|
+
return instruction;
|
|
759
|
+
}
|
|
760
|
+
const { accountIndices, data, ...rest } = instruction;
|
|
761
|
+
return {
|
|
762
|
+
...rest,
|
|
763
|
+
...accountIndices.length ? { accountIndices } : null,
|
|
764
|
+
...data.byteLength ? { data } : null
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
);
|
|
768
|
+
}
|
|
769
|
+
return memoizedGetInstructionDecoder;
|
|
770
|
+
}
|
|
560
771
|
var VERSION_FLAG_MASK = 128;
|
|
561
772
|
var BASE_CONFIG = {
|
|
562
773
|
description: __DEV__ ? "A single byte that encodes the version of the transaction" : "",
|
|
563
774
|
fixedSize: null,
|
|
564
775
|
maxSize: 1
|
|
565
776
|
};
|
|
777
|
+
function decode(bytes, offset = 0) {
|
|
778
|
+
const firstByte = bytes[offset];
|
|
779
|
+
if ((firstByte & VERSION_FLAG_MASK) === 0) {
|
|
780
|
+
return ["legacy", offset];
|
|
781
|
+
} else {
|
|
782
|
+
const version = firstByte ^ VERSION_FLAG_MASK;
|
|
783
|
+
return [version, offset + 1];
|
|
784
|
+
}
|
|
785
|
+
}
|
|
566
786
|
function encode(value) {
|
|
567
787
|
if (value === "legacy") {
|
|
568
788
|
return new Uint8Array();
|
|
@@ -572,6 +792,12 @@ function encode(value) {
|
|
|
572
792
|
}
|
|
573
793
|
return new Uint8Array([value | VERSION_FLAG_MASK]);
|
|
574
794
|
}
|
|
795
|
+
function getTransactionVersionDecoder() {
|
|
796
|
+
return {
|
|
797
|
+
...BASE_CONFIG,
|
|
798
|
+
decode
|
|
799
|
+
};
|
|
800
|
+
}
|
|
575
801
|
function getTransactionVersionEncoder() {
|
|
576
802
|
return {
|
|
577
803
|
...BASE_CONFIG,
|
|
@@ -632,12 +858,47 @@ function getPreludeStructEncoderTuple() {
|
|
|
632
858
|
]
|
|
633
859
|
];
|
|
634
860
|
}
|
|
861
|
+
function getPreludeStructDecoderTuple() {
|
|
862
|
+
return [
|
|
863
|
+
["version", getTransactionVersionDecoder()],
|
|
864
|
+
["header", getMessageHeaderDecoder()],
|
|
865
|
+
[
|
|
866
|
+
"staticAccounts",
|
|
867
|
+
getArrayDecoder(getAddressDecoder(), {
|
|
868
|
+
description: staticAccountsDescription,
|
|
869
|
+
size: getShortU16Decoder()
|
|
870
|
+
})
|
|
871
|
+
],
|
|
872
|
+
[
|
|
873
|
+
"lifetimeToken",
|
|
874
|
+
getStringDecoder({
|
|
875
|
+
description: lifetimeTokenDescription,
|
|
876
|
+
encoding: getBase58Decoder(),
|
|
877
|
+
size: 32
|
|
878
|
+
})
|
|
879
|
+
],
|
|
880
|
+
[
|
|
881
|
+
"instructions",
|
|
882
|
+
getArrayDecoder(getInstructionDecoder(), {
|
|
883
|
+
description: instructionsDescription,
|
|
884
|
+
size: getShortU16Decoder()
|
|
885
|
+
})
|
|
886
|
+
],
|
|
887
|
+
["addressTableLookups", getAddressTableLookupArrayDecoder()]
|
|
888
|
+
];
|
|
889
|
+
}
|
|
635
890
|
function getAddressTableLookupArrayEncoder() {
|
|
636
891
|
return getArrayEncoder(getAddressTableLookupEncoder(), {
|
|
637
892
|
description: addressTableLookupsDescription,
|
|
638
893
|
size: getShortU16Encoder()
|
|
639
894
|
});
|
|
640
895
|
}
|
|
896
|
+
function getAddressTableLookupArrayDecoder() {
|
|
897
|
+
return getArrayDecoder(getAddressTableLookupDecoder(), {
|
|
898
|
+
description: addressTableLookupsDescription,
|
|
899
|
+
size: getShortU16Decoder()
|
|
900
|
+
});
|
|
901
|
+
}
|
|
641
902
|
var messageDescription = __DEV__ ? "The wire format of a Solana transaction message" : "message";
|
|
642
903
|
function getCompiledMessageEncoder() {
|
|
643
904
|
return {
|
|
@@ -653,10 +914,23 @@ function getCompiledMessageEncoder() {
|
|
|
653
914
|
maxSize: null
|
|
654
915
|
};
|
|
655
916
|
}
|
|
917
|
+
function getCompiledMessageDecoder() {
|
|
918
|
+
return mapDecoder(
|
|
919
|
+
getStructDecoder(getPreludeStructDecoderTuple(), {
|
|
920
|
+
description: messageDescription
|
|
921
|
+
}),
|
|
922
|
+
({ addressTableLookups, ...restOfMessage }) => {
|
|
923
|
+
if (restOfMessage.version === "legacy" || !addressTableLookups?.length) {
|
|
924
|
+
return restOfMessage;
|
|
925
|
+
}
|
|
926
|
+
return { ...restOfMessage, addressTableLookups };
|
|
927
|
+
}
|
|
928
|
+
);
|
|
929
|
+
}
|
|
656
930
|
|
|
657
931
|
// src/serializers/transaction.ts
|
|
658
|
-
var transactionDescription = __DEV__ ? "The wire format of a Solana transaction" : "transaction";
|
|
659
932
|
var signaturesDescription = __DEV__ ? "A compact array of 64-byte, base-64 encoded Ed25519 signatures" : "signatures";
|
|
933
|
+
var transactionDescription = __DEV__ ? "The wire format of a Solana transaction" : "transaction";
|
|
660
934
|
function getCompiledTransactionEncoder() {
|
|
661
935
|
return getStructEncoder(
|
|
662
936
|
[
|
|
@@ -674,68 +948,58 @@ function getCompiledTransactionEncoder() {
|
|
|
674
948
|
}
|
|
675
949
|
);
|
|
676
950
|
}
|
|
677
|
-
function
|
|
678
|
-
return
|
|
951
|
+
function getSignatureDecoder() {
|
|
952
|
+
return mapDecoder(getBytesDecoder({ size: 64 }), (bytes) => bytes);
|
|
679
953
|
}
|
|
680
|
-
function
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
954
|
+
function getCompiledTransactionDecoder() {
|
|
955
|
+
return getStructDecoder(
|
|
956
|
+
[
|
|
957
|
+
[
|
|
958
|
+
"signatures",
|
|
959
|
+
getArrayDecoder(getSignatureDecoder(), {
|
|
960
|
+
description: signaturesDescription,
|
|
961
|
+
size: getShortU16Decoder()
|
|
962
|
+
})
|
|
963
|
+
],
|
|
964
|
+
["compiledMessage", getCompiledMessageDecoder()]
|
|
965
|
+
],
|
|
966
|
+
{
|
|
967
|
+
description: transactionDescription
|
|
693
968
|
}
|
|
694
|
-
|
|
695
|
-
throw new Error(`\`${putativeTransactionSignature}\` is not a transaction signature`, {
|
|
696
|
-
cause: e
|
|
697
|
-
});
|
|
698
|
-
}
|
|
969
|
+
);
|
|
699
970
|
}
|
|
700
|
-
function
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
const bytes = base58.serialize(putativeTransactionSignature);
|
|
709
|
-
const numBytes = bytes.byteLength;
|
|
710
|
-
if (numBytes !== 64) {
|
|
711
|
-
return false;
|
|
712
|
-
}
|
|
713
|
-
return true;
|
|
971
|
+
function getTransactionEncoder() {
|
|
972
|
+
return mapEncoder(getCompiledTransactionEncoder(), getCompiledTransaction);
|
|
973
|
+
}
|
|
974
|
+
function getTransactionDecoder(lastValidBlockHeight) {
|
|
975
|
+
return mapDecoder(
|
|
976
|
+
getCompiledTransactionDecoder(),
|
|
977
|
+
(compiledTransaction) => decompileTransaction(compiledTransaction, lastValidBlockHeight)
|
|
978
|
+
);
|
|
714
979
|
}
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
const signature = await signBytes(secretKey, wireMessageBytes);
|
|
718
|
-
return signature;
|
|
980
|
+
function getTransactionCodec(lastValidBlockHeight) {
|
|
981
|
+
return combineCodec(getTransactionEncoder(), getTransactionDecoder(lastValidBlockHeight));
|
|
719
982
|
}
|
|
983
|
+
var base58Decoder;
|
|
720
984
|
function getSignatureFromTransaction(transaction) {
|
|
985
|
+
if (!base58Decoder)
|
|
986
|
+
base58Decoder = getBase58Decoder();
|
|
721
987
|
const signatureBytes = transaction.signatures[transaction.feePayer];
|
|
722
988
|
if (!signatureBytes) {
|
|
723
989
|
throw new Error(
|
|
724
990
|
"Could not determine this transaction's signature. Make sure that the transaction has been signed by its fee payer."
|
|
725
991
|
);
|
|
726
992
|
}
|
|
727
|
-
const
|
|
728
|
-
return
|
|
993
|
+
const transactionSignature = base58Decoder.decode(signatureBytes)[0];
|
|
994
|
+
return transactionSignature;
|
|
729
995
|
}
|
|
730
|
-
async function
|
|
996
|
+
async function partiallySignTransaction(keyPairs, transaction) {
|
|
731
997
|
const compiledMessage = compileMessage(transaction);
|
|
732
998
|
const nextSignatures = "signatures" in transaction ? { ...transaction.signatures } : {};
|
|
999
|
+
const wireMessageBytes = getCompiledMessageEncoder().encode(compiledMessage);
|
|
733
1000
|
const publicKeySignaturePairs = await Promise.all(
|
|
734
1001
|
keyPairs.map(
|
|
735
|
-
(keyPair) => Promise.all([
|
|
736
|
-
getAddressFromPublicKey(keyPair.publicKey),
|
|
737
|
-
getCompiledMessageSignature(compiledMessage, keyPair.privateKey)
|
|
738
|
-
])
|
|
1002
|
+
(keyPair) => Promise.all([getAddressFromPublicKey(keyPair.publicKey), signBytes(keyPair.privateKey, wireMessageBytes)])
|
|
739
1003
|
)
|
|
740
1004
|
);
|
|
741
1005
|
for (const [signerPublicKey, signature] of publicKeySignaturePairs) {
|
|
@@ -748,17 +1012,26 @@ async function signTransaction(keyPairs, transaction) {
|
|
|
748
1012
|
Object.freeze(out);
|
|
749
1013
|
return out;
|
|
750
1014
|
}
|
|
751
|
-
function
|
|
752
|
-
|
|
753
|
-
|
|
1015
|
+
async function signTransaction(keyPairs, transaction) {
|
|
1016
|
+
const out = await partiallySignTransaction(keyPairs, transaction);
|
|
1017
|
+
assertTransactionIsFullySigned(out);
|
|
1018
|
+
Object.freeze(out);
|
|
1019
|
+
return out;
|
|
1020
|
+
}
|
|
1021
|
+
function assertTransactionIsFullySigned(transaction) {
|
|
1022
|
+
const signerAddressesFromInstructions = transaction.instructions.flatMap((i) => i.accounts?.filter((a) => isSignerRole(a.role)) ?? []).map((a) => a.address);
|
|
1023
|
+
const requiredSigners = /* @__PURE__ */ new Set([transaction.feePayer, ...signerAddressesFromInstructions]);
|
|
1024
|
+
requiredSigners.forEach((address) => {
|
|
1025
|
+
if (!transaction.signatures[address]) {
|
|
1026
|
+
throw new Error(`Transaction is missing signature for address \`${address}\``);
|
|
1027
|
+
}
|
|
1028
|
+
});
|
|
754
1029
|
}
|
|
755
|
-
|
|
756
|
-
// src/wire-transaction.ts
|
|
757
1030
|
function getBase64EncodedWireTransaction(transaction) {
|
|
758
1031
|
const wireTransactionBytes = getTransactionEncoder().encode(transaction);
|
|
759
|
-
|
|
760
|
-
return btoa(String.fromCharCode(...wireTransactionBytes));
|
|
761
|
-
}
|
|
1032
|
+
return getBase64Decoder().decode(wireTransactionBytes)[0];
|
|
762
1033
|
}
|
|
763
1034
|
|
|
764
|
-
export { appendTransactionInstruction, assertIsBlockhash, assertIsDurableNonceTransaction,
|
|
1035
|
+
export { appendTransactionInstruction, assertIsBlockhash, assertIsDurableNonceTransaction, assertTransactionIsFullySigned, createTransaction, getBase64EncodedWireTransaction, getSignatureFromTransaction, getTransactionCodec, getTransactionDecoder, getTransactionEncoder, isAdvanceNonceAccountInstruction, partiallySignTransaction, prependTransactionInstruction, setTransactionFeePayer, setTransactionLifetimeUsingBlockhash, setTransactionLifetimeUsingDurableNonce, signTransaction };
|
|
1036
|
+
//# sourceMappingURL=out.js.map
|
|
1037
|
+
//# sourceMappingURL=index.browser.js.map
|