@solana/transactions 2.0.0-experimental.e1ca396 → 2.0.0-experimental.e3e579c
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 +197 -144
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +197 -148
- package/dist/index.browser.js.map +1 -1
- package/dist/index.native.js +197 -148
- package/dist/index.native.js.map +1 -1
- package/dist/index.node.cjs +197 -144
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +199 -148
- package/dist/index.node.js.map +1 -1
- package/dist/types/blockhash.d.ts +4 -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/fee-payer.d.ts +2 -2
- package/dist/types/index.d.ts +13 -11
- 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 +1 -1
- package/dist/types/serializers/header.d.ts +1 -1
- package/dist/types/serializers/index.d.ts +2 -2
- package/dist/types/serializers/instruction.d.ts +1 -1
- package/dist/types/serializers/message.d.ts +1 -1
- package/dist/types/serializers/message.d.ts.map +1 -1
- package/dist/types/serializers/transaction-version.d.ts +1 -1
- package/dist/types/serializers/transaction.d.ts +7 -4
- 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/package.json +18 -39
- package/dist/index.development.js +0 -1628
- package/dist/index.development.js.map +0 -1
- package/dist/index.production.min.js +0 -32
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ const transferTransaction = pipe(
|
|
|
30
30
|
createTransaction({ version: 0 }),
|
|
31
31
|
tx => setTransactionFeePayer(myAddress, tx),
|
|
32
32
|
tx => setTransactionLifetimeUsingBlockhash(latestBlockhash, tx),
|
|
33
|
-
tx => appendTransactionInstruction(createTransferInstruction(myAddress, toAddress, amountInLamports), tx)
|
|
33
|
+
tx => appendTransactionInstruction(createTransferInstruction(myAddress, toAddress, amountInLamports), tx),
|
|
34
34
|
);
|
|
35
35
|
```
|
|
36
36
|
|
|
@@ -144,7 +144,7 @@ const nonce =
|
|
|
144
144
|
|
|
145
145
|
const durableNonceTransaction = setTransactionLifetimeUsingDurableNonce(
|
|
146
146
|
{ nonce, nonceAccountAddress, nonceAuthorityAddress },
|
|
147
|
-
tx
|
|
147
|
+
tx,
|
|
148
148
|
);
|
|
149
149
|
```
|
|
150
150
|
|
|
@@ -210,14 +210,18 @@ const memoTransaction = appendTransactionInstruction(
|
|
|
210
210
|
data: new TextEncoder().encode('Hello world!'),
|
|
211
211
|
programAddress: address('MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'),
|
|
212
212
|
},
|
|
213
|
-
tx
|
|
213
|
+
tx,
|
|
214
214
|
);
|
|
215
215
|
```
|
|
216
216
|
|
|
217
|
+
If you'd like to add multiple instructions to a transaction at once, you may use the `appendTransactionInstructions` function instead which accepts an array of instructions.
|
|
218
|
+
|
|
217
219
|
#### `prependTransactionInstruction()`
|
|
218
220
|
|
|
219
221
|
Given an instruction, this method will return a new transaction with that instruction having been added to the beginning of the list of existing instructions.
|
|
220
222
|
|
|
223
|
+
If you'd like to prepend multiple instructions to a transaction at once, you may use the `prependTransactionInstructions` function instead which accepts an array of instructions.
|
|
224
|
+
|
|
221
225
|
See [`appendTransactionInstruction()`](#appendtransactioninstruction) for an example of how to use this function.
|
|
222
226
|
|
|
223
227
|
## Signing transactions
|
package/dist/index.browser.cjs
CHANGED
|
@@ -2,29 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
var codecsStrings = require('@solana/codecs-strings');
|
|
4
4
|
var addresses = require('@solana/addresses');
|
|
5
|
+
var functional = require('@solana/functional');
|
|
5
6
|
var codecsCore = require('@solana/codecs-core');
|
|
6
7
|
var codecsDataStructures = require('@solana/codecs-data-structures');
|
|
7
8
|
var codecsNumbers = require('@solana/codecs-numbers');
|
|
8
|
-
var
|
|
9
|
+
var errors = require('@solana/errors');
|
|
9
10
|
var keys = require('@solana/keys');
|
|
10
11
|
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
// src/unsigned-transaction.ts
|
|
14
|
-
function getUnsignedTransaction(transaction) {
|
|
15
|
-
if ("signatures" in transaction) {
|
|
16
|
-
const {
|
|
17
|
-
signatures: _,
|
|
18
|
-
// eslint-disable-line @typescript-eslint/no-unused-vars
|
|
19
|
-
...unsignedTransaction
|
|
20
|
-
} = transaction;
|
|
21
|
-
return unsignedTransaction;
|
|
22
|
-
} else {
|
|
23
|
-
return transaction;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// src/blockhash.ts
|
|
12
|
+
// ../rpc-types/dist/index.browser.js
|
|
28
13
|
var base58Encoder;
|
|
29
14
|
function assertIsBlockhash(putativeBlockhash) {
|
|
30
15
|
if (!base58Encoder)
|
|
@@ -48,6 +33,22 @@ function assertIsBlockhash(putativeBlockhash) {
|
|
|
48
33
|
});
|
|
49
34
|
}
|
|
50
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
|
|
51
52
|
function isTransactionWithBlockhashLifetime(transaction) {
|
|
52
53
|
const lifetimeConstraintShapeMatches = "lifetimeConstraint" in transaction && typeof transaction.lifetimeConstraint.blockhash === "string" && typeof transaction.lifetimeConstraint.lastValidBlockHeight === "bigint";
|
|
53
54
|
if (!lifetimeConstraintShapeMatches)
|
|
@@ -202,21 +203,172 @@ function setTransactionFeePayer(feePayer, transaction) {
|
|
|
202
203
|
|
|
203
204
|
// src/instructions.ts
|
|
204
205
|
function appendTransactionInstruction(instruction, transaction) {
|
|
206
|
+
return appendTransactionInstructions([instruction], transaction);
|
|
207
|
+
}
|
|
208
|
+
function appendTransactionInstructions(instructions, transaction) {
|
|
205
209
|
const out = {
|
|
206
210
|
...getUnsignedTransaction(transaction),
|
|
207
|
-
instructions: [...transaction.instructions,
|
|
211
|
+
instructions: [...transaction.instructions, ...instructions]
|
|
208
212
|
};
|
|
209
213
|
Object.freeze(out);
|
|
210
214
|
return out;
|
|
211
215
|
}
|
|
212
216
|
function prependTransactionInstruction(instruction, transaction) {
|
|
217
|
+
return prependTransactionInstructions([instruction], transaction);
|
|
218
|
+
}
|
|
219
|
+
function prependTransactionInstructions(instructions, transaction) {
|
|
213
220
|
const out = {
|
|
214
221
|
...getUnsignedTransaction(transaction),
|
|
215
|
-
instructions: [
|
|
222
|
+
instructions: [...instructions, ...transaction.instructions]
|
|
216
223
|
};
|
|
217
224
|
Object.freeze(out);
|
|
218
225
|
return out;
|
|
219
226
|
}
|
|
227
|
+
|
|
228
|
+
// src/decompile-transaction.ts
|
|
229
|
+
function getAccountMetas(message) {
|
|
230
|
+
const { header } = message;
|
|
231
|
+
const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
|
|
232
|
+
const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
|
|
233
|
+
const accountMetas = [];
|
|
234
|
+
let accountIndex = 0;
|
|
235
|
+
for (let i = 0; i < numWritableSignerAccounts; i++) {
|
|
236
|
+
accountMetas.push({
|
|
237
|
+
address: message.staticAccounts[accountIndex],
|
|
238
|
+
role: AccountRole.WRITABLE_SIGNER
|
|
239
|
+
});
|
|
240
|
+
accountIndex++;
|
|
241
|
+
}
|
|
242
|
+
for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
|
|
243
|
+
accountMetas.push({
|
|
244
|
+
address: message.staticAccounts[accountIndex],
|
|
245
|
+
role: AccountRole.READONLY_SIGNER
|
|
246
|
+
});
|
|
247
|
+
accountIndex++;
|
|
248
|
+
}
|
|
249
|
+
for (let i = 0; i < numWritableNonSignerAccounts; i++) {
|
|
250
|
+
accountMetas.push({
|
|
251
|
+
address: message.staticAccounts[accountIndex],
|
|
252
|
+
role: AccountRole.WRITABLE
|
|
253
|
+
});
|
|
254
|
+
accountIndex++;
|
|
255
|
+
}
|
|
256
|
+
for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
|
|
257
|
+
accountMetas.push({
|
|
258
|
+
address: message.staticAccounts[accountIndex],
|
|
259
|
+
role: AccountRole.READONLY
|
|
260
|
+
});
|
|
261
|
+
accountIndex++;
|
|
262
|
+
}
|
|
263
|
+
return accountMetas;
|
|
264
|
+
}
|
|
265
|
+
function getAddressLookupMetas(compiledAddressTableLookups, addressesByLookupTableAddress) {
|
|
266
|
+
const compiledAddressTableLookupAddresses = compiledAddressTableLookups.map((l) => l.lookupTableAddress);
|
|
267
|
+
const missing = compiledAddressTableLookupAddresses.filter((a) => addressesByLookupTableAddress[a] === void 0);
|
|
268
|
+
if (missing.length > 0) {
|
|
269
|
+
const missingAddresses = missing.join(", ");
|
|
270
|
+
throw new Error(`Addresses not provided for lookup tables: [${missingAddresses}]`);
|
|
271
|
+
}
|
|
272
|
+
const readOnlyMetas = [];
|
|
273
|
+
const writableMetas = [];
|
|
274
|
+
for (const lookup of compiledAddressTableLookups) {
|
|
275
|
+
const addresses = addressesByLookupTableAddress[lookup.lookupTableAddress];
|
|
276
|
+
const highestIndex = Math.max(...lookup.readableIndices, ...lookup.writableIndices);
|
|
277
|
+
if (highestIndex >= addresses.length) {
|
|
278
|
+
throw new Error(
|
|
279
|
+
`Cannot look up index ${highestIndex} in lookup table [${lookup.lookupTableAddress}]. The lookup table may have been extended since the addresses provided were retrieved.`
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
const readOnlyForLookup = lookup.readableIndices.map((r) => ({
|
|
283
|
+
address: addresses[r],
|
|
284
|
+
addressIndex: r,
|
|
285
|
+
lookupTableAddress: lookup.lookupTableAddress,
|
|
286
|
+
role: AccountRole.READONLY
|
|
287
|
+
}));
|
|
288
|
+
readOnlyMetas.push(...readOnlyForLookup);
|
|
289
|
+
const writableForLookup = lookup.writableIndices.map((w) => ({
|
|
290
|
+
address: addresses[w],
|
|
291
|
+
addressIndex: w,
|
|
292
|
+
lookupTableAddress: lookup.lookupTableAddress,
|
|
293
|
+
role: AccountRole.WRITABLE
|
|
294
|
+
}));
|
|
295
|
+
writableMetas.push(...writableForLookup);
|
|
296
|
+
}
|
|
297
|
+
return [...writableMetas, ...readOnlyMetas];
|
|
298
|
+
}
|
|
299
|
+
function convertInstruction(instruction, accountMetas) {
|
|
300
|
+
const programAddress = accountMetas[instruction.programAddressIndex]?.address;
|
|
301
|
+
if (!programAddress) {
|
|
302
|
+
throw new Error(`Could not find program address at index ${instruction.programAddressIndex}`);
|
|
303
|
+
}
|
|
304
|
+
const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
|
|
305
|
+
const { data } = instruction;
|
|
306
|
+
return {
|
|
307
|
+
programAddress,
|
|
308
|
+
...accounts && accounts.length ? { accounts } : {},
|
|
309
|
+
...data && data.length ? { data } : {}
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
|
|
313
|
+
if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
|
|
314
|
+
return {
|
|
315
|
+
blockhash: messageLifetimeToken,
|
|
316
|
+
lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
|
|
317
|
+
// U64 MAX
|
|
318
|
+
};
|
|
319
|
+
} else {
|
|
320
|
+
const nonceAccountAddress = firstInstruction.accounts[0].address;
|
|
321
|
+
addresses.assertIsAddress(nonceAccountAddress);
|
|
322
|
+
const nonceAuthorityAddress = firstInstruction.accounts[2].address;
|
|
323
|
+
addresses.assertIsAddress(nonceAuthorityAddress);
|
|
324
|
+
return {
|
|
325
|
+
nonce: messageLifetimeToken,
|
|
326
|
+
nonceAccountAddress,
|
|
327
|
+
nonceAuthorityAddress
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
function convertSignatures(compiledTransaction) {
|
|
332
|
+
const {
|
|
333
|
+
compiledMessage: { staticAccounts },
|
|
334
|
+
signatures
|
|
335
|
+
} = compiledTransaction;
|
|
336
|
+
return signatures.reduce((acc, sig, index) => {
|
|
337
|
+
const allZeros = sig.every((byte) => byte === 0);
|
|
338
|
+
if (allZeros)
|
|
339
|
+
return acc;
|
|
340
|
+
const address = staticAccounts[index];
|
|
341
|
+
return { ...acc, [address]: sig };
|
|
342
|
+
}, {});
|
|
343
|
+
}
|
|
344
|
+
function decompileTransaction(compiledTransaction, config) {
|
|
345
|
+
const { compiledMessage } = compiledTransaction;
|
|
346
|
+
const feePayer = compiledMessage.staticAccounts[0];
|
|
347
|
+
if (!feePayer)
|
|
348
|
+
throw new Error("No fee payer set in CompiledTransaction");
|
|
349
|
+
const accountMetas = getAccountMetas(compiledMessage);
|
|
350
|
+
const accountLookupMetas = "addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups !== void 0 && compiledMessage.addressTableLookups.length > 0 ? getAddressLookupMetas(compiledMessage.addressTableLookups, config?.addressesByLookupTableAddress ?? {}) : [];
|
|
351
|
+
const transactionMetas = [...accountMetas, ...accountLookupMetas];
|
|
352
|
+
const instructions = compiledMessage.instructions.map(
|
|
353
|
+
(compiledInstruction) => convertInstruction(compiledInstruction, transactionMetas)
|
|
354
|
+
);
|
|
355
|
+
const firstInstruction = instructions[0];
|
|
356
|
+
const lifetimeConstraint = getLifetimeConstraint(
|
|
357
|
+
compiledMessage.lifetimeToken,
|
|
358
|
+
firstInstruction,
|
|
359
|
+
config?.lastValidBlockHeight
|
|
360
|
+
);
|
|
361
|
+
const signatures = convertSignatures(compiledTransaction);
|
|
362
|
+
return functional.pipe(
|
|
363
|
+
createTransaction({ version: compiledMessage.version }),
|
|
364
|
+
(tx) => setTransactionFeePayer(feePayer, tx),
|
|
365
|
+
(tx) => instructions.reduce((acc, instruction) => {
|
|
366
|
+
return appendTransactionInstruction(instruction, acc);
|
|
367
|
+
}, tx),
|
|
368
|
+
(tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
|
|
369
|
+
(tx) => Object.keys(signatures).length > 0 ? { ...tx, signatures } : tx
|
|
370
|
+
);
|
|
371
|
+
}
|
|
220
372
|
function upsert(addressMap, address, update) {
|
|
221
373
|
addressMap[address] = update(addressMap[address] ?? { role: AccountRole.READONLY });
|
|
222
374
|
}
|
|
@@ -682,12 +834,15 @@ function getCompiledMessageEncoder() {
|
|
|
682
834
|
});
|
|
683
835
|
}
|
|
684
836
|
function getCompiledMessageDecoder() {
|
|
685
|
-
return codecsCore.mapDecoder(
|
|
686
|
-
|
|
687
|
-
|
|
837
|
+
return codecsCore.mapDecoder(
|
|
838
|
+
codecsDataStructures.getStructDecoder(getPreludeStructDecoderTuple()),
|
|
839
|
+
({ addressTableLookups, ...restOfMessage }) => {
|
|
840
|
+
if (restOfMessage.version === "legacy" || !addressTableLookups?.length) {
|
|
841
|
+
return restOfMessage;
|
|
842
|
+
}
|
|
843
|
+
return { ...restOfMessage, addressTableLookups };
|
|
688
844
|
}
|
|
689
|
-
|
|
690
|
-
});
|
|
845
|
+
);
|
|
691
846
|
}
|
|
692
847
|
function getCompiledMessageCodec() {
|
|
693
848
|
return codecsCore.combineCodec(getCompiledMessageEncoder(), getCompiledMessageDecoder());
|
|
@@ -710,116 +865,6 @@ function getCompiledTransaction(transaction) {
|
|
|
710
865
|
signatures
|
|
711
866
|
};
|
|
712
867
|
}
|
|
713
|
-
function getAccountMetas(message) {
|
|
714
|
-
const { header } = message;
|
|
715
|
-
const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
|
|
716
|
-
const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
|
|
717
|
-
const accountMetas = [];
|
|
718
|
-
let accountIndex = 0;
|
|
719
|
-
for (let i = 0; i < numWritableSignerAccounts; i++) {
|
|
720
|
-
accountMetas.push({
|
|
721
|
-
address: message.staticAccounts[accountIndex],
|
|
722
|
-
role: AccountRole.WRITABLE_SIGNER
|
|
723
|
-
});
|
|
724
|
-
accountIndex++;
|
|
725
|
-
}
|
|
726
|
-
for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
|
|
727
|
-
accountMetas.push({
|
|
728
|
-
address: message.staticAccounts[accountIndex],
|
|
729
|
-
role: AccountRole.READONLY_SIGNER
|
|
730
|
-
});
|
|
731
|
-
accountIndex++;
|
|
732
|
-
}
|
|
733
|
-
for (let i = 0; i < numWritableNonSignerAccounts; i++) {
|
|
734
|
-
accountMetas.push({
|
|
735
|
-
address: message.staticAccounts[accountIndex],
|
|
736
|
-
role: AccountRole.WRITABLE
|
|
737
|
-
});
|
|
738
|
-
accountIndex++;
|
|
739
|
-
}
|
|
740
|
-
for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
|
|
741
|
-
accountMetas.push({
|
|
742
|
-
address: message.staticAccounts[accountIndex],
|
|
743
|
-
role: AccountRole.READONLY
|
|
744
|
-
});
|
|
745
|
-
accountIndex++;
|
|
746
|
-
}
|
|
747
|
-
return accountMetas;
|
|
748
|
-
}
|
|
749
|
-
function convertInstruction(instruction, accountMetas) {
|
|
750
|
-
const programAddress = accountMetas[instruction.programAddressIndex]?.address;
|
|
751
|
-
if (!programAddress) {
|
|
752
|
-
throw new Error(`Could not find program address at index ${instruction.programAddressIndex}`);
|
|
753
|
-
}
|
|
754
|
-
const accounts = instruction.accountIndices?.map((accountIndex) => accountMetas[accountIndex]);
|
|
755
|
-
const { data } = instruction;
|
|
756
|
-
return {
|
|
757
|
-
programAddress,
|
|
758
|
-
...accounts && accounts.length ? { accounts } : {},
|
|
759
|
-
...data && data.length ? { data } : {}
|
|
760
|
-
};
|
|
761
|
-
}
|
|
762
|
-
function getLifetimeConstraint(messageLifetimeToken, firstInstruction, lastValidBlockHeight) {
|
|
763
|
-
if (!firstInstruction || !isAdvanceNonceAccountInstruction(firstInstruction)) {
|
|
764
|
-
return {
|
|
765
|
-
blockhash: messageLifetimeToken,
|
|
766
|
-
lastValidBlockHeight: lastValidBlockHeight ?? 2n ** 64n - 1n
|
|
767
|
-
// U64 MAX
|
|
768
|
-
};
|
|
769
|
-
} else {
|
|
770
|
-
const nonceAccountAddress = firstInstruction.accounts[0].address;
|
|
771
|
-
addresses.assertIsAddress(nonceAccountAddress);
|
|
772
|
-
const nonceAuthorityAddress = firstInstruction.accounts[2].address;
|
|
773
|
-
addresses.assertIsAddress(nonceAuthorityAddress);
|
|
774
|
-
return {
|
|
775
|
-
nonce: messageLifetimeToken,
|
|
776
|
-
nonceAccountAddress,
|
|
777
|
-
nonceAuthorityAddress
|
|
778
|
-
};
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
function convertSignatures(compiledTransaction) {
|
|
782
|
-
const {
|
|
783
|
-
compiledMessage: { staticAccounts },
|
|
784
|
-
signatures
|
|
785
|
-
} = compiledTransaction;
|
|
786
|
-
return signatures.reduce((acc, sig, index) => {
|
|
787
|
-
const allZeros = sig.every((byte) => byte === 0);
|
|
788
|
-
if (allZeros)
|
|
789
|
-
return acc;
|
|
790
|
-
const address = staticAccounts[index];
|
|
791
|
-
return { ...acc, [address]: sig };
|
|
792
|
-
}, {});
|
|
793
|
-
}
|
|
794
|
-
function decompileTransaction(compiledTransaction, lastValidBlockHeight) {
|
|
795
|
-
const { compiledMessage } = compiledTransaction;
|
|
796
|
-
if ("addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups.length > 0) {
|
|
797
|
-
throw new Error("Cannot convert transaction with addressTableLookups");
|
|
798
|
-
}
|
|
799
|
-
const feePayer = compiledMessage.staticAccounts[0];
|
|
800
|
-
if (!feePayer)
|
|
801
|
-
throw new Error("No fee payer set in CompiledTransaction");
|
|
802
|
-
const accountMetas = getAccountMetas(compiledMessage);
|
|
803
|
-
const instructions = compiledMessage.instructions.map(
|
|
804
|
-
(compiledInstruction) => convertInstruction(compiledInstruction, accountMetas)
|
|
805
|
-
);
|
|
806
|
-
const firstInstruction = instructions[0];
|
|
807
|
-
const lifetimeConstraint = getLifetimeConstraint(
|
|
808
|
-
compiledMessage.lifetimeToken,
|
|
809
|
-
firstInstruction,
|
|
810
|
-
lastValidBlockHeight
|
|
811
|
-
);
|
|
812
|
-
const signatures = convertSignatures(compiledTransaction);
|
|
813
|
-
return functional.pipe(
|
|
814
|
-
createTransaction({ version: compiledMessage.version }),
|
|
815
|
-
(tx) => setTransactionFeePayer(feePayer, tx),
|
|
816
|
-
(tx) => instructions.reduce((acc, instruction) => {
|
|
817
|
-
return appendTransactionInstruction(instruction, acc);
|
|
818
|
-
}, tx),
|
|
819
|
-
(tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
|
|
820
|
-
(tx) => compiledTransaction.signatures.length ? { ...tx, signatures } : tx
|
|
821
|
-
);
|
|
822
|
-
}
|
|
823
868
|
|
|
824
869
|
// src/serializers/transaction.ts
|
|
825
870
|
function getCompiledTransactionEncoder() {
|
|
@@ -842,14 +887,14 @@ function getCompiledTransactionDecoder() {
|
|
|
842
887
|
function getTransactionEncoder() {
|
|
843
888
|
return codecsCore.mapEncoder(getCompiledTransactionEncoder(), getCompiledTransaction);
|
|
844
889
|
}
|
|
845
|
-
function getTransactionDecoder(
|
|
890
|
+
function getTransactionDecoder(config) {
|
|
846
891
|
return codecsCore.mapDecoder(
|
|
847
892
|
getCompiledTransactionDecoder(),
|
|
848
|
-
(compiledTransaction) => decompileTransaction(compiledTransaction,
|
|
893
|
+
(compiledTransaction) => decompileTransaction(compiledTransaction, config)
|
|
849
894
|
);
|
|
850
895
|
}
|
|
851
|
-
function getTransactionCodec(
|
|
852
|
-
return codecsCore.combineCodec(getTransactionEncoder(), getTransactionDecoder(
|
|
896
|
+
function getTransactionCodec(config) {
|
|
897
|
+
return codecsCore.combineCodec(getTransactionEncoder(), getTransactionDecoder(config));
|
|
853
898
|
}
|
|
854
899
|
var base58Decoder;
|
|
855
900
|
function getSignatureFromTransaction(transaction) {
|
|
@@ -857,9 +902,7 @@ function getSignatureFromTransaction(transaction) {
|
|
|
857
902
|
base58Decoder = codecsStrings.getBase58Decoder();
|
|
858
903
|
const signatureBytes = transaction.signatures[transaction.feePayer];
|
|
859
904
|
if (!signatureBytes) {
|
|
860
|
-
throw new
|
|
861
|
-
"Could not determine this transaction's signature. Make sure that the transaction has been signed by its fee payer."
|
|
862
|
-
);
|
|
905
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_SIGNATURE_NOT_COMPUTABLE);
|
|
863
906
|
}
|
|
864
907
|
const transactionSignature = base58Decoder.decode(signatureBytes);
|
|
865
908
|
return transactionSignature;
|
|
@@ -892,11 +935,17 @@ async function signTransaction(keyPairs, transaction) {
|
|
|
892
935
|
function assertTransactionIsFullySigned(transaction) {
|
|
893
936
|
const signerAddressesFromInstructions = transaction.instructions.flatMap((i) => i.accounts?.filter((a) => isSignerRole(a.role)) ?? []).map((a) => a.address);
|
|
894
937
|
const requiredSigners = /* @__PURE__ */ new Set([transaction.feePayer, ...signerAddressesFromInstructions]);
|
|
938
|
+
const missingSigs = [];
|
|
895
939
|
requiredSigners.forEach((address) => {
|
|
896
940
|
if (!transaction.signatures[address]) {
|
|
897
|
-
|
|
941
|
+
missingSigs.push(address);
|
|
898
942
|
}
|
|
899
943
|
});
|
|
944
|
+
if (missingSigs.length > 0) {
|
|
945
|
+
throw new errors.SolanaError(errors.SOLANA_ERROR__TRANSACTION_MISSING_SIGNATURES, {
|
|
946
|
+
addresses: missingSigs
|
|
947
|
+
});
|
|
948
|
+
}
|
|
900
949
|
}
|
|
901
950
|
function getBase64EncodedWireTransaction(transaction) {
|
|
902
951
|
const wireTransactionBytes = getTransactionEncoder().encode(transaction);
|
|
@@ -904,23 +953,27 @@ function getBase64EncodedWireTransaction(transaction) {
|
|
|
904
953
|
}
|
|
905
954
|
|
|
906
955
|
exports.appendTransactionInstruction = appendTransactionInstruction;
|
|
907
|
-
exports.
|
|
956
|
+
exports.appendTransactionInstructions = appendTransactionInstructions;
|
|
908
957
|
exports.assertIsDurableNonceTransaction = assertIsDurableNonceTransaction;
|
|
909
958
|
exports.assertIsTransactionWithBlockhashLifetime = assertIsTransactionWithBlockhashLifetime;
|
|
910
959
|
exports.assertTransactionIsFullySigned = assertTransactionIsFullySigned;
|
|
911
960
|
exports.compileMessage = compileMessage;
|
|
912
961
|
exports.createTransaction = createTransaction;
|
|
962
|
+
exports.decompileTransaction = decompileTransaction;
|
|
913
963
|
exports.getBase64EncodedWireTransaction = getBase64EncodedWireTransaction;
|
|
914
964
|
exports.getCompiledMessageCodec = getCompiledMessageCodec;
|
|
915
965
|
exports.getCompiledMessageDecoder = getCompiledMessageDecoder;
|
|
916
966
|
exports.getCompiledMessageEncoder = getCompiledMessageEncoder;
|
|
967
|
+
exports.getCompiledTransactionDecoder = getCompiledTransactionDecoder;
|
|
917
968
|
exports.getSignatureFromTransaction = getSignatureFromTransaction;
|
|
918
969
|
exports.getTransactionCodec = getTransactionCodec;
|
|
919
970
|
exports.getTransactionDecoder = getTransactionDecoder;
|
|
920
971
|
exports.getTransactionEncoder = getTransactionEncoder;
|
|
972
|
+
exports.getUnsignedTransaction = getUnsignedTransaction;
|
|
921
973
|
exports.isAdvanceNonceAccountInstruction = isAdvanceNonceAccountInstruction;
|
|
922
974
|
exports.partiallySignTransaction = partiallySignTransaction;
|
|
923
975
|
exports.prependTransactionInstruction = prependTransactionInstruction;
|
|
976
|
+
exports.prependTransactionInstructions = prependTransactionInstructions;
|
|
924
977
|
exports.setTransactionFeePayer = setTransactionFeePayer;
|
|
925
978
|
exports.setTransactionLifetimeUsingBlockhash = setTransactionLifetimeUsingBlockhash;
|
|
926
979
|
exports.setTransactionLifetimeUsingDurableNonce = setTransactionLifetimeUsingDurableNonce;
|