@solana/transactions 2.0.0-experimental.b927e84 → 2.0.0-experimental.b93299a
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 +490 -292
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +480 -293
- package/dist/index.browser.js.map +1 -1
- package/dist/index.native.js +480 -293
- package/dist/index.native.js.map +1 -1
- package/dist/index.node.cjs +490 -292
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +480 -293
- package/dist/index.node.js.map +1 -1
- package/dist/types/accounts.d.ts +3 -3
- package/dist/types/accounts.d.ts.map +1 -0
- package/dist/types/blockhash.d.ts +5 -7
- package/dist/types/blockhash.d.ts.map +1 -0
- 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 +3 -3
- package/dist/types/compile-address-table-lookups.d.ts.map +1 -0
- package/dist/types/compile-header.d.ts +1 -1
- package/dist/types/compile-header.d.ts.map +1 -0
- package/dist/types/compile-instructions.d.ts +2 -2
- package/dist/types/compile-instructions.d.ts.map +1 -0
- package/dist/types/compile-lifetime-token.d.ts +1 -1
- package/dist/types/compile-lifetime-token.d.ts.map +1 -0
- package/dist/types/compile-static-accounts.d.ts +3 -3
- package/dist/types/compile-static-accounts.d.ts.map +1 -0
- package/dist/types/compile-transaction.d.ts +6 -7
- package/dist/types/compile-transaction.d.ts.map +1 -0
- package/dist/types/create-transaction.d.ts +1 -1
- package/dist/types/create-transaction.d.ts.map +1 -0
- package/dist/types/decompile-transaction.d.ts +13 -0
- package/dist/types/decompile-transaction.d.ts.map +1 -0
- package/dist/types/durable-nonce.d.ts +11 -10
- package/dist/types/durable-nonce.d.ts.map +1 -0
- package/dist/types/fee-payer.d.ts +6 -5
- package/dist/types/fee-payer.d.ts.map +1 -0
- package/dist/types/index.d.ts +12 -8
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/instructions.d.ts +2 -2
- package/dist/types/instructions.d.ts.map +1 -0
- package/dist/types/message.d.ts +6 -10
- package/dist/types/message.d.ts.map +1 -0
- package/dist/types/serializers/address-table-lookup.d.ts +5 -3
- package/dist/types/serializers/address-table-lookup.d.ts.map +1 -0
- package/dist/types/serializers/header.d.ts +5 -3
- package/dist/types/serializers/header.d.ts.map +1 -0
- 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 +5 -3
- package/dist/types/serializers/instruction.d.ts.map +1 -0
- package/dist/types/serializers/message.d.ts +5 -5
- package/dist/types/serializers/message.d.ts.map +1 -0
- package/dist/types/serializers/transaction-version.d.ts +5 -5
- package/dist/types/serializers/transaction-version.d.ts.map +1 -0
- package/dist/types/serializers/transaction.d.ts +9 -5
- package/dist/types/serializers/transaction.d.ts.map +1 -0
- package/dist/types/signatures.d.ts +10 -5
- package/dist/types/signatures.d.ts.map +1 -0
- package/dist/types/types.d.ts +13 -13
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/unsigned-transaction.d.ts +1 -1
- package/dist/types/unsigned-transaction.d.ts.map +1 -0
- package/dist/types/wire-transaction.d.ts +3 -3
- package/dist/types/wire-transaction.d.ts.map +1 -0
- package/package.json +26 -20
- package/dist/index.development.js +0 -1323
- package/dist/index.development.js.map +0 -1
- package/dist/index.production.min.js +0 -20
- package/dist/types/serializers/unimplemented.d.ts +0 -3
package/dist/index.browser.cjs
CHANGED
|
@@ -1,10 +1,38 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var codecsStrings = require('@solana/codecs-strings');
|
|
4
|
+
var addresses = require('@solana/addresses');
|
|
5
|
+
var functional = require('@solana/functional');
|
|
6
|
+
var codecsCore = require('@solana/codecs-core');
|
|
7
|
+
var codecsDataStructures = require('@solana/codecs-data-structures');
|
|
8
|
+
var codecsNumbers = require('@solana/codecs-numbers');
|
|
9
|
+
var errors = require('@solana/errors');
|
|
4
10
|
var keys = require('@solana/keys');
|
|
5
11
|
|
|
6
|
-
// ../
|
|
7
|
-
var
|
|
12
|
+
// ../rpc-types/dist/index.browser.js
|
|
13
|
+
var base58Encoder;
|
|
14
|
+
function assertIsBlockhash(putativeBlockhash) {
|
|
15
|
+
if (!base58Encoder)
|
|
16
|
+
base58Encoder = codecsStrings.getBase58Encoder();
|
|
17
|
+
try {
|
|
18
|
+
if (
|
|
19
|
+
// Lowest value (32 bytes of zeroes)
|
|
20
|
+
putativeBlockhash.length < 32 || // Highest value (32 bytes of 255)
|
|
21
|
+
putativeBlockhash.length > 44
|
|
22
|
+
) {
|
|
23
|
+
throw new Error("Expected input string to decode to a byte array of length 32.");
|
|
24
|
+
}
|
|
25
|
+
const bytes = base58Encoder.encode(putativeBlockhash);
|
|
26
|
+
const numBytes = bytes.byteLength;
|
|
27
|
+
if (numBytes !== 32) {
|
|
28
|
+
throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${numBytes}`);
|
|
29
|
+
}
|
|
30
|
+
} catch (e) {
|
|
31
|
+
throw new Error(`\`${putativeBlockhash}\` is not a blockhash`, {
|
|
32
|
+
cause: e
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
8
36
|
|
|
9
37
|
// src/unsigned-transaction.ts
|
|
10
38
|
function getUnsignedTransaction(transaction) {
|
|
@@ -21,24 +49,20 @@ function getUnsignedTransaction(transaction) {
|
|
|
21
49
|
}
|
|
22
50
|
|
|
23
51
|
// src/blockhash.ts
|
|
24
|
-
function
|
|
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;
|
|
25
56
|
try {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (numBytes !== 32) {
|
|
36
|
-
throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${numBytes}`);
|
|
37
|
-
}
|
|
38
|
-
} catch (e) {
|
|
39
|
-
throw new Error(`\`${putativeBlockhash}\` is not a blockhash`, {
|
|
40
|
-
cause: e
|
|
41
|
-
});
|
|
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 Error("Transaction does not have a blockhash lifetime");
|
|
42
66
|
}
|
|
43
67
|
}
|
|
44
68
|
function setTransactionLifetimeUsingBlockhash(blockhashLifetimeConstraint, transaction) {
|
|
@@ -116,7 +140,7 @@ function isAdvanceNonceAccountInstruction(instruction) {
|
|
|
116
140
|
instruction.accounts?.length === 3 && // First account is nonce account address
|
|
117
141
|
instruction.accounts[0].address != null && instruction.accounts[0].role === AccountRole.WRITABLE && // Second account is recent blockhashes sysvar
|
|
118
142
|
instruction.accounts[1].address === RECENT_BLOCKHASHES_SYSVAR_ADDRESS && instruction.accounts[1].role === AccountRole.READONLY && // Third account is nonce authority account
|
|
119
|
-
instruction.accounts[2].address != null && instruction.accounts[2].role
|
|
143
|
+
instruction.accounts[2].address != null && isSignerRole(instruction.accounts[2].role);
|
|
120
144
|
}
|
|
121
145
|
function isAdvanceNonceAccountInstructionData(data) {
|
|
122
146
|
return data.byteLength === 4 && data[0] === 4 && data[1] === 0 && data[2] === 0 && data[3] === 0;
|
|
@@ -124,21 +148,38 @@ function isAdvanceNonceAccountInstructionData(data) {
|
|
|
124
148
|
function isDurableNonceTransaction(transaction) {
|
|
125
149
|
return "lifetimeConstraint" in transaction && typeof transaction.lifetimeConstraint.nonce === "string" && transaction.instructions[0] != null && isAdvanceNonceAccountInstruction(transaction.instructions[0]);
|
|
126
150
|
}
|
|
151
|
+
function isAdvanceNonceAccountInstructionForNonce(instruction, nonceAccountAddress, nonceAuthorityAddress) {
|
|
152
|
+
return instruction.accounts[0].address === nonceAccountAddress && instruction.accounts[2].address === nonceAuthorityAddress;
|
|
153
|
+
}
|
|
127
154
|
function setTransactionLifetimeUsingDurableNonce({
|
|
128
155
|
nonce,
|
|
129
156
|
nonceAccountAddress,
|
|
130
157
|
nonceAuthorityAddress
|
|
131
158
|
}, transaction) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
159
|
+
let newInstructions;
|
|
160
|
+
const firstInstruction = transaction.instructions[0];
|
|
161
|
+
if (firstInstruction && isAdvanceNonceAccountInstruction(firstInstruction)) {
|
|
162
|
+
if (isAdvanceNonceAccountInstructionForNonce(firstInstruction, nonceAccountAddress, nonceAuthorityAddress)) {
|
|
163
|
+
if (isDurableNonceTransaction(transaction) && transaction.lifetimeConstraint.nonce === nonce) {
|
|
164
|
+
return transaction;
|
|
165
|
+
} else {
|
|
166
|
+
newInstructions = [firstInstruction, ...transaction.instructions.slice(1)];
|
|
167
|
+
}
|
|
168
|
+
} else {
|
|
169
|
+
newInstructions = [
|
|
170
|
+
createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
|
|
171
|
+
...transaction.instructions.slice(1)
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
} else {
|
|
175
|
+
newInstructions = [
|
|
176
|
+
createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
|
|
177
|
+
...transaction.instructions
|
|
178
|
+
];
|
|
135
179
|
}
|
|
136
180
|
const out = {
|
|
137
181
|
...getUnsignedTransaction(transaction),
|
|
138
|
-
instructions:
|
|
139
|
-
createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
|
|
140
|
-
...isAlreadyDurableNonceTransaction ? transaction.instructions.slice(1) : transaction.instructions
|
|
141
|
-
],
|
|
182
|
+
instructions: newInstructions,
|
|
142
183
|
lifetimeConstraint: {
|
|
143
184
|
nonce
|
|
144
185
|
}
|
|
@@ -177,6 +218,151 @@ function prependTransactionInstruction(instruction, transaction) {
|
|
|
177
218
|
Object.freeze(out);
|
|
178
219
|
return out;
|
|
179
220
|
}
|
|
221
|
+
|
|
222
|
+
// src/decompile-transaction.ts
|
|
223
|
+
function getAccountMetas(message) {
|
|
224
|
+
const { header } = message;
|
|
225
|
+
const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
|
|
226
|
+
const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
|
|
227
|
+
const accountMetas = [];
|
|
228
|
+
let accountIndex = 0;
|
|
229
|
+
for (let i = 0; i < numWritableSignerAccounts; i++) {
|
|
230
|
+
accountMetas.push({
|
|
231
|
+
address: message.staticAccounts[accountIndex],
|
|
232
|
+
role: AccountRole.WRITABLE_SIGNER
|
|
233
|
+
});
|
|
234
|
+
accountIndex++;
|
|
235
|
+
}
|
|
236
|
+
for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
|
|
237
|
+
accountMetas.push({
|
|
238
|
+
address: message.staticAccounts[accountIndex],
|
|
239
|
+
role: AccountRole.READONLY_SIGNER
|
|
240
|
+
});
|
|
241
|
+
accountIndex++;
|
|
242
|
+
}
|
|
243
|
+
for (let i = 0; i < numWritableNonSignerAccounts; i++) {
|
|
244
|
+
accountMetas.push({
|
|
245
|
+
address: message.staticAccounts[accountIndex],
|
|
246
|
+
role: AccountRole.WRITABLE
|
|
247
|
+
});
|
|
248
|
+
accountIndex++;
|
|
249
|
+
}
|
|
250
|
+
for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
|
|
251
|
+
accountMetas.push({
|
|
252
|
+
address: message.staticAccounts[accountIndex],
|
|
253
|
+
role: AccountRole.READONLY
|
|
254
|
+
});
|
|
255
|
+
accountIndex++;
|
|
256
|
+
}
|
|
257
|
+
return accountMetas;
|
|
258
|
+
}
|
|
259
|
+
function getAddressLookupMetas(compiledAddressTableLookups, addressesByLookupTableAddress) {
|
|
260
|
+
const compiledAddressTableLookupAddresses = compiledAddressTableLookups.map((l) => l.lookupTableAddress);
|
|
261
|
+
const missing = compiledAddressTableLookupAddresses.filter((a) => addressesByLookupTableAddress[a] === void 0);
|
|
262
|
+
if (missing.length > 0) {
|
|
263
|
+
const missingAddresses = missing.join(", ");
|
|
264
|
+
throw new Error(`Addresses not provided for lookup tables: [${missingAddresses}]`);
|
|
265
|
+
}
|
|
266
|
+
const readOnlyMetas = [];
|
|
267
|
+
const writableMetas = [];
|
|
268
|
+
for (const lookup of compiledAddressTableLookups) {
|
|
269
|
+
const addresses = addressesByLookupTableAddress[lookup.lookupTableAddress];
|
|
270
|
+
const highestIndex = Math.max(...lookup.readableIndices, ...lookup.writableIndices);
|
|
271
|
+
if (highestIndex >= addresses.length) {
|
|
272
|
+
throw new Error(
|
|
273
|
+
`Cannot look up index ${highestIndex} in lookup table [${lookup.lookupTableAddress}]. The lookup table may have been extended since the addresses provided were retrieved.`
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
const readOnlyForLookup = lookup.readableIndices.map((r) => ({
|
|
277
|
+
address: addresses[r],
|
|
278
|
+
addressIndex: r,
|
|
279
|
+
lookupTableAddress: lookup.lookupTableAddress,
|
|
280
|
+
role: AccountRole.READONLY
|
|
281
|
+
}));
|
|
282
|
+
readOnlyMetas.push(...readOnlyForLookup);
|
|
283
|
+
const writableForLookup = lookup.writableIndices.map((w) => ({
|
|
284
|
+
address: addresses[w],
|
|
285
|
+
addressIndex: w,
|
|
286
|
+
lookupTableAddress: lookup.lookupTableAddress,
|
|
287
|
+
role: AccountRole.WRITABLE
|
|
288
|
+
}));
|
|
289
|
+
writableMetas.push(...writableForLookup);
|
|
290
|
+
}
|
|
291
|
+
return [...writableMetas, ...readOnlyMetas];
|
|
292
|
+
}
|
|
293
|
+
function convertInstruction(instruction, accountMetas) {
|
|
294
|
+
const programAddress = accountMetas[instruction.programAddressIndex]?.address;
|
|
295
|
+
if (!programAddress) {
|
|
296
|
+
throw new Error(`Could not find program address at index ${instruction.programAddressIndex}`);
|
|
297
|
+
}
|
|
298
|
+
const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
|
|
299
|
+
const { data } = instruction;
|
|
300
|
+
return {
|
|
301
|
+
programAddress,
|
|
302
|
+
...accounts && accounts.length ? { accounts } : {},
|
|
303
|
+
...data && data.length ? { data } : {}
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
|
|
307
|
+
if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
|
|
308
|
+
return {
|
|
309
|
+
blockhash: messageLifetimeToken,
|
|
310
|
+
lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
|
|
311
|
+
// U64 MAX
|
|
312
|
+
};
|
|
313
|
+
} else {
|
|
314
|
+
const nonceAccountAddress = firstInstruction.accounts[0].address;
|
|
315
|
+
addresses.assertIsAddress(nonceAccountAddress);
|
|
316
|
+
const nonceAuthorityAddress = firstInstruction.accounts[2].address;
|
|
317
|
+
addresses.assertIsAddress(nonceAuthorityAddress);
|
|
318
|
+
return {
|
|
319
|
+
nonce: messageLifetimeToken,
|
|
320
|
+
nonceAccountAddress,
|
|
321
|
+
nonceAuthorityAddress
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function convertSignatures(compiledTransaction) {
|
|
326
|
+
const {
|
|
327
|
+
compiledMessage: { staticAccounts },
|
|
328
|
+
signatures
|
|
329
|
+
} = compiledTransaction;
|
|
330
|
+
return signatures.reduce((acc, sig, index) => {
|
|
331
|
+
const allZeros = sig.every((byte) => byte === 0);
|
|
332
|
+
if (allZeros)
|
|
333
|
+
return acc;
|
|
334
|
+
const address = staticAccounts[index];
|
|
335
|
+
return { ...acc, [address]: sig };
|
|
336
|
+
}, {});
|
|
337
|
+
}
|
|
338
|
+
function decompileTransaction(compiledTransaction, config) {
|
|
339
|
+
const { compiledMessage } = compiledTransaction;
|
|
340
|
+
const feePayer = compiledMessage.staticAccounts[0];
|
|
341
|
+
if (!feePayer)
|
|
342
|
+
throw new Error("No fee payer set in CompiledTransaction");
|
|
343
|
+
const accountMetas = getAccountMetas(compiledMessage);
|
|
344
|
+
const accountLookupMetas = "addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups !== void 0 && compiledMessage.addressTableLookups.length > 0 ? getAddressLookupMetas(compiledMessage.addressTableLookups, config?.addressesByLookupTableAddress ?? {}) : [];
|
|
345
|
+
const transactionMetas = [...accountMetas, ...accountLookupMetas];
|
|
346
|
+
const instructions = compiledMessage.instructions.map(
|
|
347
|
+
(compiledInstruction) => convertInstruction(compiledInstruction, transactionMetas)
|
|
348
|
+
);
|
|
349
|
+
const firstInstruction = instructions[0];
|
|
350
|
+
const lifetimeConstraint = getLifetimeConstraint(
|
|
351
|
+
compiledMessage.lifetimeToken,
|
|
352
|
+
firstInstruction,
|
|
353
|
+
config?.lastValidBlockHeight
|
|
354
|
+
);
|
|
355
|
+
const signatures = convertSignatures(compiledTransaction);
|
|
356
|
+
return functional.pipe(
|
|
357
|
+
createTransaction({ version: compiledMessage.version }),
|
|
358
|
+
(tx) => setTransactionFeePayer(feePayer, tx),
|
|
359
|
+
(tx) => instructions.reduce((acc, instruction) => {
|
|
360
|
+
return appendTransactionInstruction(instruction, acc);
|
|
361
|
+
}, tx),
|
|
362
|
+
(tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
|
|
363
|
+
(tx) => Object.keys(signatures).length > 0 ? { ...tx, signatures } : tx
|
|
364
|
+
);
|
|
365
|
+
}
|
|
180
366
|
function upsert(addressMap, address, update) {
|
|
181
367
|
addressMap[address] = update(addressMap[address] ?? { role: AccountRole.READONLY });
|
|
182
368
|
}
|
|
@@ -229,7 +415,7 @@ function getAddressMapFromInstructions(feePayer, instructions) {
|
|
|
229
415
|
const shouldReplaceEntry = (
|
|
230
416
|
// Consider using the new LOOKUP_TABLE if its address is different...
|
|
231
417
|
entry.lookupTableAddress !== accountMeta.lookupTableAddress && // ...and sorts before the existing one.
|
|
232
|
-
(addressComparator
|
|
418
|
+
(addressComparator ||= addresses.getAddressComparator())(
|
|
233
419
|
accountMeta.lookupTableAddress,
|
|
234
420
|
entry.lookupTableAddress
|
|
235
421
|
) < 0
|
|
@@ -335,7 +521,7 @@ function getOrderedAccountsFromAddressMap(addressMap) {
|
|
|
335
521
|
if (leftIsWritable !== isWritableRole(rightEntry.role)) {
|
|
336
522
|
return leftIsWritable ? -1 : 1;
|
|
337
523
|
}
|
|
338
|
-
addressComparator
|
|
524
|
+
addressComparator ||= addresses.getAddressComparator();
|
|
339
525
|
if (leftEntry[TYPE] === 1 /* LOOKUP_TABLE */ && rightEntry[TYPE] === 1 /* LOOKUP_TABLE */ && leftEntry.lookupTableAddress !== rightEntry.lookupTableAddress) {
|
|
340
526
|
return addressComparator(leftEntry.lookupTableAddress, rightEntry.lookupTableAddress);
|
|
341
527
|
} else {
|
|
@@ -348,23 +534,22 @@ function getOrderedAccountsFromAddressMap(addressMap) {
|
|
|
348
534
|
return orderedAccounts;
|
|
349
535
|
}
|
|
350
536
|
function getCompiledAddressTableLookups(orderedAccounts) {
|
|
351
|
-
var _a;
|
|
352
537
|
const index = {};
|
|
353
538
|
for (const account of orderedAccounts) {
|
|
354
539
|
if (!("lookupTableAddress" in account)) {
|
|
355
540
|
continue;
|
|
356
541
|
}
|
|
357
|
-
const entry = index[
|
|
542
|
+
const entry = index[account.lookupTableAddress] ||= {
|
|
358
543
|
readableIndices: [],
|
|
359
544
|
writableIndices: []
|
|
360
|
-
}
|
|
545
|
+
};
|
|
361
546
|
if (account.role === AccountRole.WRITABLE) {
|
|
362
547
|
entry.writableIndices.push(account.addressIndex);
|
|
363
548
|
} else {
|
|
364
549
|
entry.readableIndices.push(account.addressIndex);
|
|
365
550
|
}
|
|
366
551
|
}
|
|
367
|
-
return Object.keys(index).sort(
|
|
552
|
+
return Object.keys(index).sort(addresses.getAddressComparator()).map((lookupTableAddress) => ({
|
|
368
553
|
lookupTableAddress,
|
|
369
554
|
...index[lookupTableAddress]
|
|
370
555
|
}));
|
|
@@ -443,266 +628,215 @@ function compileMessage(transaction) {
|
|
|
443
628
|
version: transaction.version
|
|
444
629
|
};
|
|
445
630
|
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
keys.getBase58EncodedAddressCodec(
|
|
452
|
-
__DEV__ ? {
|
|
453
|
-
description: "The address of the address lookup table account from which instruction addresses should be looked up"
|
|
454
|
-
} : void 0
|
|
455
|
-
)
|
|
456
|
-
],
|
|
631
|
+
var memoizedAddressTableLookupEncoder;
|
|
632
|
+
function getAddressTableLookupEncoder() {
|
|
633
|
+
if (!memoizedAddressTableLookupEncoder) {
|
|
634
|
+
memoizedAddressTableLookupEncoder = codecsDataStructures.getStructEncoder([
|
|
635
|
+
["lookupTableAddress", addresses.getAddressEncoder()],
|
|
457
636
|
[
|
|
458
637
|
"writableIndices",
|
|
459
|
-
|
|
460
|
-
...__DEV__ ? {
|
|
461
|
-
description: "The indices of the accounts in the lookup table that should be loaded as writeable"
|
|
462
|
-
} : null,
|
|
463
|
-
size: umiSerializers.shortU16()
|
|
464
|
-
})
|
|
638
|
+
codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder(), { size: codecsNumbers.getShortU16Encoder() })
|
|
465
639
|
],
|
|
466
640
|
[
|
|
467
641
|
"readableIndices",
|
|
468
|
-
|
|
469
|
-
...__DEV__ ? {
|
|
470
|
-
description: "The indices of the accounts in the lookup table that should be loaded as read-only"
|
|
471
|
-
} : void 0,
|
|
472
|
-
size: umiSerializers.shortU16()
|
|
473
|
-
})
|
|
642
|
+
codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder(), { size: codecsNumbers.getShortU16Encoder() })
|
|
474
643
|
]
|
|
475
|
-
]
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
644
|
+
]);
|
|
645
|
+
}
|
|
646
|
+
return memoizedAddressTableLookupEncoder;
|
|
647
|
+
}
|
|
648
|
+
var memoizedAddressTableLookupDecoder;
|
|
649
|
+
function getAddressTableLookupDecoder() {
|
|
650
|
+
if (!memoizedAddressTableLookupDecoder) {
|
|
651
|
+
memoizedAddressTableLookupDecoder = codecsDataStructures.getStructDecoder([
|
|
652
|
+
["lookupTableAddress", addresses.getAddressDecoder()],
|
|
653
|
+
["writableIndices", codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), { size: codecsNumbers.getShortU16Decoder() })],
|
|
654
|
+
["readableIndices", codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), { size: codecsNumbers.getShortU16Decoder() })]
|
|
655
|
+
]);
|
|
656
|
+
}
|
|
657
|
+
return memoizedAddressTableLookupDecoder;
|
|
658
|
+
}
|
|
659
|
+
var memoizedU8Encoder;
|
|
660
|
+
function getMemoizedU8Encoder() {
|
|
661
|
+
if (!memoizedU8Encoder)
|
|
662
|
+
memoizedU8Encoder = codecsNumbers.getU8Encoder();
|
|
663
|
+
return memoizedU8Encoder;
|
|
664
|
+
}
|
|
665
|
+
var memoizedU8Decoder;
|
|
666
|
+
function getMemoizedU8Decoder() {
|
|
667
|
+
if (!memoizedU8Decoder)
|
|
668
|
+
memoizedU8Decoder = codecsNumbers.getU8Decoder();
|
|
669
|
+
return memoizedU8Decoder;
|
|
670
|
+
}
|
|
671
|
+
function getMessageHeaderEncoder() {
|
|
672
|
+
return codecsDataStructures.getStructEncoder([
|
|
673
|
+
["numSignerAccounts", getMemoizedU8Encoder()],
|
|
674
|
+
["numReadonlySignerAccounts", getMemoizedU8Encoder()],
|
|
675
|
+
["numReadonlyNonSignerAccounts", getMemoizedU8Encoder()]
|
|
676
|
+
]);
|
|
480
677
|
}
|
|
481
|
-
function
|
|
482
|
-
return
|
|
483
|
-
[
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
__DEV__ ? {
|
|
488
|
-
description: "The expected number of addresses in the static address list belonging to accounts that are required to sign this transaction"
|
|
489
|
-
} : void 0
|
|
490
|
-
)
|
|
491
|
-
],
|
|
492
|
-
[
|
|
493
|
-
"numReadonlySignerAccounts",
|
|
494
|
-
umiSerializers.u8(
|
|
495
|
-
__DEV__ ? {
|
|
496
|
-
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"
|
|
497
|
-
} : void 0
|
|
498
|
-
)
|
|
499
|
-
],
|
|
500
|
-
[
|
|
501
|
-
"numReadonlyNonSignerAccounts",
|
|
502
|
-
umiSerializers.u8(
|
|
503
|
-
__DEV__ ? {
|
|
504
|
-
description: "The expected number of addresses in the static address list belonging to accounts that are neither signers, nor writable"
|
|
505
|
-
} : void 0
|
|
506
|
-
)
|
|
507
|
-
]
|
|
508
|
-
],
|
|
509
|
-
__DEV__ ? {
|
|
510
|
-
description: "The transaction message header containing counts of the signer, readonly-signer, and readonly-nonsigner account addresses"
|
|
511
|
-
} : void 0
|
|
512
|
-
);
|
|
678
|
+
function getMessageHeaderDecoder() {
|
|
679
|
+
return codecsDataStructures.getStructDecoder([
|
|
680
|
+
["numSignerAccounts", getMemoizedU8Decoder()],
|
|
681
|
+
["numReadonlySignerAccounts", getMemoizedU8Decoder()],
|
|
682
|
+
["numReadonlyNonSignerAccounts", getMemoizedU8Decoder()]
|
|
683
|
+
]);
|
|
513
684
|
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
685
|
+
var memoizedGetInstructionEncoder;
|
|
686
|
+
function getInstructionEncoder() {
|
|
687
|
+
if (!memoizedGetInstructionEncoder) {
|
|
688
|
+
memoizedGetInstructionEncoder = codecsCore.mapEncoder(
|
|
689
|
+
codecsDataStructures.getStructEncoder([
|
|
690
|
+
["programAddressIndex", codecsNumbers.getU8Encoder()],
|
|
691
|
+
["accountIndices", codecsDataStructures.getArrayEncoder(codecsNumbers.getU8Encoder(), { size: codecsNumbers.getShortU16Encoder() })],
|
|
692
|
+
["data", codecsDataStructures.getBytesEncoder({ size: codecsNumbers.getShortU16Encoder() })]
|
|
693
|
+
]),
|
|
694
|
+
// Convert an instruction to have all fields defined
|
|
695
|
+
(instruction) => {
|
|
696
|
+
if (instruction.accountIndices !== void 0 && instruction.data !== void 0) {
|
|
697
|
+
return instruction;
|
|
698
|
+
}
|
|
699
|
+
return {
|
|
700
|
+
...instruction,
|
|
701
|
+
accountIndices: instruction.accountIndices ?? [],
|
|
702
|
+
data: instruction.data ?? new Uint8Array(0)
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
return memoizedGetInstructionEncoder;
|
|
708
|
+
}
|
|
709
|
+
var memoizedGetInstructionDecoder;
|
|
710
|
+
function getInstructionDecoder() {
|
|
711
|
+
if (!memoizedGetInstructionDecoder) {
|
|
712
|
+
memoizedGetInstructionDecoder = codecsCore.mapDecoder(
|
|
713
|
+
codecsDataStructures.getStructDecoder([
|
|
714
|
+
["programAddressIndex", codecsNumbers.getU8Decoder()],
|
|
715
|
+
["accountIndices", codecsDataStructures.getArrayDecoder(codecsNumbers.getU8Decoder(), { size: codecsNumbers.getShortU16Decoder() })],
|
|
716
|
+
["data", codecsDataStructures.getBytesDecoder({ size: codecsNumbers.getShortU16Decoder() })]
|
|
717
|
+
]),
|
|
718
|
+
// Convert an instruction to exclude optional fields if they are empty
|
|
719
|
+
(instruction) => {
|
|
720
|
+
if (instruction.accountIndices.length && instruction.data.byteLength) {
|
|
721
|
+
return instruction;
|
|
722
|
+
}
|
|
723
|
+
const { accountIndices, data, ...rest } = instruction;
|
|
724
|
+
return {
|
|
725
|
+
...rest,
|
|
726
|
+
...accountIndices.length ? { accountIndices } : null,
|
|
727
|
+
...data.byteLength ? { data } : null
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
return memoizedGetInstructionDecoder;
|
|
733
|
+
}
|
|
734
|
+
var VERSION_FLAG_MASK = 128;
|
|
735
|
+
function getTransactionVersionEncoder() {
|
|
736
|
+
return codecsCore.createEncoder({
|
|
737
|
+
getSizeFromValue: (value) => value === "legacy" ? 0 : 1,
|
|
738
|
+
maxSize: 1,
|
|
739
|
+
write: (value, bytes, offset) => {
|
|
740
|
+
if (value === "legacy") {
|
|
741
|
+
return offset;
|
|
742
|
+
}
|
|
743
|
+
if (value < 0 || value > 127) {
|
|
744
|
+
throw new Error(`Transaction version must be in the range [0, 127]. \`${value}\` given.`);
|
|
745
|
+
}
|
|
746
|
+
bytes.set([value | VERSION_FLAG_MASK], offset);
|
|
747
|
+
return offset + 1;
|
|
748
|
+
}
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
function getTransactionVersionDecoder() {
|
|
752
|
+
return codecsCore.createDecoder({
|
|
753
|
+
maxSize: 1,
|
|
754
|
+
read: (bytes, offset) => {
|
|
755
|
+
const firstByte = bytes[offset];
|
|
756
|
+
if ((firstByte & VERSION_FLAG_MASK) === 0) {
|
|
757
|
+
return ["legacy", offset];
|
|
758
|
+
} else {
|
|
759
|
+
const version = firstByte ^ VERSION_FLAG_MASK;
|
|
760
|
+
return [version, offset + 1];
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// src/serializers/message.ts
|
|
767
|
+
function getCompiledMessageLegacyEncoder() {
|
|
768
|
+
return codecsDataStructures.getStructEncoder(getPreludeStructEncoderTuple());
|
|
769
|
+
}
|
|
770
|
+
function getCompiledMessageVersionedEncoder() {
|
|
771
|
+
return codecsCore.mapEncoder(
|
|
772
|
+
codecsDataStructures.getStructEncoder([
|
|
773
|
+
...getPreludeStructEncoderTuple(),
|
|
774
|
+
["addressTableLookups", getAddressTableLookupArrayEncoder()]
|
|
544
775
|
]),
|
|
545
776
|
(value) => {
|
|
546
|
-
if (value.
|
|
777
|
+
if (value.version === "legacy") {
|
|
547
778
|
return value;
|
|
548
779
|
}
|
|
549
780
|
return {
|
|
550
781
|
...value,
|
|
551
|
-
|
|
552
|
-
data: value.data ?? new Uint8Array(0)
|
|
553
|
-
};
|
|
554
|
-
},
|
|
555
|
-
(value) => {
|
|
556
|
-
if (value.addressIndices.length && value.data.byteLength) {
|
|
557
|
-
return value;
|
|
558
|
-
}
|
|
559
|
-
const { addressIndices, data, ...rest } = value;
|
|
560
|
-
return {
|
|
561
|
-
...rest,
|
|
562
|
-
...addressIndices.length ? { addressIndices } : null,
|
|
563
|
-
...data.byteLength ? { data } : null
|
|
782
|
+
addressTableLookups: value.addressTableLookups ?? []
|
|
564
783
|
};
|
|
565
784
|
}
|
|
566
785
|
);
|
|
567
786
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
function getUnimplementedDecoder(name) {
|
|
577
|
-
return () => {
|
|
578
|
-
throw getError("decoder", name);
|
|
579
|
-
};
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
// src/serializers/transaction-version.ts
|
|
583
|
-
var VERSION_FLAG_MASK = 128;
|
|
584
|
-
var BASE_CONFIG = {
|
|
585
|
-
description: __DEV__ ? "A single byte that encodes the version of the transaction" : "",
|
|
586
|
-
fixedSize: null,
|
|
587
|
-
maxSize: 1
|
|
588
|
-
};
|
|
589
|
-
function deserialize(bytes3, offset = 0) {
|
|
590
|
-
const firstByte = bytes3[offset];
|
|
591
|
-
if ((firstByte & VERSION_FLAG_MASK) === 0) {
|
|
592
|
-
return ["legacy", offset];
|
|
593
|
-
} else {
|
|
594
|
-
const version = firstByte ^ VERSION_FLAG_MASK;
|
|
595
|
-
return [version, offset + 1];
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
function serialize(value) {
|
|
599
|
-
if (value === "legacy") {
|
|
600
|
-
return new Uint8Array();
|
|
601
|
-
}
|
|
602
|
-
if (value < 0 || value > 127) {
|
|
603
|
-
throw new Error(`Transaction version must be in the range [0, 127]. \`${value}\` given.`);
|
|
604
|
-
}
|
|
605
|
-
return new Uint8Array([value | VERSION_FLAG_MASK]);
|
|
606
|
-
}
|
|
607
|
-
function getTransactionVersionCodec() {
|
|
608
|
-
return {
|
|
609
|
-
...BASE_CONFIG,
|
|
610
|
-
deserialize,
|
|
611
|
-
serialize
|
|
612
|
-
};
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
// src/serializers/message.ts
|
|
616
|
-
var BASE_CONFIG2 = {
|
|
617
|
-
description: __DEV__ ? "The wire format of a Solana transaction message" : "",
|
|
618
|
-
fixedSize: null,
|
|
619
|
-
maxSize: null
|
|
620
|
-
};
|
|
621
|
-
function serialize2(compiledMessage) {
|
|
622
|
-
if (compiledMessage.version === "legacy") {
|
|
623
|
-
return umiSerializers.struct(getPreludeStructSerializerTuple()).serialize(compiledMessage);
|
|
624
|
-
} else {
|
|
625
|
-
return umiSerializers.mapSerializer(
|
|
626
|
-
umiSerializers.struct([
|
|
627
|
-
...getPreludeStructSerializerTuple(),
|
|
628
|
-
["addressTableLookups", getAddressTableLookupsSerializer()]
|
|
629
|
-
]),
|
|
630
|
-
(value) => {
|
|
631
|
-
if (value.version === "legacy") {
|
|
632
|
-
return value;
|
|
633
|
-
}
|
|
634
|
-
return {
|
|
635
|
-
...value,
|
|
636
|
-
addressTableLookups: value.addressTableLookups ?? []
|
|
637
|
-
};
|
|
638
|
-
}
|
|
639
|
-
).serialize(compiledMessage);
|
|
640
|
-
}
|
|
787
|
+
function getPreludeStructEncoderTuple() {
|
|
788
|
+
return [
|
|
789
|
+
["version", getTransactionVersionEncoder()],
|
|
790
|
+
["header", getMessageHeaderEncoder()],
|
|
791
|
+
["staticAccounts", codecsDataStructures.getArrayEncoder(addresses.getAddressEncoder(), { size: codecsNumbers.getShortU16Encoder() })],
|
|
792
|
+
["lifetimeToken", codecsStrings.getStringEncoder({ encoding: codecsStrings.getBase58Encoder(), size: 32 })],
|
|
793
|
+
["instructions", codecsDataStructures.getArrayEncoder(getInstructionEncoder(), { size: codecsNumbers.getShortU16Encoder() })]
|
|
794
|
+
];
|
|
641
795
|
}
|
|
642
|
-
function
|
|
796
|
+
function getPreludeStructDecoderTuple() {
|
|
643
797
|
return [
|
|
644
|
-
["version",
|
|
645
|
-
["header",
|
|
646
|
-
[
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
size: umiSerializers.shortU16()
|
|
651
|
-
})
|
|
652
|
-
],
|
|
653
|
-
[
|
|
654
|
-
"lifetimeToken",
|
|
655
|
-
umiSerializers.string({
|
|
656
|
-
description: __DEV__ ? "A 32-byte token that specifies the lifetime of this transaction (eg. a recent blockhash, or a durable nonce)" : "",
|
|
657
|
-
encoding: umiSerializers.base58,
|
|
658
|
-
size: 32
|
|
659
|
-
})
|
|
660
|
-
],
|
|
661
|
-
[
|
|
662
|
-
"instructions",
|
|
663
|
-
umiSerializers.array(getInstructionCodec(), {
|
|
664
|
-
description: __DEV__ ? "A compact-array of instructions belonging to this transaction" : "",
|
|
665
|
-
size: umiSerializers.shortU16()
|
|
666
|
-
})
|
|
667
|
-
]
|
|
798
|
+
["version", getTransactionVersionDecoder()],
|
|
799
|
+
["header", getMessageHeaderDecoder()],
|
|
800
|
+
["staticAccounts", codecsDataStructures.getArrayDecoder(addresses.getAddressDecoder(), { size: codecsNumbers.getShortU16Decoder() })],
|
|
801
|
+
["lifetimeToken", codecsStrings.getStringDecoder({ encoding: codecsStrings.getBase58Decoder(), size: 32 })],
|
|
802
|
+
["instructions", codecsDataStructures.getArrayDecoder(getInstructionDecoder(), { size: codecsNumbers.getShortU16Decoder() })],
|
|
803
|
+
["addressTableLookups", getAddressTableLookupArrayDecoder()]
|
|
668
804
|
];
|
|
669
805
|
}
|
|
670
|
-
function
|
|
671
|
-
return
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
});
|
|
806
|
+
function getAddressTableLookupArrayEncoder() {
|
|
807
|
+
return codecsDataStructures.getArrayEncoder(getAddressTableLookupEncoder(), { size: codecsNumbers.getShortU16Encoder() });
|
|
808
|
+
}
|
|
809
|
+
function getAddressTableLookupArrayDecoder() {
|
|
810
|
+
return codecsDataStructures.getArrayDecoder(getAddressTableLookupDecoder(), { size: codecsNumbers.getShortU16Decoder() });
|
|
675
811
|
}
|
|
676
812
|
function getCompiledMessageEncoder() {
|
|
677
|
-
return {
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
813
|
+
return codecsCore.createEncoder({
|
|
814
|
+
getSizeFromValue: (compiledMessage) => {
|
|
815
|
+
if (compiledMessage.version === "legacy") {
|
|
816
|
+
return getCompiledMessageLegacyEncoder().getSizeFromValue(compiledMessage);
|
|
817
|
+
} else {
|
|
818
|
+
return getCompiledMessageVersionedEncoder().getSizeFromValue(compiledMessage);
|
|
819
|
+
}
|
|
820
|
+
},
|
|
821
|
+
write: (compiledMessage, bytes, offset) => {
|
|
822
|
+
if (compiledMessage.version === "legacy") {
|
|
823
|
+
return getCompiledMessageLegacyEncoder().write(compiledMessage, bytes, offset);
|
|
824
|
+
} else {
|
|
825
|
+
return getCompiledMessageVersionedEncoder().write(compiledMessage, bytes, offset);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
});
|
|
682
829
|
}
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
830
|
+
function getCompiledMessageDecoder() {
|
|
831
|
+
return codecsCore.mapDecoder(codecsDataStructures.getStructDecoder(getPreludeStructDecoderTuple()), ({ addressTableLookups, ...restOfMessage }) => {
|
|
832
|
+
if (restOfMessage.version === "legacy" || !addressTableLookups?.length) {
|
|
833
|
+
return restOfMessage;
|
|
834
|
+
}
|
|
835
|
+
return { ...restOfMessage, addressTableLookups };
|
|
836
|
+
});
|
|
689
837
|
}
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
const [signerPublicKey, signature] = await Promise.all([
|
|
693
|
-
keys.getBase58EncodedAddressFromPublicKey(keyPair.publicKey),
|
|
694
|
-
getCompiledMessageSignature(compiledMessage, keyPair.privateKey)
|
|
695
|
-
]);
|
|
696
|
-
const nextSignatures = {
|
|
697
|
-
..."signatures" in transaction ? transaction.signatures : null,
|
|
698
|
-
...{ [signerPublicKey]: signature }
|
|
699
|
-
};
|
|
700
|
-
const out = {
|
|
701
|
-
...transaction,
|
|
702
|
-
signatures: nextSignatures
|
|
703
|
-
};
|
|
704
|
-
Object.freeze(out);
|
|
705
|
-
return out;
|
|
838
|
+
function getCompiledMessageCodec() {
|
|
839
|
+
return codecsCore.combineCodec(getCompiledMessageEncoder(), getCompiledMessageDecoder());
|
|
706
840
|
}
|
|
707
841
|
|
|
708
842
|
// src/compile-transaction.ts
|
|
@@ -724,45 +858,109 @@ function getCompiledTransaction(transaction) {
|
|
|
724
858
|
}
|
|
725
859
|
|
|
726
860
|
// src/serializers/transaction.ts
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
return
|
|
861
|
+
function getCompiledTransactionEncoder() {
|
|
862
|
+
return codecsDataStructures.getStructEncoder([
|
|
863
|
+
["signatures", codecsDataStructures.getArrayEncoder(codecsDataStructures.getBytesEncoder({ size: 64 }), { size: codecsNumbers.getShortU16Encoder() })],
|
|
864
|
+
["compiledMessage", getCompiledMessageEncoder()]
|
|
865
|
+
]);
|
|
866
|
+
}
|
|
867
|
+
function getCompiledTransactionDecoder() {
|
|
868
|
+
return codecsDataStructures.getStructDecoder([
|
|
735
869
|
[
|
|
736
870
|
"signatures",
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
size: umiSerializers.shortU16()
|
|
871
|
+
codecsDataStructures.getArrayDecoder(codecsDataStructures.getBytesDecoder({ size: 64 }), {
|
|
872
|
+
size: codecsNumbers.getShortU16Decoder()
|
|
740
873
|
})
|
|
741
874
|
],
|
|
742
|
-
["compiledMessage",
|
|
743
|
-
])
|
|
875
|
+
["compiledMessage", getCompiledMessageDecoder()]
|
|
876
|
+
]);
|
|
744
877
|
}
|
|
745
878
|
function getTransactionEncoder() {
|
|
746
|
-
return
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
879
|
+
return codecsCore.mapEncoder(getCompiledTransactionEncoder(), getCompiledTransaction);
|
|
880
|
+
}
|
|
881
|
+
function getTransactionDecoder(config) {
|
|
882
|
+
return codecsCore.mapDecoder(
|
|
883
|
+
getCompiledTransactionDecoder(),
|
|
884
|
+
(compiledTransaction) => decompileTransaction(compiledTransaction, config)
|
|
885
|
+
);
|
|
886
|
+
}
|
|
887
|
+
function getTransactionCodec(config) {
|
|
888
|
+
return codecsCore.combineCodec(getTransactionEncoder(), getTransactionDecoder(config));
|
|
889
|
+
}
|
|
890
|
+
var base58Decoder;
|
|
891
|
+
function getSignatureFromTransaction(transaction) {
|
|
892
|
+
if (!base58Decoder)
|
|
893
|
+
base58Decoder = codecsStrings.getBase58Decoder();
|
|
894
|
+
const signatureBytes = transaction.signatures[transaction.feePayer];
|
|
895
|
+
if (!signatureBytes) {
|
|
896
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_SIGNATURE_NOT_COMPUTABLE);
|
|
897
|
+
}
|
|
898
|
+
const transactionSignature = base58Decoder.decode(signatureBytes);
|
|
899
|
+
return transactionSignature;
|
|
900
|
+
}
|
|
901
|
+
async function partiallySignTransaction(keyPairs, transaction) {
|
|
902
|
+
const compiledMessage = compileMessage(transaction);
|
|
903
|
+
const nextSignatures = "signatures" in transaction ? { ...transaction.signatures } : {};
|
|
904
|
+
const wireMessageBytes = getCompiledMessageEncoder().encode(compiledMessage);
|
|
905
|
+
const publicKeySignaturePairs = await Promise.all(
|
|
906
|
+
keyPairs.map(
|
|
907
|
+
(keyPair) => Promise.all([addresses.getAddressFromPublicKey(keyPair.publicKey), keys.signBytes(keyPair.privateKey, wireMessageBytes)])
|
|
908
|
+
)
|
|
909
|
+
);
|
|
910
|
+
for (const [signerPublicKey, signature] of publicKeySignaturePairs) {
|
|
911
|
+
nextSignatures[signerPublicKey] = signature;
|
|
912
|
+
}
|
|
913
|
+
const out = {
|
|
914
|
+
...transaction,
|
|
915
|
+
signatures: nextSignatures
|
|
750
916
|
};
|
|
917
|
+
Object.freeze(out);
|
|
918
|
+
return out;
|
|
751
919
|
}
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
920
|
+
async function signTransaction(keyPairs, transaction) {
|
|
921
|
+
const out = await partiallySignTransaction(keyPairs, transaction);
|
|
922
|
+
assertTransactionIsFullySigned(out);
|
|
923
|
+
Object.freeze(out);
|
|
924
|
+
return out;
|
|
925
|
+
}
|
|
926
|
+
function assertTransactionIsFullySigned(transaction) {
|
|
927
|
+
const signerAddressesFromInstructions = transaction.instructions.flatMap((i) => i.accounts?.filter((a) => isSignerRole(a.role)) ?? []).map((a) => a.address);
|
|
928
|
+
const requiredSigners = /* @__PURE__ */ new Set([transaction.feePayer, ...signerAddressesFromInstructions]);
|
|
929
|
+
const missingSigs = [];
|
|
930
|
+
requiredSigners.forEach((address) => {
|
|
931
|
+
if (!transaction.signatures[address]) {
|
|
932
|
+
missingSigs.push(address);
|
|
933
|
+
}
|
|
934
|
+
});
|
|
935
|
+
if (missingSigs.length > 0) {
|
|
936
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_MISSING_SIGNATURES, {
|
|
937
|
+
addresses: missingSigs
|
|
938
|
+
});
|
|
758
939
|
}
|
|
759
940
|
}
|
|
941
|
+
function getBase64EncodedWireTransaction(transaction) {
|
|
942
|
+
const wireTransactionBytes = getTransactionEncoder().encode(transaction);
|
|
943
|
+
return codecsStrings.getBase64Decoder().decode(wireTransactionBytes);
|
|
944
|
+
}
|
|
760
945
|
|
|
761
946
|
exports.appendTransactionInstruction = appendTransactionInstruction;
|
|
762
|
-
exports.assertIsBlockhash = assertIsBlockhash;
|
|
763
947
|
exports.assertIsDurableNonceTransaction = assertIsDurableNonceTransaction;
|
|
948
|
+
exports.assertIsTransactionWithBlockhashLifetime = assertIsTransactionWithBlockhashLifetime;
|
|
949
|
+
exports.assertTransactionIsFullySigned = assertTransactionIsFullySigned;
|
|
950
|
+
exports.compileMessage = compileMessage;
|
|
764
951
|
exports.createTransaction = createTransaction;
|
|
952
|
+
exports.decompileTransaction = decompileTransaction;
|
|
765
953
|
exports.getBase64EncodedWireTransaction = getBase64EncodedWireTransaction;
|
|
954
|
+
exports.getCompiledMessageCodec = getCompiledMessageCodec;
|
|
955
|
+
exports.getCompiledMessageDecoder = getCompiledMessageDecoder;
|
|
956
|
+
exports.getCompiledMessageEncoder = getCompiledMessageEncoder;
|
|
957
|
+
exports.getCompiledTransactionDecoder = getCompiledTransactionDecoder;
|
|
958
|
+
exports.getSignatureFromTransaction = getSignatureFromTransaction;
|
|
959
|
+
exports.getTransactionCodec = getTransactionCodec;
|
|
960
|
+
exports.getTransactionDecoder = getTransactionDecoder;
|
|
961
|
+
exports.getTransactionEncoder = getTransactionEncoder;
|
|
962
|
+
exports.isAdvanceNonceAccountInstruction = isAdvanceNonceAccountInstruction;
|
|
963
|
+
exports.partiallySignTransaction = partiallySignTransaction;
|
|
766
964
|
exports.prependTransactionInstruction = prependTransactionInstruction;
|
|
767
965
|
exports.setTransactionFeePayer = setTransactionFeePayer;
|
|
768
966
|
exports.setTransactionLifetimeUsingBlockhash = setTransactionLifetimeUsingBlockhash;
|