@solana/transactions 2.0.0-experimental.df45965 → 2.0.0-experimental.e00f668
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 +8 -46
- package/dist/index.browser.cjs +462 -253
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +452 -253
- package/dist/index.browser.js.map +1 -1
- package/dist/index.native.js +450 -253
- package/dist/index.native.js.map +1 -1
- package/dist/index.node.cjs +460 -253
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +452 -253
- package/dist/index.node.js.map +1 -1
- package/dist/types/accounts.d.ts +2 -2
- 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 +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 -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 +3 -3
- package/dist/types/compile-static-accounts.d.ts.map +1 -1
- package/dist/types/compile-transaction.d.ts +6 -7
- package/dist/types/compile-transaction.d.ts.map +1 -1
- package/dist/types/create-transaction.d.ts +1 -1
- 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 +7 -8
- package/dist/types/durable-nonce.d.ts.map +1 -1
- package/dist/types/fee-payer.d.ts +6 -6
- package/dist/types/fee-payer.d.ts.map +1 -1
- package/dist/types/index.d.ts +13 -9
- 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 -10
- package/dist/types/message.d.ts.map +1 -1
- 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 +9 -13
- package/dist/types/signatures.d.ts.map +1 -1
- package/dist/types/types.d.ts +6 -13
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/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 -1378
- package/dist/index.development.js.map +0 -1
- package/dist/index.production.min.js +0 -26
package/dist/index.browser.js
CHANGED
|
@@ -1,13 +1,34 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { SolanaError, SOLANA_ERROR__TRANSACTION_EXPECTED_BLOCKHASH_LIFETIME, SOLANA_ERROR__TRANSACTION_EXPECTED_NONCE_LIFETIME, SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_FEE_PAYER_MISSING, SOLANA_ERROR__TRANSACTION_SIGNATURE_NOT_COMPUTABLE, SOLANA_ERROR__TRANSACTION_MISSING_SIGNATURES, SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_CONTENTS_MISSING, SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_INDEX_OUT_OF_RANGE, SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_INSTRUCTION_PROGRAM_ADDRESS_NOT_FOUND, SOLANA_ERROR__BLOCKHASH_STRING_LENGTH_OUT_OF_RANGE, SOLANA_ERROR__BLOCKHASH_BYTE_LENGTH_OUT_OF_RANGE, SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE, SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_CANNOT_PAY_FEES, SOLANA_ERROR__TRANSACTION_VERSION_NUMBER_OUT_OF_RANGE } from '@solana/errors';
|
|
2
|
+
import { getBase58Decoder, getBase64Decoder, getStringEncoder, getBase58Encoder, getStringDecoder } from '@solana/codecs-strings';
|
|
3
|
+
import { getAddressFromPublicKey, assertIsAddress, getAddressComparator, getAddressEncoder, getAddressDecoder } from '@solana/addresses';
|
|
4
|
+
import { pipe } from '@solana/functional';
|
|
5
|
+
import { createEncoder, mapDecoder, combineCodec, mapEncoder, createDecoder } from '@solana/codecs-core';
|
|
6
|
+
import { getStructDecoder, getArrayDecoder, getBytesDecoder, getStructEncoder, getArrayEncoder, getBytesEncoder } from '@solana/codecs-data-structures';
|
|
7
|
+
import { getShortU16Decoder, getShortU16Encoder, getU8Encoder, getU8Decoder } from '@solana/codecs-numbers';
|
|
7
8
|
import { signBytes } from '@solana/keys';
|
|
8
9
|
|
|
9
|
-
//
|
|
10
|
-
var
|
|
10
|
+
// src/blockhash.ts
|
|
11
|
+
var base58Encoder;
|
|
12
|
+
function assertIsBlockhash(putativeBlockhash) {
|
|
13
|
+
if (!base58Encoder)
|
|
14
|
+
base58Encoder = getBase58Encoder();
|
|
15
|
+
if (
|
|
16
|
+
// Lowest value (32 bytes of zeroes)
|
|
17
|
+
putativeBlockhash.length < 32 || // Highest value (32 bytes of 255)
|
|
18
|
+
putativeBlockhash.length > 44
|
|
19
|
+
) {
|
|
20
|
+
throw new SolanaError(SOLANA_ERROR__BLOCKHASH_STRING_LENGTH_OUT_OF_RANGE, {
|
|
21
|
+
actualLength: putativeBlockhash.length
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
const bytes = base58Encoder.encode(putativeBlockhash);
|
|
25
|
+
const numBytes = bytes.byteLength;
|
|
26
|
+
if (numBytes !== 32) {
|
|
27
|
+
throw new SolanaError(SOLANA_ERROR__BLOCKHASH_BYTE_LENGTH_OUT_OF_RANGE, {
|
|
28
|
+
actualLength: numBytes
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
11
32
|
|
|
12
33
|
// src/unsigned-transaction.ts
|
|
13
34
|
function getUnsignedTransaction(transaction) {
|
|
@@ -24,24 +45,20 @@ function getUnsignedTransaction(transaction) {
|
|
|
24
45
|
}
|
|
25
46
|
|
|
26
47
|
// src/blockhash.ts
|
|
27
|
-
function
|
|
48
|
+
function isTransactionWithBlockhashLifetime(transaction) {
|
|
49
|
+
const lifetimeConstraintShapeMatches = "lifetimeConstraint" in transaction && typeof transaction.lifetimeConstraint.blockhash === "string" && typeof transaction.lifetimeConstraint.lastValidBlockHeight === "bigint";
|
|
50
|
+
if (!lifetimeConstraintShapeMatches)
|
|
51
|
+
return false;
|
|
28
52
|
try {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (numBytes !== 32) {
|
|
39
|
-
throw new Error(`Expected input string to decode to a byte array of length 32. Actual length: ${numBytes}`);
|
|
40
|
-
}
|
|
41
|
-
} catch (e) {
|
|
42
|
-
throw new Error(`\`${putativeBlockhash}\` is not a blockhash`, {
|
|
43
|
-
cause: e
|
|
44
|
-
});
|
|
53
|
+
assertIsBlockhash(transaction.lifetimeConstraint.blockhash);
|
|
54
|
+
return true;
|
|
55
|
+
} catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function assertIsTransactionWithBlockhashLifetime(transaction) {
|
|
60
|
+
if (!isTransactionWithBlockhashLifetime(transaction)) {
|
|
61
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_EXPECTED_BLOCKHASH_LIFETIME);
|
|
45
62
|
}
|
|
46
63
|
}
|
|
47
64
|
function setTransactionLifetimeUsingBlockhash(blockhashLifetimeConstraint, transaction) {
|
|
@@ -67,8 +84,6 @@ function createTransaction({
|
|
|
67
84
|
Object.freeze(out);
|
|
68
85
|
return out;
|
|
69
86
|
}
|
|
70
|
-
|
|
71
|
-
// ../instructions/dist/index.browser.js
|
|
72
87
|
var AccountRole = /* @__PURE__ */ ((AccountRole2) => {
|
|
73
88
|
AccountRole2[AccountRole2["WRITABLE_SIGNER"] = /* 3 */
|
|
74
89
|
3] = "WRITABLE_SIGNER";
|
|
@@ -90,13 +105,11 @@ function isWritableRole(role) {
|
|
|
90
105
|
function mergeRoles(roleA, roleB) {
|
|
91
106
|
return roleA | roleB;
|
|
92
107
|
}
|
|
93
|
-
|
|
94
|
-
// src/durable-nonce.ts
|
|
95
108
|
var RECENT_BLOCKHASHES_SYSVAR_ADDRESS = "SysvarRecentB1ockHashes11111111111111111111";
|
|
96
109
|
var SYSTEM_PROGRAM_ADDRESS = "11111111111111111111111111111111";
|
|
97
110
|
function assertIsDurableNonceTransaction(transaction) {
|
|
98
111
|
if (!isDurableNonceTransaction(transaction)) {
|
|
99
|
-
throw new
|
|
112
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_EXPECTED_NONCE_LIFETIME);
|
|
100
113
|
}
|
|
101
114
|
}
|
|
102
115
|
function createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress) {
|
|
@@ -119,7 +132,7 @@ function isAdvanceNonceAccountInstruction(instruction) {
|
|
|
119
132
|
instruction.accounts?.length === 3 && // First account is nonce account address
|
|
120
133
|
instruction.accounts[0].address != null && instruction.accounts[0].role === AccountRole.WRITABLE && // Second account is recent blockhashes sysvar
|
|
121
134
|
instruction.accounts[1].address === RECENT_BLOCKHASHES_SYSVAR_ADDRESS && instruction.accounts[1].role === AccountRole.READONLY && // Third account is nonce authority account
|
|
122
|
-
instruction.accounts[2].address != null && instruction.accounts[2].role
|
|
135
|
+
instruction.accounts[2].address != null && isSignerRole(instruction.accounts[2].role);
|
|
123
136
|
}
|
|
124
137
|
function isAdvanceNonceAccountInstructionData(data) {
|
|
125
138
|
return data.byteLength === 4 && data[0] === 4 && data[1] === 0 && data[2] === 0 && data[3] === 0;
|
|
@@ -127,21 +140,38 @@ function isAdvanceNonceAccountInstructionData(data) {
|
|
|
127
140
|
function isDurableNonceTransaction(transaction) {
|
|
128
141
|
return "lifetimeConstraint" in transaction && typeof transaction.lifetimeConstraint.nonce === "string" && transaction.instructions[0] != null && isAdvanceNonceAccountInstruction(transaction.instructions[0]);
|
|
129
142
|
}
|
|
143
|
+
function isAdvanceNonceAccountInstructionForNonce(instruction, nonceAccountAddress, nonceAuthorityAddress) {
|
|
144
|
+
return instruction.accounts[0].address === nonceAccountAddress && instruction.accounts[2].address === nonceAuthorityAddress;
|
|
145
|
+
}
|
|
130
146
|
function setTransactionLifetimeUsingDurableNonce({
|
|
131
147
|
nonce,
|
|
132
148
|
nonceAccountAddress,
|
|
133
149
|
nonceAuthorityAddress
|
|
134
150
|
}, transaction) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
151
|
+
let newInstructions;
|
|
152
|
+
const firstInstruction = transaction.instructions[0];
|
|
153
|
+
if (firstInstruction && isAdvanceNonceAccountInstruction(firstInstruction)) {
|
|
154
|
+
if (isAdvanceNonceAccountInstructionForNonce(firstInstruction, nonceAccountAddress, nonceAuthorityAddress)) {
|
|
155
|
+
if (isDurableNonceTransaction(transaction) && transaction.lifetimeConstraint.nonce === nonce) {
|
|
156
|
+
return transaction;
|
|
157
|
+
} else {
|
|
158
|
+
newInstructions = [firstInstruction, ...transaction.instructions.slice(1)];
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
newInstructions = [
|
|
162
|
+
createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
|
|
163
|
+
...transaction.instructions.slice(1)
|
|
164
|
+
];
|
|
165
|
+
}
|
|
166
|
+
} else {
|
|
167
|
+
newInstructions = [
|
|
168
|
+
createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
|
|
169
|
+
...transaction.instructions
|
|
170
|
+
];
|
|
138
171
|
}
|
|
139
172
|
const out = {
|
|
140
173
|
...getUnsignedTransaction(transaction),
|
|
141
|
-
instructions:
|
|
142
|
-
createAdvanceNonceAccountInstruction(nonceAccountAddress, nonceAuthorityAddress),
|
|
143
|
-
...isAlreadyDurableNonceTransaction ? transaction.instructions.slice(1) : transaction.instructions
|
|
144
|
-
],
|
|
174
|
+
instructions: newInstructions,
|
|
145
175
|
lifetimeConstraint: {
|
|
146
176
|
nonce
|
|
147
177
|
}
|
|
@@ -165,21 +195,181 @@ function setTransactionFeePayer(feePayer, transaction) {
|
|
|
165
195
|
|
|
166
196
|
// src/instructions.ts
|
|
167
197
|
function appendTransactionInstruction(instruction, transaction) {
|
|
198
|
+
return appendTransactionInstructions([instruction], transaction);
|
|
199
|
+
}
|
|
200
|
+
function appendTransactionInstructions(instructions, transaction) {
|
|
168
201
|
const out = {
|
|
169
202
|
...getUnsignedTransaction(transaction),
|
|
170
|
-
instructions: [...transaction.instructions,
|
|
203
|
+
instructions: [...transaction.instructions, ...instructions]
|
|
171
204
|
};
|
|
172
205
|
Object.freeze(out);
|
|
173
206
|
return out;
|
|
174
207
|
}
|
|
175
208
|
function prependTransactionInstruction(instruction, transaction) {
|
|
209
|
+
return prependTransactionInstructions([instruction], transaction);
|
|
210
|
+
}
|
|
211
|
+
function prependTransactionInstructions(instructions, transaction) {
|
|
176
212
|
const out = {
|
|
177
213
|
...getUnsignedTransaction(transaction),
|
|
178
|
-
instructions: [
|
|
214
|
+
instructions: [...instructions, ...transaction.instructions]
|
|
179
215
|
};
|
|
180
216
|
Object.freeze(out);
|
|
181
217
|
return out;
|
|
182
218
|
}
|
|
219
|
+
|
|
220
|
+
// src/decompile-transaction.ts
|
|
221
|
+
function getAccountMetas(message) {
|
|
222
|
+
const { header } = message;
|
|
223
|
+
const numWritableSignerAccounts = header.numSignerAccounts - header.numReadonlySignerAccounts;
|
|
224
|
+
const numWritableNonSignerAccounts = message.staticAccounts.length - header.numSignerAccounts - header.numReadonlyNonSignerAccounts;
|
|
225
|
+
const accountMetas = [];
|
|
226
|
+
let accountIndex = 0;
|
|
227
|
+
for (let i = 0; i < numWritableSignerAccounts; i++) {
|
|
228
|
+
accountMetas.push({
|
|
229
|
+
address: message.staticAccounts[accountIndex],
|
|
230
|
+
role: AccountRole.WRITABLE_SIGNER
|
|
231
|
+
});
|
|
232
|
+
accountIndex++;
|
|
233
|
+
}
|
|
234
|
+
for (let i = 0; i < header.numReadonlySignerAccounts; i++) {
|
|
235
|
+
accountMetas.push({
|
|
236
|
+
address: message.staticAccounts[accountIndex],
|
|
237
|
+
role: AccountRole.READONLY_SIGNER
|
|
238
|
+
});
|
|
239
|
+
accountIndex++;
|
|
240
|
+
}
|
|
241
|
+
for (let i = 0; i < numWritableNonSignerAccounts; i++) {
|
|
242
|
+
accountMetas.push({
|
|
243
|
+
address: message.staticAccounts[accountIndex],
|
|
244
|
+
role: AccountRole.WRITABLE
|
|
245
|
+
});
|
|
246
|
+
accountIndex++;
|
|
247
|
+
}
|
|
248
|
+
for (let i = 0; i < header.numReadonlyNonSignerAccounts; i++) {
|
|
249
|
+
accountMetas.push({
|
|
250
|
+
address: message.staticAccounts[accountIndex],
|
|
251
|
+
role: AccountRole.READONLY
|
|
252
|
+
});
|
|
253
|
+
accountIndex++;
|
|
254
|
+
}
|
|
255
|
+
return accountMetas;
|
|
256
|
+
}
|
|
257
|
+
function getAddressLookupMetas(compiledAddressTableLookups, addressesByLookupTableAddress) {
|
|
258
|
+
const compiledAddressTableLookupAddresses = compiledAddressTableLookups.map((l) => l.lookupTableAddress);
|
|
259
|
+
const missing = compiledAddressTableLookupAddresses.filter((a) => addressesByLookupTableAddress[a] === void 0);
|
|
260
|
+
if (missing.length > 0) {
|
|
261
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_CONTENTS_MISSING, {
|
|
262
|
+
lookupTableAddresses: missing
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
const readOnlyMetas = [];
|
|
266
|
+
const writableMetas = [];
|
|
267
|
+
for (const lookup of compiledAddressTableLookups) {
|
|
268
|
+
const addresses = addressesByLookupTableAddress[lookup.lookupTableAddress];
|
|
269
|
+
const highestIndex = Math.max(...lookup.readableIndices, ...lookup.writableIndices);
|
|
270
|
+
if (highestIndex >= addresses.length) {
|
|
271
|
+
throw new SolanaError(
|
|
272
|
+
SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_ADDRESS_LOOKUP_TABLE_INDEX_OUT_OF_RANGE,
|
|
273
|
+
{
|
|
274
|
+
highestKnownIndex: addresses.length - 1,
|
|
275
|
+
highestRequestedIndex: highestIndex,
|
|
276
|
+
lookupTableAddress: lookup.lookupTableAddress
|
|
277
|
+
}
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
const readOnlyForLookup = lookup.readableIndices.map((r) => ({
|
|
281
|
+
address: addresses[r],
|
|
282
|
+
addressIndex: r,
|
|
283
|
+
lookupTableAddress: lookup.lookupTableAddress,
|
|
284
|
+
role: AccountRole.READONLY
|
|
285
|
+
}));
|
|
286
|
+
readOnlyMetas.push(...readOnlyForLookup);
|
|
287
|
+
const writableForLookup = lookup.writableIndices.map((w) => ({
|
|
288
|
+
address: addresses[w],
|
|
289
|
+
addressIndex: w,
|
|
290
|
+
lookupTableAddress: lookup.lookupTableAddress,
|
|
291
|
+
role: AccountRole.WRITABLE
|
|
292
|
+
}));
|
|
293
|
+
writableMetas.push(...writableForLookup);
|
|
294
|
+
}
|
|
295
|
+
return [...writableMetas, ...readOnlyMetas];
|
|
296
|
+
}
|
|
297
|
+
function convertInstruction(instruction, accountMetas) {
|
|
298
|
+
const programAddress = accountMetas[instruction.programAddressIndex]?.address;
|
|
299
|
+
if (!programAddress) {
|
|
300
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_INSTRUCTION_PROGRAM_ADDRESS_NOT_FOUND, {
|
|
301
|
+
index: instruction.programAddressIndex
|
|
302
|
+
});
|
|
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
|
+
assertIsAddress(nonceAccountAddress);
|
|
322
|
+
const nonceAuthorityAddress = firstInstruction.accounts[2].address;
|
|
323
|
+
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 SolanaError(SOLANA_ERROR__TRANSACTION_FAILED_TO_DECOMPILE_FEE_PAYER_MISSING);
|
|
349
|
+
}
|
|
350
|
+
const accountMetas = getAccountMetas(compiledMessage);
|
|
351
|
+
const accountLookupMetas = "addressTableLookups" in compiledMessage && compiledMessage.addressTableLookups !== void 0 && compiledMessage.addressTableLookups.length > 0 ? getAddressLookupMetas(compiledMessage.addressTableLookups, config?.addressesByLookupTableAddress ?? {}) : [];
|
|
352
|
+
const transactionMetas = [...accountMetas, ...accountLookupMetas];
|
|
353
|
+
const instructions = compiledMessage.instructions.map(
|
|
354
|
+
(compiledInstruction) => convertInstruction(compiledInstruction, transactionMetas)
|
|
355
|
+
);
|
|
356
|
+
const firstInstruction = instructions[0];
|
|
357
|
+
const lifetimeConstraint = getLifetimeConstraint(
|
|
358
|
+
compiledMessage.lifetimeToken,
|
|
359
|
+
firstInstruction,
|
|
360
|
+
config?.lastValidBlockHeight
|
|
361
|
+
);
|
|
362
|
+
const signatures = convertSignatures(compiledTransaction);
|
|
363
|
+
return pipe(
|
|
364
|
+
createTransaction({ version: compiledMessage.version }),
|
|
365
|
+
(tx) => setTransactionFeePayer(feePayer, tx),
|
|
366
|
+
(tx) => instructions.reduce((acc, instruction) => {
|
|
367
|
+
return appendTransactionInstruction(instruction, acc);
|
|
368
|
+
}, tx),
|
|
369
|
+
(tx) => "blockhash" in lifetimeConstraint ? setTransactionLifetimeUsingBlockhash(lifetimeConstraint, tx) : setTransactionLifetimeUsingDurableNonce(lifetimeConstraint, tx),
|
|
370
|
+
(tx) => Object.keys(signatures).length > 0 ? { ...tx, signatures } : tx
|
|
371
|
+
);
|
|
372
|
+
}
|
|
183
373
|
function upsert(addressMap, address, update) {
|
|
184
374
|
addressMap[address] = update(addressMap[address] ?? { role: AccountRole.READONLY });
|
|
185
375
|
}
|
|
@@ -196,13 +386,13 @@ function getAddressMapFromInstructions(feePayer, instructions) {
|
|
|
196
386
|
if (isWritableRole(entry.role)) {
|
|
197
387
|
switch (entry[TYPE]) {
|
|
198
388
|
case 0 /* FEE_PAYER */:
|
|
199
|
-
throw new
|
|
200
|
-
|
|
201
|
-
);
|
|
389
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_CANNOT_PAY_FEES, {
|
|
390
|
+
programAddress: instruction.programAddress
|
|
391
|
+
});
|
|
202
392
|
default:
|
|
203
|
-
throw new
|
|
204
|
-
|
|
205
|
-
);
|
|
393
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE, {
|
|
394
|
+
programAddress: instruction.programAddress
|
|
395
|
+
});
|
|
206
396
|
}
|
|
207
397
|
}
|
|
208
398
|
if (entry[TYPE] === 2 /* STATIC */) {
|
|
@@ -232,7 +422,7 @@ function getAddressMapFromInstructions(feePayer, instructions) {
|
|
|
232
422
|
const shouldReplaceEntry = (
|
|
233
423
|
// Consider using the new LOOKUP_TABLE if its address is different...
|
|
234
424
|
entry.lookupTableAddress !== accountMeta.lookupTableAddress && // ...and sorts before the existing one.
|
|
235
|
-
(addressComparator
|
|
425
|
+
(addressComparator ||= getAddressComparator())(
|
|
236
426
|
accountMeta.lookupTableAddress,
|
|
237
427
|
entry.lookupTableAddress
|
|
238
428
|
) < 0
|
|
@@ -267,8 +457,11 @@ function getAddressMapFromInstructions(feePayer, instructions) {
|
|
|
267
457
|
addressesOfInvokedPrograms.has(account.address)
|
|
268
458
|
) {
|
|
269
459
|
if (isWritableRole(accountMeta.role)) {
|
|
270
|
-
throw new
|
|
271
|
-
|
|
460
|
+
throw new SolanaError(
|
|
461
|
+
SOLANA_ERROR__TRANSACTION_INVOKED_PROGRAMS_MUST_NOT_BE_WRITABLE,
|
|
462
|
+
{
|
|
463
|
+
programAddress: account.address
|
|
464
|
+
}
|
|
272
465
|
);
|
|
273
466
|
}
|
|
274
467
|
if (entry.role !== nextRole) {
|
|
@@ -338,7 +531,7 @@ function getOrderedAccountsFromAddressMap(addressMap) {
|
|
|
338
531
|
if (leftIsWritable !== isWritableRole(rightEntry.role)) {
|
|
339
532
|
return leftIsWritable ? -1 : 1;
|
|
340
533
|
}
|
|
341
|
-
addressComparator
|
|
534
|
+
addressComparator ||= getAddressComparator();
|
|
342
535
|
if (leftEntry[TYPE] === 1 /* LOOKUP_TABLE */ && rightEntry[TYPE] === 1 /* LOOKUP_TABLE */ && leftEntry.lookupTableAddress !== rightEntry.lookupTableAddress) {
|
|
343
536
|
return addressComparator(leftEntry.lookupTableAddress, rightEntry.lookupTableAddress);
|
|
344
537
|
} else {
|
|
@@ -351,16 +544,15 @@ function getOrderedAccountsFromAddressMap(addressMap) {
|
|
|
351
544
|
return orderedAccounts;
|
|
352
545
|
}
|
|
353
546
|
function getCompiledAddressTableLookups(orderedAccounts) {
|
|
354
|
-
var _a;
|
|
355
547
|
const index = {};
|
|
356
548
|
for (const account of orderedAccounts) {
|
|
357
549
|
if (!("lookupTableAddress" in account)) {
|
|
358
550
|
continue;
|
|
359
551
|
}
|
|
360
|
-
const entry = index[
|
|
552
|
+
const entry = index[account.lookupTableAddress] ||= {
|
|
361
553
|
readableIndices: [],
|
|
362
554
|
writableIndices: []
|
|
363
|
-
}
|
|
555
|
+
};
|
|
364
556
|
if (account.role === AccountRole.WRITABLE) {
|
|
365
557
|
entry.writableIndices.push(account.addressIndex);
|
|
366
558
|
} else {
|
|
@@ -446,101 +638,68 @@ function compileMessage(transaction) {
|
|
|
446
638
|
version: transaction.version
|
|
447
639
|
};
|
|
448
640
|
}
|
|
449
|
-
|
|
450
|
-
// src/compile-transaction.ts
|
|
451
|
-
function getCompiledTransaction(transaction) {
|
|
452
|
-
const compiledMessage = compileMessage(transaction);
|
|
453
|
-
let signatures;
|
|
454
|
-
if ("signatures" in transaction) {
|
|
455
|
-
signatures = [];
|
|
456
|
-
for (let ii = 0; ii < compiledMessage.header.numSignerAccounts; ii++) {
|
|
457
|
-
signatures[ii] = transaction.signatures[compiledMessage.staticAccounts[ii]] ?? new Uint8Array(Array(64).fill(0));
|
|
458
|
-
}
|
|
459
|
-
} else {
|
|
460
|
-
signatures = Array(compiledMessage.header.numSignerAccounts).fill(new Uint8Array(Array(64).fill(0)));
|
|
461
|
-
}
|
|
462
|
-
return {
|
|
463
|
-
compiledMessage,
|
|
464
|
-
signatures
|
|
465
|
-
};
|
|
466
|
-
}
|
|
467
|
-
var lookupTableAddressDescription = __DEV__ ? "The address of the address lookup table account from which instruction addresses should be looked up" : "lookupTableAddress";
|
|
468
|
-
var writableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as writeable" : "writableIndices";
|
|
469
|
-
var readableIndicesDescription = __DEV__ ? "The indices of the accounts in the lookup table that should be loaded as read-only" : "readableIndices";
|
|
470
|
-
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";
|
|
471
641
|
var memoizedAddressTableLookupEncoder;
|
|
472
642
|
function getAddressTableLookupEncoder() {
|
|
473
643
|
if (!memoizedAddressTableLookupEncoder) {
|
|
474
|
-
memoizedAddressTableLookupEncoder = getStructEncoder(
|
|
644
|
+
memoizedAddressTableLookupEncoder = getStructEncoder([
|
|
645
|
+
["lookupTableAddress", getAddressEncoder()],
|
|
475
646
|
[
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
"writableIndices",
|
|
479
|
-
getArrayEncoder(getU8Encoder(), {
|
|
480
|
-
description: writableIndicesDescription,
|
|
481
|
-
size: getShortU16Encoder()
|
|
482
|
-
})
|
|
483
|
-
],
|
|
484
|
-
[
|
|
485
|
-
"readableIndices",
|
|
486
|
-
getArrayEncoder(getU8Encoder(), {
|
|
487
|
-
description: readableIndicesDescription,
|
|
488
|
-
size: getShortU16Encoder()
|
|
489
|
-
})
|
|
490
|
-
]
|
|
647
|
+
"writableIndices",
|
|
648
|
+
getArrayEncoder(getU8Encoder(), { size: getShortU16Encoder() })
|
|
491
649
|
],
|
|
492
|
-
|
|
493
|
-
|
|
650
|
+
[
|
|
651
|
+
"readableIndices",
|
|
652
|
+
getArrayEncoder(getU8Encoder(), { size: getShortU16Encoder() })
|
|
653
|
+
]
|
|
654
|
+
]);
|
|
494
655
|
}
|
|
495
656
|
return memoizedAddressTableLookupEncoder;
|
|
496
657
|
}
|
|
658
|
+
var memoizedAddressTableLookupDecoder;
|
|
659
|
+
function getAddressTableLookupDecoder() {
|
|
660
|
+
if (!memoizedAddressTableLookupDecoder) {
|
|
661
|
+
memoizedAddressTableLookupDecoder = getStructDecoder([
|
|
662
|
+
["lookupTableAddress", getAddressDecoder()],
|
|
663
|
+
["writableIndices", getArrayDecoder(getU8Decoder(), { size: getShortU16Decoder() })],
|
|
664
|
+
["readableIndices", getArrayDecoder(getU8Decoder(), { size: getShortU16Decoder() })]
|
|
665
|
+
]);
|
|
666
|
+
}
|
|
667
|
+
return memoizedAddressTableLookupDecoder;
|
|
668
|
+
}
|
|
497
669
|
var memoizedU8Encoder;
|
|
498
670
|
function getMemoizedU8Encoder() {
|
|
499
671
|
if (!memoizedU8Encoder)
|
|
500
672
|
memoizedU8Encoder = getU8Encoder();
|
|
501
673
|
return memoizedU8Encoder;
|
|
502
674
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
};
|
|
675
|
+
var memoizedU8Decoder;
|
|
676
|
+
function getMemoizedU8Decoder() {
|
|
677
|
+
if (!memoizedU8Decoder)
|
|
678
|
+
memoizedU8Decoder = getU8Decoder();
|
|
679
|
+
return memoizedU8Decoder;
|
|
509
680
|
}
|
|
510
|
-
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;
|
|
511
|
-
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;
|
|
512
|
-
var numReadonlyNonSignerAccountsDescription = __DEV__ ? "The expected number of addresses in the static address list belonging to accounts that are neither signers, nor writable" : void 0;
|
|
513
|
-
var messageHeaderDescription = __DEV__ ? "The transaction message header containing counts of the signer, readonly-signer, and readonly-nonsigner account addresses" : void 0;
|
|
514
681
|
function getMessageHeaderEncoder() {
|
|
515
|
-
return getStructEncoder(
|
|
516
|
-
[
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
682
|
+
return getStructEncoder([
|
|
683
|
+
["numSignerAccounts", getMemoizedU8Encoder()],
|
|
684
|
+
["numReadonlySignerAccounts", getMemoizedU8Encoder()],
|
|
685
|
+
["numReadonlyNonSignerAccounts", getMemoizedU8Encoder()]
|
|
686
|
+
]);
|
|
687
|
+
}
|
|
688
|
+
function getMessageHeaderDecoder() {
|
|
689
|
+
return getStructDecoder([
|
|
690
|
+
["numSignerAccounts", getMemoizedU8Decoder()],
|
|
691
|
+
["numReadonlySignerAccounts", getMemoizedU8Decoder()],
|
|
692
|
+
["numReadonlyNonSignerAccounts", getMemoizedU8Decoder()]
|
|
693
|
+
]);
|
|
525
694
|
}
|
|
526
|
-
var programAddressIndexDescription = __DEV__ ? "The index of the program being called, according to the well-ordered accounts list for this transaction" : "programAddressIndex";
|
|
527
|
-
var accountIndexDescription = __DEV__ ? "The index of an account, according to the well-ordered accounts list for this transaction" : void 0;
|
|
528
|
-
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";
|
|
529
|
-
var dataDescription = __DEV__ ? "An optional buffer of data passed to the instruction" : "data";
|
|
530
695
|
var memoizedGetInstructionEncoder;
|
|
531
696
|
function getInstructionEncoder() {
|
|
532
697
|
if (!memoizedGetInstructionEncoder) {
|
|
533
698
|
memoizedGetInstructionEncoder = mapEncoder(
|
|
534
699
|
getStructEncoder([
|
|
535
|
-
["programAddressIndex", getU8Encoder(
|
|
536
|
-
[
|
|
537
|
-
|
|
538
|
-
getArrayEncoder(getU8Encoder({ description: accountIndexDescription }), {
|
|
539
|
-
description: accountIndicesDescription,
|
|
540
|
-
size: getShortU16Encoder()
|
|
541
|
-
})
|
|
542
|
-
],
|
|
543
|
-
["data", getBytesEncoder({ description: dataDescription, size: getShortU16Encoder() })]
|
|
700
|
+
["programAddressIndex", getU8Encoder()],
|
|
701
|
+
["accountIndices", getArrayEncoder(getU8Encoder(), { size: getShortU16Encoder() })],
|
|
702
|
+
["data", getBytesEncoder({ size: getShortU16Encoder() })]
|
|
544
703
|
]),
|
|
545
704
|
// Convert an instruction to have all fields defined
|
|
546
705
|
(instruction) => {
|
|
@@ -557,33 +716,66 @@ function getInstructionEncoder() {
|
|
|
557
716
|
}
|
|
558
717
|
return memoizedGetInstructionEncoder;
|
|
559
718
|
}
|
|
560
|
-
var
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
719
|
+
var memoizedGetInstructionDecoder;
|
|
720
|
+
function getInstructionDecoder() {
|
|
721
|
+
if (!memoizedGetInstructionDecoder) {
|
|
722
|
+
memoizedGetInstructionDecoder = mapDecoder(
|
|
723
|
+
getStructDecoder([
|
|
724
|
+
["programAddressIndex", getU8Decoder()],
|
|
725
|
+
["accountIndices", getArrayDecoder(getU8Decoder(), { size: getShortU16Decoder() })],
|
|
726
|
+
["data", getBytesDecoder({ size: getShortU16Decoder() })]
|
|
727
|
+
]),
|
|
728
|
+
// Convert an instruction to exclude optional fields if they are empty
|
|
729
|
+
(instruction) => {
|
|
730
|
+
if (instruction.accountIndices.length && instruction.data.byteLength) {
|
|
731
|
+
return instruction;
|
|
732
|
+
}
|
|
733
|
+
const { accountIndices, data, ...rest } = instruction;
|
|
734
|
+
return {
|
|
735
|
+
...rest,
|
|
736
|
+
...accountIndices.length ? { accountIndices } : null,
|
|
737
|
+
...data.byteLength ? { data } : null
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
);
|
|
572
741
|
}
|
|
573
|
-
return
|
|
742
|
+
return memoizedGetInstructionDecoder;
|
|
574
743
|
}
|
|
744
|
+
var VERSION_FLAG_MASK = 128;
|
|
575
745
|
function getTransactionVersionEncoder() {
|
|
576
|
-
return {
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
746
|
+
return createEncoder({
|
|
747
|
+
getSizeFromValue: (value) => value === "legacy" ? 0 : 1,
|
|
748
|
+
maxSize: 1,
|
|
749
|
+
write: (value, bytes, offset) => {
|
|
750
|
+
if (value === "legacy") {
|
|
751
|
+
return offset;
|
|
752
|
+
}
|
|
753
|
+
if (value < 0 || value > 127) {
|
|
754
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_VERSION_NUMBER_OUT_OF_RANGE, {
|
|
755
|
+
actualVersion: value
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
bytes.set([value | VERSION_FLAG_MASK], offset);
|
|
759
|
+
return offset + 1;
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
function getTransactionVersionDecoder() {
|
|
764
|
+
return createDecoder({
|
|
765
|
+
maxSize: 1,
|
|
766
|
+
read: (bytes, offset) => {
|
|
767
|
+
const firstByte = bytes[offset];
|
|
768
|
+
if ((firstByte & VERSION_FLAG_MASK) === 0) {
|
|
769
|
+
return ["legacy", offset];
|
|
770
|
+
} else {
|
|
771
|
+
const version = firstByte ^ VERSION_FLAG_MASK;
|
|
772
|
+
return [version, offset + 1];
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
});
|
|
580
776
|
}
|
|
581
777
|
|
|
582
778
|
// src/serializers/message.ts
|
|
583
|
-
var staticAccountsDescription = __DEV__ ? "A compact-array of static account addresses belonging to this transaction" : "staticAccounts";
|
|
584
|
-
var lifetimeTokenDescription = __DEV__ ? "A 32-byte token that specifies the lifetime of this transaction (eg. a recent blockhash, or a durable nonce)" : "lifetimeToken";
|
|
585
|
-
var instructionsDescription = __DEV__ ? "A compact-array of instructions belonging to this transaction" : "instructions";
|
|
586
|
-
var addressTableLookupsDescription = __DEV__ ? "A compact array of address table lookups belonging to this transaction" : "addressTableLookups";
|
|
587
779
|
function getCompiledMessageLegacyEncoder() {
|
|
588
780
|
return getStructEncoder(getPreludeStructEncoderTuple());
|
|
589
781
|
}
|
|
@@ -608,134 +800,126 @@ function getPreludeStructEncoderTuple() {
|
|
|
608
800
|
return [
|
|
609
801
|
["version", getTransactionVersionEncoder()],
|
|
610
802
|
["header", getMessageHeaderEncoder()],
|
|
611
|
-
[
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
[
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
})
|
|
625
|
-
],
|
|
626
|
-
[
|
|
627
|
-
"instructions",
|
|
628
|
-
getArrayEncoder(getInstructionEncoder(), {
|
|
629
|
-
description: instructionsDescription,
|
|
630
|
-
size: getShortU16Encoder()
|
|
631
|
-
})
|
|
632
|
-
]
|
|
803
|
+
["staticAccounts", getArrayEncoder(getAddressEncoder(), { size: getShortU16Encoder() })],
|
|
804
|
+
["lifetimeToken", getStringEncoder({ encoding: getBase58Encoder(), size: 32 })],
|
|
805
|
+
["instructions", getArrayEncoder(getInstructionEncoder(), { size: getShortU16Encoder() })]
|
|
806
|
+
];
|
|
807
|
+
}
|
|
808
|
+
function getPreludeStructDecoderTuple() {
|
|
809
|
+
return [
|
|
810
|
+
["version", getTransactionVersionDecoder()],
|
|
811
|
+
["header", getMessageHeaderDecoder()],
|
|
812
|
+
["staticAccounts", getArrayDecoder(getAddressDecoder(), { size: getShortU16Decoder() })],
|
|
813
|
+
["lifetimeToken", getStringDecoder({ encoding: getBase58Decoder(), size: 32 })],
|
|
814
|
+
["instructions", getArrayDecoder(getInstructionDecoder(), { size: getShortU16Decoder() })],
|
|
815
|
+
["addressTableLookups", getAddressTableLookupArrayDecoder()]
|
|
633
816
|
];
|
|
634
817
|
}
|
|
635
818
|
function getAddressTableLookupArrayEncoder() {
|
|
636
|
-
return getArrayEncoder(getAddressTableLookupEncoder(), {
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
});
|
|
819
|
+
return getArrayEncoder(getAddressTableLookupEncoder(), { size: getShortU16Encoder() });
|
|
820
|
+
}
|
|
821
|
+
function getAddressTableLookupArrayDecoder() {
|
|
822
|
+
return getArrayDecoder(getAddressTableLookupDecoder(), { size: getShortU16Decoder() });
|
|
640
823
|
}
|
|
641
|
-
var messageDescription = __DEV__ ? "The wire format of a Solana transaction message" : "message";
|
|
642
824
|
function getCompiledMessageEncoder() {
|
|
643
|
-
return {
|
|
644
|
-
|
|
645
|
-
encode: (compiledMessage) => {
|
|
825
|
+
return createEncoder({
|
|
826
|
+
getSizeFromValue: (compiledMessage) => {
|
|
646
827
|
if (compiledMessage.version === "legacy") {
|
|
647
|
-
return getCompiledMessageLegacyEncoder().
|
|
828
|
+
return getCompiledMessageLegacyEncoder().getSizeFromValue(compiledMessage);
|
|
648
829
|
} else {
|
|
649
|
-
return getCompiledMessageVersionedEncoder().
|
|
830
|
+
return getCompiledMessageVersionedEncoder().getSizeFromValue(compiledMessage);
|
|
650
831
|
}
|
|
651
832
|
},
|
|
652
|
-
|
|
653
|
-
|
|
833
|
+
write: (compiledMessage, bytes, offset) => {
|
|
834
|
+
if (compiledMessage.version === "legacy") {
|
|
835
|
+
return getCompiledMessageLegacyEncoder().write(compiledMessage, bytes, offset);
|
|
836
|
+
} else {
|
|
837
|
+
return getCompiledMessageVersionedEncoder().write(compiledMessage, bytes, offset);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
function getCompiledMessageDecoder() {
|
|
843
|
+
return mapDecoder(
|
|
844
|
+
getStructDecoder(getPreludeStructDecoderTuple()),
|
|
845
|
+
({ addressTableLookups, ...restOfMessage }) => {
|
|
846
|
+
if (restOfMessage.version === "legacy" || !addressTableLookups?.length) {
|
|
847
|
+
return restOfMessage;
|
|
848
|
+
}
|
|
849
|
+
return { ...restOfMessage, addressTableLookups };
|
|
850
|
+
}
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
function getCompiledMessageCodec() {
|
|
854
|
+
return combineCodec(getCompiledMessageEncoder(), getCompiledMessageDecoder());
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// src/compile-transaction.ts
|
|
858
|
+
function getCompiledTransaction(transaction) {
|
|
859
|
+
const compiledMessage = compileMessage(transaction);
|
|
860
|
+
let signatures;
|
|
861
|
+
if ("signatures" in transaction) {
|
|
862
|
+
signatures = [];
|
|
863
|
+
for (let ii = 0; ii < compiledMessage.header.numSignerAccounts; ii++) {
|
|
864
|
+
signatures[ii] = transaction.signatures[compiledMessage.staticAccounts[ii]] ?? new Uint8Array(Array(64).fill(0));
|
|
865
|
+
}
|
|
866
|
+
} else {
|
|
867
|
+
signatures = Array(compiledMessage.header.numSignerAccounts).fill(new Uint8Array(Array(64).fill(0)));
|
|
868
|
+
}
|
|
869
|
+
return {
|
|
870
|
+
compiledMessage,
|
|
871
|
+
signatures
|
|
654
872
|
};
|
|
655
873
|
}
|
|
656
874
|
|
|
657
875
|
// src/serializers/transaction.ts
|
|
658
|
-
var transactionDescription = __DEV__ ? "The wire format of a Solana transaction" : "transaction";
|
|
659
|
-
var signaturesDescription = __DEV__ ? "A compact array of 64-byte, base-64 encoded Ed25519 signatures" : "signatures";
|
|
660
876
|
function getCompiledTransactionEncoder() {
|
|
661
|
-
return getStructEncoder(
|
|
877
|
+
return getStructEncoder([
|
|
878
|
+
["signatures", getArrayEncoder(getBytesEncoder({ size: 64 }), { size: getShortU16Encoder() })],
|
|
879
|
+
["compiledMessage", getCompiledMessageEncoder()]
|
|
880
|
+
]);
|
|
881
|
+
}
|
|
882
|
+
function getCompiledTransactionDecoder() {
|
|
883
|
+
return getStructDecoder([
|
|
662
884
|
[
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
size: getShortU16Encoder()
|
|
668
|
-
})
|
|
669
|
-
],
|
|
670
|
-
["compiledMessage", getCompiledMessageEncoder()]
|
|
885
|
+
"signatures",
|
|
886
|
+
getArrayDecoder(getBytesDecoder({ size: 64 }), {
|
|
887
|
+
size: getShortU16Decoder()
|
|
888
|
+
})
|
|
671
889
|
],
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
}
|
|
675
|
-
);
|
|
890
|
+
["compiledMessage", getCompiledMessageDecoder()]
|
|
891
|
+
]);
|
|
676
892
|
}
|
|
677
893
|
function getTransactionEncoder() {
|
|
678
894
|
return mapEncoder(getCompiledTransactionEncoder(), getCompiledTransaction);
|
|
679
895
|
}
|
|
680
|
-
function
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
putativeTransactionSignature.length > 88
|
|
686
|
-
) {
|
|
687
|
-
throw new Error("Expected input string to decode to a byte array of length 64.");
|
|
688
|
-
}
|
|
689
|
-
const bytes = base58.serialize(putativeTransactionSignature);
|
|
690
|
-
const numBytes = bytes.byteLength;
|
|
691
|
-
if (numBytes !== 64) {
|
|
692
|
-
throw new Error(`Expected input string to decode to a byte array of length 64. Actual length: ${numBytes}`);
|
|
693
|
-
}
|
|
694
|
-
} catch (e) {
|
|
695
|
-
throw new Error(`\`${putativeTransactionSignature}\` is not a transaction signature`, {
|
|
696
|
-
cause: e
|
|
697
|
-
});
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
function isTransactionSignature(putativeTransactionSignature) {
|
|
701
|
-
if (
|
|
702
|
-
// Lowest value (64 bytes of zeroes)
|
|
703
|
-
putativeTransactionSignature.length < 64 || // Highest value (64 bytes of 255)
|
|
704
|
-
putativeTransactionSignature.length > 88
|
|
705
|
-
) {
|
|
706
|
-
return false;
|
|
707
|
-
}
|
|
708
|
-
const bytes = base58.serialize(putativeTransactionSignature);
|
|
709
|
-
const numBytes = bytes.byteLength;
|
|
710
|
-
if (numBytes !== 64) {
|
|
711
|
-
return false;
|
|
712
|
-
}
|
|
713
|
-
return true;
|
|
896
|
+
function getTransactionDecoder(config) {
|
|
897
|
+
return mapDecoder(
|
|
898
|
+
getCompiledTransactionDecoder(),
|
|
899
|
+
(compiledTransaction) => decompileTransaction(compiledTransaction, config)
|
|
900
|
+
);
|
|
714
901
|
}
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
const signature = await signBytes(secretKey, wireMessageBytes);
|
|
718
|
-
return signature;
|
|
902
|
+
function getTransactionCodec(config) {
|
|
903
|
+
return combineCodec(getTransactionEncoder(), getTransactionDecoder(config));
|
|
719
904
|
}
|
|
905
|
+
var base58Decoder;
|
|
720
906
|
function getSignatureFromTransaction(transaction) {
|
|
907
|
+
if (!base58Decoder)
|
|
908
|
+
base58Decoder = getBase58Decoder();
|
|
721
909
|
const signatureBytes = transaction.signatures[transaction.feePayer];
|
|
722
910
|
if (!signatureBytes) {
|
|
723
|
-
throw new
|
|
724
|
-
"Could not determine this transaction's signature. Make sure that the transaction has been signed by its fee payer."
|
|
725
|
-
);
|
|
911
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_SIGNATURE_NOT_COMPUTABLE);
|
|
726
912
|
}
|
|
727
|
-
const
|
|
728
|
-
return
|
|
913
|
+
const transactionSignature = base58Decoder.decode(signatureBytes);
|
|
914
|
+
return transactionSignature;
|
|
729
915
|
}
|
|
730
|
-
async function
|
|
916
|
+
async function partiallySignTransaction(keyPairs, transaction) {
|
|
731
917
|
const compiledMessage = compileMessage(transaction);
|
|
732
918
|
const nextSignatures = "signatures" in transaction ? { ...transaction.signatures } : {};
|
|
919
|
+
const wireMessageBytes = getCompiledMessageEncoder().encode(compiledMessage);
|
|
733
920
|
const publicKeySignaturePairs = await Promise.all(
|
|
734
921
|
keyPairs.map(
|
|
735
|
-
(keyPair) => Promise.all([
|
|
736
|
-
getAddressFromPublicKey(keyPair.publicKey),
|
|
737
|
-
getCompiledMessageSignature(compiledMessage, keyPair.privateKey)
|
|
738
|
-
])
|
|
922
|
+
(keyPair) => Promise.all([getAddressFromPublicKey(keyPair.publicKey), signBytes(keyPair.privateKey, wireMessageBytes)])
|
|
739
923
|
)
|
|
740
924
|
);
|
|
741
925
|
for (const [signerPublicKey, signature] of publicKeySignaturePairs) {
|
|
@@ -748,17 +932,32 @@ async function signTransaction(keyPairs, transaction) {
|
|
|
748
932
|
Object.freeze(out);
|
|
749
933
|
return out;
|
|
750
934
|
}
|
|
751
|
-
function
|
|
752
|
-
|
|
753
|
-
|
|
935
|
+
async function signTransaction(keyPairs, transaction) {
|
|
936
|
+
const out = await partiallySignTransaction(keyPairs, transaction);
|
|
937
|
+
assertTransactionIsFullySigned(out);
|
|
938
|
+
Object.freeze(out);
|
|
939
|
+
return out;
|
|
940
|
+
}
|
|
941
|
+
function assertTransactionIsFullySigned(transaction) {
|
|
942
|
+
const signerAddressesFromInstructions = transaction.instructions.flatMap((i) => i.accounts?.filter((a) => isSignerRole(a.role)) ?? []).map((a) => a.address);
|
|
943
|
+
const requiredSigners = /* @__PURE__ */ new Set([transaction.feePayer, ...signerAddressesFromInstructions]);
|
|
944
|
+
const missingSigs = [];
|
|
945
|
+
requiredSigners.forEach((address) => {
|
|
946
|
+
if (!transaction.signatures[address]) {
|
|
947
|
+
missingSigs.push(address);
|
|
948
|
+
}
|
|
949
|
+
});
|
|
950
|
+
if (missingSigs.length > 0) {
|
|
951
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION_MISSING_SIGNATURES, {
|
|
952
|
+
addresses: missingSigs
|
|
953
|
+
});
|
|
954
|
+
}
|
|
754
955
|
}
|
|
755
|
-
|
|
756
|
-
// src/wire-transaction.ts
|
|
757
956
|
function getBase64EncodedWireTransaction(transaction) {
|
|
758
957
|
const wireTransactionBytes = getTransactionEncoder().encode(transaction);
|
|
759
|
-
|
|
760
|
-
return btoa(String.fromCharCode(...wireTransactionBytes));
|
|
761
|
-
}
|
|
958
|
+
return getBase64Decoder().decode(wireTransactionBytes);
|
|
762
959
|
}
|
|
763
960
|
|
|
764
|
-
export { appendTransactionInstruction,
|
|
961
|
+
export { appendTransactionInstruction, appendTransactionInstructions, assertIsDurableNonceTransaction, assertIsTransactionWithBlockhashLifetime, assertTransactionIsFullySigned, compileMessage, createTransaction, decompileTransaction, getBase64EncodedWireTransaction, getCompiledMessageCodec, getCompiledMessageDecoder, getCompiledMessageEncoder, getCompiledTransactionDecoder, getSignatureFromTransaction, getTransactionCodec, getTransactionDecoder, getTransactionEncoder, getUnsignedTransaction, isAdvanceNonceAccountInstruction, partiallySignTransaction, prependTransactionInstruction, prependTransactionInstructions, setTransactionFeePayer, setTransactionLifetimeUsingBlockhash, setTransactionLifetimeUsingDurableNonce, signTransaction };
|
|
962
|
+
//# sourceMappingURL=out.js.map
|
|
963
|
+
//# sourceMappingURL=index.browser.js.map
|