@solana/transactions 2.0.0-experimental.cc94aa3 → 2.0.0-experimental.ccd92fd
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 +349 -415
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +343 -418
- package/dist/index.browser.js.map +1 -1
- package/dist/index.native.js +343 -418
- package/dist/index.native.js.map +1 -1
- package/dist/index.node.cjs +349 -415
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +343 -418
- package/dist/index.node.js.map +1 -1
- package/dist/types/accounts.d.ts.map +1 -1
- package/dist/types/blockhash.d.ts +5 -7
- package/dist/types/blockhash.d.ts.map +1 -1
- package/dist/types/compilable-transaction.d.ts +4 -4
- package/dist/types/compile-address-table-lookups.d.ts +1 -1
- package/dist/types/compile-header.d.ts +1 -1
- package/dist/types/compile-instructions.d.ts +1 -1
- package/dist/types/compile-lifetime-token.d.ts +1 -1
- package/dist/types/compile-static-accounts.d.ts +1 -1
- package/dist/types/compile-transaction.d.ts +3 -3
- package/dist/types/create-transaction.d.ts +1 -1
- package/dist/types/decompile-transaction.d.ts +12 -4
- package/dist/types/decompile-transaction.d.ts.map +1 -1
- package/dist/types/durable-nonce.d.ts +2 -2
- package/dist/types/durable-nonce.d.ts.map +1 -1
- package/dist/types/fee-payer.d.ts +2 -2
- package/dist/types/index.d.ts +13 -10
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/instructions.d.ts +4 -2
- package/dist/types/instructions.d.ts.map +1 -1
- package/dist/types/message.d.ts +6 -6
- package/dist/types/serializers/address-table-lookup.d.ts +5 -5
- package/dist/types/serializers/address-table-lookup.d.ts.map +1 -1
- package/dist/types/serializers/header.d.ts +5 -5
- package/dist/types/serializers/header.d.ts.map +1 -1
- package/dist/types/serializers/index.d.ts +2 -1
- package/dist/types/serializers/index.d.ts.map +1 -1
- package/dist/types/serializers/instruction.d.ts +5 -5
- package/dist/types/serializers/instruction.d.ts.map +1 -1
- package/dist/types/serializers/message.d.ts +5 -5
- package/dist/types/serializers/message.d.ts.map +1 -1
- package/dist/types/serializers/transaction-version.d.ts +5 -5
- package/dist/types/serializers/transaction-version.d.ts.map +1 -1
- package/dist/types/serializers/transaction.d.ts +9 -6
- package/dist/types/serializers/transaction.d.ts.map +1 -1
- package/dist/types/signatures.d.ts +2 -2
- package/dist/types/signatures.d.ts.map +1 -1
- package/dist/types/unsigned-transaction.d.ts +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 -39
- package/dist/index.development.js +0 -1738
- package/dist/index.development.js.map +0 -1
- package/dist/index.production.min.js +0 -27
package/dist/index.browser.cjs
CHANGED
|
@@ -1,30 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var errors = require('@solana/errors');
|
|
3
4
|
var codecsStrings = require('@solana/codecs-strings');
|
|
5
|
+
var addresses = require('@solana/addresses');
|
|
6
|
+
var functional = require('@solana/functional');
|
|
4
7
|
var codecsCore = require('@solana/codecs-core');
|
|
5
8
|
var codecsDataStructures = require('@solana/codecs-data-structures');
|
|
6
9
|
var codecsNumbers = require('@solana/codecs-numbers');
|
|
7
|
-
var addresses = require('@solana/addresses');
|
|
8
|
-
var functional = require('@solana/functional');
|
|
9
10
|
var keys = require('@solana/keys');
|
|
10
11
|
|
|
11
|
-
// ../build-scripts/env-shim.ts
|
|
12
|
-
var __DEV__ = /* @__PURE__ */ (() => process["env"].NODE_ENV === "development")();
|
|
13
|
-
|
|
14
|
-
// src/unsigned-transaction.ts
|
|
15
|
-
function getUnsignedTransaction(transaction) {
|
|
16
|
-
if ("signatures" in transaction) {
|
|
17
|
-
const {
|
|
18
|
-
signatures: _,
|
|
19
|
-
// eslint-disable-line @typescript-eslint/no-unused-vars
|
|
20
|
-
...unsignedTransaction
|
|
21
|
-
} = transaction;
|
|
22
|
-
return unsignedTransaction;
|
|
23
|
-
} else {
|
|
24
|
-
return transaction;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
12
|
// src/blockhash.ts
|
|
29
13
|
var base58Encoder;
|
|
30
14
|
function assertIsBlockhash(putativeBlockhash) {
|
|
@@ -49,6 +33,38 @@ function assertIsBlockhash(putativeBlockhash) {
|
|
|
49
33
|
});
|
|
50
34
|
}
|
|
51
35
|
}
|
|
36
|
+
|
|
37
|
+
// src/unsigned-transaction.ts
|
|
38
|
+
function getUnsignedTransaction(transaction) {
|
|
39
|
+
if ("signatures" in transaction) {
|
|
40
|
+
const {
|
|
41
|
+
signatures: _,
|
|
42
|
+
// eslint-disable-line @typescript-eslint/no-unused-vars
|
|
43
|
+
...unsignedTransaction
|
|
44
|
+
} = transaction;
|
|
45
|
+
return unsignedTransaction;
|
|
46
|
+
} else {
|
|
47
|
+
return transaction;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/blockhash.ts
|
|
52
|
+
function isTransactionWithBlockhashLifetime(transaction) {
|
|
53
|
+
const lifetimeConstraintShapeMatches = "lifetimeConstraint" in transaction && typeof transaction.lifetimeConstraint.blockhash === "string" && typeof transaction.lifetimeConstraint.lastValidBlockHeight === "bigint";
|
|
54
|
+
if (!lifetimeConstraintShapeMatches)
|
|
55
|
+
return false;
|
|
56
|
+
try {
|
|
57
|
+
assertIsBlockhash(transaction.lifetimeConstraint.blockhash);
|
|
58
|
+
return true;
|
|
59
|
+
} catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function assertIsTransactionWithBlockhashLifetime(transaction) {
|
|
64
|
+
if (!isTransactionWithBlockhashLifetime(transaction)) {
|
|
65
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_EXPECTED_BLOCKHASH_LIFETIME);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
52
68
|
function setTransactionLifetimeUsingBlockhash(blockhashLifetimeConstraint, transaction) {
|
|
53
69
|
if ("lifetimeConstraint" in transaction && transaction.lifetimeConstraint.blockhash === blockhashLifetimeConstraint.blockhash && transaction.lifetimeConstraint.lastValidBlockHeight === blockhashLifetimeConstraint.lastValidBlockHeight) {
|
|
54
70
|
return transaction;
|
|
@@ -95,13 +111,11 @@ function isWritableRole(role) {
|
|
|
95
111
|
function mergeRoles(roleA, roleB) {
|
|
96
112
|
return roleA | roleB;
|
|
97
113
|
}
|
|
98
|
-
|
|
99
|
-
// src/durable-nonce.ts
|
|
100
114
|
var RECENT_BLOCKHASHES_SYSVAR_ADDRESS = "SysvarRecentB1ockHashes11111111111111111111";
|
|
101
115
|
var SYSTEM_PROGRAM_ADDRESS = "11111111111111111111111111111111";
|
|
102
116
|
function assertIsDurableNonceTransaction(transaction) {
|
|
103
117
|
if (!isDurableNonceTransaction(transaction)) {
|
|
104
|
-
throw new
|
|
118
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_EXPECTED_NONCE_LIFETIME);
|
|
105
119
|
}
|
|
106
120
|
}
|
|
107
121
|
function createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress) {
|
|
@@ -187,21 +201,181 @@ function setTransactionFeePayer(feePayer, transaction) {
|
|
|
187
201
|
|
|
188
202
|
// src/instructions.ts
|
|
189
203
|
function appendTransactionInstruction(instruction, transaction) {
|
|
204
|
+
return appendTransactionInstructions([instruction], transaction);
|
|
205
|
+
}
|
|
206
|
+
function appendTransactionInstructions(instructions, transaction) {
|
|
190
207
|
const out = {
|
|
191
208
|
...getUnsignedTransaction(transaction),
|
|
192
|
-
instructions: [...transaction.instructions,
|
|
209
|
+
instructions: [...transaction.instructions, ...instructions]
|
|
193
210
|
};
|
|
194
211
|
Object.freeze(out);
|
|
195
212
|
return out;
|
|
196
213
|
}
|
|
197
214
|
function prependTransactionInstruction(instruction, transaction) {
|
|
215
|
+
return prependTransactionInstructions([instruction], transaction);
|
|
216
|
+
}
|
|
217
|
+
function prependTransactionInstructions(instructions, transaction) {
|
|
198
218
|
const out = {
|
|
199
219
|
...getUnsignedTransaction(transaction),
|
|
200
|
-
instructions: [
|
|
220
|
+
instructions: [...instructions, ...transaction.instructions]
|
|
201
221
|
};
|
|
202
222
|
Object.freeze(out);
|
|
203
223
|
return out;
|
|
204
224
|
}
|
|
225
|
+
|
|
226
|
+
// src/decompile-transaction.ts
|
|
227
|
+
function getAccountMetas(message) {
|
|
228
|
+
const { header } = message;
|
|
229
|
+
const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
|
|
230
|
+
const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
|
|
231
|
+
const accountMetas = [];
|
|
232
|
+
let accountIndex = 0;
|
|
233
|
+
for (let i = 0; i < numWritableSignerAccounts; i++) {
|
|
234
|
+
accountMetas.push({
|
|
235
|
+
address: message.staticAccounts[accountIndex],
|
|
236
|
+
role: AccountRole.WRITABLE_SIGNER
|
|
237
|
+
});
|
|
238
|
+
accountIndex++;
|
|
239
|
+
}
|
|
240
|
+
for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
|
|
241
|
+
accountMetas.push({
|
|
242
|
+
address: message.staticAccounts[accountIndex],
|
|
243
|
+
role: AccountRole.READONLY_SIGNER
|
|
244
|
+
});
|
|
245
|
+
accountIndex++;
|
|
246
|
+
}
|
|
247
|
+
for (let i = 0; i < numWritableNonSignerAccounts; i++) {
|
|
248
|
+
accountMetas.push({
|
|
249
|
+
address: message.staticAccounts[accountIndex],
|
|
250
|
+
role: AccountRole.WRITABLE
|
|
251
|
+
});
|
|
252
|
+
accountIndex++;
|
|
253
|
+
}
|
|
254
|
+
for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
|
|
255
|
+
accountMetas.push({
|
|
256
|
+
address: message.staticAccounts[accountIndex],
|
|
257
|
+
role: AccountRole.READONLY
|
|
258
|
+
});
|
|
259
|
+
accountIndex++;
|
|
260
|
+
}
|
|
261
|
+
return accountMetas;
|
|
262
|
+
}
|
|
263
|
+
function getAddressLookupMetas(compiledAddressTableLookups, addressesByLookupTableAddress) {
|
|
264
|
+
const compiledAddressTableLookupAddresses = compiledAddressTableLookups.map((l) => l.lookupTableAddress);
|
|
265
|
+
const missing = compiledAddressTableLookupAddresses.filter((a) => addressesByLookupTableAddress[a] === void 0);
|
|
266
|
+
if (missing.length > 0) {
|
|
267
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_CONTENTS_MISSING, {
|
|
268
|
+
lookupTableAddresses: missing
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
const readOnlyMetas = [];
|
|
272
|
+
const writableMetas = [];
|
|
273
|
+
for (const lookup of compiledAddressTableLookups) {
|
|
274
|
+
const addresses = addressesByLookupTableAddress[lookup.lookupTableAddress];
|
|
275
|
+
const highestIndex = Math.max(...lookup.readableIndices, ...lookup.writableIndices);
|
|
276
|
+
if (highestIndex >= addresses.length) {
|
|
277
|
+
throw new errors.SolanaError(
|
|
278
|
+
errors.SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_INDEX_OUT_OF_RANGE,
|
|
279
|
+
{
|
|
280
|
+
highestKnownIndex: addresses.length - 1,
|
|
281
|
+
highestRequestedIndex: highestIndex,
|
|
282
|
+
lookupTableAddress: lookup.lookupTableAddress
|
|
283
|
+
}
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
const readOnlyForLookup = lookup.readableIndices.map((r) => ({
|
|
287
|
+
address: addresses[r],
|
|
288
|
+
addressIndex: r,
|
|
289
|
+
lookupTableAddress: lookup.lookupTableAddress,
|
|
290
|
+
role: AccountRole.READONLY
|
|
291
|
+
}));
|
|
292
|
+
readOnlyMetas.push(...readOnlyForLookup);
|
|
293
|
+
const writableForLookup = lookup.writableIndices.map((w) => ({
|
|
294
|
+
address: addresses[w],
|
|
295
|
+
addressIndex: w,
|
|
296
|
+
lookupTableAddress: lookup.lookupTableAddress,
|
|
297
|
+
role: AccountRole.WRITABLE
|
|
298
|
+
}));
|
|
299
|
+
writableMetas.push(...writableForLookup);
|
|
300
|
+
}
|
|
301
|
+
return [...writableMetas, ...readOnlyMetas];
|
|
302
|
+
}
|
|
303
|
+
function convertInstruction(instruction, accountMetas) {
|
|
304
|
+
const programAddress = accountMetas[instruction.programAddressIndex]?.address;
|
|
305
|
+
if (!programAddress) {
|
|
306
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_INSTRUCTION_PROGRAM_ADDRESS_NOT_FOUND, {
|
|
307
|
+
index: instruction.programAddressIndex
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
|
|
311
|
+
const { data } = instruction;
|
|
312
|
+
return {
|
|
313
|
+
programAddress,
|
|
314
|
+
...accounts && accounts.length ? { accounts } : {},
|
|
315
|
+
...data && data.length ? { data } : {}
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
|
|
319
|
+
if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
|
|
320
|
+
return {
|
|
321
|
+
blockhash: messageLifetimeToken,
|
|
322
|
+
lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
|
|
323
|
+
// U64 MAX
|
|
324
|
+
};
|
|
325
|
+
} else {
|
|
326
|
+
const nonceAccountAddress = firstInstruction.accounts[0].address;
|
|
327
|
+
addresses.assertIsAddress(nonceAccountAddress);
|
|
328
|
+
const nonceAuthorityAddress = firstInstruction.accounts[2].address;
|
|
329
|
+
addresses.assertIsAddress(nonceAuthorityAddress);
|
|
330
|
+
return {
|
|
331
|
+
nonce: messageLifetimeToken,
|
|
332
|
+
nonceAccountAddress,
|
|
333
|
+
nonceAuthorityAddress
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
function convertSignatures(compiledTransaction) {
|
|
338
|
+
const {
|
|
339
|
+
compiledMessage: { staticAccounts },
|
|
340
|
+
signatures
|
|
341
|
+
} = compiledTransaction;
|
|
342
|
+
return signatures.reduce((acc, sig, index) => {
|
|
343
|
+
const allZeros = sig.every((byte) => byte === 0);
|
|
344
|
+
if (allZeros)
|
|
345
|
+
return acc;
|
|
346
|
+
const address = staticAccounts[index];
|
|
347
|
+
return { ...acc, [address]: sig };
|
|
348
|
+
}, {});
|
|
349
|
+
}
|
|
350
|
+
function decompileTransaction(compiledTransaction, config) {
|
|
351
|
+
const { compiledMessage } = compiledTransaction;
|
|
352
|
+
const feePayer = compiledMessage.staticAccounts[0];
|
|
353
|
+
if (!feePayer) {
|
|
354
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_FEE_PAYER_MISSING);
|
|
355
|
+
}
|
|
356
|
+
const accountMetas = getAccountMetas(compiledMessage);
|
|
357
|
+
const accountLookupMetas = "addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups !== void 0 && compiledMessage.addressTableLookups.length > 0 ? getAddressLookupMetas(compiledMessage.addressTableLookups, config?.addressesByLookupTableAddress ?? {}) : [];
|
|
358
|
+
const transactionMetas = [...accountMetas, ...accountLookupMetas];
|
|
359
|
+
const instructions = compiledMessage.instructions.map(
|
|
360
|
+
(compiledInstruction) => convertInstruction(compiledInstruction, transactionMetas)
|
|
361
|
+
);
|
|
362
|
+
const firstInstruction = instructions[0];
|
|
363
|
+
const lifetimeConstraint = getLifetimeConstraint(
|
|
364
|
+
compiledMessage.lifetimeToken,
|
|
365
|
+
firstInstruction,
|
|
366
|
+
config?.lastValidBlockHeight
|
|
367
|
+
);
|
|
368
|
+
const signatures = convertSignatures(compiledTransaction);
|
|
369
|
+
return functional.pipe(
|
|
370
|
+
createTransaction({ version: compiledMessage.version }),
|
|
371
|
+
(tx) => setTransactionFeePayer(feePayer, tx),
|
|
372
|
+
(tx) => instructions.reduce((acc, instruction) => {
|
|
373
|
+
return appendTransactionInstruction(instruction, acc);
|
|
374
|
+
}, tx),
|
|
375
|
+
(tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
|
|
376
|
+
(tx) => Object.keys(signatures).length > 0 ? { ...tx, signatures } : tx
|
|
377
|
+
);
|
|
378
|
+
}
|
|
205
379
|
function upsert(addressMap, address, update) {
|
|
206
380
|
addressMap[address] = update(addressMap[address] ?? { role: AccountRole.READONLY });
|
|
207
381
|
}
|
|
@@ -218,13 +392,13 @@ function getAddressMapFromInstructions(feePayer, instructions) {
|
|
|
218
392
|
if (isWritableRole(entry.role)) {
|
|
219
393
|
switch (entry[TYPE]) {
|
|
220
394
|
case 0 /* FEE_PAYER */:
|
|
221
|
-
throw new
|
|
222
|
-
|
|
223
|
-
);
|
|
395
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_CANNOT_PAY_FEES, {
|
|
396
|
+
programAddress: instruction.programAddress
|
|
397
|
+
});
|
|
224
398
|
default:
|
|
225
|
-
throw new
|
|
226
|
-
|
|
227
|
-
);
|
|
399
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE, {
|
|
400
|
+
programAddress: instruction.programAddress
|
|
401
|
+
});
|
|
228
402
|
}
|
|
229
403
|
}
|
|
230
404
|
if (entry[TYPE] === 2 /* STATIC */) {
|
|
@@ -254,7 +428,7 @@ function getAddressMapFromInstructions(feePayer, instructions) {
|
|
|
254
428
|
const shouldReplaceEntry = (
|
|
255
429
|
// Consider using the new LOOKUP_TABLE if its address is different...
|
|
256
430
|
entry.lookupTableAddress !== accountMeta.lookupTableAddress && // ...and sorts before the existing one.
|
|
257
|
-
(addressComparator
|
|
431
|
+
(addressComparator ||= addresses.getAddressComparator())(
|
|
258
432
|
accountMeta.lookupTableAddress,
|
|
259
433
|
entry.lookupTableAddress
|
|
260
434
|
) < 0
|
|
@@ -289,8 +463,11 @@ function getAddressMapFromInstructions(feePayer, instructions) {
|
|
|
289
463
|
addressesOfInvokedPrograms.has(account.address)
|
|
290
464
|
) {
|
|
291
465
|
if (isWritableRole(accountMeta.role)) {
|
|
292
|
-
throw new
|
|
293
|
-
|
|
466
|
+
throw new errors.SolanaError(
|
|
467
|
+
errors.SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE,
|
|
468
|
+
{
|
|
469
|
+
programAddress: account.address
|
|
470
|
+
}
|
|
294
471
|
);
|
|
295
472
|
}
|
|
296
473
|
if (entry.role !== nextRole) {
|
|
@@ -360,7 +537,7 @@ function getOrderedAccountsFromAddressMap(addressMap) {
|
|
|
360
537
|
if (leftIsWritable !== isWritableRole(rightEntry.role)) {
|
|
361
538
|
return leftIsWritable ? -1 : 1;
|
|
362
539
|
}
|
|
363
|
-
addressComparator
|
|
540
|
+
addressComparator ||= addresses.getAddressComparator();
|
|
364
541
|
if (leftEntry[TYPE] === 1 /* LOOKUP_TABLE */ && rightEntry[TYPE] === 1 /* LOOKUP_TABLE */ && leftEntry.lookupTableAddress !== rightEntry.lookupTableAddress) {
|
|
365
542
|
return addressComparator(leftEntry.lookupTableAddress, rightEntry.lookupTableAddress);
|
|
366
543
|
} else {
|
|
@@ -373,16 +550,15 @@ function getOrderedAccountsFromAddressMap(addressMap) {
|
|
|
373
550
|
return orderedAccounts;
|
|
374
551
|
}
|
|
375
552
|
function getCompiledAddressTableLookups(orderedAccounts) {
|
|
376
|
-
var _a;
|
|
377
553
|
const index = {};
|
|
378
554
|
for (const account of orderedAccounts) {
|
|
379
555
|
if (!("lookupTableAddress" in account)) {
|
|
380
556
|
continue;
|
|
381
557
|
}
|
|
382
|
-
const entry = index[
|
|
558
|
+
const entry = index[account.lookupTableAddress] ||= {
|
|
383
559
|
readableIndices: [],
|
|
384
560
|
writableIndices: []
|
|
385
|
-
}
|
|
561
|
+
};
|
|
386
562
|
if (account.role === AccountRole.WRITABLE) {
|
|
387
563
|
entry.writableIndices.push(account.addressIndex);
|
|
388
564
|
} else {
|
|
@@ -468,187 +644,31 @@ function compileMessage(transaction) {
|
|
|
468
644
|
version: transaction.version
|
|
469
645
|
};
|
|
470
646
|
}
|
|
471
|
-
|
|
472
|
-
// src/compile-transaction.ts
|
|
473
|
-
function getCompiledTransaction(transaction) {
|
|
474
|
-
const compiledMessage = compileMessage(transaction);
|
|
475
|
-
let signatures;
|
|
476
|
-
if ("signatures" in transaction) {
|
|
477
|
-
signatures = [];
|
|
478
|
-
for (let ii = 0; ii < compiledMessage.header.numSignerAccounts; ii++) {
|
|
479
|
-
signatures[ii] = transaction.signatures[compiledMessage.staticAccounts[ii]] ?? new Uint8Array(Array(64).fill(0));
|
|
480
|
-
}
|
|
481
|
-
} else {
|
|
482
|
-
signatures = Array(compiledMessage.header.numSignerAccounts).fill(new Uint8Array(Array(64).fill(0)));
|
|
483
|
-
}
|
|
484
|
-
return {
|
|
485
|
-
compiledMessage,
|
|
486
|
-
signatures
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
function getAccountMetas(message) {
|
|
490
|
-
const { header } = message;
|
|
491
|
-
const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
|
|
492
|
-
const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
|
|
493
|
-
const accountMetas = [];
|
|
494
|
-
let accountIndex = 0;
|
|
495
|
-
for (let i = 0; i < numWritableSignerAccounts; i++) {
|
|
496
|
-
accountMetas.push({
|
|
497
|
-
address: message.staticAccounts[accountIndex],
|
|
498
|
-
role: AccountRole.WRITABLE_SIGNER
|
|
499
|
-
});
|
|
500
|
-
accountIndex++;
|
|
501
|
-
}
|
|
502
|
-
for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
|
|
503
|
-
accountMetas.push({
|
|
504
|
-
address: message.staticAccounts[accountIndex],
|
|
505
|
-
role: AccountRole.READONLY_SIGNER
|
|
506
|
-
});
|
|
507
|
-
accountIndex++;
|
|
508
|
-
}
|
|
509
|
-
for (let i = 0; i < numWritableNonSignerAccounts; i++) {
|
|
510
|
-
accountMetas.push({
|
|
511
|
-
address: message.staticAccounts[accountIndex],
|
|
512
|
-
role: AccountRole.WRITABLE
|
|
513
|
-
});
|
|
514
|
-
accountIndex++;
|
|
515
|
-
}
|
|
516
|
-
for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
|
|
517
|
-
accountMetas.push({
|
|
518
|
-
address: message.staticAccounts[accountIndex],
|
|
519
|
-
role: AccountRole.READONLY
|
|
520
|
-
});
|
|
521
|
-
accountIndex++;
|
|
522
|
-
}
|
|
523
|
-
return accountMetas;
|
|
524
|
-
}
|
|
525
|
-
function convertInstruction(instruction, accountMetas) {
|
|
526
|
-
const programAddress = accountMetas[instruction.programAddressIndex]?.address;
|
|
527
|
-
if (!programAddress) {
|
|
528
|
-
throw new Error(`Could not find program address at index ${instruction.programAddressIndex}`);
|
|
529
|
-
}
|
|
530
|
-
const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
|
|
531
|
-
const { data } = instruction;
|
|
532
|
-
return {
|
|
533
|
-
programAddress,
|
|
534
|
-
...accounts && accounts.length ? { accounts } : {},
|
|
535
|
-
...data && data.length ? { data } : {}
|
|
536
|
-
};
|
|
537
|
-
}
|
|
538
|
-
function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
|
|
539
|
-
if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
|
|
540
|
-
return {
|
|
541
|
-
blockhash: messageLifetimeToken,
|
|
542
|
-
lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
|
|
543
|
-
// U64 MAX
|
|
544
|
-
};
|
|
545
|
-
} else {
|
|
546
|
-
const nonceAccountAddress = firstInstruction.accounts[0].address;
|
|
547
|
-
addresses.assertIsAddress(nonceAccountAddress);
|
|
548
|
-
const nonceAuthorityAddress = firstInstruction.accounts[2].address;
|
|
549
|
-
addresses.assertIsAddress(nonceAuthorityAddress);
|
|
550
|
-
return {
|
|
551
|
-
nonce: messageLifetimeToken,
|
|
552
|
-
nonceAccountAddress,
|
|
553
|
-
nonceAuthorityAddress
|
|
554
|
-
};
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
function convertSignatures(compiledTransaction) {
|
|
558
|
-
const {
|
|
559
|
-
compiledMessage: { staticAccounts },
|
|
560
|
-
signatures
|
|
561
|
-
} = compiledTransaction;
|
|
562
|
-
return signatures.reduce((acc, sig, index) => {
|
|
563
|
-
const allZeros = sig.every((byte) => byte === 0);
|
|
564
|
-
if (allZeros)
|
|
565
|
-
return acc;
|
|
566
|
-
const address = staticAccounts[index];
|
|
567
|
-
return { ...acc, [address]: sig };
|
|
568
|
-
}, {});
|
|
569
|
-
}
|
|
570
|
-
function decompileTransaction(compiledTransaction, lastValidBlockHeight) {
|
|
571
|
-
const { compiledMessage } = compiledTransaction;
|
|
572
|
-
if ("addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups.length > 0) {
|
|
573
|
-
throw new Error("Cannot convert transaction with addressTableLookups");
|
|
574
|
-
}
|
|
575
|
-
const feePayer = compiledMessage.staticAccounts[0];
|
|
576
|
-
if (!feePayer)
|
|
577
|
-
throw new Error("No fee payer set in CompiledTransaction");
|
|
578
|
-
const accountMetas = getAccountMetas(compiledMessage);
|
|
579
|
-
const instructions = compiledMessage.instructions.map(
|
|
580
|
-
(compiledInstruction) => convertInstruction(compiledInstruction, accountMetas)
|
|
581
|
-
);
|
|
582
|
-
const firstInstruction = instructions[0];
|
|
583
|
-
const lifetimeConstraint = getLifetimeConstraint(
|
|
584
|
-
compiledMessage.lifetimeToken,
|
|
585
|
-
firstInstruction,
|
|
586
|
-
lastValidBlockHeight
|
|
587
|
-
);
|
|
588
|
-
const signatures = convertSignatures(compiledTransaction);
|
|
589
|
-
return functional.pipe(
|
|
590
|
-
createTransaction({ version: compiledMessage.version }),
|
|
591
|
-
(tx) => setTransactionFeePayer(feePayer, tx),
|
|
592
|
-
(tx) => instructions.reduce((acc, instruction) => {
|
|
593
|
-
return appendTransactionInstruction(instruction, acc);
|
|
594
|
-
}, tx),
|
|
595
|
-
(tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
|
|
596
|
-
(tx) => compiledTransaction.signatures.length ? { ...tx, signatures } : tx
|
|
597
|
-
);
|
|
598
|
-
}
|
|
599
|
-
var lookupTableAddressDescription = __DEV__ ? "The address of the address lookup table account from which instruction addresses should be looked up" : "lookupTableAddress";
|
|
600
|
-
var writableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as writeable" : "writableIndices";
|
|
601
|
-
var readableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as read-only" : "readableIndices";
|
|
602
|
-
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";
|
|
603
647
|
var memoizedAddressTableLookupEncoder;
|
|
604
648
|
function getAddressTableLookupEncoder() {
|
|
605
649
|
if (!memoizedAddressTableLookupEncoder) {
|
|
606
|
-
memoizedAddressTableLookupEncoder = codecsDataStructures.getStructEncoder(
|
|
650
|
+
memoizedAddressTableLookupEncoder = codecsDataStructures.getStructEncoder([
|
|
651
|
+
["lookupTableAddress", addresses.getAddressEncoder()],
|
|
607
652
|
[
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
"writableIndices",
|
|
611
|
-
codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder(), {
|
|
612
|
-
description: writableIndicesDescription,
|
|
613
|
-
size: codecsNumbers.getShortU16Encoder()
|
|
614
|
-
})
|
|
615
|
-
],
|
|
616
|
-
[
|
|
617
|
-
"readableIndices",
|
|
618
|
-
codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder(), {
|
|
619
|
-
description: readableIndicesDescription,
|
|
620
|
-
size: codecsNumbers.getShortU16Encoder()
|
|
621
|
-
})
|
|
622
|
-
]
|
|
653
|
+
"writableIndices",
|
|
654
|
+
codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder(), { size: codecsNumbers.getShortU16Encoder() })
|
|
623
655
|
],
|
|
624
|
-
|
|
625
|
-
|
|
656
|
+
[
|
|
657
|
+
"readableIndices",
|
|
658
|
+
codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder(), { size: codecsNumbers.getShortU16Encoder() })
|
|
659
|
+
]
|
|
660
|
+
]);
|
|
626
661
|
}
|
|
627
662
|
return memoizedAddressTableLookupEncoder;
|
|
628
663
|
}
|
|
629
664
|
var memoizedAddressTableLookupDecoder;
|
|
630
665
|
function getAddressTableLookupDecoder() {
|
|
631
666
|
if (!memoizedAddressTableLookupDecoder) {
|
|
632
|
-
memoizedAddressTableLookupDecoder = codecsDataStructures.getStructDecoder(
|
|
633
|
-
[
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), {
|
|
638
|
-
description: writableIndicesDescription,
|
|
639
|
-
size: codecsNumbers.getShortU16Decoder()
|
|
640
|
-
})
|
|
641
|
-
],
|
|
642
|
-
[
|
|
643
|
-
"readableIndices",
|
|
644
|
-
codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), {
|
|
645
|
-
description: readableIndicesDescription,
|
|
646
|
-
size: codecsNumbers.getShortU16Decoder()
|
|
647
|
-
})
|
|
648
|
-
]
|
|
649
|
-
],
|
|
650
|
-
{ description: addressTableLookupDescription }
|
|
651
|
-
);
|
|
667
|
+
memoizedAddressTableLookupDecoder = codecsDataStructures.getStructDecoder([
|
|
668
|
+
["lookupTableAddress", addresses.getAddressDecoder()],
|
|
669
|
+
["writableIndices", codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), { size: codecsNumbers.getShortU16Decoder() })],
|
|
670
|
+
["readableIndices", codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), { size: codecsNumbers.getShortU16Decoder() })]
|
|
671
|
+
]);
|
|
652
672
|
}
|
|
653
673
|
return memoizedAddressTableLookupDecoder;
|
|
654
674
|
}
|
|
@@ -658,72 +678,34 @@ function getMemoizedU8Encoder() {
|
|
|
658
678
|
memoizedU8Encoder = codecsNumbers.getU8Encoder();
|
|
659
679
|
return memoizedU8Encoder;
|
|
660
680
|
}
|
|
661
|
-
function getMemoizedU8EncoderDescription(description) {
|
|
662
|
-
const encoder = getMemoizedU8Encoder();
|
|
663
|
-
return {
|
|
664
|
-
...encoder,
|
|
665
|
-
description: description ?? encoder.description
|
|
666
|
-
};
|
|
667
|
-
}
|
|
668
681
|
var memoizedU8Decoder;
|
|
669
682
|
function getMemoizedU8Decoder() {
|
|
670
683
|
if (!memoizedU8Decoder)
|
|
671
684
|
memoizedU8Decoder = codecsNumbers.getU8Decoder();
|
|
672
685
|
return memoizedU8Decoder;
|
|
673
686
|
}
|
|
674
|
-
function getMemoizedU8DecoderDescription(description) {
|
|
675
|
-
const decoder = getMemoizedU8Decoder();
|
|
676
|
-
return {
|
|
677
|
-
...decoder,
|
|
678
|
-
description: description ?? decoder.description
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
|
-
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;
|
|
682
|
-
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;
|
|
683
|
-
var numReadonlyNonSignerAccountsDescription = __DEV__ ? "The expected number of addresses in the static address list belonging to accounts that are neither signers, nor writable" : void 0;
|
|
684
|
-
var messageHeaderDescription = __DEV__ ? "The transaction message header containing counts of the signer, readonly-signer, and readonly-nonsigner account addresses" : void 0;
|
|
685
687
|
function getMessageHeaderEncoder() {
|
|
686
|
-
return codecsDataStructures.getStructEncoder(
|
|
687
|
-
[
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
],
|
|
692
|
-
{
|
|
693
|
-
description: messageHeaderDescription
|
|
694
|
-
}
|
|
695
|
-
);
|
|
688
|
+
return codecsDataStructures.getStructEncoder([
|
|
689
|
+
["numSignerAccounts", getMemoizedU8Encoder()],
|
|
690
|
+
["numReadonlySignerAccounts", getMemoizedU8Encoder()],
|
|
691
|
+
["numReadonlyNonSignerAccounts", getMemoizedU8Encoder()]
|
|
692
|
+
]);
|
|
696
693
|
}
|
|
697
694
|
function getMessageHeaderDecoder() {
|
|
698
|
-
return codecsDataStructures.getStructDecoder(
|
|
699
|
-
[
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
],
|
|
704
|
-
{
|
|
705
|
-
description: messageHeaderDescription
|
|
706
|
-
}
|
|
707
|
-
);
|
|
695
|
+
return codecsDataStructures.getStructDecoder([
|
|
696
|
+
["numSignerAccounts", getMemoizedU8Decoder()],
|
|
697
|
+
["numReadonlySignerAccounts", getMemoizedU8Decoder()],
|
|
698
|
+
["numReadonlyNonSignerAccounts", getMemoizedU8Decoder()]
|
|
699
|
+
]);
|
|
708
700
|
}
|
|
709
|
-
var programAddressIndexDescription = __DEV__ ? "The index of the program being called, according to the well-ordered accounts list for this transaction" : "programAddressIndex";
|
|
710
|
-
var accountIndexDescription = __DEV__ ? "The index of an account, according to the well-ordered accounts list for this transaction" : void 0;
|
|
711
|
-
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";
|
|
712
|
-
var dataDescription = __DEV__ ? "An optional buffer of data passed to the instruction" : "data";
|
|
713
701
|
var memoizedGetInstructionEncoder;
|
|
714
702
|
function getInstructionEncoder() {
|
|
715
703
|
if (!memoizedGetInstructionEncoder) {
|
|
716
704
|
memoizedGetInstructionEncoder = codecsCore.mapEncoder(
|
|
717
705
|
codecsDataStructures.getStructEncoder([
|
|
718
|
-
["programAddressIndex", codecsNumbers.getU8Encoder(
|
|
719
|
-
[
|
|
720
|
-
|
|
721
|
-
codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder({ description: accountIndexDescription }), {
|
|
722
|
-
description: accountIndicesDescription,
|
|
723
|
-
size: codecsNumbers.getShortU16Encoder()
|
|
724
|
-
})
|
|
725
|
-
],
|
|
726
|
-
["data", codecsDataStructures.getBytesEncoder({ description: dataDescription, size: codecsNumbers.getShortU16Encoder() })]
|
|
706
|
+
["programAddressIndex", codecsNumbers.getU8Encoder()],
|
|
707
|
+
["accountIndices", codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder(), { size: codecsNumbers.getShortU16Encoder() })],
|
|
708
|
+
["data", codecsDataStructures.getBytesEncoder({ size: codecsNumbers.getShortU16Encoder() })]
|
|
727
709
|
]),
|
|
728
710
|
// Convert an instruction to have all fields defined
|
|
729
711
|
(instruction) => {
|
|
@@ -745,15 +727,9 @@ function getInstructionDecoder() {
|
|
|
745
727
|
if (!memoizedGetInstructionDecoder) {
|
|
746
728
|
memoizedGetInstructionDecoder = codecsCore.mapDecoder(
|
|
747
729
|
codecsDataStructures.getStructDecoder([
|
|
748
|
-
["programAddressIndex", codecsNumbers.getU8Decoder(
|
|
749
|
-
[
|
|
750
|
-
|
|
751
|
-
codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder({ description: accountIndexDescription }), {
|
|
752
|
-
description: accountIndicesDescription,
|
|
753
|
-
size: codecsNumbers.getShortU16Decoder()
|
|
754
|
-
})
|
|
755
|
-
],
|
|
756
|
-
["data", codecsDataStructures.getBytesDecoder({ description: dataDescription, size: codecsNumbers.getShortU16Decoder() })]
|
|
730
|
+
["programAddressIndex", codecsNumbers.getU8Decoder()],
|
|
731
|
+
["accountIndices", codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), { size: codecsNumbers.getShortU16Decoder() })],
|
|
732
|
+
["data", codecsDataStructures.getBytesDecoder({ size: codecsNumbers.getShortU16Decoder() })]
|
|
757
733
|
]),
|
|
758
734
|
// Convert an instruction to exclude optional fields if they are empty
|
|
759
735
|
(instruction) => {
|
|
@@ -772,47 +748,40 @@ function getInstructionDecoder() {
|
|
|
772
748
|
return memoizedGetInstructionDecoder;
|
|
773
749
|
}
|
|
774
750
|
var VERSION_FLAG_MASK = 128;
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
}
|
|
793
|
-
if (value < 0 || value > 127) {
|
|
794
|
-
throw new Error(`Transaction version must be in the range [0, 127]. \`${value}\` given.`);
|
|
795
|
-
}
|
|
796
|
-
return new Uint8Array([value | VERSION_FLAG_MASK]);
|
|
751
|
+
function getTransactionVersionEncoder() {
|
|
752
|
+
return codecsCore.createEncoder({
|
|
753
|
+
getSizeFromValue: (value) => value === "legacy" ? 0 : 1,
|
|
754
|
+
maxSize: 1,
|
|
755
|
+
write: (value, bytes, offset) => {
|
|
756
|
+
if (value === "legacy") {
|
|
757
|
+
return offset;
|
|
758
|
+
}
|
|
759
|
+
if (value < 0 || value > 127) {
|
|
760
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_VERSION_NUMBER_OUT_OF_RANGE, {
|
|
761
|
+
actualVersion: value
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
bytes.set([value | VERSION_FLAG_MASK], offset);
|
|
765
|
+
return offset + 1;
|
|
766
|
+
}
|
|
767
|
+
});
|
|
797
768
|
}
|
|
798
769
|
function getTransactionVersionDecoder() {
|
|
799
|
-
return {
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
770
|
+
return codecsCore.createDecoder({
|
|
771
|
+
maxSize: 1,
|
|
772
|
+
read: (bytes, offset) => {
|
|
773
|
+
const firstByte = bytes[offset];
|
|
774
|
+
if ((firstByte & VERSION_FLAG_MASK) === 0) {
|
|
775
|
+
return ["legacy", offset];
|
|
776
|
+
} else {
|
|
777
|
+
const version = firstByte ^ VERSION_FLAG_MASK;
|
|
778
|
+
return [version, offset + 1];
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
});
|
|
809
782
|
}
|
|
810
783
|
|
|
811
784
|
// src/serializers/message.ts
|
|
812
|
-
var staticAccountsDescription = __DEV__ ? "A compact-array of static account addresses belonging to this transaction" : "staticAccounts";
|
|
813
|
-
var lifetimeTokenDescription = __DEV__ ? "A 32-byte token that specifies the lifetime of this transaction (eg. a recent blockhash, or a durable nonce)" : "lifetimeToken";
|
|
814
|
-
var instructionsDescription = __DEV__ ? "A compact-array of instructions belonging to this transaction" : "instructions";
|
|
815
|
-
var addressTableLookupsDescription = __DEV__ ? "A compact array of address table lookups belonging to this transaction" : "addressTableLookups";
|
|
816
785
|
function getCompiledMessageLegacyEncoder() {
|
|
817
786
|
return codecsDataStructures.getStructEncoder(getPreludeStructEncoderTuple());
|
|
818
787
|
}
|
|
@@ -837,91 +806,48 @@ function getPreludeStructEncoderTuple() {
|
|
|
837
806
|
return [
|
|
838
807
|
["version", getTransactionVersionEncoder()],
|
|
839
808
|
["header", getMessageHeaderEncoder()],
|
|
840
|
-
[
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
description: staticAccountsDescription,
|
|
844
|
-
size: codecsNumbers.getShortU16Encoder()
|
|
845
|
-
})
|
|
846
|
-
],
|
|
847
|
-
[
|
|
848
|
-
"lifetimeToken",
|
|
849
|
-
codecsStrings.getStringEncoder({
|
|
850
|
-
description: lifetimeTokenDescription,
|
|
851
|
-
encoding: codecsStrings.getBase58Encoder(),
|
|
852
|
-
size: 32
|
|
853
|
-
})
|
|
854
|
-
],
|
|
855
|
-
[
|
|
856
|
-
"instructions",
|
|
857
|
-
codecsDataStructures.getArrayEncoder(getInstructionEncoder(), {
|
|
858
|
-
description: instructionsDescription,
|
|
859
|
-
size: codecsNumbers.getShortU16Encoder()
|
|
860
|
-
})
|
|
861
|
-
]
|
|
809
|
+
["staticAccounts", codecsDataStructures.getArrayEncoder(addresses.getAddressEncoder(), { size: codecsNumbers.getShortU16Encoder() })],
|
|
810
|
+
["lifetimeToken", codecsStrings.getStringEncoder({ encoding: codecsStrings.getBase58Encoder(), size: 32 })],
|
|
811
|
+
["instructions", codecsDataStructures.getArrayEncoder(getInstructionEncoder(), { size: codecsNumbers.getShortU16Encoder() })]
|
|
862
812
|
];
|
|
863
813
|
}
|
|
864
814
|
function getPreludeStructDecoderTuple() {
|
|
865
815
|
return [
|
|
866
816
|
["version", getTransactionVersionDecoder()],
|
|
867
817
|
["header", getMessageHeaderDecoder()],
|
|
868
|
-
[
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
description: staticAccountsDescription,
|
|
872
|
-
size: codecsNumbers.getShortU16Decoder()
|
|
873
|
-
})
|
|
874
|
-
],
|
|
875
|
-
[
|
|
876
|
-
"lifetimeToken",
|
|
877
|
-
codecsStrings.getStringDecoder({
|
|
878
|
-
description: lifetimeTokenDescription,
|
|
879
|
-
encoding: codecsStrings.getBase58Decoder(),
|
|
880
|
-
size: 32
|
|
881
|
-
})
|
|
882
|
-
],
|
|
883
|
-
[
|
|
884
|
-
"instructions",
|
|
885
|
-
codecsDataStructures.getArrayDecoder(getInstructionDecoder(), {
|
|
886
|
-
description: instructionsDescription,
|
|
887
|
-
size: codecsNumbers.getShortU16Decoder()
|
|
888
|
-
})
|
|
889
|
-
],
|
|
818
|
+
["staticAccounts", codecsDataStructures.getArrayDecoder(addresses.getAddressDecoder(), { size: codecsNumbers.getShortU16Decoder() })],
|
|
819
|
+
["lifetimeToken", codecsStrings.getStringDecoder({ encoding: codecsStrings.getBase58Decoder(), size: 32 })],
|
|
820
|
+
["instructions", codecsDataStructures.getArrayDecoder(getInstructionDecoder(), { size: codecsNumbers.getShortU16Decoder() })],
|
|
890
821
|
["addressTableLookups", getAddressTableLookupArrayDecoder()]
|
|
891
822
|
];
|
|
892
823
|
}
|
|
893
824
|
function getAddressTableLookupArrayEncoder() {
|
|
894
|
-
return codecsDataStructures.getArrayEncoder(getAddressTableLookupEncoder(), {
|
|
895
|
-
description: addressTableLookupsDescription,
|
|
896
|
-
size: codecsNumbers.getShortU16Encoder()
|
|
897
|
-
});
|
|
825
|
+
return codecsDataStructures.getArrayEncoder(getAddressTableLookupEncoder(), { size: codecsNumbers.getShortU16Encoder() });
|
|
898
826
|
}
|
|
899
827
|
function getAddressTableLookupArrayDecoder() {
|
|
900
|
-
return codecsDataStructures.getArrayDecoder(getAddressTableLookupDecoder(), {
|
|
901
|
-
description: addressTableLookupsDescription,
|
|
902
|
-
size: codecsNumbers.getShortU16Decoder()
|
|
903
|
-
});
|
|
828
|
+
return codecsDataStructures.getArrayDecoder(getAddressTableLookupDecoder(), { size: codecsNumbers.getShortU16Decoder() });
|
|
904
829
|
}
|
|
905
|
-
var messageDescription = __DEV__ ? "The wire format of a Solana transaction message" : "message";
|
|
906
830
|
function getCompiledMessageEncoder() {
|
|
907
|
-
return {
|
|
908
|
-
|
|
909
|
-
encode: (compiledMessage) => {
|
|
831
|
+
return codecsCore.createEncoder({
|
|
832
|
+
getSizeFromValue: (compiledMessage) => {
|
|
910
833
|
if (compiledMessage.version === "legacy") {
|
|
911
|
-
return getCompiledMessageLegacyEncoder().
|
|
834
|
+
return getCompiledMessageLegacyEncoder().getSizeFromValue(compiledMessage);
|
|
912
835
|
} else {
|
|
913
|
-
return getCompiledMessageVersionedEncoder().
|
|
836
|
+
return getCompiledMessageVersionedEncoder().getSizeFromValue(compiledMessage);
|
|
914
837
|
}
|
|
915
838
|
},
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
839
|
+
write: (compiledMessage, bytes, offset) => {
|
|
840
|
+
if (compiledMessage.version === "legacy") {
|
|
841
|
+
return getCompiledMessageLegacyEncoder().write(compiledMessage, bytes, offset);
|
|
842
|
+
} else {
|
|
843
|
+
return getCompiledMessageVersionedEncoder().write(compiledMessage, bytes, offset);
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
});
|
|
919
847
|
}
|
|
920
848
|
function getCompiledMessageDecoder() {
|
|
921
849
|
return codecsCore.mapDecoder(
|
|
922
|
-
codecsDataStructures.getStructDecoder(getPreludeStructDecoderTuple(),
|
|
923
|
-
description: messageDescription
|
|
924
|
-
}),
|
|
850
|
+
codecsDataStructures.getStructDecoder(getPreludeStructDecoderTuple()),
|
|
925
851
|
({ addressTableLookups, ...restOfMessage }) => {
|
|
926
852
|
if (restOfMessage.version === "legacy" || !addressTableLookups?.length) {
|
|
927
853
|
return restOfMessage;
|
|
@@ -930,58 +856,57 @@ function getCompiledMessageDecoder() {
|
|
|
930
856
|
}
|
|
931
857
|
);
|
|
932
858
|
}
|
|
859
|
+
function getCompiledMessageCodec() {
|
|
860
|
+
return codecsCore.combineCodec(getCompiledMessageEncoder(), getCompiledMessageDecoder());
|
|
861
|
+
}
|
|
933
862
|
|
|
934
|
-
// src/
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
[
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
codecsDataStructures.getArrayEncoder(codecsDataStructures.getBytesEncoder({ size: 64 }), {
|
|
943
|
-
description: signaturesDescription,
|
|
944
|
-
size: codecsNumbers.getShortU16Encoder()
|
|
945
|
-
})
|
|
946
|
-
],
|
|
947
|
-
["compiledMessage", getCompiledMessageEncoder()]
|
|
948
|
-
],
|
|
949
|
-
{
|
|
950
|
-
description: transactionDescription
|
|
863
|
+
// src/compile-transaction.ts
|
|
864
|
+
function getCompiledTransaction(transaction) {
|
|
865
|
+
const compiledMessage = compileMessage(transaction);
|
|
866
|
+
let signatures;
|
|
867
|
+
if ("signatures" in transaction) {
|
|
868
|
+
signatures = [];
|
|
869
|
+
for (let ii = 0; ii < compiledMessage.header.numSignerAccounts; ii++) {
|
|
870
|
+
signatures[ii] = transaction.signatures[compiledMessage.staticAccounts[ii]] ?? new Uint8Array(Array(64).fill(0));
|
|
951
871
|
}
|
|
952
|
-
|
|
872
|
+
} else {
|
|
873
|
+
signatures = Array(compiledMessage.header.numSignerAccounts).fill(new Uint8Array(Array(64).fill(0)));
|
|
874
|
+
}
|
|
875
|
+
return {
|
|
876
|
+
compiledMessage,
|
|
877
|
+
signatures
|
|
878
|
+
};
|
|
953
879
|
}
|
|
954
|
-
|
|
955
|
-
|
|
880
|
+
|
|
881
|
+
// src/serializers/transaction.ts
|
|
882
|
+
function getCompiledTransactionEncoder() {
|
|
883
|
+
return codecsDataStructures.getStructEncoder([
|
|
884
|
+
["signatures", codecsDataStructures.getArrayEncoder(codecsDataStructures.getBytesEncoder({ size: 64 }), { size: codecsNumbers.getShortU16Encoder() })],
|
|
885
|
+
["compiledMessage", getCompiledMessageEncoder()]
|
|
886
|
+
]);
|
|
956
887
|
}
|
|
957
888
|
function getCompiledTransactionDecoder() {
|
|
958
|
-
return codecsDataStructures.getStructDecoder(
|
|
889
|
+
return codecsDataStructures.getStructDecoder([
|
|
959
890
|
[
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
size: codecsNumbers.getShortU16Decoder()
|
|
965
|
-
})
|
|
966
|
-
],
|
|
967
|
-
["compiledMessage", getCompiledMessageDecoder()]
|
|
891
|
+
"signatures",
|
|
892
|
+
codecsDataStructures.getArrayDecoder(codecsDataStructures.getBytesDecoder({ size: 64 }), {
|
|
893
|
+
size: codecsNumbers.getShortU16Decoder()
|
|
894
|
+
})
|
|
968
895
|
],
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
}
|
|
972
|
-
);
|
|
896
|
+
["compiledMessage", getCompiledMessageDecoder()]
|
|
897
|
+
]);
|
|
973
898
|
}
|
|
974
899
|
function getTransactionEncoder() {
|
|
975
900
|
return codecsCore.mapEncoder(getCompiledTransactionEncoder(), getCompiledTransaction);
|
|
976
901
|
}
|
|
977
|
-
function getTransactionDecoder(
|
|
902
|
+
function getTransactionDecoder(config) {
|
|
978
903
|
return codecsCore.mapDecoder(
|
|
979
904
|
getCompiledTransactionDecoder(),
|
|
980
|
-
(compiledTransaction) => decompileTransaction(compiledTransaction,
|
|
905
|
+
(compiledTransaction) => decompileTransaction(compiledTransaction, config)
|
|
981
906
|
);
|
|
982
907
|
}
|
|
983
|
-
function getTransactionCodec(
|
|
984
|
-
return codecsCore.combineCodec(getTransactionEncoder(), getTransactionDecoder(
|
|
908
|
+
function getTransactionCodec(config) {
|
|
909
|
+
return codecsCore.combineCodec(getTransactionEncoder(), getTransactionDecoder(config));
|
|
985
910
|
}
|
|
986
911
|
var base58Decoder;
|
|
987
912
|
function getSignatureFromTransaction(transaction) {
|
|
@@ -989,11 +914,9 @@ function getSignatureFromTransaction(transaction) {
|
|
|
989
914
|
base58Decoder = codecsStrings.getBase58Decoder();
|
|
990
915
|
const signatureBytes = transaction.signatures[transaction.feePayer];
|
|
991
916
|
if (!signatureBytes) {
|
|
992
|
-
throw new
|
|
993
|
-
"Could not determine this transaction's signature. Make sure that the transaction has been signed by its fee payer."
|
|
994
|
-
);
|
|
917
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_SIGNATURE_NOT_COMPUTABLE);
|
|
995
918
|
}
|
|
996
|
-
const transactionSignature = base58Decoder.decode(signatureBytes)
|
|
919
|
+
const transactionSignature = base58Decoder.decode(signatureBytes);
|
|
997
920
|
return transactionSignature;
|
|
998
921
|
}
|
|
999
922
|
async function partiallySignTransaction(keyPairs, transaction) {
|
|
@@ -1024,34 +947,45 @@ async function signTransaction(keyPairs, transaction) {
|
|
|
1024
947
|
function assertTransactionIsFullySigned(transaction) {
|
|
1025
948
|
const signerAddressesFromInstructions = transaction.instructions.flatMap((i) => i.accounts?.filter((a) => isSignerRole(a.role)) ?? []).map((a) => a.address);
|
|
1026
949
|
const requiredSigners = /* @__PURE__ */ new Set([transaction.feePayer, ...signerAddressesFromInstructions]);
|
|
950
|
+
const missingSigs = [];
|
|
1027
951
|
requiredSigners.forEach((address) => {
|
|
1028
952
|
if (!transaction.signatures[address]) {
|
|
1029
|
-
|
|
953
|
+
missingSigs.push(address);
|
|
1030
954
|
}
|
|
1031
955
|
});
|
|
956
|
+
if (missingSigs.length > 0) {
|
|
957
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_MISSING_SIGNATURES, {
|
|
958
|
+
addresses: missingSigs
|
|
959
|
+
});
|
|
960
|
+
}
|
|
1032
961
|
}
|
|
1033
|
-
|
|
1034
|
-
// src/wire-transaction.ts
|
|
1035
962
|
function getBase64EncodedWireTransaction(transaction) {
|
|
1036
963
|
const wireTransactionBytes = getTransactionEncoder().encode(transaction);
|
|
1037
|
-
|
|
1038
|
-
return btoa(String.fromCharCode(...wireTransactionBytes));
|
|
1039
|
-
}
|
|
964
|
+
return codecsStrings.getBase64Decoder().decode(wireTransactionBytes);
|
|
1040
965
|
}
|
|
1041
966
|
|
|
1042
967
|
exports.appendTransactionInstruction = appendTransactionInstruction;
|
|
1043
|
-
exports.
|
|
968
|
+
exports.appendTransactionInstructions = appendTransactionInstructions;
|
|
1044
969
|
exports.assertIsDurableNonceTransaction = assertIsDurableNonceTransaction;
|
|
970
|
+
exports.assertIsTransactionWithBlockhashLifetime = assertIsTransactionWithBlockhashLifetime;
|
|
1045
971
|
exports.assertTransactionIsFullySigned = assertTransactionIsFullySigned;
|
|
972
|
+
exports.compileMessage = compileMessage;
|
|
1046
973
|
exports.createTransaction = createTransaction;
|
|
974
|
+
exports.decompileTransaction = decompileTransaction;
|
|
1047
975
|
exports.getBase64EncodedWireTransaction = getBase64EncodedWireTransaction;
|
|
976
|
+
exports.getCompiledMessageCodec = getCompiledMessageCodec;
|
|
977
|
+
exports.getCompiledMessageDecoder = getCompiledMessageDecoder;
|
|
978
|
+
exports.getCompiledMessageEncoder = getCompiledMessageEncoder;
|
|
979
|
+
exports.getCompiledTransactionDecoder = getCompiledTransactionDecoder;
|
|
1048
980
|
exports.getSignatureFromTransaction = getSignatureFromTransaction;
|
|
1049
981
|
exports.getTransactionCodec = getTransactionCodec;
|
|
1050
982
|
exports.getTransactionDecoder = getTransactionDecoder;
|
|
1051
983
|
exports.getTransactionEncoder = getTransactionEncoder;
|
|
984
|
+
exports.getUnsignedTransaction = getUnsignedTransaction;
|
|
1052
985
|
exports.isAdvanceNonceAccountInstruction = isAdvanceNonceAccountInstruction;
|
|
1053
986
|
exports.partiallySignTransaction = partiallySignTransaction;
|
|
1054
987
|
exports.prependTransactionInstruction = prependTransactionInstruction;
|
|
988
|
+
exports.prependTransactionInstructions = prependTransactionInstructions;
|
|
1055
989
|
exports.setTransactionFeePayer = setTransactionFeePayer;
|
|
1056
990
|
exports.setTransactionLifetimeUsingBlockhash = setTransactionLifetimeUsingBlockhash;
|
|
1057
991
|
exports.setTransactionLifetimeUsingDurableNonce = setTransactionLifetimeUsingDurableNonce;
|