@solana/transactions 2.0.0-experimental.76cf6b4 → 2.0.0-experimental.7712fc3
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 +7 -3
- package/dist/index.browser.cjs +221 -156
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +221 -160
- package/dist/index.browser.js.map +1 -1
- package/dist/index.native.js +223 -160
- package/dist/index.native.js.map +1 -1
- package/dist/index.node.cjs +221 -156
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +223 -160
- package/dist/index.node.js.map +1 -1
- package/dist/types/accounts.d.ts.map +1 -1
- package/dist/types/blockhash.d.ts +1 -4
- package/dist/types/blockhash.d.ts.map +1 -1
- package/dist/types/decompile-transaction.d.ts +9 -1
- package/dist/types/decompile-transaction.d.ts.map +1 -1
- package/dist/types/durable-nonce.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/instructions.d.ts +2 -0
- package/dist/types/instructions.d.ts.map +1 -1
- package/dist/types/serializers/message.d.ts.map +1 -1
- package/dist/types/serializers/transaction-version.d.ts.map +1 -1
- package/dist/types/serializers/transaction.d.ts +5 -2
- package/dist/types/serializers/transaction.d.ts.map +1 -1
- package/dist/types/signatures.d.ts.map +1 -1
- package/package.json +18 -39
- package/dist/index.development.js +0 -1628
- package/dist/index.development.js.map +0 -1
- package/dist/index.production.min.js +0 -32
package/dist/index.browser.js
CHANGED
|
@@ -1,27 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { getStructDecoder, getStructEncoder, getArrayEncoder, getArrayDecoder, getBytesEncoder, getBytesDecoder } from '@solana/codecs-data-structures';
|
|
5
|
-
import { getShortU16Encoder, getShortU16Decoder, getU8Encoder, getU8Decoder } from '@solana/codecs-numbers';
|
|
1
|
+
import { SolanaError, SOLANA_ERROR__TRANSACTION_EXPECTED_BLOCKHASH_LIFETIME, SOLANA_ERROR__TRANSACTION_EXPECTED_NONCE_LIFETIME, SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_FEE_PAYER_MISSING, SOLANA_ERROR__TRANSACTION_SIGNATURE_NOT_COMPUTABLE, SOLANA_ERROR__TRANSACTION_MISSING_SIGNATURES, SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_CONTENTS_MISSING, SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_INDEX_OUT_OF_RANGE, SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_INSTRUCTION_PROGRAM_ADDRESS_NOT_FOUND, SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE, SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_CANNOT_PAY_FEES, SOLANA_ERROR__TRANSACTION_VERSION_NUMBER_OUT_OF_RANGE } from '@solana/errors';
|
|
2
|
+
import { getBase58Decoder, getBase64Decoder, getStringEncoder, getBase58Encoder, getStringDecoder } from '@solana/codecs-strings';
|
|
3
|
+
import { getAddressFromPublicKey, assertIsAddress, getAddressComparator, getAddressEncoder, getAddressDecoder } from '@solana/addresses';
|
|
6
4
|
import { pipe } from '@solana/functional';
|
|
5
|
+
import { createEncoder, mapDecoder, combineCodec, mapEncoder, createDecoder } from '@solana/codecs-core';
|
|
6
|
+
import { getStructDecoder, getArrayDecoder, getBytesDecoder, getStructEncoder, getArrayEncoder, getBytesEncoder } from '@solana/codecs-data-structures';
|
|
7
|
+
import { getShortU16Decoder, getShortU16Encoder, getU8Encoder, getU8Decoder } from '@solana/codecs-numbers';
|
|
7
8
|
import { signBytes } from '@solana/keys';
|
|
8
9
|
|
|
9
|
-
// src/blockhash.ts
|
|
10
|
-
|
|
11
|
-
// src/unsigned-transaction.ts
|
|
12
|
-
function getUnsignedTransaction(transaction) {
|
|
13
|
-
if ("signatures" in transaction) {
|
|
14
|
-
const {
|
|
15
|
-
signatures: _,
|
|
16
|
-
// eslint-disable-line @typescript-eslint/no-unused-vars
|
|
17
|
-
...unsignedTransaction
|
|
18
|
-
} = transaction;
|
|
19
|
-
return unsignedTransaction;
|
|
20
|
-
} else {
|
|
21
|
-
return transaction;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
10
|
// src/blockhash.ts
|
|
26
11
|
var base58Encoder;
|
|
27
12
|
function assertIsBlockhash(putativeBlockhash) {
|
|
@@ -46,6 +31,22 @@ function assertIsBlockhash(putativeBlockhash) {
|
|
|
46
31
|
});
|
|
47
32
|
}
|
|
48
33
|
}
|
|
34
|
+
|
|
35
|
+
// src/unsigned-transaction.ts
|
|
36
|
+
function getUnsignedTransaction(transaction) {
|
|
37
|
+
if ("signatures" in transaction) {
|
|
38
|
+
const {
|
|
39
|
+
signatures: _,
|
|
40
|
+
// eslint-disable-line @typescript-eslint/no-unused-vars
|
|
41
|
+
...unsignedTransaction
|
|
42
|
+
} = transaction;
|
|
43
|
+
return unsignedTransaction;
|
|
44
|
+
} else {
|
|
45
|
+
return transaction;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/blockhash.ts
|
|
49
50
|
function isTransactionWithBlockhashLifetime(transaction) {
|
|
50
51
|
const lifetimeConstraintShapeMatches = "lifetimeConstraint" in transaction && typeof transaction.lifetimeConstraint.blockhash === "string" && typeof transaction.lifetimeConstraint.lastValidBlockHeight === "bigint";
|
|
51
52
|
if (!lifetimeConstraintShapeMatches)
|
|
@@ -59,7 +60,7 @@ function isTransactionWithBlockhashLifetime(transaction) {
|
|
|
59
60
|
}
|
|
60
61
|
function assertIsTransactionWithBlockhashLifetime(transaction) {
|
|
61
62
|
if (!isTransactionWithBlockhashLifetime(transaction)) {
|
|
62
|
-
throw new
|
|
63
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_EXPECTED_BLOCKHASH_LIFETIME);
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
function setTransactionLifetimeUsingBlockhash(blockhashLifetimeConstraint, transaction) {
|
|
@@ -108,13 +109,11 @@ function isWritableRole(role) {
|
|
|
108
109
|
function mergeRoles(roleA, roleB) {
|
|
109
110
|
return roleA | roleB;
|
|
110
111
|
}
|
|
111
|
-
|
|
112
|
-
// src/durable-nonce.ts
|
|
113
112
|
var RECENT_BLOCKHASHES_SYSVAR_ADDRESS = "SysvarRecentB1ockHashes11111111111111111111";
|
|
114
113
|
var SYSTEM_PROGRAM_ADDRESS = "11111111111111111111111111111111";
|
|
115
114
|
function assertIsDurableNonceTransaction(transaction) {
|
|
116
115
|
if (!isDurableNonceTransaction(transaction)) {
|
|
117
|
-
throw new
|
|
116
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_EXPECTED_NONCE_LIFETIME);
|
|
118
117
|
}
|
|
119
118
|
}
|
|
120
119
|
function createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress) {
|
|
@@ -200,21 +199,181 @@ function setTransactionFeePayer(feePayer, transaction) {
|
|
|
200
199
|
|
|
201
200
|
// src/instructions.ts
|
|
202
201
|
function appendTransactionInstruction(instruction, transaction) {
|
|
202
|
+
return appendTransactionInstructions([instruction], transaction);
|
|
203
|
+
}
|
|
204
|
+
function appendTransactionInstructions(instructions, transaction) {
|
|
203
205
|
const out = {
|
|
204
206
|
...getUnsignedTransaction(transaction),
|
|
205
|
-
instructions: [...transaction.instructions,
|
|
207
|
+
instructions: [...transaction.instructions, ...instructions]
|
|
206
208
|
};
|
|
207
209
|
Object.freeze(out);
|
|
208
210
|
return out;
|
|
209
211
|
}
|
|
210
212
|
function prependTransactionInstruction(instruction, transaction) {
|
|
213
|
+
return prependTransactionInstructions([instruction], transaction);
|
|
214
|
+
}
|
|
215
|
+
function prependTransactionInstructions(instructions, transaction) {
|
|
211
216
|
const out = {
|
|
212
217
|
...getUnsignedTransaction(transaction),
|
|
213
|
-
instructions: [
|
|
218
|
+
instructions: [...instructions, ...transaction.instructions]
|
|
214
219
|
};
|
|
215
220
|
Object.freeze(out);
|
|
216
221
|
return out;
|
|
217
222
|
}
|
|
223
|
+
|
|
224
|
+
// src/decompile-transaction.ts
|
|
225
|
+
function getAccountMetas(message) {
|
|
226
|
+
const { header } = message;
|
|
227
|
+
const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
|
|
228
|
+
const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
|
|
229
|
+
const accountMetas = [];
|
|
230
|
+
let accountIndex = 0;
|
|
231
|
+
for (let i = 0; i < numWritableSignerAccounts; i++) {
|
|
232
|
+
accountMetas.push({
|
|
233
|
+
address: message.staticAccounts[accountIndex],
|
|
234
|
+
role: AccountRole.WRITABLE_SIGNER
|
|
235
|
+
});
|
|
236
|
+
accountIndex++;
|
|
237
|
+
}
|
|
238
|
+
for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
|
|
239
|
+
accountMetas.push({
|
|
240
|
+
address: message.staticAccounts[accountIndex],
|
|
241
|
+
role: AccountRole.READONLY_SIGNER
|
|
242
|
+
});
|
|
243
|
+
accountIndex++;
|
|
244
|
+
}
|
|
245
|
+
for (let i = 0; i < numWritableNonSignerAccounts; i++) {
|
|
246
|
+
accountMetas.push({
|
|
247
|
+
address: message.staticAccounts[accountIndex],
|
|
248
|
+
role: AccountRole.WRITABLE
|
|
249
|
+
});
|
|
250
|
+
accountIndex++;
|
|
251
|
+
}
|
|
252
|
+
for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
|
|
253
|
+
accountMetas.push({
|
|
254
|
+
address: message.staticAccounts[accountIndex],
|
|
255
|
+
role: AccountRole.READONLY
|
|
256
|
+
});
|
|
257
|
+
accountIndex++;
|
|
258
|
+
}
|
|
259
|
+
return accountMetas;
|
|
260
|
+
}
|
|
261
|
+
function getAddressLookupMetas(compiledAddressTableLookups, addressesByLookupTableAddress) {
|
|
262
|
+
const compiledAddressTableLookupAddresses = compiledAddressTableLookups.map((l) => l.lookupTableAddress);
|
|
263
|
+
const missing = compiledAddressTableLookupAddresses.filter((a) => addressesByLookupTableAddress[a] === void 0);
|
|
264
|
+
if (missing.length > 0) {
|
|
265
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_CONTENTS_MISSING, {
|
|
266
|
+
lookupTableAddresses: missing
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
const readOnlyMetas = [];
|
|
270
|
+
const writableMetas = [];
|
|
271
|
+
for (const lookup of compiledAddressTableLookups) {
|
|
272
|
+
const addresses = addressesByLookupTableAddress[lookup.lookupTableAddress];
|
|
273
|
+
const highestIndex = Math.max(...lookup.readableIndices, ...lookup.writableIndices);
|
|
274
|
+
if (highestIndex >= addresses.length) {
|
|
275
|
+
throw new SolanaError(
|
|
276
|
+
SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_INDEX_OUT_OF_RANGE,
|
|
277
|
+
{
|
|
278
|
+
highestKnownIndex: addresses.length - 1,
|
|
279
|
+
highestRequestedIndex: highestIndex,
|
|
280
|
+
lookupTableAddress: lookup.lookupTableAddress
|
|
281
|
+
}
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
const readOnlyForLookup = lookup.readableIndices.map((r) => ({
|
|
285
|
+
address: addresses[r],
|
|
286
|
+
addressIndex: r,
|
|
287
|
+
lookupTableAddress: lookup.lookupTableAddress,
|
|
288
|
+
role: AccountRole.READONLY
|
|
289
|
+
}));
|
|
290
|
+
readOnlyMetas.push(...readOnlyForLookup);
|
|
291
|
+
const writableForLookup = lookup.writableIndices.map((w) => ({
|
|
292
|
+
address: addresses[w],
|
|
293
|
+
addressIndex: w,
|
|
294
|
+
lookupTableAddress: lookup.lookupTableAddress,
|
|
295
|
+
role: AccountRole.WRITABLE
|
|
296
|
+
}));
|
|
297
|
+
writableMetas.push(...writableForLookup);
|
|
298
|
+
}
|
|
299
|
+
return [...writableMetas, ...readOnlyMetas];
|
|
300
|
+
}
|
|
301
|
+
function convertInstruction(instruction, accountMetas) {
|
|
302
|
+
const programAddress = accountMetas[instruction.programAddressIndex]?.address;
|
|
303
|
+
if (!programAddress) {
|
|
304
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_INSTRUCTION_PROGRAM_ADDRESS_NOT_FOUND, {
|
|
305
|
+
index: instruction.programAddressIndex
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
|
|
309
|
+
const { data } = instruction;
|
|
310
|
+
return {
|
|
311
|
+
programAddress,
|
|
312
|
+
...accounts && accounts.length ? { accounts } : {},
|
|
313
|
+
...data && data.length ? { data } : {}
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
|
|
317
|
+
if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
|
|
318
|
+
return {
|
|
319
|
+
blockhash: messageLifetimeToken,
|
|
320
|
+
lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
|
|
321
|
+
// U64 MAX
|
|
322
|
+
};
|
|
323
|
+
} else {
|
|
324
|
+
const nonceAccountAddress = firstInstruction.accounts[0].address;
|
|
325
|
+
assertIsAddress(nonceAccountAddress);
|
|
326
|
+
const nonceAuthorityAddress = firstInstruction.accounts[2].address;
|
|
327
|
+
assertIsAddress(nonceAuthorityAddress);
|
|
328
|
+
return {
|
|
329
|
+
nonce: messageLifetimeToken,
|
|
330
|
+
nonceAccountAddress,
|
|
331
|
+
nonceAuthorityAddress
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
function convertSignatures(compiledTransaction) {
|
|
336
|
+
const {
|
|
337
|
+
compiledMessage: { staticAccounts },
|
|
338
|
+
signatures
|
|
339
|
+
} = compiledTransaction;
|
|
340
|
+
return signatures.reduce((acc, sig, index) => {
|
|
341
|
+
const allZeros = sig.every((byte) => byte === 0);
|
|
342
|
+
if (allZeros)
|
|
343
|
+
return acc;
|
|
344
|
+
const address = staticAccounts[index];
|
|
345
|
+
return { ...acc, [address]: sig };
|
|
346
|
+
}, {});
|
|
347
|
+
}
|
|
348
|
+
function decompileTransaction(compiledTransaction, config) {
|
|
349
|
+
const { compiledMessage } = compiledTransaction;
|
|
350
|
+
const feePayer = compiledMessage.staticAccounts[0];
|
|
351
|
+
if (!feePayer) {
|
|
352
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_FEE_PAYER_MISSING);
|
|
353
|
+
}
|
|
354
|
+
const accountMetas = getAccountMetas(compiledMessage);
|
|
355
|
+
const accountLookupMetas = "addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups !== void 0 && compiledMessage.addressTableLookups.length > 0 ? getAddressLookupMetas(compiledMessage.addressTableLookups, config?.addressesByLookupTableAddress ?? {}) : [];
|
|
356
|
+
const transactionMetas = [...accountMetas, ...accountLookupMetas];
|
|
357
|
+
const instructions = compiledMessage.instructions.map(
|
|
358
|
+
(compiledInstruction) => convertInstruction(compiledInstruction, transactionMetas)
|
|
359
|
+
);
|
|
360
|
+
const firstInstruction = instructions[0];
|
|
361
|
+
const lifetimeConstraint = getLifetimeConstraint(
|
|
362
|
+
compiledMessage.lifetimeToken,
|
|
363
|
+
firstInstruction,
|
|
364
|
+
config?.lastValidBlockHeight
|
|
365
|
+
);
|
|
366
|
+
const signatures = convertSignatures(compiledTransaction);
|
|
367
|
+
return pipe(
|
|
368
|
+
createTransaction({ version: compiledMessage.version }),
|
|
369
|
+
(tx) => setTransactionFeePayer(feePayer, tx),
|
|
370
|
+
(tx) => instructions.reduce((acc, instruction) => {
|
|
371
|
+
return appendTransactionInstruction(instruction, acc);
|
|
372
|
+
}, tx),
|
|
373
|
+
(tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
|
|
374
|
+
(tx) => Object.keys(signatures).length > 0 ? { ...tx, signatures } : tx
|
|
375
|
+
);
|
|
376
|
+
}
|
|
218
377
|
function upsert(addressMap, address, update) {
|
|
219
378
|
addressMap[address] = update(addressMap[address] ?? { role: AccountRole.READONLY });
|
|
220
379
|
}
|
|
@@ -231,13 +390,13 @@ function getAddressMapFromInstructions(feePayer, instructions) {
|
|
|
231
390
|
if (isWritableRole(entry.role)) {
|
|
232
391
|
switch (entry[TYPE]) {
|
|
233
392
|
case 0 /* FEE_PAYER */:
|
|
234
|
-
throw new
|
|
235
|
-
|
|
236
|
-
);
|
|
393
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_CANNOT_PAY_FEES, {
|
|
394
|
+
programAddress: instruction.programAddress
|
|
395
|
+
});
|
|
237
396
|
default:
|
|
238
|
-
throw new
|
|
239
|
-
|
|
240
|
-
);
|
|
397
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE, {
|
|
398
|
+
programAddress: instruction.programAddress
|
|
399
|
+
});
|
|
241
400
|
}
|
|
242
401
|
}
|
|
243
402
|
if (entry[TYPE] === 2 /* STATIC */) {
|
|
@@ -302,8 +461,11 @@ function getAddressMapFromInstructions(feePayer, instructions) {
|
|
|
302
461
|
addressesOfInvokedPrograms.has(account.address)
|
|
303
462
|
) {
|
|
304
463
|
if (isWritableRole(accountMeta.role)) {
|
|
305
|
-
throw new
|
|
306
|
-
|
|
464
|
+
throw new SolanaError(
|
|
465
|
+
SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE,
|
|
466
|
+
{
|
|
467
|
+
programAddress: account.address
|
|
468
|
+
}
|
|
307
469
|
);
|
|
308
470
|
}
|
|
309
471
|
if (entry.role !== nextRole) {
|
|
@@ -593,7 +755,9 @@ function getTransactionVersionEncoder() {
|
|
|
593
755
|
return offset;
|
|
594
756
|
}
|
|
595
757
|
if (value < 0 || value > 127) {
|
|
596
|
-
throw new
|
|
758
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_VERSION_NUMBER_OUT_OF_RANGE, {
|
|
759
|
+
actualVersion: value
|
|
760
|
+
});
|
|
597
761
|
}
|
|
598
762
|
bytes.set([value | VERSION_FLAG_MASK], offset);
|
|
599
763
|
return offset + 1;
|
|
@@ -680,12 +844,15 @@ function getCompiledMessageEncoder() {
|
|
|
680
844
|
});
|
|
681
845
|
}
|
|
682
846
|
function getCompiledMessageDecoder() {
|
|
683
|
-
return mapDecoder(
|
|
684
|
-
|
|
685
|
-
|
|
847
|
+
return mapDecoder(
|
|
848
|
+
getStructDecoder(getPreludeStructDecoderTuple()),
|
|
849
|
+
({ addressTableLookups, ...restOfMessage }) => {
|
|
850
|
+
if (restOfMessage.version === "legacy" || !addressTableLookups?.length) {
|
|
851
|
+
return restOfMessage;
|
|
852
|
+
}
|
|
853
|
+
return { ...restOfMessage, addressTableLookups };
|
|
686
854
|
}
|
|
687
|
-
|
|
688
|
-
});
|
|
855
|
+
);
|
|
689
856
|
}
|
|
690
857
|
function getCompiledMessageCodec() {
|
|
691
858
|
return combineCodec(getCompiledMessageEncoder(), getCompiledMessageDecoder());
|
|
@@ -708,116 +875,6 @@ function getCompiledTransaction(transaction) {
|
|
|
708
875
|
signatures
|
|
709
876
|
};
|
|
710
877
|
}
|
|
711
|
-
function getAccountMetas(message) {
|
|
712
|
-
const { header } = message;
|
|
713
|
-
const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
|
|
714
|
-
const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
|
|
715
|
-
const accountMetas = [];
|
|
716
|
-
let accountIndex = 0;
|
|
717
|
-
for (let i = 0; i < numWritableSignerAccounts; i++) {
|
|
718
|
-
accountMetas.push({
|
|
719
|
-
address: message.staticAccounts[accountIndex],
|
|
720
|
-
role: AccountRole.WRITABLE_SIGNER
|
|
721
|
-
});
|
|
722
|
-
accountIndex++;
|
|
723
|
-
}
|
|
724
|
-
for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
|
|
725
|
-
accountMetas.push({
|
|
726
|
-
address: message.staticAccounts[accountIndex],
|
|
727
|
-
role: AccountRole.READONLY_SIGNER
|
|
728
|
-
});
|
|
729
|
-
accountIndex++;
|
|
730
|
-
}
|
|
731
|
-
for (let i = 0; i < numWritableNonSignerAccounts; i++) {
|
|
732
|
-
accountMetas.push({
|
|
733
|
-
address: message.staticAccounts[accountIndex],
|
|
734
|
-
role: AccountRole.WRITABLE
|
|
735
|
-
});
|
|
736
|
-
accountIndex++;
|
|
737
|
-
}
|
|
738
|
-
for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
|
|
739
|
-
accountMetas.push({
|
|
740
|
-
address: message.staticAccounts[accountIndex],
|
|
741
|
-
role: AccountRole.READONLY
|
|
742
|
-
});
|
|
743
|
-
accountIndex++;
|
|
744
|
-
}
|
|
745
|
-
return accountMetas;
|
|
746
|
-
}
|
|
747
|
-
function convertInstruction(instruction, accountMetas) {
|
|
748
|
-
const programAddress = accountMetas[instruction.programAddressIndex]?.address;
|
|
749
|
-
if (!programAddress) {
|
|
750
|
-
throw new Error(`Could not find program address at index ${instruction.programAddressIndex}`);
|
|
751
|
-
}
|
|
752
|
-
const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
|
|
753
|
-
const { data } = instruction;
|
|
754
|
-
return {
|
|
755
|
-
programAddress,
|
|
756
|
-
...accounts && accounts.length ? { accounts } : {},
|
|
757
|
-
...data && data.length ? { data } : {}
|
|
758
|
-
};
|
|
759
|
-
}
|
|
760
|
-
function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
|
|
761
|
-
if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
|
|
762
|
-
return {
|
|
763
|
-
blockhash: messageLifetimeToken,
|
|
764
|
-
lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
|
|
765
|
-
// U64 MAX
|
|
766
|
-
};
|
|
767
|
-
} else {
|
|
768
|
-
const nonceAccountAddress = firstInstruction.accounts[0].address;
|
|
769
|
-
assertIsAddress(nonceAccountAddress);
|
|
770
|
-
const nonceAuthorityAddress = firstInstruction.accounts[2].address;
|
|
771
|
-
assertIsAddress(nonceAuthorityAddress);
|
|
772
|
-
return {
|
|
773
|
-
nonce: messageLifetimeToken,
|
|
774
|
-
nonceAccountAddress,
|
|
775
|
-
nonceAuthorityAddress
|
|
776
|
-
};
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
function convertSignatures(compiledTransaction) {
|
|
780
|
-
const {
|
|
781
|
-
compiledMessage: { staticAccounts },
|
|
782
|
-
signatures
|
|
783
|
-
} = compiledTransaction;
|
|
784
|
-
return signatures.reduce((acc, sig, index) => {
|
|
785
|
-
const allZeros = sig.every((byte) => byte === 0);
|
|
786
|
-
if (allZeros)
|
|
787
|
-
return acc;
|
|
788
|
-
const address = staticAccounts[index];
|
|
789
|
-
return { ...acc, [address]: sig };
|
|
790
|
-
}, {});
|
|
791
|
-
}
|
|
792
|
-
function decompileTransaction(compiledTransaction, lastValidBlockHeight) {
|
|
793
|
-
const { compiledMessage } = compiledTransaction;
|
|
794
|
-
if ("addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups.length > 0) {
|
|
795
|
-
throw new Error("Cannot convert transaction with addressTableLookups");
|
|
796
|
-
}
|
|
797
|
-
const feePayer = compiledMessage.staticAccounts[0];
|
|
798
|
-
if (!feePayer)
|
|
799
|
-
throw new Error("No fee payer set in CompiledTransaction");
|
|
800
|
-
const accountMetas = getAccountMetas(compiledMessage);
|
|
801
|
-
const instructions = compiledMessage.instructions.map(
|
|
802
|
-
(compiledInstruction) => convertInstruction(compiledInstruction, accountMetas)
|
|
803
|
-
);
|
|
804
|
-
const firstInstruction = instructions[0];
|
|
805
|
-
const lifetimeConstraint = getLifetimeConstraint(
|
|
806
|
-
compiledMessage.lifetimeToken,
|
|
807
|
-
firstInstruction,
|
|
808
|
-
lastValidBlockHeight
|
|
809
|
-
);
|
|
810
|
-
const signatures = convertSignatures(compiledTransaction);
|
|
811
|
-
return pipe(
|
|
812
|
-
createTransaction({ version: compiledMessage.version }),
|
|
813
|
-
(tx) => setTransactionFeePayer(feePayer, tx),
|
|
814
|
-
(tx) => instructions.reduce((acc, instruction) => {
|
|
815
|
-
return appendTransactionInstruction(instruction, acc);
|
|
816
|
-
}, tx),
|
|
817
|
-
(tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
|
|
818
|
-
(tx) => compiledTransaction.signatures.length ? { ...tx, signatures } : tx
|
|
819
|
-
);
|
|
820
|
-
}
|
|
821
878
|
|
|
822
879
|
// src/serializers/transaction.ts
|
|
823
880
|
function getCompiledTransactionEncoder() {
|
|
@@ -840,14 +897,14 @@ function getCompiledTransactionDecoder() {
|
|
|
840
897
|
function getTransactionEncoder() {
|
|
841
898
|
return mapEncoder(getCompiledTransactionEncoder(), getCompiledTransaction);
|
|
842
899
|
}
|
|
843
|
-
function getTransactionDecoder(
|
|
900
|
+
function getTransactionDecoder(config) {
|
|
844
901
|
return mapDecoder(
|
|
845
902
|
getCompiledTransactionDecoder(),
|
|
846
|
-
(compiledTransaction) => decompileTransaction(compiledTransaction,
|
|
903
|
+
(compiledTransaction) => decompileTransaction(compiledTransaction, config)
|
|
847
904
|
);
|
|
848
905
|
}
|
|
849
|
-
function getTransactionCodec(
|
|
850
|
-
return combineCodec(getTransactionEncoder(), getTransactionDecoder(
|
|
906
|
+
function getTransactionCodec(config) {
|
|
907
|
+
return combineCodec(getTransactionEncoder(), getTransactionDecoder(config));
|
|
851
908
|
}
|
|
852
909
|
var base58Decoder;
|
|
853
910
|
function getSignatureFromTransaction(transaction) {
|
|
@@ -855,9 +912,7 @@ function getSignatureFromTransaction(transaction) {
|
|
|
855
912
|
base58Decoder = getBase58Decoder();
|
|
856
913
|
const signatureBytes = transaction.signatures[transaction.feePayer];
|
|
857
914
|
if (!signatureBytes) {
|
|
858
|
-
throw new
|
|
859
|
-
"Could not determine this transaction's signature. Make sure that the transaction has been signed by its fee payer."
|
|
860
|
-
);
|
|
915
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_SIGNATURE_NOT_COMPUTABLE);
|
|
861
916
|
}
|
|
862
917
|
const transactionSignature = base58Decoder.decode(signatureBytes);
|
|
863
918
|
return transactionSignature;
|
|
@@ -890,17 +945,23 @@ async function signTransaction(keyPairs, transaction) {
|
|
|
890
945
|
function assertTransactionIsFullySigned(transaction) {
|
|
891
946
|
const signerAddressesFromInstructions = transaction.instructions.flatMap((i) => i.accounts?.filter((a) => isSignerRole(a.role)) ?? []).map((a) => a.address);
|
|
892
947
|
const requiredSigners = /* @__PURE__ */ new Set([transaction.feePayer, ...signerAddressesFromInstructions]);
|
|
948
|
+
const missingSigs = [];
|
|
893
949
|
requiredSigners.forEach((address) => {
|
|
894
950
|
if (!transaction.signatures[address]) {
|
|
895
|
-
|
|
951
|
+
missingSigs.push(address);
|
|
896
952
|
}
|
|
897
953
|
});
|
|
954
|
+
if (missingSigs.length > 0) {
|
|
955
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_MISSING_SIGNATURES, {
|
|
956
|
+
addresses: missingSigs
|
|
957
|
+
});
|
|
958
|
+
}
|
|
898
959
|
}
|
|
899
960
|
function getBase64EncodedWireTransaction(transaction) {
|
|
900
961
|
const wireTransactionBytes = getTransactionEncoder().encode(transaction);
|
|
901
962
|
return getBase64Decoder().decode(wireTransactionBytes);
|
|
902
963
|
}
|
|
903
964
|
|
|
904
|
-
export { appendTransactionInstruction,
|
|
965
|
+
export { appendTransactionInstruction, appendTransactionInstructions, assertIsDurableNonceTransaction, assertIsTransactionWithBlockhashLifetime, assertTransactionIsFullySigned, compileMessage, createTransaction, decompileTransaction, getBase64EncodedWireTransaction, getCompiledMessageCodec, getCompiledMessageDecoder, getCompiledMessageEncoder, getCompiledTransactionDecoder, getSignatureFromTransaction, getTransactionCodec, getTransactionDecoder, getTransactionEncoder, getUnsignedTransaction, isAdvanceNonceAccountInstruction, partiallySignTransaction, prependTransactionInstruction, prependTransactionInstructions, setTransactionFeePayer, setTransactionLifetimeUsingBlockhash, setTransactionLifetimeUsingDurableNonce, signTransaction };
|
|
905
966
|
//# sourceMappingURL=out.js.map
|
|
906
967
|
//# sourceMappingURL=index.browser.js.map
|