@solana/transactions 2.0.0-experimental.7da1908 → 2.0.0-experimental.819422a
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/LICENSE +1 -1
- package/README.md +272 -5
- package/dist/index.browser.cjs +518 -285
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +510 -284
- package/dist/index.browser.js.map +1 -1
- package/dist/index.development.js +1103 -703
- package/dist/index.development.js.map +1 -1
- package/dist/index.native.js +510 -284
- package/dist/index.native.js.map +1 -1
- package/dist/index.node.cjs +520 -285
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +510 -284
- package/dist/index.node.js.map +1 -1
- package/dist/index.production.min.js +22 -15
- package/dist/types/accounts.d.ts +2 -2
- package/dist/types/accounts.d.ts.map +1 -1
- package/dist/types/blockhash.d.ts.map +1 -1
- package/dist/types/compilable-transaction.d.ts +7 -0
- package/dist/types/compilable-transaction.d.ts.map +1 -0
- package/dist/types/compile-address-table-lookups.d.ts +2 -2
- package/dist/types/compile-address-table-lookups.d.ts.map +1 -1
- package/dist/types/compile-static-accounts.d.ts +2 -2
- package/dist/types/compile-static-accounts.d.ts.map +1 -1
- package/dist/types/compile-transaction.d.ts +5 -6
- package/dist/types/compile-transaction.d.ts.map +1 -1
- package/dist/types/decompile-transaction.d.ts +5 -0
- package/dist/types/decompile-transaction.d.ts.map +1 -0
- package/dist/types/durable-nonce.d.ts +6 -6
- package/dist/types/durable-nonce.d.ts.map +1 -1
- package/dist/types/fee-payer.d.ts +4 -4
- package/dist/types/fee-payer.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/message.d.ts +1 -5
- package/dist/types/message.d.ts.map +1 -1
- package/dist/types/serializers/address-table-lookup.d.ts +5 -3
- package/dist/types/serializers/address-table-lookup.d.ts.map +1 -1
- package/dist/types/serializers/header.d.ts +4 -2
- package/dist/types/serializers/header.d.ts.map +1 -1
- package/dist/types/serializers/index.d.ts +3 -0
- package/dist/types/serializers/index.d.ts.map +1 -0
- package/dist/types/serializers/instruction.d.ts +4 -2
- package/dist/types/serializers/instruction.d.ts.map +1 -1
- package/dist/types/serializers/message.d.ts +4 -4
- package/dist/types/serializers/message.d.ts.map +1 -1
- package/dist/types/serializers/transaction-version.d.ts +4 -4
- package/dist/types/serializers/transaction-version.d.ts.map +1 -1
- package/dist/types/serializers/transaction.d.ts +6 -5
- package/dist/types/serializers/transaction.d.ts.map +1 -1
- package/dist/types/signatures.d.ts +8 -12
- package/dist/types/signatures.d.ts.map +1 -1
- package/dist/types/types.d.ts +6 -13
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/wire-transaction.d.ts +1 -1
- package/dist/types/wire-transaction.d.ts.map +1 -1
- package/package.json +18 -14
- package/dist/types/serializers/unimplemented.d.ts +0 -3
- package/dist/types/serializers/unimplemented.d.ts.map +0 -1
package/dist/index.node.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getAddressFromPublicKey,
|
|
1
|
+
import { getBase58Encoder, getBase58Decoder, getBase64Decoder, getStringEncoder, getStringDecoder } from '@solana/codecs-strings';
|
|
2
|
+
import { getAddressFromPublicKey, getAddressComparator, getAddressEncoder, getAddressDecoder, assertIsAddress } from '@solana/addresses';
|
|
3
|
+
import { mapDecoder, combineCodec, mapEncoder } from '@solana/codecs-core';
|
|
4
|
+
import { getStructDecoder, getStructEncoder, getArrayEncoder, getArrayDecoder, getBytesEncoder, getBytesDecoder } from '@solana/codecs-data-structures';
|
|
5
|
+
import { getShortU16Encoder, getShortU16Decoder, getU8Encoder, getU8Decoder } from '@solana/codecs-numbers';
|
|
6
|
+
import { pipe } from '@solana/functional';
|
|
3
7
|
import { signBytes } from '@solana/keys';
|
|
4
8
|
|
|
5
9
|
// ../build-scripts/env-shim.ts
|
|
@@ -20,7 +24,10 @@ function getUnsignedTransaction(transaction) {
|
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
// src/blockhash.ts
|
|
27
|
+
var base58Encoder;
|
|
23
28
|
function assertIsBlockhash(putativeBlockhash) {
|
|
29
|
+
if (!base58Encoder)
|
|
30
|
+
base58Encoder = getBase58Encoder();
|
|
24
31
|
try {
|
|
25
32
|
if (
|
|
26
33
|
// Lowest value (32 bytes of zeroes)
|
|
@@ -29,8 +36,8 @@ function assertIsBlockhash(putativeBlockhash) {
|
|
|
29
36
|
) {
|
|
30
37
|
throw new Error("Expected input string to decode to a byte array of length 32.");
|
|
31
38
|
}
|
|
32
|
-
const
|
|
33
|
-
const numBytes =
|
|
39
|
+
const bytes = base58Encoder.encode(putativeBlockhash);
|
|
40
|
+
const numBytes = bytes.byteLength;
|
|
34
41
|
if (numBytes !== 32) {
|
|
35
42
|
throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${numBytes}`);
|
|
36
43
|
}
|
|
@@ -115,7 +122,7 @@ function isAdvanceNonceAccountInstruction(instruction) {
|
|
|
115
122
|
instruction.accounts?.length === 3 && // First account is nonce account address
|
|
116
123
|
instruction.accounts[0].address != null && instruction.accounts[0].role === AccountRole.WRITABLE && // Second account is recent blockhashes sysvar
|
|
117
124
|
instruction.accounts[1].address === RECENT_BLOCKHASHES_SYSVAR_ADDRESS && instruction.accounts[1].role === AccountRole.READONLY && // Third account is nonce authority account
|
|
118
|
-
instruction.accounts[2].address != null && instruction.accounts[2].role
|
|
125
|
+
instruction.accounts[2].address != null && isSignerRole(instruction.accounts[2].role);
|
|
119
126
|
}
|
|
120
127
|
function isAdvanceNonceAccountInstructionData(data) {
|
|
121
128
|
return data.byteLength === 4 && data[0] === 4 && data[1] === 0 && data[2] === 0 && data[3] === 0;
|
|
@@ -123,21 +130,38 @@ function isAdvanceNonceAccountInstructionData(data) {
|
|
|
123
130
|
function isDurableNonceTransaction(transaction) {
|
|
124
131
|
return "lifetimeConstraint" in transaction && typeof transaction.lifetimeConstraint.nonce === "string" && transaction.instructions[0] != null && isAdvanceNonceAccountInstruction(transaction.instructions[0]);
|
|
125
132
|
}
|
|
133
|
+
function isAdvanceNonceAccountInstructionForNonce(instruction, nonceAccountAddress, nonceAuthorityAddress) {
|
|
134
|
+
return instruction.accounts[0].address === nonceAccountAddress && instruction.accounts[2].address === nonceAuthorityAddress;
|
|
135
|
+
}
|
|
126
136
|
function setTransactionLifetimeUsingDurableNonce({
|
|
127
137
|
nonce,
|
|
128
138
|
nonceAccountAddress,
|
|
129
139
|
nonceAuthorityAddress
|
|
130
140
|
}, transaction) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
+
];
|
|
134
161
|
}
|
|
135
162
|
const out = {
|
|
136
163
|
...getUnsignedTransaction(transaction),
|
|
137
|
-
instructions:
|
|
138
|
-
createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
|
|
139
|
-
...isAlreadyDurableNonceTransaction ? transaction.instructions.slice(1) : transaction.instructions
|
|
140
|
-
],
|
|
164
|
+
instructions: newInstructions,
|
|
141
165
|
lifetimeConstraint: {
|
|
142
166
|
nonce
|
|
143
167
|
}
|
|
@@ -228,7 +252,7 @@ function getAddressMapFromInstructions(feePayer, instructions) {
|
|
|
228
252
|
const shouldReplaceEntry = (
|
|
229
253
|
// Consider using the new LOOKUP_TABLE if its address is different...
|
|
230
254
|
entry.lookupTableAddress !== accountMeta.lookupTableAddress && // ...and sorts before the existing one.
|
|
231
|
-
(addressComparator
|
|
255
|
+
(addressComparator ||= getAddressComparator())(
|
|
232
256
|
accountMeta.lookupTableAddress,
|
|
233
257
|
entry.lookupTableAddress
|
|
234
258
|
) < 0
|
|
@@ -334,7 +358,7 @@ function getOrderedAccountsFromAddressMap(addressMap) {
|
|
|
334
358
|
if (leftIsWritable !== isWritableRole(rightEntry.role)) {
|
|
335
359
|
return leftIsWritable ? -1 : 1;
|
|
336
360
|
}
|
|
337
|
-
addressComparator
|
|
361
|
+
addressComparator ||= getAddressComparator();
|
|
338
362
|
if (leftEntry[TYPE] === 1 /* LOOKUP_TABLE */ && rightEntry[TYPE] === 1 /* LOOKUP_TABLE */ && leftEntry.lookupTableAddress !== rightEntry.lookupTableAddress) {
|
|
339
363
|
return addressComparator(leftEntry.lookupTableAddress, rightEntry.lookupTableAddress);
|
|
340
364
|
} else {
|
|
@@ -347,23 +371,22 @@ function getOrderedAccountsFromAddressMap(addressMap) {
|
|
|
347
371
|
return orderedAccounts;
|
|
348
372
|
}
|
|
349
373
|
function getCompiledAddressTableLookups(orderedAccounts) {
|
|
350
|
-
var _a;
|
|
351
374
|
const index = {};
|
|
352
375
|
for (const account of orderedAccounts) {
|
|
353
376
|
if (!("lookupTableAddress" in account)) {
|
|
354
377
|
continue;
|
|
355
378
|
}
|
|
356
|
-
const entry = index[
|
|
379
|
+
const entry = index[account.lookupTableAddress] ||= {
|
|
357
380
|
readableIndices: [],
|
|
358
381
|
writableIndices: []
|
|
359
|
-
}
|
|
382
|
+
};
|
|
360
383
|
if (account.role === AccountRole.WRITABLE) {
|
|
361
384
|
entry.writableIndices.push(account.addressIndex);
|
|
362
385
|
} else {
|
|
363
386
|
entry.readableIndices.push(account.addressIndex);
|
|
364
387
|
}
|
|
365
388
|
}
|
|
366
|
-
return Object.keys(index).sort(
|
|
389
|
+
return Object.keys(index).sort(getAddressComparator()).map((lookupTableAddress) => ({
|
|
367
390
|
lookupTableAddress,
|
|
368
391
|
...index[lookupTableAddress]
|
|
369
392
|
}));
|
|
@@ -442,151 +465,189 @@ function compileMessage(transaction) {
|
|
|
442
465
|
version: transaction.version
|
|
443
466
|
};
|
|
444
467
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
468
|
+
var lookupTableAddressDescription = __DEV__ ? "The address of the address lookup table account from which instruction addresses should be looked up" : "lookupTableAddress";
|
|
469
|
+
var writableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as writeable" : "writableIndices";
|
|
470
|
+
var readableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as read-only" : "readableIndices";
|
|
471
|
+
var addressTableLookupDescription = __DEV__ ? "A pointer to the address of an address lookup table, along with the readonly/writeable indices of the addresses that should be loaded from it" : "addressTableLookup";
|
|
472
|
+
var memoizedAddressTableLookupEncoder;
|
|
473
|
+
function getAddressTableLookupEncoder() {
|
|
474
|
+
if (!memoizedAddressTableLookupEncoder) {
|
|
475
|
+
memoizedAddressTableLookupEncoder = getStructEncoder(
|
|
448
476
|
[
|
|
449
|
-
"lookupTableAddress",
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
477
|
+
["lookupTableAddress", getAddressEncoder({ description: lookupTableAddressDescription })],
|
|
478
|
+
[
|
|
479
|
+
"writableIndices",
|
|
480
|
+
getArrayEncoder(getU8Encoder(), {
|
|
481
|
+
description: writableIndicesDescription,
|
|
482
|
+
size: getShortU16Encoder()
|
|
483
|
+
})
|
|
484
|
+
],
|
|
485
|
+
[
|
|
486
|
+
"readableIndices",
|
|
487
|
+
getArrayEncoder(getU8Encoder(), {
|
|
488
|
+
description: readableIndicesDescription,
|
|
489
|
+
size: getShortU16Encoder()
|
|
490
|
+
})
|
|
491
|
+
]
|
|
455
492
|
],
|
|
493
|
+
{ description: addressTableLookupDescription }
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
return memoizedAddressTableLookupEncoder;
|
|
497
|
+
}
|
|
498
|
+
var memoizedAddressTableLookupDecoder;
|
|
499
|
+
function getAddressTableLookupDecoder() {
|
|
500
|
+
if (!memoizedAddressTableLookupDecoder) {
|
|
501
|
+
memoizedAddressTableLookupDecoder = getStructDecoder(
|
|
456
502
|
[
|
|
457
|
-
"
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
503
|
+
["lookupTableAddress", getAddressDecoder({ description: lookupTableAddressDescription })],
|
|
504
|
+
[
|
|
505
|
+
"writableIndices",
|
|
506
|
+
getArrayDecoder(getU8Decoder(), {
|
|
507
|
+
description: writableIndicesDescription,
|
|
508
|
+
size: getShortU16Decoder()
|
|
509
|
+
})
|
|
510
|
+
],
|
|
511
|
+
[
|
|
512
|
+
"readableIndices",
|
|
513
|
+
getArrayDecoder(getU8Decoder(), {
|
|
514
|
+
description: readableIndicesDescription,
|
|
515
|
+
size: getShortU16Decoder()
|
|
516
|
+
})
|
|
517
|
+
]
|
|
464
518
|
],
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
519
|
+
{ description: addressTableLookupDescription }
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
return memoizedAddressTableLookupDecoder;
|
|
523
|
+
}
|
|
524
|
+
var memoizedU8Encoder;
|
|
525
|
+
function getMemoizedU8Encoder() {
|
|
526
|
+
if (!memoizedU8Encoder)
|
|
527
|
+
memoizedU8Encoder = getU8Encoder();
|
|
528
|
+
return memoizedU8Encoder;
|
|
529
|
+
}
|
|
530
|
+
function getMemoizedU8EncoderDescription(description) {
|
|
531
|
+
const encoder = getMemoizedU8Encoder();
|
|
532
|
+
return {
|
|
533
|
+
...encoder,
|
|
534
|
+
description: description ?? encoder.description
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
var memoizedU8Decoder;
|
|
538
|
+
function getMemoizedU8Decoder() {
|
|
539
|
+
if (!memoizedU8Decoder)
|
|
540
|
+
memoizedU8Decoder = getU8Decoder();
|
|
541
|
+
return memoizedU8Decoder;
|
|
542
|
+
}
|
|
543
|
+
function getMemoizedU8DecoderDescription(description) {
|
|
544
|
+
const decoder = getMemoizedU8Decoder();
|
|
545
|
+
return {
|
|
546
|
+
...decoder,
|
|
547
|
+
description: description ?? decoder.description
|
|
548
|
+
};
|
|
479
549
|
}
|
|
480
|
-
|
|
481
|
-
|
|
550
|
+
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;
|
|
551
|
+
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;
|
|
552
|
+
var numReadonlyNonSignerAccountsDescription = __DEV__ ? "The expected number of addresses in the static address list belonging to accounts that are neither signers, nor writable" : void 0;
|
|
553
|
+
var messageHeaderDescription = __DEV__ ? "The transaction message header containing counts of the signer, readonly-signer, and readonly-nonsigner account addresses" : void 0;
|
|
554
|
+
function getMessageHeaderEncoder() {
|
|
555
|
+
return getStructEncoder(
|
|
482
556
|
[
|
|
483
|
-
[
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
__DEV__ ? {
|
|
487
|
-
description: "The expected number of addresses in the static address list belonging to accounts that are required to sign this transaction"
|
|
488
|
-
} : void 0
|
|
489
|
-
)
|
|
490
|
-
],
|
|
491
|
-
[
|
|
492
|
-
"numReadonlySignerAccounts",
|
|
493
|
-
u8(
|
|
494
|
-
__DEV__ ? {
|
|
495
|
-
description: "The expected number of addresses in the static address list belonging to accounts that are required to sign this transaction, but may not be writable"
|
|
496
|
-
} : void 0
|
|
497
|
-
)
|
|
498
|
-
],
|
|
499
|
-
[
|
|
500
|
-
"numReadonlyNonSignerAccounts",
|
|
501
|
-
u8(
|
|
502
|
-
__DEV__ ? {
|
|
503
|
-
description: "The expected number of addresses in the static address list belonging to accounts that are neither signers, nor writable"
|
|
504
|
-
} : void 0
|
|
505
|
-
)
|
|
506
|
-
]
|
|
557
|
+
["numSignerAccounts", getMemoizedU8EncoderDescription(numSignerAccountsDescription)],
|
|
558
|
+
["numReadonlySignerAccounts", getMemoizedU8EncoderDescription(numReadonlySignerAccountsDescription)],
|
|
559
|
+
["numReadonlyNonSignerAccounts", getMemoizedU8EncoderDescription(numReadonlyNonSignerAccountsDescription)]
|
|
507
560
|
],
|
|
508
|
-
|
|
509
|
-
description:
|
|
510
|
-
}
|
|
561
|
+
{
|
|
562
|
+
description: messageHeaderDescription
|
|
563
|
+
}
|
|
511
564
|
);
|
|
512
565
|
}
|
|
513
|
-
function
|
|
514
|
-
return
|
|
515
|
-
|
|
516
|
-
[
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
)
|
|
523
|
-
],
|
|
524
|
-
[
|
|
525
|
-
"accountIndices",
|
|
526
|
-
array(
|
|
527
|
-
u8({
|
|
528
|
-
description: __DEV__ ? "The index of an account, according to the well-ordered accounts list for this transaction" : ""
|
|
529
|
-
}),
|
|
530
|
-
{
|
|
531
|
-
description: __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" : "",
|
|
532
|
-
size: shortU16()
|
|
533
|
-
}
|
|
534
|
-
)
|
|
535
|
-
],
|
|
536
|
-
[
|
|
537
|
-
"data",
|
|
538
|
-
bytes({
|
|
539
|
-
description: __DEV__ ? "An optional buffer of data passed to the instruction" : "",
|
|
540
|
-
size: shortU16()
|
|
541
|
-
})
|
|
542
|
-
]
|
|
543
|
-
]),
|
|
544
|
-
(value) => {
|
|
545
|
-
if (value.accountIndices !== void 0 && value.data !== void 0) {
|
|
546
|
-
return value;
|
|
547
|
-
}
|
|
548
|
-
return {
|
|
549
|
-
...value,
|
|
550
|
-
accountIndices: value.accountIndices ?? [],
|
|
551
|
-
data: value.data ?? new Uint8Array(0)
|
|
552
|
-
};
|
|
553
|
-
},
|
|
554
|
-
(value) => {
|
|
555
|
-
if (value.accountIndices.length && value.data.byteLength) {
|
|
556
|
-
return value;
|
|
557
|
-
}
|
|
558
|
-
const { accountIndices, data, ...rest } = value;
|
|
559
|
-
return {
|
|
560
|
-
...rest,
|
|
561
|
-
...accountIndices.length ? { accountIndices } : null,
|
|
562
|
-
...data.byteLength ? { data } : null
|
|
563
|
-
};
|
|
566
|
+
function getMessageHeaderDecoder() {
|
|
567
|
+
return getStructDecoder(
|
|
568
|
+
[
|
|
569
|
+
["numSignerAccounts", getMemoizedU8DecoderDescription(numSignerAccountsDescription)],
|
|
570
|
+
["numReadonlySignerAccounts", getMemoizedU8DecoderDescription(numReadonlySignerAccountsDescription)],
|
|
571
|
+
["numReadonlyNonSignerAccounts", getMemoizedU8DecoderDescription(numReadonlyNonSignerAccountsDescription)]
|
|
572
|
+
],
|
|
573
|
+
{
|
|
574
|
+
description: messageHeaderDescription
|
|
564
575
|
}
|
|
565
576
|
);
|
|
566
577
|
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
)
|
|
578
|
+
var programAddressIndexDescription = __DEV__ ? "The index of the program being called, according to the well-ordered accounts list for this transaction" : "programAddressIndex";
|
|
579
|
+
var accountIndexDescription = __DEV__ ? "The index of an account, according to the well-ordered accounts list for this transaction" : void 0;
|
|
580
|
+
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";
|
|
581
|
+
var dataDescription = __DEV__ ? "An optional buffer of data passed to the instruction" : "data";
|
|
582
|
+
var memoizedGetInstructionEncoder;
|
|
583
|
+
function getInstructionEncoder() {
|
|
584
|
+
if (!memoizedGetInstructionEncoder) {
|
|
585
|
+
memoizedGetInstructionEncoder = mapEncoder(
|
|
586
|
+
getStructEncoder([
|
|
587
|
+
["programAddressIndex", getU8Encoder({ description: programAddressIndexDescription })],
|
|
588
|
+
[
|
|
589
|
+
"accountIndices",
|
|
590
|
+
getArrayEncoder(getU8Encoder({ description: accountIndexDescription }), {
|
|
591
|
+
description: accountIndicesDescription,
|
|
592
|
+
size: getShortU16Encoder()
|
|
593
|
+
})
|
|
594
|
+
],
|
|
595
|
+
["data", getBytesEncoder({ description: dataDescription, size: getShortU16Encoder() })]
|
|
596
|
+
]),
|
|
597
|
+
// Convert an instruction to have all fields defined
|
|
598
|
+
(instruction) => {
|
|
599
|
+
if (instruction.accountIndices !== void 0 && instruction.data !== void 0) {
|
|
600
|
+
return instruction;
|
|
601
|
+
}
|
|
602
|
+
return {
|
|
603
|
+
...instruction,
|
|
604
|
+
accountIndices: instruction.accountIndices ?? [],
|
|
605
|
+
data: instruction.data ?? new Uint8Array(0)
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
return memoizedGetInstructionEncoder;
|
|
574
611
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
612
|
+
var memoizedGetInstructionDecoder;
|
|
613
|
+
function getInstructionDecoder() {
|
|
614
|
+
if (!memoizedGetInstructionDecoder) {
|
|
615
|
+
memoizedGetInstructionDecoder = mapDecoder(
|
|
616
|
+
getStructDecoder([
|
|
617
|
+
["programAddressIndex", getU8Decoder({ description: programAddressIndexDescription })],
|
|
618
|
+
[
|
|
619
|
+
"accountIndices",
|
|
620
|
+
getArrayDecoder(getU8Decoder({ description: accountIndexDescription }), {
|
|
621
|
+
description: accountIndicesDescription,
|
|
622
|
+
size: getShortU16Decoder()
|
|
623
|
+
})
|
|
624
|
+
],
|
|
625
|
+
["data", getBytesDecoder({ description: dataDescription, size: getShortU16Decoder() })]
|
|
626
|
+
]),
|
|
627
|
+
// Convert an instruction to exclude optional fields if they are empty
|
|
628
|
+
(instruction) => {
|
|
629
|
+
if (instruction.accountIndices.length && instruction.data.byteLength) {
|
|
630
|
+
return instruction;
|
|
631
|
+
}
|
|
632
|
+
const { accountIndices, data, ...rest } = instruction;
|
|
633
|
+
return {
|
|
634
|
+
...rest,
|
|
635
|
+
...accountIndices.length ? { accountIndices } : null,
|
|
636
|
+
...data.byteLength ? { data } : null
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
return memoizedGetInstructionDecoder;
|
|
579
642
|
}
|
|
580
|
-
|
|
581
|
-
// src/serializers/transaction-version.ts
|
|
582
643
|
var VERSION_FLAG_MASK = 128;
|
|
583
644
|
var BASE_CONFIG = {
|
|
584
645
|
description: __DEV__ ? "A single byte that encodes the version of the transaction" : "",
|
|
585
646
|
fixedSize: null,
|
|
586
647
|
maxSize: 1
|
|
587
648
|
};
|
|
588
|
-
function
|
|
589
|
-
const firstByte =
|
|
649
|
+
function decode(bytes, offset = 0) {
|
|
650
|
+
const firstByte = bytes[offset];
|
|
590
651
|
if ((firstByte & VERSION_FLAG_MASK) === 0) {
|
|
591
652
|
return ["legacy", offset];
|
|
592
653
|
} else {
|
|
@@ -594,7 +655,7 @@ function deserialize(bytes3, offset = 0) {
|
|
|
594
655
|
return [version, offset + 1];
|
|
595
656
|
}
|
|
596
657
|
}
|
|
597
|
-
function
|
|
658
|
+
function encode(value) {
|
|
598
659
|
if (value === "legacy") {
|
|
599
660
|
return new Uint8Array();
|
|
600
661
|
}
|
|
@@ -603,142 +664,345 @@ function serialize(value) {
|
|
|
603
664
|
}
|
|
604
665
|
return new Uint8Array([value | VERSION_FLAG_MASK]);
|
|
605
666
|
}
|
|
606
|
-
function
|
|
667
|
+
function getTransactionVersionDecoder() {
|
|
668
|
+
return {
|
|
669
|
+
...BASE_CONFIG,
|
|
670
|
+
decode
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
function getTransactionVersionEncoder() {
|
|
607
674
|
return {
|
|
608
675
|
...BASE_CONFIG,
|
|
609
|
-
|
|
610
|
-
serialize
|
|
676
|
+
encode
|
|
611
677
|
};
|
|
612
678
|
}
|
|
613
679
|
|
|
614
680
|
// src/serializers/message.ts
|
|
615
|
-
var
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
(value)
|
|
630
|
-
|
|
631
|
-
return value;
|
|
632
|
-
}
|
|
633
|
-
return {
|
|
634
|
-
...value,
|
|
635
|
-
addressTableLookups: value.addressTableLookups ?? []
|
|
636
|
-
};
|
|
681
|
+
var staticAccountsDescription = __DEV__ ? "A compact-array of static account addresses belonging to this transaction" : "staticAccounts";
|
|
682
|
+
var lifetimeTokenDescription = __DEV__ ? "A 32-byte token that specifies the lifetime of this transaction (eg. a recent blockhash, or a durable nonce)" : "lifetimeToken";
|
|
683
|
+
var instructionsDescription = __DEV__ ? "A compact-array of instructions belonging to this transaction" : "instructions";
|
|
684
|
+
var addressTableLookupsDescription = __DEV__ ? "A compact array of address table lookups belonging to this transaction" : "addressTableLookups";
|
|
685
|
+
function getCompiledMessageLegacyEncoder() {
|
|
686
|
+
return getStructEncoder(getPreludeStructEncoderTuple());
|
|
687
|
+
}
|
|
688
|
+
function getCompiledMessageVersionedEncoder() {
|
|
689
|
+
return mapEncoder(
|
|
690
|
+
getStructEncoder([
|
|
691
|
+
...getPreludeStructEncoderTuple(),
|
|
692
|
+
["addressTableLookups", getAddressTableLookupArrayEncoder()]
|
|
693
|
+
]),
|
|
694
|
+
(value) => {
|
|
695
|
+
if (value.version === "legacy") {
|
|
696
|
+
return value;
|
|
637
697
|
}
|
|
638
|
-
|
|
639
|
-
|
|
698
|
+
return {
|
|
699
|
+
...value,
|
|
700
|
+
addressTableLookups: value.addressTableLookups ?? []
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
);
|
|
640
704
|
}
|
|
641
|
-
function
|
|
705
|
+
function getPreludeStructEncoderTuple() {
|
|
642
706
|
return [
|
|
643
|
-
["version",
|
|
644
|
-
["header",
|
|
707
|
+
["version", getTransactionVersionEncoder()],
|
|
708
|
+
["header", getMessageHeaderEncoder()],
|
|
645
709
|
[
|
|
646
710
|
"staticAccounts",
|
|
647
|
-
|
|
648
|
-
description:
|
|
649
|
-
size:
|
|
711
|
+
getArrayEncoder(getAddressEncoder(), {
|
|
712
|
+
description: staticAccountsDescription,
|
|
713
|
+
size: getShortU16Encoder()
|
|
650
714
|
})
|
|
651
715
|
],
|
|
652
716
|
[
|
|
653
717
|
"lifetimeToken",
|
|
654
|
-
|
|
655
|
-
description:
|
|
656
|
-
encoding:
|
|
718
|
+
getStringEncoder({
|
|
719
|
+
description: lifetimeTokenDescription,
|
|
720
|
+
encoding: getBase58Encoder(),
|
|
657
721
|
size: 32
|
|
658
722
|
})
|
|
659
723
|
],
|
|
660
724
|
[
|
|
661
725
|
"instructions",
|
|
662
|
-
|
|
663
|
-
description:
|
|
664
|
-
size:
|
|
726
|
+
getArrayEncoder(getInstructionEncoder(), {
|
|
727
|
+
description: instructionsDescription,
|
|
728
|
+
size: getShortU16Encoder()
|
|
665
729
|
})
|
|
666
730
|
]
|
|
667
731
|
];
|
|
668
732
|
}
|
|
669
|
-
function
|
|
670
|
-
return
|
|
671
|
-
|
|
672
|
-
|
|
733
|
+
function getPreludeStructDecoderTuple() {
|
|
734
|
+
return [
|
|
735
|
+
["version", getTransactionVersionDecoder()],
|
|
736
|
+
["header", getMessageHeaderDecoder()],
|
|
737
|
+
[
|
|
738
|
+
"staticAccounts",
|
|
739
|
+
getArrayDecoder(getAddressDecoder(), {
|
|
740
|
+
description: staticAccountsDescription,
|
|
741
|
+
size: getShortU16Decoder()
|
|
742
|
+
})
|
|
743
|
+
],
|
|
744
|
+
[
|
|
745
|
+
"lifetimeToken",
|
|
746
|
+
getStringDecoder({
|
|
747
|
+
description: lifetimeTokenDescription,
|
|
748
|
+
encoding: getBase58Decoder(),
|
|
749
|
+
size: 32
|
|
750
|
+
})
|
|
751
|
+
],
|
|
752
|
+
[
|
|
753
|
+
"instructions",
|
|
754
|
+
getArrayDecoder(getInstructionDecoder(), {
|
|
755
|
+
description: instructionsDescription,
|
|
756
|
+
size: getShortU16Decoder()
|
|
757
|
+
})
|
|
758
|
+
],
|
|
759
|
+
["addressTableLookups", getAddressTableLookupArrayDecoder()]
|
|
760
|
+
];
|
|
761
|
+
}
|
|
762
|
+
function getAddressTableLookupArrayEncoder() {
|
|
763
|
+
return getArrayEncoder(getAddressTableLookupEncoder(), {
|
|
764
|
+
description: addressTableLookupsDescription,
|
|
765
|
+
size: getShortU16Encoder()
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
function getAddressTableLookupArrayDecoder() {
|
|
769
|
+
return getArrayDecoder(getAddressTableLookupDecoder(), {
|
|
770
|
+
description: addressTableLookupsDescription,
|
|
771
|
+
size: getShortU16Decoder()
|
|
673
772
|
});
|
|
674
773
|
}
|
|
774
|
+
var messageDescription = __DEV__ ? "The wire format of a Solana transaction message" : "message";
|
|
675
775
|
function getCompiledMessageEncoder() {
|
|
676
776
|
return {
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
777
|
+
description: messageDescription,
|
|
778
|
+
encode: (compiledMessage) => {
|
|
779
|
+
if (compiledMessage.version === "legacy") {
|
|
780
|
+
return getCompiledMessageLegacyEncoder().encode(compiledMessage);
|
|
781
|
+
} else {
|
|
782
|
+
return getCompiledMessageVersionedEncoder().encode(compiledMessage);
|
|
783
|
+
}
|
|
784
|
+
},
|
|
785
|
+
fixedSize: null,
|
|
786
|
+
maxSize: null
|
|
680
787
|
};
|
|
681
788
|
}
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
789
|
+
function getCompiledMessageDecoder() {
|
|
790
|
+
return mapDecoder(
|
|
791
|
+
getStructDecoder(getPreludeStructDecoderTuple(), {
|
|
792
|
+
description: messageDescription
|
|
793
|
+
}),
|
|
794
|
+
({ addressTableLookups, ...restOfMessage }) => {
|
|
795
|
+
if (restOfMessage.version === "legacy" || !addressTableLookups?.length) {
|
|
796
|
+
return restOfMessage;
|
|
797
|
+
}
|
|
798
|
+
return { ...restOfMessage, addressTableLookups };
|
|
692
799
|
}
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
function getCompiledMessageCodec() {
|
|
803
|
+
return combineCodec(getCompiledMessageEncoder(), getCompiledMessageDecoder());
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// src/compile-transaction.ts
|
|
807
|
+
function getCompiledTransaction(transaction) {
|
|
808
|
+
const compiledMessage = compileMessage(transaction);
|
|
809
|
+
let signatures;
|
|
810
|
+
if ("signatures" in transaction) {
|
|
811
|
+
signatures = [];
|
|
812
|
+
for (let ii = 0; ii < compiledMessage.header.numSignerAccounts; ii++) {
|
|
813
|
+
signatures[ii] = transaction.signatures[compiledMessage.staticAccounts[ii]] ?? new Uint8Array(Array(64).fill(0));
|
|
697
814
|
}
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
|
|
815
|
+
} else {
|
|
816
|
+
signatures = Array(compiledMessage.header.numSignerAccounts).fill(new Uint8Array(Array(64).fill(0)));
|
|
817
|
+
}
|
|
818
|
+
return {
|
|
819
|
+
compiledMessage,
|
|
820
|
+
signatures
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
function getAccountMetas(message) {
|
|
824
|
+
const { header } = message;
|
|
825
|
+
const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
|
|
826
|
+
const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
|
|
827
|
+
const accountMetas = [];
|
|
828
|
+
let accountIndex = 0;
|
|
829
|
+
for (let i = 0; i < numWritableSignerAccounts; i++) {
|
|
830
|
+
accountMetas.push({
|
|
831
|
+
address: message.staticAccounts[accountIndex],
|
|
832
|
+
role: AccountRole.WRITABLE_SIGNER
|
|
833
|
+
});
|
|
834
|
+
accountIndex++;
|
|
835
|
+
}
|
|
836
|
+
for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
|
|
837
|
+
accountMetas.push({
|
|
838
|
+
address: message.staticAccounts[accountIndex],
|
|
839
|
+
role: AccountRole.READONLY_SIGNER
|
|
840
|
+
});
|
|
841
|
+
accountIndex++;
|
|
842
|
+
}
|
|
843
|
+
for (let i = 0; i < numWritableNonSignerAccounts; i++) {
|
|
844
|
+
accountMetas.push({
|
|
845
|
+
address: message.staticAccounts[accountIndex],
|
|
846
|
+
role: AccountRole.WRITABLE
|
|
847
|
+
});
|
|
848
|
+
accountIndex++;
|
|
849
|
+
}
|
|
850
|
+
for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
|
|
851
|
+
accountMetas.push({
|
|
852
|
+
address: message.staticAccounts[accountIndex],
|
|
853
|
+
role: AccountRole.READONLY
|
|
701
854
|
});
|
|
855
|
+
accountIndex++;
|
|
702
856
|
}
|
|
857
|
+
return accountMetas;
|
|
703
858
|
}
|
|
704
|
-
function
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
putativeTransactionSignature.length > 88
|
|
709
|
-
) {
|
|
710
|
-
return false;
|
|
859
|
+
function convertInstruction(instruction, accountMetas) {
|
|
860
|
+
const programAddress = accountMetas[instruction.programAddressIndex]?.address;
|
|
861
|
+
if (!programAddress) {
|
|
862
|
+
throw new Error(`Could not find program address at index ${instruction.programAddressIndex}`);
|
|
711
863
|
}
|
|
712
|
-
const
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
-
|
|
864
|
+
const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
|
|
865
|
+
const { data } = instruction;
|
|
866
|
+
return {
|
|
867
|
+
programAddress,
|
|
868
|
+
...accounts && accounts.length ? { accounts } : {},
|
|
869
|
+
...data && data.length ? { data } : {}
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
|
|
873
|
+
if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
|
|
874
|
+
return {
|
|
875
|
+
blockhash: messageLifetimeToken,
|
|
876
|
+
lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
|
|
877
|
+
// U64 MAX
|
|
878
|
+
};
|
|
879
|
+
} else {
|
|
880
|
+
const nonceAccountAddress = firstInstruction.accounts[0].address;
|
|
881
|
+
assertIsAddress(nonceAccountAddress);
|
|
882
|
+
const nonceAuthorityAddress = firstInstruction.accounts[2].address;
|
|
883
|
+
assertIsAddress(nonceAuthorityAddress);
|
|
884
|
+
return {
|
|
885
|
+
nonce: messageLifetimeToken,
|
|
886
|
+
nonceAccountAddress,
|
|
887
|
+
nonceAuthorityAddress
|
|
888
|
+
};
|
|
716
889
|
}
|
|
717
|
-
return true;
|
|
718
890
|
}
|
|
719
|
-
|
|
720
|
-
const
|
|
721
|
-
|
|
722
|
-
|
|
891
|
+
function convertSignatures(compiledTransaction) {
|
|
892
|
+
const {
|
|
893
|
+
compiledMessage: { staticAccounts },
|
|
894
|
+
signatures
|
|
895
|
+
} = compiledTransaction;
|
|
896
|
+
return signatures.reduce((acc, sig, index) => {
|
|
897
|
+
const allZeros = sig.every((byte) => byte === 0);
|
|
898
|
+
if (allZeros)
|
|
899
|
+
return acc;
|
|
900
|
+
const address = staticAccounts[index];
|
|
901
|
+
return { ...acc, [address]: sig };
|
|
902
|
+
}, {});
|
|
903
|
+
}
|
|
904
|
+
function decompileTransaction(compiledTransaction, lastValidBlockHeight) {
|
|
905
|
+
const { compiledMessage } = compiledTransaction;
|
|
906
|
+
if ("addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups.length > 0) {
|
|
907
|
+
throw new Error("Cannot convert transaction with addressTableLookups");
|
|
908
|
+
}
|
|
909
|
+
const feePayer = compiledMessage.staticAccounts[0];
|
|
910
|
+
if (!feePayer)
|
|
911
|
+
throw new Error("No fee payer set in CompiledTransaction");
|
|
912
|
+
const accountMetas = getAccountMetas(compiledMessage);
|
|
913
|
+
const instructions = compiledMessage.instructions.map(
|
|
914
|
+
(compiledInstruction) => convertInstruction(compiledInstruction, accountMetas)
|
|
915
|
+
);
|
|
916
|
+
const firstInstruction = instructions[0];
|
|
917
|
+
const lifetimeConstraint = getLifetimeConstraint(
|
|
918
|
+
compiledMessage.lifetimeToken,
|
|
919
|
+
firstInstruction,
|
|
920
|
+
lastValidBlockHeight
|
|
921
|
+
);
|
|
922
|
+
const signatures = convertSignatures(compiledTransaction);
|
|
923
|
+
return pipe(
|
|
924
|
+
createTransaction({ version: compiledMessage.version }),
|
|
925
|
+
(tx) => setTransactionFeePayer(feePayer, tx),
|
|
926
|
+
(tx) => instructions.reduce((acc, instruction) => {
|
|
927
|
+
return appendTransactionInstruction(instruction, acc);
|
|
928
|
+
}, tx),
|
|
929
|
+
(tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
|
|
930
|
+
(tx) => compiledTransaction.signatures.length ? { ...tx, signatures } : tx
|
|
931
|
+
);
|
|
723
932
|
}
|
|
933
|
+
|
|
934
|
+
// src/serializers/transaction.ts
|
|
935
|
+
var signaturesDescription = __DEV__ ? "A compact array of 64-byte, base-64 encoded Ed25519 signatures" : "signatures";
|
|
936
|
+
var transactionDescription = __DEV__ ? "The wire format of a Solana transaction" : "transaction";
|
|
937
|
+
function getCompiledTransactionEncoder() {
|
|
938
|
+
return getStructEncoder(
|
|
939
|
+
[
|
|
940
|
+
[
|
|
941
|
+
"signatures",
|
|
942
|
+
getArrayEncoder(getBytesEncoder({ size: 64 }), {
|
|
943
|
+
description: signaturesDescription,
|
|
944
|
+
size: getShortU16Encoder()
|
|
945
|
+
})
|
|
946
|
+
],
|
|
947
|
+
["compiledMessage", getCompiledMessageEncoder()]
|
|
948
|
+
],
|
|
949
|
+
{
|
|
950
|
+
description: transactionDescription
|
|
951
|
+
}
|
|
952
|
+
);
|
|
953
|
+
}
|
|
954
|
+
function getSignatureDecoder() {
|
|
955
|
+
return mapDecoder(getBytesDecoder({ size: 64 }), (bytes) => bytes);
|
|
956
|
+
}
|
|
957
|
+
function getCompiledTransactionDecoder() {
|
|
958
|
+
return getStructDecoder(
|
|
959
|
+
[
|
|
960
|
+
[
|
|
961
|
+
"signatures",
|
|
962
|
+
getArrayDecoder(getSignatureDecoder(), {
|
|
963
|
+
description: signaturesDescription,
|
|
964
|
+
size: getShortU16Decoder()
|
|
965
|
+
})
|
|
966
|
+
],
|
|
967
|
+
["compiledMessage", getCompiledMessageDecoder()]
|
|
968
|
+
],
|
|
969
|
+
{
|
|
970
|
+
description: transactionDescription
|
|
971
|
+
}
|
|
972
|
+
);
|
|
973
|
+
}
|
|
974
|
+
function getTransactionEncoder() {
|
|
975
|
+
return mapEncoder(getCompiledTransactionEncoder(), getCompiledTransaction);
|
|
976
|
+
}
|
|
977
|
+
function getTransactionDecoder(lastValidBlockHeight) {
|
|
978
|
+
return mapDecoder(
|
|
979
|
+
getCompiledTransactionDecoder(),
|
|
980
|
+
(compiledTransaction) => decompileTransaction(compiledTransaction, lastValidBlockHeight)
|
|
981
|
+
);
|
|
982
|
+
}
|
|
983
|
+
function getTransactionCodec(lastValidBlockHeight) {
|
|
984
|
+
return combineCodec(getTransactionEncoder(), getTransactionDecoder(lastValidBlockHeight));
|
|
985
|
+
}
|
|
986
|
+
var base58Decoder;
|
|
724
987
|
function getSignatureFromTransaction(transaction) {
|
|
725
|
-
|
|
726
|
-
|
|
988
|
+
if (!base58Decoder)
|
|
989
|
+
base58Decoder = getBase58Decoder();
|
|
990
|
+
const signatureBytes = transaction.signatures[transaction.feePayer];
|
|
991
|
+
if (!signatureBytes) {
|
|
727
992
|
throw new Error(
|
|
728
993
|
"Could not determine this transaction's signature. Make sure that the transaction has been signed by its fee payer."
|
|
729
994
|
);
|
|
730
995
|
}
|
|
731
|
-
|
|
996
|
+
const transactionSignature = base58Decoder.decode(signatureBytes)[0];
|
|
997
|
+
return transactionSignature;
|
|
732
998
|
}
|
|
733
|
-
async function
|
|
999
|
+
async function partiallySignTransaction(keyPairs, transaction) {
|
|
734
1000
|
const compiledMessage = compileMessage(transaction);
|
|
735
1001
|
const nextSignatures = "signatures" in transaction ? { ...transaction.signatures } : {};
|
|
1002
|
+
const wireMessageBytes = getCompiledMessageEncoder().encode(compiledMessage);
|
|
736
1003
|
const publicKeySignaturePairs = await Promise.all(
|
|
737
1004
|
keyPairs.map(
|
|
738
|
-
(keyPair) => Promise.all([
|
|
739
|
-
getAddressFromPublicKey(keyPair.publicKey),
|
|
740
|
-
getCompiledMessageSignature(compiledMessage, keyPair.privateKey)
|
|
741
|
-
])
|
|
1005
|
+
(keyPair) => Promise.all([getAddressFromPublicKey(keyPair.publicKey), signBytes(keyPair.privateKey, wireMessageBytes)])
|
|
742
1006
|
)
|
|
743
1007
|
);
|
|
744
1008
|
for (const [signerPublicKey, signature] of publicKeySignaturePairs) {
|
|
@@ -751,62 +1015,24 @@ async function signTransaction(keyPairs, transaction) {
|
|
|
751
1015
|
Object.freeze(out);
|
|
752
1016
|
return out;
|
|
753
1017
|
}
|
|
754
|
-
function
|
|
755
|
-
|
|
756
|
-
|
|
1018
|
+
async function signTransaction(keyPairs, transaction) {
|
|
1019
|
+
const out = await partiallySignTransaction(keyPairs, transaction);
|
|
1020
|
+
assertTransactionIsFullySigned(out);
|
|
1021
|
+
Object.freeze(out);
|
|
1022
|
+
return out;
|
|
757
1023
|
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
signatures = [];
|
|
765
|
-
for (let ii = 0; ii < compiledMessage.header.numSignerAccounts; ii++) {
|
|
766
|
-
signatures[ii] = transaction.signatures[compiledMessage.staticAccounts[ii]] ?? new Uint8Array(Array(64).fill(0));
|
|
1024
|
+
function assertTransactionIsFullySigned(transaction) {
|
|
1025
|
+
const signerAddressesFromInstructions = transaction.instructions.flatMap((i) => i.accounts?.filter((a) => isSignerRole(a.role)) ?? []).map((a) => a.address);
|
|
1026
|
+
const requiredSigners = /* @__PURE__ */ new Set([transaction.feePayer, ...signerAddressesFromInstructions]);
|
|
1027
|
+
requiredSigners.forEach((address) => {
|
|
1028
|
+
if (!transaction.signatures[address]) {
|
|
1029
|
+
throw new Error(`Transaction is missing signature for address \`${address}\``);
|
|
767
1030
|
}
|
|
768
|
-
}
|
|
769
|
-
signatures = Array(compiledMessage.header.numSignerAccounts).fill(new Uint8Array(Array(64).fill(0)));
|
|
770
|
-
}
|
|
771
|
-
return {
|
|
772
|
-
compiledMessage,
|
|
773
|
-
signatures
|
|
774
|
-
};
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
// src/serializers/transaction.ts
|
|
778
|
-
var BASE_CONFIG3 = {
|
|
779
|
-
description: __DEV__ ? "The wire format of a Solana transaction" : "",
|
|
780
|
-
fixedSize: null,
|
|
781
|
-
maxSize: null
|
|
782
|
-
};
|
|
783
|
-
function serialize3(transaction) {
|
|
784
|
-
const compiledTransaction = getCompiledTransaction(transaction);
|
|
785
|
-
return struct([
|
|
786
|
-
[
|
|
787
|
-
"signatures",
|
|
788
|
-
array(bytes({ size: 64 }), {
|
|
789
|
-
...__DEV__ ? { description: "A compact array of 64-byte, base-64 encoded Ed25519 signatures" } : null,
|
|
790
|
-
size: shortU16()
|
|
791
|
-
})
|
|
792
|
-
],
|
|
793
|
-
["compiledMessage", getCompiledMessageEncoder()]
|
|
794
|
-
]).serialize(compiledTransaction);
|
|
795
|
-
}
|
|
796
|
-
function getTransactionEncoder() {
|
|
797
|
-
return {
|
|
798
|
-
...BASE_CONFIG3,
|
|
799
|
-
deserialize: getUnimplementedDecoder("CompiledMessage"),
|
|
800
|
-
serialize: serialize3
|
|
801
|
-
};
|
|
1031
|
+
});
|
|
802
1032
|
}
|
|
803
|
-
|
|
804
|
-
// src/wire-transaction.ts
|
|
805
1033
|
function getBase64EncodedWireTransaction(transaction) {
|
|
806
|
-
const wireTransactionBytes = getTransactionEncoder().
|
|
807
|
-
|
|
808
|
-
return Buffer.from(wireTransactionBytes).toString("base64");
|
|
809
|
-
}
|
|
1034
|
+
const wireTransactionBytes = getTransactionEncoder().encode(transaction);
|
|
1035
|
+
return getBase64Decoder().decode(wireTransactionBytes)[0];
|
|
810
1036
|
}
|
|
811
1037
|
|
|
812
|
-
export { appendTransactionInstruction, assertIsBlockhash, assertIsDurableNonceTransaction,
|
|
1038
|
+
export { appendTransactionInstruction, assertIsBlockhash, assertIsDurableNonceTransaction, assertTransactionIsFullySigned, compileMessage, createTransaction, getBase64EncodedWireTransaction, getCompiledMessageCodec, getCompiledMessageDecoder, getCompiledMessageEncoder, getSignatureFromTransaction, getTransactionCodec, getTransactionDecoder, getTransactionEncoder, isAdvanceNonceAccountInstruction, partiallySignTransaction, prependTransactionInstruction, setTransactionFeePayer, setTransactionLifetimeUsingBlockhash, setTransactionLifetimeUsingDurableNonce, signTransaction };
|