@unio-aggregator/unio-tx-sender 1.0.2 → 1.0.4
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/dist/index.cjs +75 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/index.js +79 -29
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/dist/index.cjs
CHANGED
|
@@ -35,7 +35,8 @@ __export(index_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
36
|
|
|
37
37
|
// src/buildTransaction.ts
|
|
38
|
-
var
|
|
38
|
+
var import_kit3 = require("@solana/kit");
|
|
39
|
+
var import_transaction_messages = require("@solana/transaction-messages");
|
|
39
40
|
|
|
40
41
|
// src/computeBudget.ts
|
|
41
42
|
var import_kit = require("@solana/kit");
|
|
@@ -49,16 +50,14 @@ var DEFAULT_JITO_BLOCK_ENGINE_URL = "https://bundles.jito.wtf";
|
|
|
49
50
|
async function processComputeBudgetForTxMessage(rpc, message, computeUnits, config) {
|
|
50
51
|
const computeUnitMarginMultiplier = config.computeUnitMarginMultiplier;
|
|
51
52
|
let priorityFeeMicroLamports = 0n;
|
|
52
|
-
const units =
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
Math.ceil(computeUnits * (computeUnitMarginMultiplier ?? DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER))
|
|
56
|
-
)
|
|
53
|
+
const units = Math.min(
|
|
54
|
+
14e5,
|
|
55
|
+
Math.ceil(computeUnits * (computeUnitMarginMultiplier ?? DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER))
|
|
57
56
|
);
|
|
58
57
|
const priorityFee = config.priorityFee;
|
|
59
58
|
if (priorityFee) {
|
|
60
59
|
if (priorityFee.type === "exact") {
|
|
61
|
-
priorityFeeMicroLamports = priorityFee.amountLamports * 1000000n / units;
|
|
60
|
+
priorityFeeMicroLamports = priorityFee.amountLamports * 1000000n / BigInt(units);
|
|
62
61
|
} else if (priorityFee.type === "dynamic") {
|
|
63
62
|
const estimatedPriorityFee = await calculateDynamicPriorityFees(
|
|
64
63
|
rpc,
|
|
@@ -68,7 +67,7 @@ async function processComputeBudgetForTxMessage(rpc, message, computeUnits, conf
|
|
|
68
67
|
if (!priorityFee.maxCapLamports) {
|
|
69
68
|
priorityFeeMicroLamports = estimatedPriorityFee;
|
|
70
69
|
} else {
|
|
71
|
-
const maxCapMicroLamports = priorityFee.maxCapLamports * 1000000n / units;
|
|
70
|
+
const maxCapMicroLamports = priorityFee.maxCapLamports * 1000000n / BigInt(units);
|
|
72
71
|
priorityFeeMicroLamports = maxCapMicroLamports > estimatedPriorityFee ? estimatedPriorityFee : maxCapMicroLamports;
|
|
73
72
|
}
|
|
74
73
|
}
|
|
@@ -83,7 +82,7 @@ async function processComputeBudgetForTxMessage(rpc, message, computeUnits, conf
|
|
|
83
82
|
}
|
|
84
83
|
message = (0, import_kit.prependTransactionMessageInstruction)(
|
|
85
84
|
(0, import_compute_budget.getSetComputeUnitLimitInstruction)({
|
|
86
|
-
units
|
|
85
|
+
units
|
|
87
86
|
}),
|
|
88
87
|
message
|
|
89
88
|
);
|
|
@@ -110,7 +109,6 @@ async function calculateDynamicPriorityFees(rpc, instructions, percentile) {
|
|
|
110
109
|
|
|
111
110
|
// src/jito.ts
|
|
112
111
|
var import_kit2 = require("@solana/kit");
|
|
113
|
-
var import_kit3 = require("@solana/kit");
|
|
114
112
|
var import_system = require("@solana-program/system");
|
|
115
113
|
var JITO_BUNDLE_EXPIRY_TIME = 3e4;
|
|
116
114
|
var JitoApiUrl = /* @__PURE__ */ ((JitoApiUrl2) => {
|
|
@@ -168,7 +166,7 @@ async function recentJitoTip(config) {
|
|
|
168
166
|
if (!key || !data[key]) {
|
|
169
167
|
return BigInt(0);
|
|
170
168
|
}
|
|
171
|
-
return (0,
|
|
169
|
+
return (0, import_kit2.lamports)(BigInt(Math.floor(Number(data[key]) * 10 ** 9))).valueOf();
|
|
172
170
|
}
|
|
173
171
|
var jitoTipAddresses = [
|
|
174
172
|
"96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5",
|
|
@@ -181,7 +179,7 @@ var jitoTipAddresses = [
|
|
|
181
179
|
"3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT"
|
|
182
180
|
];
|
|
183
181
|
function getJitoTipAddress() {
|
|
184
|
-
return (0,
|
|
182
|
+
return (0, import_kit2.address)(jitoTipAddresses[Math.floor(Math.random() * jitoTipAddresses.length)]);
|
|
185
183
|
}
|
|
186
184
|
async function sendJitoBundle(jitoApiUrl, transactions, jitoUUID) {
|
|
187
185
|
const encodedTransactions = transactions.map((tx) => (0, import_kit2.getBase64EncodedWireTransaction)(tx));
|
|
@@ -291,7 +289,7 @@ async function buildTransaction(rpc, instructions, feePayer, config, lookupTable
|
|
|
291
289
|
return buildTransactionMessage(
|
|
292
290
|
rpc,
|
|
293
291
|
instructions,
|
|
294
|
-
!("address" in feePayer) ? (0,
|
|
292
|
+
!("address" in feePayer) ? (0, import_kit3.createNoopSigner)(feePayer) : feePayer,
|
|
295
293
|
config,
|
|
296
294
|
lookupTableAccounts
|
|
297
295
|
);
|
|
@@ -304,57 +302,98 @@ async function buildTransactionMessage(rpc, instructions, signer, config, lookup
|
|
|
304
302
|
}).send()).value;
|
|
305
303
|
}
|
|
306
304
|
let message = await prepareTransactionMessage(instructions, signer, blockhash);
|
|
305
|
+
let computeUnits = 14e5;
|
|
306
|
+
let messageWithExtra = await addPriorityInstructions(rpc, message, signer, config, computeUnits);
|
|
307
307
|
if (lookupTableAccounts?.length) {
|
|
308
308
|
const tables = lookupTableAccounts.reduce(
|
|
309
309
|
(prev, account) => {
|
|
310
310
|
if (account.exists) {
|
|
311
|
-
(0,
|
|
311
|
+
(0, import_kit3.assertAccountDecoded)(account);
|
|
312
312
|
prev[account.address] = account.data.addresses;
|
|
313
313
|
}
|
|
314
314
|
return prev;
|
|
315
315
|
},
|
|
316
316
|
{}
|
|
317
317
|
);
|
|
318
|
-
|
|
318
|
+
messageWithExtra = (0, import_kit3.compressTransactionMessageUsingAddressLookupTables)(messageWithExtra, tables);
|
|
319
319
|
}
|
|
320
|
-
|
|
321
|
-
|
|
320
|
+
if (!config.skipSimulation) {
|
|
321
|
+
try {
|
|
322
|
+
computeUnits = await getComputeUnitsForTxMessage(rpc, messageWithExtra);
|
|
323
|
+
messageWithExtra = await addPriorityInstructions(rpc, message, signer, config, computeUnits);
|
|
324
|
+
if (lookupTableAccounts?.length) {
|
|
325
|
+
const tables = lookupTableAccounts.reduce(
|
|
326
|
+
(prev, account) => {
|
|
327
|
+
if (account.exists) {
|
|
328
|
+
(0, import_kit3.assertAccountDecoded)(account);
|
|
329
|
+
prev[account.address] = account.data.addresses;
|
|
330
|
+
}
|
|
331
|
+
return prev;
|
|
332
|
+
},
|
|
333
|
+
{}
|
|
334
|
+
);
|
|
335
|
+
messageWithExtra = (0, import_kit3.compressTransactionMessageUsingAddressLookupTables)(messageWithExtra, tables);
|
|
336
|
+
}
|
|
337
|
+
} catch (e) {
|
|
338
|
+
console.warn("Transaction simulation failed, using 1,400,000 compute units: ", e);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return (0, import_kit3.signTransactionMessageWithSigners)(messageWithExtra);
|
|
322
342
|
}
|
|
323
343
|
async function prepareTransactionMessage(instructions, signer, blockhash) {
|
|
324
|
-
return (0,
|
|
325
|
-
(0,
|
|
326
|
-
(tx) => (0,
|
|
327
|
-
(tx) => (0,
|
|
328
|
-
(tx) => (0,
|
|
344
|
+
return (0, import_kit3.pipe)(
|
|
345
|
+
(0, import_kit3.createTransactionMessage)({ version: 0 }),
|
|
346
|
+
(tx) => (0, import_kit3.setTransactionMessageLifetimeUsingBlockhash)(blockhash, tx),
|
|
347
|
+
(tx) => (0, import_kit3.setTransactionMessageFeePayerSigner)(signer, tx),
|
|
348
|
+
(tx) => (0, import_kit3.appendTransactionMessageInstructions)(instructions, tx)
|
|
329
349
|
);
|
|
330
350
|
}
|
|
331
|
-
async function addPriorityInstructions(rpc, message, signer, config) {
|
|
351
|
+
async function addPriorityInstructions(rpc, message, signer, config, computeUnits) {
|
|
332
352
|
if (config.jito && config.jito.type !== "none") {
|
|
333
353
|
message = await processJitoTipForTxMessage(message, signer, config);
|
|
334
354
|
}
|
|
335
|
-
let computeUnits = 14e5;
|
|
336
|
-
if (!config.skipSimulation) {
|
|
337
|
-
try {
|
|
338
|
-
computeUnits = await getComputeUnitsForTxMessage(rpc, message);
|
|
339
|
-
} catch {
|
|
340
|
-
console.warn("Transaction simulation failed, using 1,400,000 compute units");
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
355
|
return processComputeBudgetForTxMessage(rpc, message, computeUnits, config);
|
|
344
356
|
}
|
|
345
|
-
async function getComputeUnitsForTxMessage(rpc,
|
|
346
|
-
|
|
357
|
+
async function getComputeUnitsForTxMessage(rpc, message) {
|
|
358
|
+
const replaceRecentBlockhash = !(0, import_transaction_messages.isTransactionMessageWithDurableNonceLifetime)(message);
|
|
359
|
+
const transaction = (0, import_kit3.pipe)(message, import_kit3.compileTransaction);
|
|
360
|
+
const wireTransactionBytes = (0, import_kit3.getBase64EncodedWireTransaction)(transaction);
|
|
361
|
+
try {
|
|
362
|
+
const response = await rpc.simulateTransaction(wireTransactionBytes, {
|
|
363
|
+
encoding: "base64",
|
|
364
|
+
replaceRecentBlockhash,
|
|
365
|
+
sigVerify: false
|
|
366
|
+
}).send();
|
|
367
|
+
const { err: transactionError, ...simulationResult } = response.value;
|
|
368
|
+
if (simulationResult.unitsConsumed == null) {
|
|
369
|
+
throw new import_kit3.SolanaError(import_kit3.SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT);
|
|
370
|
+
}
|
|
371
|
+
if (transactionError) {
|
|
372
|
+
throw new import_kit3.SolanaError(import_kit3.SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT, {
|
|
373
|
+
...simulationResult,
|
|
374
|
+
cause: (0, import_kit3.getSolanaErrorFromTransactionError)(transactionError)
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
return simulationResult.unitsConsumed > 4294967295n ? 4294967295 : Number(simulationResult.unitsConsumed);
|
|
378
|
+
} catch (e) {
|
|
379
|
+
if ((0, import_kit3.isSolanaError)(e, import_kit3.SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT)) {
|
|
380
|
+
throw e;
|
|
381
|
+
}
|
|
382
|
+
throw new import_kit3.SolanaError(import_kit3.SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT, {
|
|
383
|
+
cause: e
|
|
384
|
+
});
|
|
385
|
+
}
|
|
347
386
|
}
|
|
348
387
|
|
|
349
388
|
// src/sendTransaction.ts
|
|
350
|
-
var
|
|
389
|
+
var import_kit4 = require("@solana/kit");
|
|
351
390
|
async function sendTransaction(rpc, instructions, payer, config, lookupTableAccounts, commitment = "confirmed") {
|
|
352
391
|
const tx = await buildTransaction(rpc, instructions, payer, config ?? {}, lookupTableAccounts);
|
|
353
392
|
return sendSignedTransaction(rpc, tx, config?.skipSimulation ?? false, commitment);
|
|
354
393
|
}
|
|
355
394
|
async function sendSignedTransaction(rpc, transaction, skipSimulation = false, commitment = "confirmed") {
|
|
356
395
|
const txSignature = getTxSignature(transaction);
|
|
357
|
-
const encodedTransaction = (0,
|
|
396
|
+
const encodedTransaction = (0, import_kit4.getBase64EncodedWireTransaction)(transaction);
|
|
358
397
|
if (!skipSimulation) {
|
|
359
398
|
const simResult = await rpc.simulateTransaction(encodedTransaction, {
|
|
360
399
|
encoding: "base64"
|
|
@@ -383,7 +422,7 @@ async function sendSignedTransaction(rpc, transaction, skipSimulation = false, c
|
|
|
383
422
|
}
|
|
384
423
|
function getTxSignature(transaction) {
|
|
385
424
|
const [signature] = Object.values(transaction.signatures);
|
|
386
|
-
return (0,
|
|
425
|
+
return (0, import_kit4.getBase58Decoder)().decode(signature);
|
|
387
426
|
}
|
|
388
427
|
// Annotate the CommonJS export names for ESM import in node:
|
|
389
428
|
0 && (module.exports = {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/buildTransaction.ts","../src/computeBudget.ts","../src/config.ts","../src/jito.ts","../src/sendTransaction.ts"],"sourcesContent":["export * from \"./buildTransaction\";\nexport * from \"./config\";\nexport * from \"./jito\";\nexport * from \"./sendTransaction\";\n","import {\n Address,\n appendTransactionMessageInstructions,\n assertAccountDecoded,\n BlockhashLifetimeConstraint,\n compressTransactionMessageUsingAddressLookupTables,\n createNoopSigner,\n createTransactionMessage,\n estimateComputeUnitLimitFactory,\n Instruction,\n MaybeAccount,\n pipe,\n Rpc,\n SendableTransaction,\n setTransactionMessageFeePayerSigner,\n setTransactionMessageLifetimeUsingBlockhash,\n signTransactionMessageWithSigners,\n SolanaRpcApi,\n Transaction,\n TransactionMessage,\n TransactionMessageWithFeePayer,\n TransactionSigner,\n TransactionWithLifetime,\n} from \"@solana/kit\";\nimport { AddressLookupTable } from \"@solana-program/address-lookup-table\";\n\nimport { processComputeBudgetForTxMessage } from \"./computeBudget.ts\";\nimport { TransactionConfig } from \"./config\";\nimport { processJitoTipForTxMessage } from \"./jito.ts\";\n\n/**\n * Builds and signs a transaction from the given instructions and configuration.\n *\n * @param {Rpc<SolanaRpcApi>} rpc - Solana Rpc client.\n * @param {TransactionConfig} config - The transaction config.\n * @param {Instruction[]} instructions - Array of instructions to include in the transaction\n * @param {TransactionSigner} feePayer - The signer that will pay for the transaction\n * @param {(Address | string)[]} [lookupTableAccounts] - Optional array of address lookup table accounts to compress the transaction\n *\n * @returns {Promise<Readonly<SendableTransaction & Transaction & TransactionWithLifetime>>} A signed and encoded transaction\n *\n * @example\n * const instructions = [createATAix, createTransferSolInstruction];\n * const feePayer = wallet.publicKey;\n * const message = await buildTransaction(\n * rpc,\n * instructions,\n * feePayer,\n * );\n */\nexport async function buildTransaction(\n rpc: Rpc<SolanaRpcApi>,\n instructions: Instruction[],\n feePayer: TransactionSigner | Address,\n config: TransactionConfig,\n lookupTableAccounts?: MaybeAccount<AddressLookupTable>[],\n): Promise<Readonly<SendableTransaction & Transaction & TransactionWithLifetime>> {\n return buildTransactionMessage(\n rpc,\n instructions,\n !(\"address\" in feePayer) ? createNoopSigner(feePayer) : feePayer,\n config,\n lookupTableAccounts,\n );\n}\n\nasync function buildTransactionMessage(\n rpc: Rpc<SolanaRpcApi>,\n instructions: Instruction[],\n signer: TransactionSigner,\n config: TransactionConfig,\n lookupTableAccounts?: MaybeAccount<AddressLookupTable>[],\n) {\n let blockhash = config.blockhash;\n if (!blockhash) {\n blockhash = (\n await rpc\n .getLatestBlockhash({\n commitment: \"confirmed\",\n })\n .send()\n ).value;\n }\n\n let message = await prepareTransactionMessage(instructions, signer, blockhash);\n\n if (lookupTableAccounts?.length) {\n const tables = lookupTableAccounts.reduce(\n (prev, account) => {\n if (account.exists) {\n assertAccountDecoded(account);\n prev[account.address] = account.data.addresses;\n }\n return prev;\n },\n {} as { [address: Address]: Address[] },\n );\n message = compressTransactionMessageUsingAddressLookupTables(message, tables);\n }\n\n const messageWithExtraInstructions = await addPriorityInstructions(rpc, message, signer, config);\n\n return signTransactionMessageWithSigners(messageWithExtraInstructions);\n}\n\nasync function prepareTransactionMessage(\n instructions: Instruction[],\n signer: TransactionSigner,\n blockhash: BlockhashLifetimeConstraint,\n) {\n return pipe(\n createTransactionMessage({ version: 0 }),\n tx => setTransactionMessageLifetimeUsingBlockhash(blockhash, tx),\n tx => setTransactionMessageFeePayerSigner(signer, tx),\n tx => appendTransactionMessageInstructions(instructions, tx),\n );\n}\n\nasync function addPriorityInstructions(\n rpc: Rpc<SolanaRpcApi>,\n message: TransactionMessage & TransactionMessageWithFeePayer,\n signer: TransactionSigner,\n config: TransactionConfig,\n): Promise<TransactionMessage & TransactionMessageWithFeePayer> {\n if (config.jito && config.jito.type !== \"none\") {\n message = await processJitoTipForTxMessage(message, signer, config);\n }\n\n let computeUnits = 1_400_000;\n\n if (!config.skipSimulation) {\n try {\n computeUnits = await getComputeUnitsForTxMessage(rpc, message);\n } catch {\n console.warn(\"Transaction simulation failed, using 1,400,000 compute units\");\n }\n }\n\n return processComputeBudgetForTxMessage(rpc, message, computeUnits, config);\n}\n\nasync function getComputeUnitsForTxMessage(\n rpc: Rpc<SolanaRpcApi>,\n txMessage: TransactionMessage & TransactionMessageWithFeePayer,\n) {\n return await estimateComputeUnitLimitFactory({ rpc })(txMessage);\n}\n","import {\n Address,\n Instruction,\n Rpc,\n SolanaRpcApi,\n TransactionMessage,\n TransactionMessageWithFeePayer,\n} from \"@solana/kit\";\nimport { isWritableRole, prependTransactionMessageInstruction } from \"@solana/kit\";\nimport { getSetComputeUnitLimitInstruction, getSetComputeUnitPriceInstruction } from \"@solana-program/compute-budget\";\n\nimport type { Percentile, TransactionConfig } from \"./config\";\nimport { DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER } from \"./config\";\n\nexport async function processComputeBudgetForTxMessage(\n rpc: Rpc<SolanaRpcApi>,\n message: TransactionMessage & TransactionMessageWithFeePayer,\n computeUnits: number,\n config: TransactionConfig,\n) {\n const computeUnitMarginMultiplier = config.computeUnitMarginMultiplier;\n let priorityFeeMicroLamports = 0n;\n\n const units = BigInt(\n Math.min(\n 1_400_000,\n Math.ceil(computeUnits * (computeUnitMarginMultiplier ?? DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER)),\n ),\n );\n\n const priorityFee = config.priorityFee;\n if (priorityFee) {\n if (priorityFee.type === \"exact\") {\n priorityFeeMicroLamports = (priorityFee.amountLamports * 1_000_000n) / units;\n } else if (priorityFee.type === \"dynamic\") {\n const estimatedPriorityFee = await calculateDynamicPriorityFees(\n rpc,\n message.instructions,\n priorityFee.priorityFeePercentile ?? \"50\",\n );\n\n if (!priorityFee.maxCapLamports) {\n priorityFeeMicroLamports = estimatedPriorityFee;\n } else {\n const maxCapMicroLamports = (priorityFee.maxCapLamports * 1_000_000n) / units;\n priorityFeeMicroLamports =\n maxCapMicroLamports > estimatedPriorityFee ? estimatedPriorityFee : maxCapMicroLamports;\n }\n }\n }\n\n if (priorityFeeMicroLamports > 0) {\n message = prependTransactionMessageInstruction(\n getSetComputeUnitPriceInstruction({\n microLamports: priorityFeeMicroLamports,\n }),\n message,\n );\n }\n\n message = prependTransactionMessageInstruction(\n getSetComputeUnitLimitInstruction({\n units: computeUnits,\n }),\n message,\n );\n\n return message;\n}\n\nfunction getWritableAccounts(ixs: readonly Instruction[]) {\n const writable = new Set<Address>();\n ixs.forEach(ix => {\n if (ix.accounts) {\n ix.accounts.forEach(acc => {\n if (isWritableRole(acc.role)) writable.add(acc.address);\n });\n }\n });\n return Array.from(writable);\n}\n\nasync function calculateDynamicPriorityFees(\n rpc: Rpc<SolanaRpcApi>,\n instructions: readonly Instruction[],\n percentile: Percentile,\n) {\n const writableAccounts = getWritableAccounts(instructions);\n const recent = await rpc.getRecentPrioritizationFees(writableAccounts).send();\n const nonZero = recent.filter(pf => pf.prioritizationFee > 0).map(pf => pf.prioritizationFee);\n const sorted = nonZero.sort((a, b) => Number(a - b));\n return sorted[Math.floor(sorted.length * (parseInt(percentile) / 100))] || BigInt(0);\n}\n","import { BlockhashLifetimeConstraint } from \"@solana/kit\";\n\n/**\n * Default compute unit margin multiplier used to ensure sufficient compute budget.\n */\nexport const DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER = 1.15;\nexport const DEFAULT_JITO_BLOCK_ENGINE_URL = \"https://bundles.jito.wtf\";\n\ntype FeeSetting =\n | {\n type: \"dynamic\";\n maxCapLamports?: bigint;\n }\n | {\n type: \"exact\";\n amountLamports: bigint;\n }\n | {\n type: \"none\";\n };\n\n/**\n * Configuration for transaction fees, including Jito and priority fee settings.\n */\nexport type JitoFeeSetting = FeeSetting & {\n priorityFeePercentile?: Percentile | \"50ema\";\n};\n\nexport type PriorityFeeSetting = FeeSetting & {\n priorityFeePercentile?: Percentile;\n};\n\n/**\n * Defines a percentile value for priority fee selection.\n */\nexport type Percentile = \"25\" | \"50\" | \"75\" | \"95\" | \"99\";\n\nexport type TransactionConfig = {\n jito?: JitoFeeSetting;\n priorityFee?: PriorityFeeSetting;\n computeUnitMarginMultiplier?: number;\n jitoBlockEngineUrl?: string;\n skipSimulation?: boolean;\n blockhash?: BlockhashLifetimeConstraint;\n};\n","import {\n Address,\n appendTransactionMessageInstruction,\n getBase64EncodedWireTransaction,\n Rpc,\n SendableTransaction,\n SolanaRpcApi,\n Transaction,\n TransactionMessage,\n TransactionMessageWithFeePayer,\n TransactionSigner,\n TransactionWithLifetime,\n} from \"@solana/kit\";\nimport { address, lamports } from \"@solana/kit\";\nimport { getTransferSolInstruction } from \"@solana-program/system\";\n\nimport { DEFAULT_JITO_BLOCK_ENGINE_URL, type Percentile, TransactionConfig } from \"./config\";\n\nconst JITO_BUNDLE_EXPIRY_TIME = 30_000;\n\nexport type AccountConfig = {\n accountIndex: number;\n addresses: string[];\n};\n\nexport type JitoAccountInfo = {\n executable: boolean;\n owner: string;\n lamports: number;\n data: string;\n rentEpoch: number;\n};\n\nexport type JitoRpcApi = SolanaRpcApi & {\n simulateBundle: (\n params: {\n encodedTransactions: string[];\n },\n config?: {\n preExecutionAccountsConfigs?: AccountConfig;\n postExecutionAccountsConfigs?: AccountConfig;\n skipSigVerify?: boolean;\n simulationBank?: {\n commitment?: {\n commitment: \"processed\" | \"confirmed\" | \"finalized\";\n };\n };\n transactionEncoding?: \"base64\";\n replaceRecentBlockhash?: boolean;\n },\n ) => SimulateBundleResponse;\n\n sendBundle: (\n params: string[],\n config?: {\n encoding?: \"base64\";\n },\n ) => string;\n\n getBundleStatuses: (params: string[]) => GetBundleStatusesResponse;\n};\n\nexport type SimulateBundleResponse = {\n context: {\n slot: number;\n apiVersion?: string;\n };\n value: {\n summary: \"succeeded\" | { failed: { error: unknown; tx_signature: string } };\n transactionResults: Array<{\n err: unknown;\n logs: string[] | null;\n unitsConsumed?: number;\n returnData: {\n programId: string;\n data: string;\n } | null;\n preExecutionAccounts: JitoAccountInfo[] | null;\n postExecutionAccounts: JitoAccountInfo[] | null;\n }>;\n };\n};\n\nexport type GetBundleStatusesResponse = {\n context: {\n slot: number;\n };\n value: Array<{\n bundleId: string;\n transactions: string[];\n slot: number;\n confirmation_status: \"processed\" | \"confirmed\" | \"finalized\";\n err:\n | {\n Ok: null;\n }\n | {\n Err: object;\n };\n }>;\n};\n\nexport enum JitoApiUrl {\n Amsterdam = \"https://amsterdam.mainnet.block-engine.jito.wtf\",\n Frankfurt = \"https://frankfurt.mainnet.block-engine.jito.wtf\",\n London = \"https://london.mainnet.block-engine.jito.wtf\",\n NY = \"https://ny.mainnet.block-engine.jito.wtf\",\n Singapore = \"https://singapore.mainnet.block-engine.jito.wtf\",\n SLC = \"https://slc.mainnet.block-engine.jito.wtf\",\n Tokyo = \"https://tokyo.mainnet.block-engine.jito.wtf\",\n Default = \"https://mainnet.block-engine.jito.wtf\",\n}\n\nexport async function processJitoTipForTxMessage(\n message: TransactionMessage & TransactionMessageWithFeePayer,\n signer: TransactionSigner,\n config: TransactionConfig,\n) {\n const jito = config.jito;\n if (!jito) throw new Error(\"jito config is undefined\");\n\n let jitoTipLamports = BigInt(0);\n\n if (jito.type === \"exact\") {\n jitoTipLamports = jito.amountLamports;\n } else if (jito.type === \"dynamic\") {\n jitoTipLamports = await recentJitoTip(config);\n if (jito.maxCapLamports && jitoTipLamports > jito.maxCapLamports) {\n jitoTipLamports = jito.maxCapLamports;\n }\n }\n\n if (jitoTipLamports > 0) {\n return appendTransactionMessageInstruction(\n getTransferSolInstruction({\n source: signer,\n destination: getJitoTipAddress(),\n amount: jitoTipLamports,\n }),\n message,\n );\n } else {\n return message;\n }\n}\n\n// returns recent jito tip in lamports\nexport async function recentJitoTip(config: TransactionConfig) {\n const baseUrl = config.jitoBlockEngineUrl ?? DEFAULT_JITO_BLOCK_ENGINE_URL;\n const response = await fetch(`${baseUrl}/api/v1/bundles/tip_floor`);\n if (!response.ok) {\n return BigInt(0);\n }\n const data = await response.json().then(res => res[0]);\n\n const percentileToKey: Record<Percentile | \"50ema\", string> = {\n \"25\": \"landed_tips_25th_percentile\",\n \"50\": \"landed_tips_50th_percentile\",\n \"75\": \"landed_tips_75th_percentile\",\n \"95\": \"landed_tips_95th_percentile\",\n \"99\": \"landed_tips_99th_percentile\",\n \"50ema\": \"ema_landed_tips_50th_percentile\",\n };\n\n const key = percentileToKey[config.jito?.priorityFeePercentile ?? \"50\"];\n if (!key || !data[key]) {\n return BigInt(0);\n }\n return lamports(BigInt(Math.floor(Number(data[key]) * 10 ** 9))).valueOf();\n}\n\n// should we add an argument that dictates if we should use cached value in case fetch fails ?\n\n// below is taken from legacy sdk (no need to add the whole library)\n// https://jito-foundation.gitbook.io/mev/mev-payment-and-distribution/on-chain-addresses\nconst jitoTipAddresses = [\n \"96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5\",\n \"HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe\",\n \"Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY\",\n \"ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49\",\n \"DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh\",\n \"ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt\",\n \"DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL\",\n \"3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT\",\n];\n\nfunction getJitoTipAddress(): Address {\n // just pick a random one from the list. There are multiple addresses so that no single one can cause local congestion.\n return address(jitoTipAddresses[Math.floor(Math.random() * jitoTipAddresses.length)]);\n}\n\ninterface JsonRpcResult {\n jsonrpc: string;\n id: number;\n result?: string; // bundle id\n error?: {\n code: number;\n message: string;\n data?: unknown;\n };\n}\n\nexport async function sendJitoBundle(\n jitoApiUrl: JitoApiUrl,\n transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[],\n jitoUUID?: string,\n): Promise<string> {\n const encodedTransactions = transactions.map(tx => getBase64EncodedWireTransaction(tx)) as string[];\n\n const url = new URL(\"/api/v1/bundles\", jitoApiUrl);\n if (jitoUUID && jitoUUID.length > 0) {\n url.searchParams.set(\"uuid\", jitoUUID);\n }\n\n const request = {\n id: 1,\n jsonrpc: \"2.0\",\n method: \"sendBundle\",\n params: [\n encodedTransactions,\n {\n encoding: \"base64\",\n },\n ],\n };\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n throw new Error(`Jito HTTP error: ${response.status}`);\n }\n\n const data = (await response.json()) as JsonRpcResult;\n\n if (data.error) {\n throw new Error(`Jito bundle failed: ${data.error.code} ${data.error.message}`);\n }\n\n if (!data.result) {\n throw new Error(\"sendBundle did not return a bundle id\");\n }\n\n const bundleId = data.result;\n\n const expiryTime = Date.now() + JITO_BUNDLE_EXPIRY_TIME;\n\n while (Date.now() < expiryTime) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n const request = {\n jsonrpc: \"2.0\",\n id: 1,\n method: \"getInflightBundleStatuses\",\n params: [[bundleId]],\n };\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n throw new Error(`Jito HTTP error: ${response.status}`);\n }\n\n const data = await response.json();\n const result = data.result?.value?.[0];\n if (!result) {\n throw new Error(`getInflightBundleStatuses method returned undefined result`, { cause: { bundleId } });\n }\n\n switch (result.status) {\n case \"Landed\":\n return bundleId;\n case \"Pending\":\n case \"Invalid\":\n continue;\n case \"Failed\":\n throw new Error(`Bundle failed`, { cause: { bundleId } });\n default:\n throw new Error(`Bundle status is unknown`, { cause: { bundleId } });\n }\n }\n\n throw new Error(`Bundle expired`, { cause: { bundleId } });\n}\n\nexport async function simulateBundle(\n rpc: Rpc<JitoRpcApi>,\n transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[],\n): Promise<SimulateBundleResponse> {\n const encodedTransactions = transactions.map(tx => getBase64EncodedWireTransaction(tx));\n\n return rpc\n .simulateBundle({\n encodedTransactions,\n })\n .send();\n}\n\nexport async function sendBundle(\n rpc: Rpc<JitoRpcApi>,\n transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[],\n): Promise<string> {\n const encodedTransactions = transactions.map(tx => getBase64EncodedWireTransaction(tx));\n\n const bundleId = await rpc\n .sendBundle(encodedTransactions, {\n encoding: \"base64\",\n })\n .send();\n\n if (!bundleId) throw new Error(`sendBundle method failed`);\n\n const expiryTime = Date.now() + JITO_BUNDLE_EXPIRY_TIME;\n\n while (Date.now() < expiryTime) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n const statuses = await rpc.getBundleStatuses([bundleId]).send();\n\n const bundleStatus = statuses?.value?.[0];\n if (!bundleStatus) continue;\n\n if (bundleStatus.err && \"Err\" in bundleStatus.err) {\n throw new Error(`Bundle failed`, { cause: { bundleId, error: bundleStatus.err.Err } });\n } else {\n const confirmation_status = bundleStatus.confirmation_status;\n if (confirmation_status == \"confirmed\") {\n return bundleId;\n }\n }\n }\n\n throw new Error(`Bundle expired`, { cause: { bundleId } });\n}\n","import {\n Commitment,\n getBase58Decoder,\n getBase64EncodedWireTransaction,\n Instruction,\n KeyPairSigner,\n MaybeAccount,\n Rpc,\n SendableTransaction,\n Signature,\n SolanaRpcApi,\n Transaction,\n TransactionWithLifetime,\n} from \"@solana/kit\";\nimport { AddressLookupTable } from \"@solana-program/address-lookup-table\";\n\nimport { buildTransaction } from \"./buildTransaction\";\nimport { TransactionConfig } from \"./config\";\n\n/**\n * Builds and sends a transaction with the given instructions, signers, and commitment level.\n *\n * @param {Rpc<SolanaRpcApi>} rpc - Solana Rpc client.\n * @param {Instruction[]} instructions - Array of instructions to include in the transaction.\n * @param {KeyPairSigner} payer - The fee payer for the transaction.\n * @param {TransactionConfig} config - The transaction config.\n * @param {Address[]} [lookupTableAccounts] - Optional array of address lookup table accounts to use.\n * @param {Commitment} [commitment=\"confirmed\"] - The commitment level for transaction confirmation.\n *\n * @returns {Promise<Signature>} A promise that resolves to the transaction signature.\n *\n * @throws {Error} If transaction building or sending fails.\n *\n * @example\n * ```ts\n * const signature = await sendTransaction(\n * instructions,\n * keypairSigner,\n * DEFAULT_TRANSACTION_CONFIG,\n * lookupTables,\n * \"finalized\"\n * );\n * ```\n */\nexport async function sendTransaction(\n rpc: Rpc<SolanaRpcApi>,\n instructions: Instruction[],\n payer: KeyPairSigner,\n config?: TransactionConfig,\n lookupTableAccounts?: MaybeAccount<AddressLookupTable>[],\n commitment: Commitment = \"confirmed\",\n): Promise<Signature> {\n const tx = await buildTransaction(rpc, instructions, payer, config ?? {}, lookupTableAccounts);\n return sendSignedTransaction(rpc, tx, config?.skipSimulation ?? false, commitment);\n}\n\n/**\n * Sends a signed transaction message to the Solana network with a specified commitment level.\n *\n * @param {Rpc<SolanaRpcApi>} rpc - Rpc client.\n * @param {SendableTransaction & Transaction & TransactionWithLifetime} transaction - The fully signed transaction to send.\n * @param {boolean} skipSimulation - True if skip simulation\n * @param {Commitment} [commitment=\"confirmed\"] - The commitment level for transaction confirmation.\n *\n * @returns {Promise<Signature>} A promise that resolves to the transaction signature.\n *\n * @throws {Error} If transaction sending fails, the RPC connection fails, or the transaction expires.\n *\n * @example\n * ```ts\n * const signature = await sendSignedTransaction(\n * rpc,\n * signedTransaction,\n * \"finalized\"\n * );\n * ```\n */\nexport async function sendSignedTransaction(\n rpc: Rpc<SolanaRpcApi>,\n transaction: SendableTransaction & Transaction & TransactionWithLifetime,\n skipSimulation: boolean = false,\n commitment: Commitment = \"confirmed\",\n): Promise<Signature> {\n const txSignature = getTxSignature(transaction);\n const encodedTransaction = getBase64EncodedWireTransaction(transaction);\n\n if (!skipSimulation) {\n // Simulate transaction first\n const simResult = await rpc\n .simulateTransaction(encodedTransaction, {\n encoding: \"base64\",\n })\n .send();\n\n if (simResult.value.err) {\n throw new Error(`Transaction simulation failed`, { cause: simResult.value });\n }\n }\n\n const expiryTime = Date.now() + 60_000;\n\n while (Date.now() < expiryTime) {\n await rpc\n .sendTransaction(encodedTransaction, {\n maxRetries: BigInt(0),\n skipPreflight: true,\n encoding: \"base64\",\n })\n .send();\n\n const { value } = await rpc.getSignatureStatuses([txSignature]).send();\n const status = value[0];\n if (status?.confirmationStatus === commitment) {\n if (status.err) {\n throw new Error(`Transaction failed`, { cause: status.err });\n }\n return txSignature;\n }\n }\n\n throw new Error(\"Transaction expired\");\n}\n\nexport function getTxSignature(transaction: Transaction) {\n const [signature] = Object.values(transaction.signatures);\n return getBase58Decoder().decode(signature!) as Signature;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,cAuBO;;;ACfP,iBAAqE;AACrE,4BAAqF;;;ACJ9E,IAAM,yCAAyC;AAC/C,IAAM,gCAAgC;;;ADQ7C,eAAsB,iCACpB,KACA,SACA,cACA,QACA;AACA,QAAM,8BAA8B,OAAO;AAC3C,MAAI,2BAA2B;AAE/B,QAAM,QAAQ;AAAA,IACZ,KAAK;AAAA,MACH;AAAA,MACA,KAAK,KAAK,gBAAgB,+BAA+B,uCAAuC;AAAA,IAClG;AAAA,EACF;AAEA,QAAM,cAAc,OAAO;AAC3B,MAAI,aAAa;AACf,QAAI,YAAY,SAAS,SAAS;AAChC,iCAA4B,YAAY,iBAAiB,WAAc;AAAA,IACzE,WAAW,YAAY,SAAS,WAAW;AACzC,YAAM,uBAAuB,MAAM;AAAA,QACjC;AAAA,QACA,QAAQ;AAAA,QACR,YAAY,yBAAyB;AAAA,MACvC;AAEA,UAAI,CAAC,YAAY,gBAAgB;AAC/B,mCAA2B;AAAA,MAC7B,OAAO;AACL,cAAM,sBAAuB,YAAY,iBAAiB,WAAc;AACxE,mCACE,sBAAsB,uBAAuB,uBAAuB;AAAA,MACxE;AAAA,IACF;AAAA,EACF;AAEA,MAAI,2BAA2B,GAAG;AAChC,kBAAU;AAAA,UACR,yDAAkC;AAAA,QAChC,eAAe;AAAA,MACjB,CAAC;AAAA,MACD;AAAA,IACF;AAAA,EACF;AAEA,gBAAU;AAAA,QACR,yDAAkC;AAAA,MAChC,OAAO;AAAA,IACT,CAAC;AAAA,IACD;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,oBAAoB,KAA6B;AACxD,QAAM,WAAW,oBAAI,IAAa;AAClC,MAAI,QAAQ,QAAM;AAChB,QAAI,GAAG,UAAU;AACf,SAAG,SAAS,QAAQ,SAAO;AACzB,gBAAI,2BAAe,IAAI,IAAI,EAAG,UAAS,IAAI,IAAI,OAAO;AAAA,MACxD,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACD,SAAO,MAAM,KAAK,QAAQ;AAC5B;AAEA,eAAe,6BACb,KACA,cACA,YACA;AACA,QAAM,mBAAmB,oBAAoB,YAAY;AACzD,QAAM,SAAS,MAAM,IAAI,4BAA4B,gBAAgB,EAAE,KAAK;AAC5E,QAAM,UAAU,OAAO,OAAO,QAAM,GAAG,oBAAoB,CAAC,EAAE,IAAI,QAAM,GAAG,iBAAiB;AAC5F,QAAM,SAAS,QAAQ,KAAK,CAAC,GAAG,MAAM,OAAO,IAAI,CAAC,CAAC;AACnD,SAAO,OAAO,KAAK,MAAM,OAAO,UAAU,SAAS,UAAU,IAAI,IAAI,CAAC,KAAK,OAAO,CAAC;AACrF;;;AE5FA,IAAAC,cAYO;AACP,IAAAA,cAAkC;AAClC,oBAA0C;AAI1C,IAAM,0BAA0B;AAoFzB,IAAK,aAAL,kBAAKC,gBAAL;AACL,EAAAA,YAAA,eAAY;AACZ,EAAAA,YAAA,eAAY;AACZ,EAAAA,YAAA,YAAS;AACT,EAAAA,YAAA,QAAK;AACL,EAAAA,YAAA,eAAY;AACZ,EAAAA,YAAA,SAAM;AACN,EAAAA,YAAA,WAAQ;AACR,EAAAA,YAAA,aAAU;AARA,SAAAA;AAAA,GAAA;AAWZ,eAAsB,2BACpB,SACA,QACA,QACA;AACA,QAAM,OAAO,OAAO;AACpB,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,0BAA0B;AAErD,MAAI,kBAAkB,OAAO,CAAC;AAE9B,MAAI,KAAK,SAAS,SAAS;AACzB,sBAAkB,KAAK;AAAA,EACzB,WAAW,KAAK,SAAS,WAAW;AAClC,sBAAkB,MAAM,cAAc,MAAM;AAC5C,QAAI,KAAK,kBAAkB,kBAAkB,KAAK,gBAAgB;AAChE,wBAAkB,KAAK;AAAA,IACzB;AAAA,EACF;AAEA,MAAI,kBAAkB,GAAG;AACvB,eAAO;AAAA,UACL,yCAA0B;AAAA,QACxB,QAAQ;AAAA,QACR,aAAa,kBAAkB;AAAA,QAC/B,QAAQ;AAAA,MACV,CAAC;AAAA,MACD;AAAA,IACF;AAAA,EACF,OAAO;AACL,WAAO;AAAA,EACT;AACF;AAGA,eAAsB,cAAc,QAA2B;AAC7D,QAAM,UAAU,OAAO,sBAAsB;AAC7C,QAAM,WAAW,MAAM,MAAM,GAAG,OAAO,2BAA2B;AAClE,MAAI,CAAC,SAAS,IAAI;AAChB,WAAO,OAAO,CAAC;AAAA,EACjB;AACA,QAAM,OAAO,MAAM,SAAS,KAAK,EAAE,KAAK,SAAO,IAAI,CAAC,CAAC;AAErD,QAAM,kBAAwD;AAAA,IAC5D,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,EACX;AAEA,QAAM,MAAM,gBAAgB,OAAO,MAAM,yBAAyB,IAAI;AACtE,MAAI,CAAC,OAAO,CAAC,KAAK,GAAG,GAAG;AACtB,WAAO,OAAO,CAAC;AAAA,EACjB;AACA,aAAO,sBAAS,OAAO,KAAK,MAAM,OAAO,KAAK,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ;AAC3E;AAMA,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,oBAA6B;AAEpC,aAAO,qBAAQ,iBAAiB,KAAK,MAAM,KAAK,OAAO,IAAI,iBAAiB,MAAM,CAAC,CAAC;AACtF;AAaA,eAAsB,eACpB,YACA,cACA,UACiB;AACjB,QAAM,sBAAsB,aAAa,IAAI,YAAM,6CAAgC,EAAE,CAAC;AAEtF,QAAM,MAAM,IAAI,IAAI,mBAAmB,UAAU;AACjD,MAAI,YAAY,SAAS,SAAS,GAAG;AACnC,QAAI,aAAa,IAAI,QAAQ,QAAQ;AAAA,EACvC;AAEA,QAAM,UAAU;AAAA,IACd,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,QACE,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,MAAM,MAAM,KAAK;AAAA,IAChC,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,IAClB;AAAA,IACA,MAAM,KAAK,UAAU,OAAO;AAAA,EAC9B,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI,MAAM,oBAAoB,SAAS,MAAM,EAAE;AAAA,EACvD;AAEA,QAAM,OAAQ,MAAM,SAAS,KAAK;AAElC,MAAI,KAAK,OAAO;AACd,UAAM,IAAI,MAAM,uBAAuB,KAAK,MAAM,IAAI,IAAI,KAAK,MAAM,OAAO,EAAE;AAAA,EAChF;AAEA,MAAI,CAAC,KAAK,QAAQ;AAChB,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACzD;AAEA,QAAM,WAAW,KAAK;AAEtB,QAAM,aAAa,KAAK,IAAI,IAAI;AAEhC,SAAO,KAAK,IAAI,IAAI,YAAY;AAC9B,UAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,GAAI,CAAC;AAEtD,UAAMC,WAAU;AAAA,MACd,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,QAAQ,CAAC,CAAC,QAAQ,CAAC;AAAA,IACrB;AAEA,UAAMC,YAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAUD,QAAO;AAAA,IAC9B,CAAC;AAED,QAAI,CAACC,UAAS,IAAI;AAChB,YAAM,IAAI,MAAM,oBAAoBA,UAAS,MAAM,EAAE;AAAA,IACvD;AAEA,UAAMC,QAAO,MAAMD,UAAS,KAAK;AACjC,UAAM,SAASC,MAAK,QAAQ,QAAQ,CAAC;AACrC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,8DAA8D,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAAA,IACvG;AAEA,YAAQ,OAAO,QAAQ;AAAA,MACrB,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AACH;AAAA,MACF,KAAK;AACH,cAAM,IAAI,MAAM,iBAAiB,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAAA,MAC1D;AACE,cAAM,IAAI,MAAM,4BAA4B,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAAA,IACvE;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,kBAAkB,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAC3D;AAEA,eAAsB,eACpB,KACA,cACiC;AACjC,QAAM,sBAAsB,aAAa,IAAI,YAAM,6CAAgC,EAAE,CAAC;AAEtF,SAAO,IACJ,eAAe;AAAA,IACd;AAAA,EACF,CAAC,EACA,KAAK;AACV;AAEA,eAAsB,WACpB,KACA,cACiB;AACjB,QAAM,sBAAsB,aAAa,IAAI,YAAM,6CAAgC,EAAE,CAAC;AAEtF,QAAM,WAAW,MAAM,IACpB,WAAW,qBAAqB;AAAA,IAC/B,UAAU;AAAA,EACZ,CAAC,EACA,KAAK;AAER,MAAI,CAAC,SAAU,OAAM,IAAI,MAAM,0BAA0B;AAEzD,QAAM,aAAa,KAAK,IAAI,IAAI;AAEhC,SAAO,KAAK,IAAI,IAAI,YAAY;AAC9B,UAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,GAAI,CAAC;AAEtD,UAAM,WAAW,MAAM,IAAI,kBAAkB,CAAC,QAAQ,CAAC,EAAE,KAAK;AAE9D,UAAM,eAAe,UAAU,QAAQ,CAAC;AACxC,QAAI,CAAC,aAAc;AAEnB,QAAI,aAAa,OAAO,SAAS,aAAa,KAAK;AACjD,YAAM,IAAI,MAAM,iBAAiB,EAAE,OAAO,EAAE,UAAU,OAAO,aAAa,IAAI,IAAI,EAAE,CAAC;AAAA,IACvF,OAAO;AACL,YAAM,sBAAsB,aAAa;AACzC,UAAI,uBAAuB,aAAa;AACtC,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,kBAAkB,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAC3D;;;AHtSA,eAAsB,iBACpB,KACA,cACA,UACA,QACA,qBACgF;AAChF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,EAAE,aAAa,gBAAY,8BAAiB,QAAQ,IAAI;AAAA,IACxD;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,wBACb,KACA,cACA,QACA,QACA,qBACA;AACA,MAAI,YAAY,OAAO;AACvB,MAAI,CAAC,WAAW;AACd,iBACE,MAAM,IACH,mBAAmB;AAAA,MAClB,YAAY;AAAA,IACd,CAAC,EACA,KAAK,GACR;AAAA,EACJ;AAEA,MAAI,UAAU,MAAM,0BAA0B,cAAc,QAAQ,SAAS;AAE7E,MAAI,qBAAqB,QAAQ;AAC/B,UAAM,SAAS,oBAAoB;AAAA,MACjC,CAAC,MAAM,YAAY;AACjB,YAAI,QAAQ,QAAQ;AAClB,gDAAqB,OAAO;AAC5B,eAAK,QAAQ,OAAO,IAAI,QAAQ,KAAK;AAAA,QACvC;AACA,eAAO;AAAA,MACT;AAAA,MACA,CAAC;AAAA,IACH;AACA,kBAAU,gEAAmD,SAAS,MAAM;AAAA,EAC9E;AAEA,QAAM,+BAA+B,MAAM,wBAAwB,KAAK,SAAS,QAAQ,MAAM;AAE/F,aAAO,+CAAkC,4BAA4B;AACvE;AAEA,eAAe,0BACb,cACA,QACA,WACA;AACA,aAAO;AAAA,QACL,sCAAyB,EAAE,SAAS,EAAE,CAAC;AAAA,IACvC,YAAM,yDAA4C,WAAW,EAAE;AAAA,IAC/D,YAAM,iDAAoC,QAAQ,EAAE;AAAA,IACpD,YAAM,kDAAqC,cAAc,EAAE;AAAA,EAC7D;AACF;AAEA,eAAe,wBACb,KACA,SACA,QACA,QAC8D;AAC9D,MAAI,OAAO,QAAQ,OAAO,KAAK,SAAS,QAAQ;AAC9C,cAAU,MAAM,2BAA2B,SAAS,QAAQ,MAAM;AAAA,EACpE;AAEA,MAAI,eAAe;AAEnB,MAAI,CAAC,OAAO,gBAAgB;AAC1B,QAAI;AACF,qBAAe,MAAM,4BAA4B,KAAK,OAAO;AAAA,IAC/D,QAAQ;AACN,cAAQ,KAAK,8DAA8D;AAAA,IAC7E;AAAA,EACF;AAEA,SAAO,iCAAiC,KAAK,SAAS,cAAc,MAAM;AAC5E;AAEA,eAAe,4BACb,KACA,WACA;AACA,SAAO,UAAM,6CAAgC,EAAE,IAAI,CAAC,EAAE,SAAS;AACjE;;;AIlJA,IAAAC,cAaO;AA+BP,eAAsB,gBACpB,KACA,cACA,OACA,QACA,qBACA,aAAyB,aACL;AACpB,QAAM,KAAK,MAAM,iBAAiB,KAAK,cAAc,OAAO,UAAU,CAAC,GAAG,mBAAmB;AAC7F,SAAO,sBAAsB,KAAK,IAAI,QAAQ,kBAAkB,OAAO,UAAU;AACnF;AAuBA,eAAsB,sBACpB,KACA,aACA,iBAA0B,OAC1B,aAAyB,aACL;AACpB,QAAM,cAAc,eAAe,WAAW;AAC9C,QAAM,yBAAqB,6CAAgC,WAAW;AAEtE,MAAI,CAAC,gBAAgB;AAEnB,UAAM,YAAY,MAAM,IACrB,oBAAoB,oBAAoB;AAAA,MACvC,UAAU;AAAA,IACZ,CAAC,EACA,KAAK;AAER,QAAI,UAAU,MAAM,KAAK;AACvB,YAAM,IAAI,MAAM,iCAAiC,EAAE,OAAO,UAAU,MAAM,CAAC;AAAA,IAC7E;AAAA,EACF;AAEA,QAAM,aAAa,KAAK,IAAI,IAAI;AAEhC,SAAO,KAAK,IAAI,IAAI,YAAY;AAC9B,UAAM,IACH,gBAAgB,oBAAoB;AAAA,MACnC,YAAY,OAAO,CAAC;AAAA,MACpB,eAAe;AAAA,MACf,UAAU;AAAA,IACZ,CAAC,EACA,KAAK;AAER,UAAM,EAAE,MAAM,IAAI,MAAM,IAAI,qBAAqB,CAAC,WAAW,CAAC,EAAE,KAAK;AACrE,UAAM,SAAS,MAAM,CAAC;AACtB,QAAI,QAAQ,uBAAuB,YAAY;AAC7C,UAAI,OAAO,KAAK;AACd,cAAM,IAAI,MAAM,sBAAsB,EAAE,OAAO,OAAO,IAAI,CAAC;AAAA,MAC7D;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,qBAAqB;AACvC;AAEO,SAAS,eAAe,aAA0B;AACvD,QAAM,CAAC,SAAS,IAAI,OAAO,OAAO,YAAY,UAAU;AACxD,aAAO,8BAAiB,EAAE,OAAO,SAAU;AAC7C;","names":["import_kit","import_kit","JitoApiUrl","request","response","data","import_kit"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/buildTransaction.ts","../src/computeBudget.ts","../src/config.ts","../src/jito.ts","../src/sendTransaction.ts"],"sourcesContent":["export * from \"./buildTransaction\";\nexport * from \"./config\";\nexport * from \"./jito\";\nexport * from \"./sendTransaction\";\n","import {\n Address,\n appendTransactionMessageInstructions,\n assertAccountDecoded,\n BlockhashLifetimeConstraint,\n compileTransaction,\n compressTransactionMessageUsingAddressLookupTables,\n createNoopSigner,\n createTransactionMessage,\n getBase64EncodedWireTransaction,\n getSolanaErrorFromTransactionError,\n Instruction,\n isSolanaError,\n MaybeAccount,\n pipe,\n Rpc,\n RpcSimulateTransactionResult,\n SendableTransaction,\n setTransactionMessageFeePayerSigner,\n setTransactionMessageLifetimeUsingBlockhash,\n signTransactionMessageWithSigners,\n SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT,\n SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT,\n SolanaError,\n SolanaRpcApi,\n Transaction,\n TransactionMessage,\n TransactionMessageWithFeePayer,\n TransactionMessageWithSigners,\n TransactionSigner,\n TransactionWithLifetime,\n} from \"@solana/kit\";\nimport { isTransactionMessageWithDurableNonceLifetime } from \"@solana/transaction-messages\";\nimport { AddressLookupTable } from \"@solana-program/address-lookup-table\";\n\nimport { processComputeBudgetForTxMessage } from \"./computeBudget.ts\";\nimport { TransactionConfig } from \"./config\";\nimport { processJitoTipForTxMessage } from \"./jito.ts\";\n\n/**\n * Builds and signs a transaction from the given instructions and configuration.\n *\n * @param {Rpc<SolanaRpcApi>} rpc - Solana Rpc client.\n * @param {TransactionConfig} config - The transaction config.\n * @param {Instruction[]} instructions - Array of instructions to include in the transaction\n * @param {TransactionSigner} feePayer - The signer that will pay for the transaction\n * @param {(Address | string)[]} [lookupTableAccounts] - Optional array of address lookup table accounts to compress the transaction\n *\n * @returns {Promise<Readonly<SendableTransaction & Transaction & TransactionWithLifetime>>} A signed and encoded transaction\n *\n * @example\n * const instructions = [createATAix, createTransferSolInstruction];\n * const feePayer = wallet.publicKey;\n * const message = await buildTransaction(\n * rpc,\n * instructions,\n * feePayer,\n * );\n */\nexport async function buildTransaction(\n rpc: Rpc<SolanaRpcApi>,\n instructions: Instruction[],\n feePayer: TransactionSigner | Address,\n config: TransactionConfig,\n lookupTableAccounts?: MaybeAccount<AddressLookupTable>[],\n): Promise<Readonly<SendableTransaction & Transaction & TransactionWithLifetime>> {\n return buildTransactionMessage(\n rpc,\n instructions,\n !(\"address\" in feePayer) ? createNoopSigner(feePayer) : feePayer,\n config,\n lookupTableAccounts,\n );\n}\n\nasync function buildTransactionMessage(\n rpc: Rpc<SolanaRpcApi>,\n instructions: Instruction[],\n signer: TransactionSigner,\n config: TransactionConfig,\n lookupTableAccounts?: MaybeAccount<AddressLookupTable>[],\n) {\n let blockhash = config.blockhash;\n if (!blockhash) {\n blockhash = (\n await rpc\n .getLatestBlockhash({\n commitment: \"confirmed\",\n })\n .send()\n ).value;\n }\n\n let message = await prepareTransactionMessage(instructions, signer, blockhash);\n\n let computeUnits = 1_400_000;\n let messageWithExtra = await addPriorityInstructions(rpc, message, signer, config, computeUnits);\n\n if (lookupTableAccounts?.length) {\n const tables = lookupTableAccounts.reduce(\n (prev, account) => {\n if (account.exists) {\n assertAccountDecoded(account);\n prev[account.address] = account.data.addresses;\n }\n return prev;\n },\n {} as { [address: Address]: Address[] },\n );\n messageWithExtra = compressTransactionMessageUsingAddressLookupTables(messageWithExtra, tables);\n }\n\n if (!config.skipSimulation) {\n try {\n computeUnits = await getComputeUnitsForTxMessage(rpc, messageWithExtra);\n\n // Rebuild the message\n messageWithExtra = await addPriorityInstructions(rpc, message, signer, config, computeUnits);\n\n if (lookupTableAccounts?.length) {\n const tables = lookupTableAccounts.reduce(\n (prev, account) => {\n if (account.exists) {\n assertAccountDecoded(account);\n prev[account.address] = account.data.addresses;\n }\n return prev;\n },\n {} as { [address: Address]: Address[] },\n );\n messageWithExtra = compressTransactionMessageUsingAddressLookupTables(messageWithExtra, tables);\n }\n } catch (e) {\n console.warn(\"Transaction simulation failed, using 1,400,000 compute units: \", e);\n }\n }\n\n return signTransactionMessageWithSigners(messageWithExtra);\n}\n\nasync function prepareTransactionMessage(\n instructions: Instruction[],\n signer: TransactionSigner,\n blockhash: BlockhashLifetimeConstraint,\n) {\n return pipe(\n createTransactionMessage({ version: 0 }),\n tx => setTransactionMessageLifetimeUsingBlockhash(blockhash, tx),\n tx => setTransactionMessageFeePayerSigner(signer, tx),\n tx => appendTransactionMessageInstructions(instructions, tx),\n );\n}\n\nasync function addPriorityInstructions(\n rpc: Rpc<SolanaRpcApi>,\n message: TransactionMessageWithFeePayer &\n TransactionMessageWithSigners &\n Exclude<TransactionMessage, { version: \"legacy\" }>,\n signer: TransactionSigner,\n config: TransactionConfig,\n computeUnits: number,\n) {\n if (config.jito && config.jito.type !== \"none\") {\n message = await processJitoTipForTxMessage(message, signer, config);\n }\n\n return processComputeBudgetForTxMessage(rpc, message, computeUnits, config);\n}\n\nasync function getComputeUnitsForTxMessage(\n rpc: Rpc<SolanaRpcApi>,\n message: TransactionMessageWithFeePayer &\n TransactionMessageWithSigners &\n Exclude<TransactionMessage, { version: \"legacy\" }>,\n) {\n const replaceRecentBlockhash = !isTransactionMessageWithDurableNonceLifetime(message);\n\n const transaction = pipe(message, compileTransaction);\n const wireTransactionBytes = getBase64EncodedWireTransaction(transaction);\n\n try {\n const response = await rpc\n .simulateTransaction(wireTransactionBytes, {\n encoding: \"base64\",\n replaceRecentBlockhash,\n sigVerify: false,\n })\n .send();\n // The API response type varies based on config (eg. `replacementBlockhash` is only\n // present when `replaceRecentBlockhash` is true), but `RpcSimulateTransactionResult`\n // is a flat superset. Cast through `unknown` to bridge the structural gap.\n const { err: transactionError, ...simulationResult } = response.value as unknown as RpcSimulateTransactionResult;\n\n if (simulationResult.unitsConsumed == null) {\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT);\n }\n\n if (transactionError) {\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT, {\n ...simulationResult,\n cause: getSolanaErrorFromTransactionError(transactionError),\n });\n }\n\n // Downcast from bigint to number, capping at u32 max.\n return simulationResult.unitsConsumed > 4_294_967_295n ? 4_294_967_295 : Number(simulationResult.unitsConsumed);\n } catch (e) {\n if (isSolanaError(e, SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT)) {\n throw e;\n }\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT, {\n cause: e,\n });\n }\n}\n","import {\n Address,\n Instruction,\n isWritableRole,\n prependTransactionMessageInstruction,\n Rpc,\n SolanaRpcApi,\n TransactionMessage,\n TransactionMessageWithFeePayer,\n TransactionMessageWithSigners,\n} from \"@solana/kit\";\nimport { getSetComputeUnitLimitInstruction, getSetComputeUnitPriceInstruction } from \"@solana-program/compute-budget\";\n\nimport type { Percentile, TransactionConfig } from \"./config\";\nimport { DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER } from \"./config\";\n\nexport async function processComputeBudgetForTxMessage(\n rpc: Rpc<SolanaRpcApi>,\n message: TransactionMessageWithFeePayer &\n TransactionMessageWithSigners &\n Exclude<TransactionMessage, { version: \"legacy\" }>,\n computeUnits: number,\n config: TransactionConfig,\n) {\n const computeUnitMarginMultiplier = config.computeUnitMarginMultiplier;\n let priorityFeeMicroLamports = 0n;\n\n const units = Math.min(\n 1_400_000,\n Math.ceil(computeUnits * (computeUnitMarginMultiplier ?? DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER)),\n );\n\n const priorityFee = config.priorityFee;\n if (priorityFee) {\n if (priorityFee.type === \"exact\") {\n priorityFeeMicroLamports = (priorityFee.amountLamports * 1_000_000n) / BigInt(units);\n } else if (priorityFee.type === \"dynamic\") {\n const estimatedPriorityFee = await calculateDynamicPriorityFees(\n rpc,\n message.instructions,\n priorityFee.priorityFeePercentile ?? \"50\",\n );\n\n if (!priorityFee.maxCapLamports) {\n priorityFeeMicroLamports = estimatedPriorityFee;\n } else {\n const maxCapMicroLamports = (priorityFee.maxCapLamports * 1_000_000n) / BigInt(units);\n priorityFeeMicroLamports =\n maxCapMicroLamports > estimatedPriorityFee ? estimatedPriorityFee : maxCapMicroLamports;\n }\n }\n }\n\n if (priorityFeeMicroLamports > 0) {\n message = prependTransactionMessageInstruction(\n getSetComputeUnitPriceInstruction({\n microLamports: priorityFeeMicroLamports,\n }),\n message,\n );\n }\n\n message = prependTransactionMessageInstruction(\n getSetComputeUnitLimitInstruction({\n units,\n }),\n message,\n );\n\n return message;\n}\n\nfunction getWritableAccounts(ixs: readonly Instruction[]) {\n const writable = new Set<Address>();\n ixs.forEach(ix => {\n if (ix.accounts) {\n ix.accounts.forEach(acc => {\n if (isWritableRole(acc.role)) writable.add(acc.address);\n });\n }\n });\n return Array.from(writable);\n}\n\nasync function calculateDynamicPriorityFees(\n rpc: Rpc<SolanaRpcApi>,\n instructions: readonly Instruction[],\n percentile: Percentile,\n) {\n const writableAccounts = getWritableAccounts(instructions);\n const recent = await rpc.getRecentPrioritizationFees(writableAccounts).send();\n const nonZero = recent.filter(pf => pf.prioritizationFee > 0).map(pf => pf.prioritizationFee);\n const sorted = nonZero.sort((a, b) => Number(a - b));\n return sorted[Math.floor(sorted.length * (parseInt(percentile) / 100))] || BigInt(0);\n}\n","import { BlockhashLifetimeConstraint } from \"@solana/kit\";\n\n/**\n * Default compute unit margin multiplier used to ensure sufficient compute budget.\n */\nexport const DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER = 1.15;\nexport const DEFAULT_JITO_BLOCK_ENGINE_URL = \"https://bundles.jito.wtf\";\n\ntype FeeSetting =\n | {\n type: \"dynamic\";\n maxCapLamports?: bigint;\n }\n | {\n type: \"exact\";\n amountLamports: bigint;\n }\n | {\n type: \"none\";\n };\n\n/**\n * Configuration for transaction fees, including Jito and priority fee settings.\n */\nexport type JitoFeeSetting = FeeSetting & {\n priorityFeePercentile?: Percentile | \"50ema\";\n};\n\nexport type PriorityFeeSetting = FeeSetting & {\n priorityFeePercentile?: Percentile;\n};\n\n/**\n * Defines a percentile value for priority fee selection.\n */\nexport type Percentile = \"25\" | \"50\" | \"75\" | \"95\" | \"99\";\n\nexport type TransactionConfig = {\n jito?: JitoFeeSetting;\n priorityFee?: PriorityFeeSetting;\n computeUnitMarginMultiplier?: number;\n jitoBlockEngineUrl?: string;\n skipSimulation?: boolean;\n blockhash?: BlockhashLifetimeConstraint;\n};\n","import {\n Address,\n address,\n appendTransactionMessageInstruction,\n getBase64EncodedWireTransaction,\n lamports,\n Rpc,\n SendableTransaction,\n SolanaRpcApi,\n Transaction,\n TransactionMessage,\n TransactionMessageWithFeePayer,\n TransactionMessageWithSigners,\n TransactionSigner,\n TransactionWithLifetime,\n} from \"@solana/kit\";\nimport { getTransferSolInstruction } from \"@solana-program/system\";\n\nimport { DEFAULT_JITO_BLOCK_ENGINE_URL, type Percentile, TransactionConfig } from \"./config\";\n\nconst JITO_BUNDLE_EXPIRY_TIME = 30_000;\n\nexport type AccountConfig = {\n accountIndex: number;\n addresses: string[];\n};\n\nexport type JitoAccountInfo = {\n executable: boolean;\n owner: string;\n lamports: number;\n data: string;\n rentEpoch: number;\n};\n\nexport type JitoRpcApi = SolanaRpcApi & {\n simulateBundle: (\n params: {\n encodedTransactions: string[];\n },\n config?: {\n preExecutionAccountsConfigs?: AccountConfig;\n postExecutionAccountsConfigs?: AccountConfig;\n skipSigVerify?: boolean;\n simulationBank?: {\n commitment?: {\n commitment: \"processed\" | \"confirmed\" | \"finalized\";\n };\n };\n transactionEncoding?: \"base64\";\n replaceRecentBlockhash?: boolean;\n },\n ) => SimulateBundleResponse;\n\n sendBundle: (\n params: string[],\n config?: {\n encoding?: \"base64\";\n },\n ) => string;\n\n getBundleStatuses: (params: string[]) => GetBundleStatusesResponse;\n};\n\nexport type SimulateBundleResponse = {\n context: {\n slot: number;\n apiVersion?: string;\n };\n value: {\n summary: \"succeeded\" | { failed: { error: unknown; tx_signature: string } };\n transactionResults: Array<{\n err: unknown;\n logs: string[] | null;\n unitsConsumed?: number;\n returnData: {\n programId: string;\n data: string;\n } | null;\n preExecutionAccounts: JitoAccountInfo[] | null;\n postExecutionAccounts: JitoAccountInfo[] | null;\n }>;\n };\n};\n\nexport type GetBundleStatusesResponse = {\n context: {\n slot: number;\n };\n value: Array<{\n bundleId: string;\n transactions: string[];\n slot: number;\n confirmation_status: \"processed\" | \"confirmed\" | \"finalized\";\n err:\n | {\n Ok: null;\n }\n | {\n Err: object;\n };\n }>;\n};\n\nexport enum JitoApiUrl {\n Amsterdam = \"https://amsterdam.mainnet.block-engine.jito.wtf\",\n Frankfurt = \"https://frankfurt.mainnet.block-engine.jito.wtf\",\n London = \"https://london.mainnet.block-engine.jito.wtf\",\n NY = \"https://ny.mainnet.block-engine.jito.wtf\",\n Singapore = \"https://singapore.mainnet.block-engine.jito.wtf\",\n SLC = \"https://slc.mainnet.block-engine.jito.wtf\",\n Tokyo = \"https://tokyo.mainnet.block-engine.jito.wtf\",\n Default = \"https://mainnet.block-engine.jito.wtf\",\n}\n\nexport async function processJitoTipForTxMessage(\n message: TransactionMessageWithFeePayer &\n TransactionMessageWithSigners &\n Exclude<TransactionMessage, { version: \"legacy\" }>,\n signer: TransactionSigner,\n config: TransactionConfig,\n) {\n const jito = config.jito;\n if (!jito) throw new Error(\"jito config is undefined\");\n\n let jitoTipLamports = BigInt(0);\n\n if (jito.type === \"exact\") {\n jitoTipLamports = jito.amountLamports;\n } else if (jito.type === \"dynamic\") {\n jitoTipLamports = await recentJitoTip(config);\n if (jito.maxCapLamports && jitoTipLamports > jito.maxCapLamports) {\n jitoTipLamports = jito.maxCapLamports;\n }\n }\n\n if (jitoTipLamports > 0) {\n return appendTransactionMessageInstruction(\n getTransferSolInstruction({\n source: signer,\n destination: getJitoTipAddress(),\n amount: jitoTipLamports,\n }),\n message,\n );\n } else {\n return message;\n }\n}\n\n// returns recent jito tip in lamports\nexport async function recentJitoTip(config: TransactionConfig) {\n const baseUrl = config.jitoBlockEngineUrl ?? DEFAULT_JITO_BLOCK_ENGINE_URL;\n const response = await fetch(`${baseUrl}/api/v1/bundles/tip_floor`);\n if (!response.ok) {\n return BigInt(0);\n }\n const data = await response.json().then(res => res[0]);\n\n const percentileToKey: Record<Percentile | \"50ema\", string> = {\n \"25\": \"landed_tips_25th_percentile\",\n \"50\": \"landed_tips_50th_percentile\",\n \"75\": \"landed_tips_75th_percentile\",\n \"95\": \"landed_tips_95th_percentile\",\n \"99\": \"landed_tips_99th_percentile\",\n \"50ema\": \"ema_landed_tips_50th_percentile\",\n };\n\n const key = percentileToKey[config.jito?.priorityFeePercentile ?? \"50\"];\n if (!key || !data[key]) {\n return BigInt(0);\n }\n return lamports(BigInt(Math.floor(Number(data[key]) * 10 ** 9))).valueOf();\n}\n\n// should we add an argument that dictates if we should use cached value in case fetch fails ?\n\n// below is taken from legacy sdk (no need to add the whole library)\n// https://jito-foundation.gitbook.io/mev/mev-payment-and-distribution/on-chain-addresses\nconst jitoTipAddresses = [\n \"96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5\",\n \"HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe\",\n \"Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY\",\n \"ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49\",\n \"DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh\",\n \"ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt\",\n \"DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL\",\n \"3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT\",\n];\n\nfunction getJitoTipAddress(): Address {\n // just pick a random one from the list. There are multiple addresses so that no single one can cause local congestion.\n return address(jitoTipAddresses[Math.floor(Math.random() * jitoTipAddresses.length)]);\n}\n\ninterface JsonRpcResult {\n jsonrpc: string;\n id: number;\n result?: string; // bundle id\n error?: {\n code: number;\n message: string;\n data?: unknown;\n };\n}\n\nexport async function sendJitoBundle(\n jitoApiUrl: JitoApiUrl,\n transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[],\n jitoUUID?: string,\n): Promise<string> {\n const encodedTransactions = transactions.map(tx => getBase64EncodedWireTransaction(tx)) as string[];\n\n const url = new URL(\"/api/v1/bundles\", jitoApiUrl);\n if (jitoUUID && jitoUUID.length > 0) {\n url.searchParams.set(\"uuid\", jitoUUID);\n }\n\n const request = {\n id: 1,\n jsonrpc: \"2.0\",\n method: \"sendBundle\",\n params: [\n encodedTransactions,\n {\n encoding: \"base64\",\n },\n ],\n };\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n throw new Error(`Jito HTTP error: ${response.status}`);\n }\n\n const data = (await response.json()) as JsonRpcResult;\n\n if (data.error) {\n throw new Error(`Jito bundle failed: ${data.error.code} ${data.error.message}`);\n }\n\n if (!data.result) {\n throw new Error(\"sendBundle did not return a bundle id\");\n }\n\n const bundleId = data.result;\n\n const expiryTime = Date.now() + JITO_BUNDLE_EXPIRY_TIME;\n\n while (Date.now() < expiryTime) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n const request = {\n jsonrpc: \"2.0\",\n id: 1,\n method: \"getInflightBundleStatuses\",\n params: [[bundleId]],\n };\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n throw new Error(`Jito HTTP error: ${response.status}`);\n }\n\n const data = await response.json();\n const result = data.result?.value?.[0];\n if (!result) {\n throw new Error(`getInflightBundleStatuses method returned undefined result`, { cause: { bundleId } });\n }\n\n switch (result.status) {\n case \"Landed\":\n return bundleId;\n case \"Pending\":\n case \"Invalid\":\n continue;\n case \"Failed\":\n throw new Error(`Bundle failed`, { cause: { bundleId } });\n default:\n throw new Error(`Bundle status is unknown`, { cause: { bundleId } });\n }\n }\n\n throw new Error(`Bundle expired`, { cause: { bundleId } });\n}\n\nexport async function simulateBundle(\n rpc: Rpc<JitoRpcApi>,\n transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[],\n): Promise<SimulateBundleResponse> {\n const encodedTransactions = transactions.map(tx => getBase64EncodedWireTransaction(tx));\n\n return rpc\n .simulateBundle({\n encodedTransactions,\n })\n .send();\n}\n\nexport async function sendBundle(\n rpc: Rpc<JitoRpcApi>,\n transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[],\n): Promise<string> {\n const encodedTransactions = transactions.map(tx => getBase64EncodedWireTransaction(tx));\n\n const bundleId = await rpc\n .sendBundle(encodedTransactions, {\n encoding: \"base64\",\n })\n .send();\n\n if (!bundleId) throw new Error(`sendBundle method failed`);\n\n const expiryTime = Date.now() + JITO_BUNDLE_EXPIRY_TIME;\n\n while (Date.now() < expiryTime) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n const statuses = await rpc.getBundleStatuses([bundleId]).send();\n\n const bundleStatus = statuses?.value?.[0];\n if (!bundleStatus) continue;\n\n if (bundleStatus.err && \"Err\" in bundleStatus.err) {\n throw new Error(`Bundle failed`, { cause: { bundleId, error: bundleStatus.err.Err } });\n } else {\n const confirmation_status = bundleStatus.confirmation_status;\n if (confirmation_status == \"confirmed\") {\n return bundleId;\n }\n }\n }\n\n throw new Error(`Bundle expired`, { cause: { bundleId } });\n}\n","import {\n Commitment,\n getBase58Decoder,\n getBase64EncodedWireTransaction,\n Instruction,\n KeyPairSigner,\n MaybeAccount,\n Rpc,\n SendableTransaction,\n Signature,\n SolanaRpcApi,\n Transaction,\n TransactionWithLifetime,\n} from \"@solana/kit\";\nimport { AddressLookupTable } from \"@solana-program/address-lookup-table\";\n\nimport { buildTransaction } from \"./buildTransaction\";\nimport { TransactionConfig } from \"./config\";\n\n/**\n * Builds and sends a transaction with the given instructions, signers, and commitment level.\n *\n * @param {Rpc<SolanaRpcApi>} rpc - Solana Rpc client.\n * @param {Instruction[]} instructions - Array of instructions to include in the transaction.\n * @param {KeyPairSigner} payer - The fee payer for the transaction.\n * @param {TransactionConfig} config - The transaction config.\n * @param {Address[]} [lookupTableAccounts] - Optional array of address lookup table accounts to use.\n * @param {Commitment} [commitment=\"confirmed\"] - The commitment level for transaction confirmation.\n *\n * @returns {Promise<Signature>} A promise that resolves to the transaction signature.\n *\n * @throws {Error} If transaction building or sending fails.\n *\n * @example\n * ```ts\n * const signature = await sendTransaction(\n * instructions,\n * keypairSigner,\n * DEFAULT_TRANSACTION_CONFIG,\n * lookupTables,\n * \"finalized\"\n * );\n * ```\n */\nexport async function sendTransaction(\n rpc: Rpc<SolanaRpcApi>,\n instructions: Instruction[],\n payer: KeyPairSigner,\n config?: TransactionConfig,\n lookupTableAccounts?: MaybeAccount<AddressLookupTable>[],\n commitment: Commitment = \"confirmed\",\n): Promise<Signature> {\n const tx = await buildTransaction(rpc, instructions, payer, config ?? {}, lookupTableAccounts);\n return sendSignedTransaction(rpc, tx, config?.skipSimulation ?? false, commitment);\n}\n\n/**\n * Sends a signed transaction message to the Solana network with a specified commitment level.\n *\n * @param {Rpc<SolanaRpcApi>} rpc - Rpc client.\n * @param {SendableTransaction & Transaction & TransactionWithLifetime} transaction - The fully signed transaction to send.\n * @param {boolean} skipSimulation - True if skip simulation\n * @param {Commitment} [commitment=\"confirmed\"] - The commitment level for transaction confirmation.\n *\n * @returns {Promise<Signature>} A promise that resolves to the transaction signature.\n *\n * @throws {Error} If transaction sending fails, the RPC connection fails, or the transaction expires.\n *\n * @example\n * ```ts\n * const signature = await sendSignedTransaction(\n * rpc,\n * signedTransaction,\n * \"finalized\"\n * );\n * ```\n */\nexport async function sendSignedTransaction(\n rpc: Rpc<SolanaRpcApi>,\n transaction: SendableTransaction & Transaction & TransactionWithLifetime,\n skipSimulation: boolean = false,\n commitment: Commitment = \"confirmed\",\n): Promise<Signature> {\n const txSignature = getTxSignature(transaction);\n const encodedTransaction = getBase64EncodedWireTransaction(transaction);\n\n if (!skipSimulation) {\n // Simulate transaction first\n const simResult = await rpc\n .simulateTransaction(encodedTransaction, {\n encoding: \"base64\",\n })\n .send();\n\n if (simResult.value.err) {\n throw new Error(`Transaction simulation failed`, { cause: simResult.value });\n }\n }\n\n const expiryTime = Date.now() + 60_000;\n\n while (Date.now() < expiryTime) {\n await rpc\n .sendTransaction(encodedTransaction, {\n maxRetries: BigInt(0),\n skipPreflight: true,\n encoding: \"base64\",\n })\n .send();\n\n const { value } = await rpc.getSignatureStatuses([txSignature]).send();\n const status = value[0];\n if (status?.confirmationStatus === commitment) {\n if (status.err) {\n throw new Error(`Transaction failed`, { cause: status.err });\n }\n return txSignature;\n }\n }\n\n throw new Error(\"Transaction expired\");\n}\n\nexport function getTxSignature(transaction: Transaction) {\n const [signature] = Object.values(transaction.signatures);\n return getBase58Decoder().decode(signature!) as Signature;\n}\n"],"mappings":"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","names":["import_kit","import_kit","JitoApiUrl","request","response","data","import_kit"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as _solana_kit from '@solana/kit';
|
|
2
|
+
import { BlockhashLifetimeConstraint, Rpc, SolanaRpcApi, Instruction, TransactionSigner, Address, MaybeAccount, SendableTransaction, Transaction, TransactionWithLifetime, TransactionMessageWithFeePayer, TransactionMessageWithSigners, TransactionMessage, Signature, Commitment, KeyPairSigner } from '@solana/kit';
|
|
2
3
|
import { AddressLookupTable } from '@solana-program/address-lookup-table';
|
|
4
|
+
import * as _solana_transaction_messages_dist_types_v1_transaction_config from '@solana/transaction-messages/dist/types/v1-transaction-config';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Default compute unit margin multiplier used to ensure sufficient compute budget.
|
|
@@ -141,7 +143,19 @@ declare enum JitoApiUrl {
|
|
|
141
143
|
Tokyo = "https://tokyo.mainnet.block-engine.jito.wtf",
|
|
142
144
|
Default = "https://mainnet.block-engine.jito.wtf"
|
|
143
145
|
}
|
|
144
|
-
declare function processJitoTipForTxMessage(message:
|
|
146
|
+
declare function processJitoTipForTxMessage(message: TransactionMessageWithFeePayer & TransactionMessageWithSigners & Exclude<TransactionMessage, {
|
|
147
|
+
version: "legacy";
|
|
148
|
+
}>, signer: TransactionSigner, config: TransactionConfig): Promise<TransactionMessageWithFeePayer<string> & Partial<Pick<TransactionMessageWithFeePayer<string> | _solana_kit.TransactionMessageWithFeePayerSigner<string, TransactionSigner<string>>, "feePayer">> & (Readonly<{
|
|
149
|
+
instructions: readonly (_solana_kit.Instruction<string, readonly (_solana_kit.AccountLookupMeta<string, string> | _solana_kit.AccountMeta<string>)[]> & _solana_kit.InstructionWithSigners<TransactionSigner<string>, readonly (_solana_kit.AccountLookupMeta<string, string> | _solana_kit.AccountMeta<string> | _solana_kit.AccountSignerMeta<string, TransactionSigner<string>>)[]>)[];
|
|
150
|
+
}> & (Readonly<{
|
|
151
|
+
instructions: readonly _solana_kit.Instruction<string, readonly (_solana_kit.AccountLookupMeta<string, string> | _solana_kit.AccountMeta<string>)[]>[];
|
|
152
|
+
version: 0;
|
|
153
|
+
}> | (Readonly<{
|
|
154
|
+
instructions: readonly _solana_kit.Instruction<string, readonly _solana_kit.AccountMeta<string>[]>[];
|
|
155
|
+
version: 1;
|
|
156
|
+
}> & Readonly<{
|
|
157
|
+
config?: _solana_transaction_messages_dist_types_v1_transaction_config.V1TransactionConfig;
|
|
158
|
+
}>)))>;
|
|
145
159
|
declare function recentJitoTip(config: TransactionConfig): Promise<bigint>;
|
|
146
160
|
declare function sendJitoBundle(jitoApiUrl: JitoApiUrl, transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[], jitoUUID?: string): Promise<string>;
|
|
147
161
|
declare function simulateBundle(rpc: Rpc<JitoRpcApi>, transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[]): Promise<SimulateBundleResponse>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as _solana_kit from '@solana/kit';
|
|
2
|
+
import { BlockhashLifetimeConstraint, Rpc, SolanaRpcApi, Instruction, TransactionSigner, Address, MaybeAccount, SendableTransaction, Transaction, TransactionWithLifetime, TransactionMessageWithFeePayer, TransactionMessageWithSigners, TransactionMessage, Signature, Commitment, KeyPairSigner } from '@solana/kit';
|
|
2
3
|
import { AddressLookupTable } from '@solana-program/address-lookup-table';
|
|
4
|
+
import * as _solana_transaction_messages_dist_types_v1_transaction_config from '@solana/transaction-messages/dist/types/v1-transaction-config';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Default compute unit margin multiplier used to ensure sufficient compute budget.
|
|
@@ -141,7 +143,19 @@ declare enum JitoApiUrl {
|
|
|
141
143
|
Tokyo = "https://tokyo.mainnet.block-engine.jito.wtf",
|
|
142
144
|
Default = "https://mainnet.block-engine.jito.wtf"
|
|
143
145
|
}
|
|
144
|
-
declare function processJitoTipForTxMessage(message:
|
|
146
|
+
declare function processJitoTipForTxMessage(message: TransactionMessageWithFeePayer & TransactionMessageWithSigners & Exclude<TransactionMessage, {
|
|
147
|
+
version: "legacy";
|
|
148
|
+
}>, signer: TransactionSigner, config: TransactionConfig): Promise<TransactionMessageWithFeePayer<string> & Partial<Pick<TransactionMessageWithFeePayer<string> | _solana_kit.TransactionMessageWithFeePayerSigner<string, TransactionSigner<string>>, "feePayer">> & (Readonly<{
|
|
149
|
+
instructions: readonly (_solana_kit.Instruction<string, readonly (_solana_kit.AccountLookupMeta<string, string> | _solana_kit.AccountMeta<string>)[]> & _solana_kit.InstructionWithSigners<TransactionSigner<string>, readonly (_solana_kit.AccountLookupMeta<string, string> | _solana_kit.AccountMeta<string> | _solana_kit.AccountSignerMeta<string, TransactionSigner<string>>)[]>)[];
|
|
150
|
+
}> & (Readonly<{
|
|
151
|
+
instructions: readonly _solana_kit.Instruction<string, readonly (_solana_kit.AccountLookupMeta<string, string> | _solana_kit.AccountMeta<string>)[]>[];
|
|
152
|
+
version: 0;
|
|
153
|
+
}> | (Readonly<{
|
|
154
|
+
instructions: readonly _solana_kit.Instruction<string, readonly _solana_kit.AccountMeta<string>[]>[];
|
|
155
|
+
version: 1;
|
|
156
|
+
}> & Readonly<{
|
|
157
|
+
config?: _solana_transaction_messages_dist_types_v1_transaction_config.V1TransactionConfig;
|
|
158
|
+
}>)))>;
|
|
145
159
|
declare function recentJitoTip(config: TransactionConfig): Promise<bigint>;
|
|
146
160
|
declare function sendJitoBundle(jitoApiUrl: JitoApiUrl, transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[], jitoUUID?: string): Promise<string>;
|
|
147
161
|
declare function simulateBundle(rpc: Rpc<JitoRpcApi>, transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[]): Promise<SimulateBundleResponse>;
|
package/dist/index.js
CHANGED
|
@@ -2,18 +2,28 @@
|
|
|
2
2
|
import {
|
|
3
3
|
appendTransactionMessageInstructions,
|
|
4
4
|
assertAccountDecoded,
|
|
5
|
+
compileTransaction,
|
|
5
6
|
compressTransactionMessageUsingAddressLookupTables,
|
|
6
7
|
createNoopSigner,
|
|
7
8
|
createTransactionMessage,
|
|
8
|
-
|
|
9
|
+
getBase64EncodedWireTransaction as getBase64EncodedWireTransaction2,
|
|
10
|
+
getSolanaErrorFromTransactionError,
|
|
11
|
+
isSolanaError,
|
|
9
12
|
pipe,
|
|
10
13
|
setTransactionMessageFeePayerSigner,
|
|
11
14
|
setTransactionMessageLifetimeUsingBlockhash,
|
|
12
|
-
signTransactionMessageWithSigners
|
|
15
|
+
signTransactionMessageWithSigners,
|
|
16
|
+
SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT,
|
|
17
|
+
SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT,
|
|
18
|
+
SolanaError
|
|
13
19
|
} from "@solana/kit";
|
|
20
|
+
import { isTransactionMessageWithDurableNonceLifetime } from "@solana/transaction-messages";
|
|
14
21
|
|
|
15
22
|
// src/computeBudget.ts
|
|
16
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
isWritableRole,
|
|
25
|
+
prependTransactionMessageInstruction
|
|
26
|
+
} from "@solana/kit";
|
|
17
27
|
import { getSetComputeUnitLimitInstruction, getSetComputeUnitPriceInstruction } from "@solana-program/compute-budget";
|
|
18
28
|
|
|
19
29
|
// src/config.ts
|
|
@@ -24,16 +34,14 @@ var DEFAULT_JITO_BLOCK_ENGINE_URL = "https://bundles.jito.wtf";
|
|
|
24
34
|
async function processComputeBudgetForTxMessage(rpc, message, computeUnits, config) {
|
|
25
35
|
const computeUnitMarginMultiplier = config.computeUnitMarginMultiplier;
|
|
26
36
|
let priorityFeeMicroLamports = 0n;
|
|
27
|
-
const units =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
Math.ceil(computeUnits * (computeUnitMarginMultiplier ?? DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER))
|
|
31
|
-
)
|
|
37
|
+
const units = Math.min(
|
|
38
|
+
14e5,
|
|
39
|
+
Math.ceil(computeUnits * (computeUnitMarginMultiplier ?? DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER))
|
|
32
40
|
);
|
|
33
41
|
const priorityFee = config.priorityFee;
|
|
34
42
|
if (priorityFee) {
|
|
35
43
|
if (priorityFee.type === "exact") {
|
|
36
|
-
priorityFeeMicroLamports = priorityFee.amountLamports * 1000000n / units;
|
|
44
|
+
priorityFeeMicroLamports = priorityFee.amountLamports * 1000000n / BigInt(units);
|
|
37
45
|
} else if (priorityFee.type === "dynamic") {
|
|
38
46
|
const estimatedPriorityFee = await calculateDynamicPriorityFees(
|
|
39
47
|
rpc,
|
|
@@ -43,7 +51,7 @@ async function processComputeBudgetForTxMessage(rpc, message, computeUnits, conf
|
|
|
43
51
|
if (!priorityFee.maxCapLamports) {
|
|
44
52
|
priorityFeeMicroLamports = estimatedPriorityFee;
|
|
45
53
|
} else {
|
|
46
|
-
const maxCapMicroLamports = priorityFee.maxCapLamports * 1000000n / units;
|
|
54
|
+
const maxCapMicroLamports = priorityFee.maxCapLamports * 1000000n / BigInt(units);
|
|
47
55
|
priorityFeeMicroLamports = maxCapMicroLamports > estimatedPriorityFee ? estimatedPriorityFee : maxCapMicroLamports;
|
|
48
56
|
}
|
|
49
57
|
}
|
|
@@ -58,7 +66,7 @@ async function processComputeBudgetForTxMessage(rpc, message, computeUnits, conf
|
|
|
58
66
|
}
|
|
59
67
|
message = prependTransactionMessageInstruction(
|
|
60
68
|
getSetComputeUnitLimitInstruction({
|
|
61
|
-
units
|
|
69
|
+
units
|
|
62
70
|
}),
|
|
63
71
|
message
|
|
64
72
|
);
|
|
@@ -85,10 +93,11 @@ async function calculateDynamicPriorityFees(rpc, instructions, percentile) {
|
|
|
85
93
|
|
|
86
94
|
// src/jito.ts
|
|
87
95
|
import {
|
|
96
|
+
address,
|
|
88
97
|
appendTransactionMessageInstruction,
|
|
89
|
-
getBase64EncodedWireTransaction
|
|
98
|
+
getBase64EncodedWireTransaction,
|
|
99
|
+
lamports
|
|
90
100
|
} from "@solana/kit";
|
|
91
|
-
import { address, lamports } from "@solana/kit";
|
|
92
101
|
import { getTransferSolInstruction } from "@solana-program/system";
|
|
93
102
|
var JITO_BUNDLE_EXPIRY_TIME = 3e4;
|
|
94
103
|
var JitoApiUrl = /* @__PURE__ */ ((JitoApiUrl2) => {
|
|
@@ -282,6 +291,8 @@ async function buildTransactionMessage(rpc, instructions, signer, config, lookup
|
|
|
282
291
|
}).send()).value;
|
|
283
292
|
}
|
|
284
293
|
let message = await prepareTransactionMessage(instructions, signer, blockhash);
|
|
294
|
+
let computeUnits = 14e5;
|
|
295
|
+
let messageWithExtra = await addPriorityInstructions(rpc, message, signer, config, computeUnits);
|
|
285
296
|
if (lookupTableAccounts?.length) {
|
|
286
297
|
const tables = lookupTableAccounts.reduce(
|
|
287
298
|
(prev, account) => {
|
|
@@ -293,10 +304,30 @@ async function buildTransactionMessage(rpc, instructions, signer, config, lookup
|
|
|
293
304
|
},
|
|
294
305
|
{}
|
|
295
306
|
);
|
|
296
|
-
|
|
307
|
+
messageWithExtra = compressTransactionMessageUsingAddressLookupTables(messageWithExtra, tables);
|
|
308
|
+
}
|
|
309
|
+
if (!config.skipSimulation) {
|
|
310
|
+
try {
|
|
311
|
+
computeUnits = await getComputeUnitsForTxMessage(rpc, messageWithExtra);
|
|
312
|
+
messageWithExtra = await addPriorityInstructions(rpc, message, signer, config, computeUnits);
|
|
313
|
+
if (lookupTableAccounts?.length) {
|
|
314
|
+
const tables = lookupTableAccounts.reduce(
|
|
315
|
+
(prev, account) => {
|
|
316
|
+
if (account.exists) {
|
|
317
|
+
assertAccountDecoded(account);
|
|
318
|
+
prev[account.address] = account.data.addresses;
|
|
319
|
+
}
|
|
320
|
+
return prev;
|
|
321
|
+
},
|
|
322
|
+
{}
|
|
323
|
+
);
|
|
324
|
+
messageWithExtra = compressTransactionMessageUsingAddressLookupTables(messageWithExtra, tables);
|
|
325
|
+
}
|
|
326
|
+
} catch (e) {
|
|
327
|
+
console.warn("Transaction simulation failed, using 1,400,000 compute units: ", e);
|
|
328
|
+
}
|
|
297
329
|
}
|
|
298
|
-
|
|
299
|
-
return signTransactionMessageWithSigners(messageWithExtraInstructions);
|
|
330
|
+
return signTransactionMessageWithSigners(messageWithExtra);
|
|
300
331
|
}
|
|
301
332
|
async function prepareTransactionMessage(instructions, signer, blockhash) {
|
|
302
333
|
return pipe(
|
|
@@ -306,28 +337,47 @@ async function prepareTransactionMessage(instructions, signer, blockhash) {
|
|
|
306
337
|
(tx) => appendTransactionMessageInstructions(instructions, tx)
|
|
307
338
|
);
|
|
308
339
|
}
|
|
309
|
-
async function addPriorityInstructions(rpc, message, signer, config) {
|
|
340
|
+
async function addPriorityInstructions(rpc, message, signer, config, computeUnits) {
|
|
310
341
|
if (config.jito && config.jito.type !== "none") {
|
|
311
342
|
message = await processJitoTipForTxMessage(message, signer, config);
|
|
312
343
|
}
|
|
313
|
-
let computeUnits = 14e5;
|
|
314
|
-
if (!config.skipSimulation) {
|
|
315
|
-
try {
|
|
316
|
-
computeUnits = await getComputeUnitsForTxMessage(rpc, message);
|
|
317
|
-
} catch {
|
|
318
|
-
console.warn("Transaction simulation failed, using 1,400,000 compute units");
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
344
|
return processComputeBudgetForTxMessage(rpc, message, computeUnits, config);
|
|
322
345
|
}
|
|
323
|
-
async function getComputeUnitsForTxMessage(rpc,
|
|
324
|
-
|
|
346
|
+
async function getComputeUnitsForTxMessage(rpc, message) {
|
|
347
|
+
const replaceRecentBlockhash = !isTransactionMessageWithDurableNonceLifetime(message);
|
|
348
|
+
const transaction = pipe(message, compileTransaction);
|
|
349
|
+
const wireTransactionBytes = getBase64EncodedWireTransaction2(transaction);
|
|
350
|
+
try {
|
|
351
|
+
const response = await rpc.simulateTransaction(wireTransactionBytes, {
|
|
352
|
+
encoding: "base64",
|
|
353
|
+
replaceRecentBlockhash,
|
|
354
|
+
sigVerify: false
|
|
355
|
+
}).send();
|
|
356
|
+
const { err: transactionError, ...simulationResult } = response.value;
|
|
357
|
+
if (simulationResult.unitsConsumed == null) {
|
|
358
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT);
|
|
359
|
+
}
|
|
360
|
+
if (transactionError) {
|
|
361
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT, {
|
|
362
|
+
...simulationResult,
|
|
363
|
+
cause: getSolanaErrorFromTransactionError(transactionError)
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
return simulationResult.unitsConsumed > 4294967295n ? 4294967295 : Number(simulationResult.unitsConsumed);
|
|
367
|
+
} catch (e) {
|
|
368
|
+
if (isSolanaError(e, SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT)) {
|
|
369
|
+
throw e;
|
|
370
|
+
}
|
|
371
|
+
throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT, {
|
|
372
|
+
cause: e
|
|
373
|
+
});
|
|
374
|
+
}
|
|
325
375
|
}
|
|
326
376
|
|
|
327
377
|
// src/sendTransaction.ts
|
|
328
378
|
import {
|
|
329
379
|
getBase58Decoder,
|
|
330
|
-
getBase64EncodedWireTransaction as
|
|
380
|
+
getBase64EncodedWireTransaction as getBase64EncodedWireTransaction3
|
|
331
381
|
} from "@solana/kit";
|
|
332
382
|
async function sendTransaction(rpc, instructions, payer, config, lookupTableAccounts, commitment = "confirmed") {
|
|
333
383
|
const tx = await buildTransaction(rpc, instructions, payer, config ?? {}, lookupTableAccounts);
|
|
@@ -335,7 +385,7 @@ async function sendTransaction(rpc, instructions, payer, config, lookupTableAcco
|
|
|
335
385
|
}
|
|
336
386
|
async function sendSignedTransaction(rpc, transaction, skipSimulation = false, commitment = "confirmed") {
|
|
337
387
|
const txSignature = getTxSignature(transaction);
|
|
338
|
-
const encodedTransaction =
|
|
388
|
+
const encodedTransaction = getBase64EncodedWireTransaction3(transaction);
|
|
339
389
|
if (!skipSimulation) {
|
|
340
390
|
const simResult = await rpc.simulateTransaction(encodedTransaction, {
|
|
341
391
|
encoding: "base64"
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/buildTransaction.ts","../src/computeBudget.ts","../src/config.ts","../src/jito.ts","../src/sendTransaction.ts"],"sourcesContent":["import {\n Address,\n appendTransactionMessageInstructions,\n assertAccountDecoded,\n BlockhashLifetimeConstraint,\n compressTransactionMessageUsingAddressLookupTables,\n createNoopSigner,\n createTransactionMessage,\n estimateComputeUnitLimitFactory,\n Instruction,\n MaybeAccount,\n pipe,\n Rpc,\n SendableTransaction,\n setTransactionMessageFeePayerSigner,\n setTransactionMessageLifetimeUsingBlockhash,\n signTransactionMessageWithSigners,\n SolanaRpcApi,\n Transaction,\n TransactionMessage,\n TransactionMessageWithFeePayer,\n TransactionSigner,\n TransactionWithLifetime,\n} from \"@solana/kit\";\nimport { AddressLookupTable } from \"@solana-program/address-lookup-table\";\n\nimport { processComputeBudgetForTxMessage } from \"./computeBudget.ts\";\nimport { TransactionConfig } from \"./config\";\nimport { processJitoTipForTxMessage } from \"./jito.ts\";\n\n/**\n * Builds and signs a transaction from the given instructions and configuration.\n *\n * @param {Rpc<SolanaRpcApi>} rpc - Solana Rpc client.\n * @param {TransactionConfig} config - The transaction config.\n * @param {Instruction[]} instructions - Array of instructions to include in the transaction\n * @param {TransactionSigner} feePayer - The signer that will pay for the transaction\n * @param {(Address | string)[]} [lookupTableAccounts] - Optional array of address lookup table accounts to compress the transaction\n *\n * @returns {Promise<Readonly<SendableTransaction & Transaction & TransactionWithLifetime>>} A signed and encoded transaction\n *\n * @example\n * const instructions = [createATAix, createTransferSolInstruction];\n * const feePayer = wallet.publicKey;\n * const message = await buildTransaction(\n * rpc,\n * instructions,\n * feePayer,\n * );\n */\nexport async function buildTransaction(\n rpc: Rpc<SolanaRpcApi>,\n instructions: Instruction[],\n feePayer: TransactionSigner | Address,\n config: TransactionConfig,\n lookupTableAccounts?: MaybeAccount<AddressLookupTable>[],\n): Promise<Readonly<SendableTransaction & Transaction & TransactionWithLifetime>> {\n return buildTransactionMessage(\n rpc,\n instructions,\n !(\"address\" in feePayer) ? createNoopSigner(feePayer) : feePayer,\n config,\n lookupTableAccounts,\n );\n}\n\nasync function buildTransactionMessage(\n rpc: Rpc<SolanaRpcApi>,\n instructions: Instruction[],\n signer: TransactionSigner,\n config: TransactionConfig,\n lookupTableAccounts?: MaybeAccount<AddressLookupTable>[],\n) {\n let blockhash = config.blockhash;\n if (!blockhash) {\n blockhash = (\n await rpc\n .getLatestBlockhash({\n commitment: \"confirmed\",\n })\n .send()\n ).value;\n }\n\n let message = await prepareTransactionMessage(instructions, signer, blockhash);\n\n if (lookupTableAccounts?.length) {\n const tables = lookupTableAccounts.reduce(\n (prev, account) => {\n if (account.exists) {\n assertAccountDecoded(account);\n prev[account.address] = account.data.addresses;\n }\n return prev;\n },\n {} as { [address: Address]: Address[] },\n );\n message = compressTransactionMessageUsingAddressLookupTables(message, tables);\n }\n\n const messageWithExtraInstructions = await addPriorityInstructions(rpc, message, signer, config);\n\n return signTransactionMessageWithSigners(messageWithExtraInstructions);\n}\n\nasync function prepareTransactionMessage(\n instructions: Instruction[],\n signer: TransactionSigner,\n blockhash: BlockhashLifetimeConstraint,\n) {\n return pipe(\n createTransactionMessage({ version: 0 }),\n tx => setTransactionMessageLifetimeUsingBlockhash(blockhash, tx),\n tx => setTransactionMessageFeePayerSigner(signer, tx),\n tx => appendTransactionMessageInstructions(instructions, tx),\n );\n}\n\nasync function addPriorityInstructions(\n rpc: Rpc<SolanaRpcApi>,\n message: TransactionMessage & TransactionMessageWithFeePayer,\n signer: TransactionSigner,\n config: TransactionConfig,\n): Promise<TransactionMessage & TransactionMessageWithFeePayer> {\n if (config.jito && config.jito.type !== \"none\") {\n message = await processJitoTipForTxMessage(message, signer, config);\n }\n\n let computeUnits = 1_400_000;\n\n if (!config.skipSimulation) {\n try {\n computeUnits = await getComputeUnitsForTxMessage(rpc, message);\n } catch {\n console.warn(\"Transaction simulation failed, using 1,400,000 compute units\");\n }\n }\n\n return processComputeBudgetForTxMessage(rpc, message, computeUnits, config);\n}\n\nasync function getComputeUnitsForTxMessage(\n rpc: Rpc<SolanaRpcApi>,\n txMessage: TransactionMessage & TransactionMessageWithFeePayer,\n) {\n return await estimateComputeUnitLimitFactory({ rpc })(txMessage);\n}\n","import {\n Address,\n Instruction,\n Rpc,\n SolanaRpcApi,\n TransactionMessage,\n TransactionMessageWithFeePayer,\n} from \"@solana/kit\";\nimport { isWritableRole, prependTransactionMessageInstruction } from \"@solana/kit\";\nimport { getSetComputeUnitLimitInstruction, getSetComputeUnitPriceInstruction } from \"@solana-program/compute-budget\";\n\nimport type { Percentile, TransactionConfig } from \"./config\";\nimport { DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER } from \"./config\";\n\nexport async function processComputeBudgetForTxMessage(\n rpc: Rpc<SolanaRpcApi>,\n message: TransactionMessage & TransactionMessageWithFeePayer,\n computeUnits: number,\n config: TransactionConfig,\n) {\n const computeUnitMarginMultiplier = config.computeUnitMarginMultiplier;\n let priorityFeeMicroLamports = 0n;\n\n const units = BigInt(\n Math.min(\n 1_400_000,\n Math.ceil(computeUnits * (computeUnitMarginMultiplier ?? DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER)),\n ),\n );\n\n const priorityFee = config.priorityFee;\n if (priorityFee) {\n if (priorityFee.type === \"exact\") {\n priorityFeeMicroLamports = (priorityFee.amountLamports * 1_000_000n) / units;\n } else if (priorityFee.type === \"dynamic\") {\n const estimatedPriorityFee = await calculateDynamicPriorityFees(\n rpc,\n message.instructions,\n priorityFee.priorityFeePercentile ?? \"50\",\n );\n\n if (!priorityFee.maxCapLamports) {\n priorityFeeMicroLamports = estimatedPriorityFee;\n } else {\n const maxCapMicroLamports = (priorityFee.maxCapLamports * 1_000_000n) / units;\n priorityFeeMicroLamports =\n maxCapMicroLamports > estimatedPriorityFee ? estimatedPriorityFee : maxCapMicroLamports;\n }\n }\n }\n\n if (priorityFeeMicroLamports > 0) {\n message = prependTransactionMessageInstruction(\n getSetComputeUnitPriceInstruction({\n microLamports: priorityFeeMicroLamports,\n }),\n message,\n );\n }\n\n message = prependTransactionMessageInstruction(\n getSetComputeUnitLimitInstruction({\n units: computeUnits,\n }),\n message,\n );\n\n return message;\n}\n\nfunction getWritableAccounts(ixs: readonly Instruction[]) {\n const writable = new Set<Address>();\n ixs.forEach(ix => {\n if (ix.accounts) {\n ix.accounts.forEach(acc => {\n if (isWritableRole(acc.role)) writable.add(acc.address);\n });\n }\n });\n return Array.from(writable);\n}\n\nasync function calculateDynamicPriorityFees(\n rpc: Rpc<SolanaRpcApi>,\n instructions: readonly Instruction[],\n percentile: Percentile,\n) {\n const writableAccounts = getWritableAccounts(instructions);\n const recent = await rpc.getRecentPrioritizationFees(writableAccounts).send();\n const nonZero = recent.filter(pf => pf.prioritizationFee > 0).map(pf => pf.prioritizationFee);\n const sorted = nonZero.sort((a, b) => Number(a - b));\n return sorted[Math.floor(sorted.length * (parseInt(percentile) / 100))] || BigInt(0);\n}\n","import { BlockhashLifetimeConstraint } from \"@solana/kit\";\n\n/**\n * Default compute unit margin multiplier used to ensure sufficient compute budget.\n */\nexport const DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER = 1.15;\nexport const DEFAULT_JITO_BLOCK_ENGINE_URL = \"https://bundles.jito.wtf\";\n\ntype FeeSetting =\n | {\n type: \"dynamic\";\n maxCapLamports?: bigint;\n }\n | {\n type: \"exact\";\n amountLamports: bigint;\n }\n | {\n type: \"none\";\n };\n\n/**\n * Configuration for transaction fees, including Jito and priority fee settings.\n */\nexport type JitoFeeSetting = FeeSetting & {\n priorityFeePercentile?: Percentile | \"50ema\";\n};\n\nexport type PriorityFeeSetting = FeeSetting & {\n priorityFeePercentile?: Percentile;\n};\n\n/**\n * Defines a percentile value for priority fee selection.\n */\nexport type Percentile = \"25\" | \"50\" | \"75\" | \"95\" | \"99\";\n\nexport type TransactionConfig = {\n jito?: JitoFeeSetting;\n priorityFee?: PriorityFeeSetting;\n computeUnitMarginMultiplier?: number;\n jitoBlockEngineUrl?: string;\n skipSimulation?: boolean;\n blockhash?: BlockhashLifetimeConstraint;\n};\n","import {\n Address,\n appendTransactionMessageInstruction,\n getBase64EncodedWireTransaction,\n Rpc,\n SendableTransaction,\n SolanaRpcApi,\n Transaction,\n TransactionMessage,\n TransactionMessageWithFeePayer,\n TransactionSigner,\n TransactionWithLifetime,\n} from \"@solana/kit\";\nimport { address, lamports } from \"@solana/kit\";\nimport { getTransferSolInstruction } from \"@solana-program/system\";\n\nimport { DEFAULT_JITO_BLOCK_ENGINE_URL, type Percentile, TransactionConfig } from \"./config\";\n\nconst JITO_BUNDLE_EXPIRY_TIME = 30_000;\n\nexport type AccountConfig = {\n accountIndex: number;\n addresses: string[];\n};\n\nexport type JitoAccountInfo = {\n executable: boolean;\n owner: string;\n lamports: number;\n data: string;\n rentEpoch: number;\n};\n\nexport type JitoRpcApi = SolanaRpcApi & {\n simulateBundle: (\n params: {\n encodedTransactions: string[];\n },\n config?: {\n preExecutionAccountsConfigs?: AccountConfig;\n postExecutionAccountsConfigs?: AccountConfig;\n skipSigVerify?: boolean;\n simulationBank?: {\n commitment?: {\n commitment: \"processed\" | \"confirmed\" | \"finalized\";\n };\n };\n transactionEncoding?: \"base64\";\n replaceRecentBlockhash?: boolean;\n },\n ) => SimulateBundleResponse;\n\n sendBundle: (\n params: string[],\n config?: {\n encoding?: \"base64\";\n },\n ) => string;\n\n getBundleStatuses: (params: string[]) => GetBundleStatusesResponse;\n};\n\nexport type SimulateBundleResponse = {\n context: {\n slot: number;\n apiVersion?: string;\n };\n value: {\n summary: \"succeeded\" | { failed: { error: unknown; tx_signature: string } };\n transactionResults: Array<{\n err: unknown;\n logs: string[] | null;\n unitsConsumed?: number;\n returnData: {\n programId: string;\n data: string;\n } | null;\n preExecutionAccounts: JitoAccountInfo[] | null;\n postExecutionAccounts: JitoAccountInfo[] | null;\n }>;\n };\n};\n\nexport type GetBundleStatusesResponse = {\n context: {\n slot: number;\n };\n value: Array<{\n bundleId: string;\n transactions: string[];\n slot: number;\n confirmation_status: \"processed\" | \"confirmed\" | \"finalized\";\n err:\n | {\n Ok: null;\n }\n | {\n Err: object;\n };\n }>;\n};\n\nexport enum JitoApiUrl {\n Amsterdam = \"https://amsterdam.mainnet.block-engine.jito.wtf\",\n Frankfurt = \"https://frankfurt.mainnet.block-engine.jito.wtf\",\n London = \"https://london.mainnet.block-engine.jito.wtf\",\n NY = \"https://ny.mainnet.block-engine.jito.wtf\",\n Singapore = \"https://singapore.mainnet.block-engine.jito.wtf\",\n SLC = \"https://slc.mainnet.block-engine.jito.wtf\",\n Tokyo = \"https://tokyo.mainnet.block-engine.jito.wtf\",\n Default = \"https://mainnet.block-engine.jito.wtf\",\n}\n\nexport async function processJitoTipForTxMessage(\n message: TransactionMessage & TransactionMessageWithFeePayer,\n signer: TransactionSigner,\n config: TransactionConfig,\n) {\n const jito = config.jito;\n if (!jito) throw new Error(\"jito config is undefined\");\n\n let jitoTipLamports = BigInt(0);\n\n if (jito.type === \"exact\") {\n jitoTipLamports = jito.amountLamports;\n } else if (jito.type === \"dynamic\") {\n jitoTipLamports = await recentJitoTip(config);\n if (jito.maxCapLamports && jitoTipLamports > jito.maxCapLamports) {\n jitoTipLamports = jito.maxCapLamports;\n }\n }\n\n if (jitoTipLamports > 0) {\n return appendTransactionMessageInstruction(\n getTransferSolInstruction({\n source: signer,\n destination: getJitoTipAddress(),\n amount: jitoTipLamports,\n }),\n message,\n );\n } else {\n return message;\n }\n}\n\n// returns recent jito tip in lamports\nexport async function recentJitoTip(config: TransactionConfig) {\n const baseUrl = config.jitoBlockEngineUrl ?? DEFAULT_JITO_BLOCK_ENGINE_URL;\n const response = await fetch(`${baseUrl}/api/v1/bundles/tip_floor`);\n if (!response.ok) {\n return BigInt(0);\n }\n const data = await response.json().then(res => res[0]);\n\n const percentileToKey: Record<Percentile | \"50ema\", string> = {\n \"25\": \"landed_tips_25th_percentile\",\n \"50\": \"landed_tips_50th_percentile\",\n \"75\": \"landed_tips_75th_percentile\",\n \"95\": \"landed_tips_95th_percentile\",\n \"99\": \"landed_tips_99th_percentile\",\n \"50ema\": \"ema_landed_tips_50th_percentile\",\n };\n\n const key = percentileToKey[config.jito?.priorityFeePercentile ?? \"50\"];\n if (!key || !data[key]) {\n return BigInt(0);\n }\n return lamports(BigInt(Math.floor(Number(data[key]) * 10 ** 9))).valueOf();\n}\n\n// should we add an argument that dictates if we should use cached value in case fetch fails ?\n\n// below is taken from legacy sdk (no need to add the whole library)\n// https://jito-foundation.gitbook.io/mev/mev-payment-and-distribution/on-chain-addresses\nconst jitoTipAddresses = [\n \"96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5\",\n \"HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe\",\n \"Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY\",\n \"ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49\",\n \"DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh\",\n \"ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt\",\n \"DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL\",\n \"3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT\",\n];\n\nfunction getJitoTipAddress(): Address {\n // just pick a random one from the list. There are multiple addresses so that no single one can cause local congestion.\n return address(jitoTipAddresses[Math.floor(Math.random() * jitoTipAddresses.length)]);\n}\n\ninterface JsonRpcResult {\n jsonrpc: string;\n id: number;\n result?: string; // bundle id\n error?: {\n code: number;\n message: string;\n data?: unknown;\n };\n}\n\nexport async function sendJitoBundle(\n jitoApiUrl: JitoApiUrl,\n transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[],\n jitoUUID?: string,\n): Promise<string> {\n const encodedTransactions = transactions.map(tx => getBase64EncodedWireTransaction(tx)) as string[];\n\n const url = new URL(\"/api/v1/bundles\", jitoApiUrl);\n if (jitoUUID && jitoUUID.length > 0) {\n url.searchParams.set(\"uuid\", jitoUUID);\n }\n\n const request = {\n id: 1,\n jsonrpc: \"2.0\",\n method: \"sendBundle\",\n params: [\n encodedTransactions,\n {\n encoding: \"base64\",\n },\n ],\n };\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n throw new Error(`Jito HTTP error: ${response.status}`);\n }\n\n const data = (await response.json()) as JsonRpcResult;\n\n if (data.error) {\n throw new Error(`Jito bundle failed: ${data.error.code} ${data.error.message}`);\n }\n\n if (!data.result) {\n throw new Error(\"sendBundle did not return a bundle id\");\n }\n\n const bundleId = data.result;\n\n const expiryTime = Date.now() + JITO_BUNDLE_EXPIRY_TIME;\n\n while (Date.now() < expiryTime) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n const request = {\n jsonrpc: \"2.0\",\n id: 1,\n method: \"getInflightBundleStatuses\",\n params: [[bundleId]],\n };\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n throw new Error(`Jito HTTP error: ${response.status}`);\n }\n\n const data = await response.json();\n const result = data.result?.value?.[0];\n if (!result) {\n throw new Error(`getInflightBundleStatuses method returned undefined result`, { cause: { bundleId } });\n }\n\n switch (result.status) {\n case \"Landed\":\n return bundleId;\n case \"Pending\":\n case \"Invalid\":\n continue;\n case \"Failed\":\n throw new Error(`Bundle failed`, { cause: { bundleId } });\n default:\n throw new Error(`Bundle status is unknown`, { cause: { bundleId } });\n }\n }\n\n throw new Error(`Bundle expired`, { cause: { bundleId } });\n}\n\nexport async function simulateBundle(\n rpc: Rpc<JitoRpcApi>,\n transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[],\n): Promise<SimulateBundleResponse> {\n const encodedTransactions = transactions.map(tx => getBase64EncodedWireTransaction(tx));\n\n return rpc\n .simulateBundle({\n encodedTransactions,\n })\n .send();\n}\n\nexport async function sendBundle(\n rpc: Rpc<JitoRpcApi>,\n transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[],\n): Promise<string> {\n const encodedTransactions = transactions.map(tx => getBase64EncodedWireTransaction(tx));\n\n const bundleId = await rpc\n .sendBundle(encodedTransactions, {\n encoding: \"base64\",\n })\n .send();\n\n if (!bundleId) throw new Error(`sendBundle method failed`);\n\n const expiryTime = Date.now() + JITO_BUNDLE_EXPIRY_TIME;\n\n while (Date.now() < expiryTime) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n const statuses = await rpc.getBundleStatuses([bundleId]).send();\n\n const bundleStatus = statuses?.value?.[0];\n if (!bundleStatus) continue;\n\n if (bundleStatus.err && \"Err\" in bundleStatus.err) {\n throw new Error(`Bundle failed`, { cause: { bundleId, error: bundleStatus.err.Err } });\n } else {\n const confirmation_status = bundleStatus.confirmation_status;\n if (confirmation_status == \"confirmed\") {\n return bundleId;\n }\n }\n }\n\n throw new Error(`Bundle expired`, { cause: { bundleId } });\n}\n","import {\n Commitment,\n getBase58Decoder,\n getBase64EncodedWireTransaction,\n Instruction,\n KeyPairSigner,\n MaybeAccount,\n Rpc,\n SendableTransaction,\n Signature,\n SolanaRpcApi,\n Transaction,\n TransactionWithLifetime,\n} from \"@solana/kit\";\nimport { AddressLookupTable } from \"@solana-program/address-lookup-table\";\n\nimport { buildTransaction } from \"./buildTransaction\";\nimport { TransactionConfig } from \"./config\";\n\n/**\n * Builds and sends a transaction with the given instructions, signers, and commitment level.\n *\n * @param {Rpc<SolanaRpcApi>} rpc - Solana Rpc client.\n * @param {Instruction[]} instructions - Array of instructions to include in the transaction.\n * @param {KeyPairSigner} payer - The fee payer for the transaction.\n * @param {TransactionConfig} config - The transaction config.\n * @param {Address[]} [lookupTableAccounts] - Optional array of address lookup table accounts to use.\n * @param {Commitment} [commitment=\"confirmed\"] - The commitment level for transaction confirmation.\n *\n * @returns {Promise<Signature>} A promise that resolves to the transaction signature.\n *\n * @throws {Error} If transaction building or sending fails.\n *\n * @example\n * ```ts\n * const signature = await sendTransaction(\n * instructions,\n * keypairSigner,\n * DEFAULT_TRANSACTION_CONFIG,\n * lookupTables,\n * \"finalized\"\n * );\n * ```\n */\nexport async function sendTransaction(\n rpc: Rpc<SolanaRpcApi>,\n instructions: Instruction[],\n payer: KeyPairSigner,\n config?: TransactionConfig,\n lookupTableAccounts?: MaybeAccount<AddressLookupTable>[],\n commitment: Commitment = \"confirmed\",\n): Promise<Signature> {\n const tx = await buildTransaction(rpc, instructions, payer, config ?? {}, lookupTableAccounts);\n return sendSignedTransaction(rpc, tx, config?.skipSimulation ?? false, commitment);\n}\n\n/**\n * Sends a signed transaction message to the Solana network with a specified commitment level.\n *\n * @param {Rpc<SolanaRpcApi>} rpc - Rpc client.\n * @param {SendableTransaction & Transaction & TransactionWithLifetime} transaction - The fully signed transaction to send.\n * @param {boolean} skipSimulation - True if skip simulation\n * @param {Commitment} [commitment=\"confirmed\"] - The commitment level for transaction confirmation.\n *\n * @returns {Promise<Signature>} A promise that resolves to the transaction signature.\n *\n * @throws {Error} If transaction sending fails, the RPC connection fails, or the transaction expires.\n *\n * @example\n * ```ts\n * const signature = await sendSignedTransaction(\n * rpc,\n * signedTransaction,\n * \"finalized\"\n * );\n * ```\n */\nexport async function sendSignedTransaction(\n rpc: Rpc<SolanaRpcApi>,\n transaction: SendableTransaction & Transaction & TransactionWithLifetime,\n skipSimulation: boolean = false,\n commitment: Commitment = \"confirmed\",\n): Promise<Signature> {\n const txSignature = getTxSignature(transaction);\n const encodedTransaction = getBase64EncodedWireTransaction(transaction);\n\n if (!skipSimulation) {\n // Simulate transaction first\n const simResult = await rpc\n .simulateTransaction(encodedTransaction, {\n encoding: \"base64\",\n })\n .send();\n\n if (simResult.value.err) {\n throw new Error(`Transaction simulation failed`, { cause: simResult.value });\n }\n }\n\n const expiryTime = Date.now() + 60_000;\n\n while (Date.now() < expiryTime) {\n await rpc\n .sendTransaction(encodedTransaction, {\n maxRetries: BigInt(0),\n skipPreflight: true,\n encoding: \"base64\",\n })\n .send();\n\n const { value } = await rpc.getSignatureStatuses([txSignature]).send();\n const status = value[0];\n if (status?.confirmationStatus === commitment) {\n if (status.err) {\n throw new Error(`Transaction failed`, { cause: status.err });\n }\n return txSignature;\n }\n }\n\n throw new Error(\"Transaction expired\");\n}\n\nexport function getTxSignature(transaction: Transaction) {\n const [signature] = Object.values(transaction.signatures);\n return getBase58Decoder().decode(signature!) as Signature;\n}\n"],"mappings":";AAAA;AAAA,EAEE;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAGA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,OAOK;;;ACfP,SAAS,gBAAgB,4CAA4C;AACrE,SAAS,mCAAmC,yCAAyC;;;ACJ9E,IAAM,yCAAyC;AAC/C,IAAM,gCAAgC;;;ADQ7C,eAAsB,iCACpB,KACA,SACA,cACA,QACA;AACA,QAAM,8BAA8B,OAAO;AAC3C,MAAI,2BAA2B;AAE/B,QAAM,QAAQ;AAAA,IACZ,KAAK;AAAA,MACH;AAAA,MACA,KAAK,KAAK,gBAAgB,+BAA+B,uCAAuC;AAAA,IAClG;AAAA,EACF;AAEA,QAAM,cAAc,OAAO;AAC3B,MAAI,aAAa;AACf,QAAI,YAAY,SAAS,SAAS;AAChC,iCAA4B,YAAY,iBAAiB,WAAc;AAAA,IACzE,WAAW,YAAY,SAAS,WAAW;AACzC,YAAM,uBAAuB,MAAM;AAAA,QACjC;AAAA,QACA,QAAQ;AAAA,QACR,YAAY,yBAAyB;AAAA,MACvC;AAEA,UAAI,CAAC,YAAY,gBAAgB;AAC/B,mCAA2B;AAAA,MAC7B,OAAO;AACL,cAAM,sBAAuB,YAAY,iBAAiB,WAAc;AACxE,mCACE,sBAAsB,uBAAuB,uBAAuB;AAAA,MACxE;AAAA,IACF;AAAA,EACF;AAEA,MAAI,2BAA2B,GAAG;AAChC,cAAU;AAAA,MACR,kCAAkC;AAAA,QAChC,eAAe;AAAA,MACjB,CAAC;AAAA,MACD;AAAA,IACF;AAAA,EACF;AAEA,YAAU;AAAA,IACR,kCAAkC;AAAA,MAChC,OAAO;AAAA,IACT,CAAC;AAAA,IACD;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,oBAAoB,KAA6B;AACxD,QAAM,WAAW,oBAAI,IAAa;AAClC,MAAI,QAAQ,QAAM;AAChB,QAAI,GAAG,UAAU;AACf,SAAG,SAAS,QAAQ,SAAO;AACzB,YAAI,eAAe,IAAI,IAAI,EAAG,UAAS,IAAI,IAAI,OAAO;AAAA,MACxD,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACD,SAAO,MAAM,KAAK,QAAQ;AAC5B;AAEA,eAAe,6BACb,KACA,cACA,YACA;AACA,QAAM,mBAAmB,oBAAoB,YAAY;AACzD,QAAM,SAAS,MAAM,IAAI,4BAA4B,gBAAgB,EAAE,KAAK;AAC5E,QAAM,UAAU,OAAO,OAAO,QAAM,GAAG,oBAAoB,CAAC,EAAE,IAAI,QAAM,GAAG,iBAAiB;AAC5F,QAAM,SAAS,QAAQ,KAAK,CAAC,GAAG,MAAM,OAAO,IAAI,CAAC,CAAC;AACnD,SAAO,OAAO,KAAK,MAAM,OAAO,UAAU,SAAS,UAAU,IAAI,IAAI,CAAC,KAAK,OAAO,CAAC;AACrF;;;AE5FA;AAAA,EAEE;AAAA,EACA;AAAA,OASK;AACP,SAAS,SAAS,gBAAgB;AAClC,SAAS,iCAAiC;AAI1C,IAAM,0BAA0B;AAoFzB,IAAK,aAAL,kBAAKA,gBAAL;AACL,EAAAA,YAAA,eAAY;AACZ,EAAAA,YAAA,eAAY;AACZ,EAAAA,YAAA,YAAS;AACT,EAAAA,YAAA,QAAK;AACL,EAAAA,YAAA,eAAY;AACZ,EAAAA,YAAA,SAAM;AACN,EAAAA,YAAA,WAAQ;AACR,EAAAA,YAAA,aAAU;AARA,SAAAA;AAAA,GAAA;AAWZ,eAAsB,2BACpB,SACA,QACA,QACA;AACA,QAAM,OAAO,OAAO;AACpB,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,0BAA0B;AAErD,MAAI,kBAAkB,OAAO,CAAC;AAE9B,MAAI,KAAK,SAAS,SAAS;AACzB,sBAAkB,KAAK;AAAA,EACzB,WAAW,KAAK,SAAS,WAAW;AAClC,sBAAkB,MAAM,cAAc,MAAM;AAC5C,QAAI,KAAK,kBAAkB,kBAAkB,KAAK,gBAAgB;AAChE,wBAAkB,KAAK;AAAA,IACzB;AAAA,EACF;AAEA,MAAI,kBAAkB,GAAG;AACvB,WAAO;AAAA,MACL,0BAA0B;AAAA,QACxB,QAAQ;AAAA,QACR,aAAa,kBAAkB;AAAA,QAC/B,QAAQ;AAAA,MACV,CAAC;AAAA,MACD;AAAA,IACF;AAAA,EACF,OAAO;AACL,WAAO;AAAA,EACT;AACF;AAGA,eAAsB,cAAc,QAA2B;AAC7D,QAAM,UAAU,OAAO,sBAAsB;AAC7C,QAAM,WAAW,MAAM,MAAM,GAAG,OAAO,2BAA2B;AAClE,MAAI,CAAC,SAAS,IAAI;AAChB,WAAO,OAAO,CAAC;AAAA,EACjB;AACA,QAAM,OAAO,MAAM,SAAS,KAAK,EAAE,KAAK,SAAO,IAAI,CAAC,CAAC;AAErD,QAAM,kBAAwD;AAAA,IAC5D,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,EACX;AAEA,QAAM,MAAM,gBAAgB,OAAO,MAAM,yBAAyB,IAAI;AACtE,MAAI,CAAC,OAAO,CAAC,KAAK,GAAG,GAAG;AACtB,WAAO,OAAO,CAAC;AAAA,EACjB;AACA,SAAO,SAAS,OAAO,KAAK,MAAM,OAAO,KAAK,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ;AAC3E;AAMA,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,oBAA6B;AAEpC,SAAO,QAAQ,iBAAiB,KAAK,MAAM,KAAK,OAAO,IAAI,iBAAiB,MAAM,CAAC,CAAC;AACtF;AAaA,eAAsB,eACpB,YACA,cACA,UACiB;AACjB,QAAM,sBAAsB,aAAa,IAAI,QAAM,gCAAgC,EAAE,CAAC;AAEtF,QAAM,MAAM,IAAI,IAAI,mBAAmB,UAAU;AACjD,MAAI,YAAY,SAAS,SAAS,GAAG;AACnC,QAAI,aAAa,IAAI,QAAQ,QAAQ;AAAA,EACvC;AAEA,QAAM,UAAU;AAAA,IACd,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,QACE,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,MAAM,MAAM,KAAK;AAAA,IAChC,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,IAClB;AAAA,IACA,MAAM,KAAK,UAAU,OAAO;AAAA,EAC9B,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI,MAAM,oBAAoB,SAAS,MAAM,EAAE;AAAA,EACvD;AAEA,QAAM,OAAQ,MAAM,SAAS,KAAK;AAElC,MAAI,KAAK,OAAO;AACd,UAAM,IAAI,MAAM,uBAAuB,KAAK,MAAM,IAAI,IAAI,KAAK,MAAM,OAAO,EAAE;AAAA,EAChF;AAEA,MAAI,CAAC,KAAK,QAAQ;AAChB,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACzD;AAEA,QAAM,WAAW,KAAK;AAEtB,QAAM,aAAa,KAAK,IAAI,IAAI;AAEhC,SAAO,KAAK,IAAI,IAAI,YAAY;AAC9B,UAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,GAAI,CAAC;AAEtD,UAAMC,WAAU;AAAA,MACd,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,QAAQ,CAAC,CAAC,QAAQ,CAAC;AAAA,IACrB;AAEA,UAAMC,YAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAUD,QAAO;AAAA,IAC9B,CAAC;AAED,QAAI,CAACC,UAAS,IAAI;AAChB,YAAM,IAAI,MAAM,oBAAoBA,UAAS,MAAM,EAAE;AAAA,IACvD;AAEA,UAAMC,QAAO,MAAMD,UAAS,KAAK;AACjC,UAAM,SAASC,MAAK,QAAQ,QAAQ,CAAC;AACrC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,8DAA8D,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAAA,IACvG;AAEA,YAAQ,OAAO,QAAQ;AAAA,MACrB,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AACH;AAAA,MACF,KAAK;AACH,cAAM,IAAI,MAAM,iBAAiB,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAAA,MAC1D;AACE,cAAM,IAAI,MAAM,4BAA4B,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAAA,IACvE;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,kBAAkB,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAC3D;AAEA,eAAsB,eACpB,KACA,cACiC;AACjC,QAAM,sBAAsB,aAAa,IAAI,QAAM,gCAAgC,EAAE,CAAC;AAEtF,SAAO,IACJ,eAAe;AAAA,IACd;AAAA,EACF,CAAC,EACA,KAAK;AACV;AAEA,eAAsB,WACpB,KACA,cACiB;AACjB,QAAM,sBAAsB,aAAa,IAAI,QAAM,gCAAgC,EAAE,CAAC;AAEtF,QAAM,WAAW,MAAM,IACpB,WAAW,qBAAqB;AAAA,IAC/B,UAAU;AAAA,EACZ,CAAC,EACA,KAAK;AAER,MAAI,CAAC,SAAU,OAAM,IAAI,MAAM,0BAA0B;AAEzD,QAAM,aAAa,KAAK,IAAI,IAAI;AAEhC,SAAO,KAAK,IAAI,IAAI,YAAY;AAC9B,UAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,GAAI,CAAC;AAEtD,UAAM,WAAW,MAAM,IAAI,kBAAkB,CAAC,QAAQ,CAAC,EAAE,KAAK;AAE9D,UAAM,eAAe,UAAU,QAAQ,CAAC;AACxC,QAAI,CAAC,aAAc;AAEnB,QAAI,aAAa,OAAO,SAAS,aAAa,KAAK;AACjD,YAAM,IAAI,MAAM,iBAAiB,EAAE,OAAO,EAAE,UAAU,OAAO,aAAa,IAAI,IAAI,EAAE,CAAC;AAAA,IACvF,OAAO;AACL,YAAM,sBAAsB,aAAa;AACzC,UAAI,uBAAuB,aAAa;AACtC,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,kBAAkB,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAC3D;;;AHtSA,eAAsB,iBACpB,KACA,cACA,UACA,QACA,qBACgF;AAChF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,EAAE,aAAa,YAAY,iBAAiB,QAAQ,IAAI;AAAA,IACxD;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,wBACb,KACA,cACA,QACA,QACA,qBACA;AACA,MAAI,YAAY,OAAO;AACvB,MAAI,CAAC,WAAW;AACd,iBACE,MAAM,IACH,mBAAmB;AAAA,MAClB,YAAY;AAAA,IACd,CAAC,EACA,KAAK,GACR;AAAA,EACJ;AAEA,MAAI,UAAU,MAAM,0BAA0B,cAAc,QAAQ,SAAS;AAE7E,MAAI,qBAAqB,QAAQ;AAC/B,UAAM,SAAS,oBAAoB;AAAA,MACjC,CAAC,MAAM,YAAY;AACjB,YAAI,QAAQ,QAAQ;AAClB,+BAAqB,OAAO;AAC5B,eAAK,QAAQ,OAAO,IAAI,QAAQ,KAAK;AAAA,QACvC;AACA,eAAO;AAAA,MACT;AAAA,MACA,CAAC;AAAA,IACH;AACA,cAAU,mDAAmD,SAAS,MAAM;AAAA,EAC9E;AAEA,QAAM,+BAA+B,MAAM,wBAAwB,KAAK,SAAS,QAAQ,MAAM;AAE/F,SAAO,kCAAkC,4BAA4B;AACvE;AAEA,eAAe,0BACb,cACA,QACA,WACA;AACA,SAAO;AAAA,IACL,yBAAyB,EAAE,SAAS,EAAE,CAAC;AAAA,IACvC,QAAM,4CAA4C,WAAW,EAAE;AAAA,IAC/D,QAAM,oCAAoC,QAAQ,EAAE;AAAA,IACpD,QAAM,qCAAqC,cAAc,EAAE;AAAA,EAC7D;AACF;AAEA,eAAe,wBACb,KACA,SACA,QACA,QAC8D;AAC9D,MAAI,OAAO,QAAQ,OAAO,KAAK,SAAS,QAAQ;AAC9C,cAAU,MAAM,2BAA2B,SAAS,QAAQ,MAAM;AAAA,EACpE;AAEA,MAAI,eAAe;AAEnB,MAAI,CAAC,OAAO,gBAAgB;AAC1B,QAAI;AACF,qBAAe,MAAM,4BAA4B,KAAK,OAAO;AAAA,IAC/D,QAAQ;AACN,cAAQ,KAAK,8DAA8D;AAAA,IAC7E;AAAA,EACF;AAEA,SAAO,iCAAiC,KAAK,SAAS,cAAc,MAAM;AAC5E;AAEA,eAAe,4BACb,KACA,WACA;AACA,SAAO,MAAM,gCAAgC,EAAE,IAAI,CAAC,EAAE,SAAS;AACjE;;;AIlJA;AAAA,EAEE;AAAA,EACA,mCAAAC;AAAA,OAUK;AA+BP,eAAsB,gBACpB,KACA,cACA,OACA,QACA,qBACA,aAAyB,aACL;AACpB,QAAM,KAAK,MAAM,iBAAiB,KAAK,cAAc,OAAO,UAAU,CAAC,GAAG,mBAAmB;AAC7F,SAAO,sBAAsB,KAAK,IAAI,QAAQ,kBAAkB,OAAO,UAAU;AACnF;AAuBA,eAAsB,sBACpB,KACA,aACA,iBAA0B,OAC1B,aAAyB,aACL;AACpB,QAAM,cAAc,eAAe,WAAW;AAC9C,QAAM,qBAAqBC,iCAAgC,WAAW;AAEtE,MAAI,CAAC,gBAAgB;AAEnB,UAAM,YAAY,MAAM,IACrB,oBAAoB,oBAAoB;AAAA,MACvC,UAAU;AAAA,IACZ,CAAC,EACA,KAAK;AAER,QAAI,UAAU,MAAM,KAAK;AACvB,YAAM,IAAI,MAAM,iCAAiC,EAAE,OAAO,UAAU,MAAM,CAAC;AAAA,IAC7E;AAAA,EACF;AAEA,QAAM,aAAa,KAAK,IAAI,IAAI;AAEhC,SAAO,KAAK,IAAI,IAAI,YAAY;AAC9B,UAAM,IACH,gBAAgB,oBAAoB;AAAA,MACnC,YAAY,OAAO,CAAC;AAAA,MACpB,eAAe;AAAA,MACf,UAAU;AAAA,IACZ,CAAC,EACA,KAAK;AAER,UAAM,EAAE,MAAM,IAAI,MAAM,IAAI,qBAAqB,CAAC,WAAW,CAAC,EAAE,KAAK;AACrE,UAAM,SAAS,MAAM,CAAC;AACtB,QAAI,QAAQ,uBAAuB,YAAY;AAC7C,UAAI,OAAO,KAAK;AACd,cAAM,IAAI,MAAM,sBAAsB,EAAE,OAAO,OAAO,IAAI,CAAC;AAAA,MAC7D;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,qBAAqB;AACvC;AAEO,SAAS,eAAe,aAA0B;AACvD,QAAM,CAAC,SAAS,IAAI,OAAO,OAAO,YAAY,UAAU;AACxD,SAAO,iBAAiB,EAAE,OAAO,SAAU;AAC7C;","names":["JitoApiUrl","request","response","data","getBase64EncodedWireTransaction","getBase64EncodedWireTransaction"]}
|
|
1
|
+
{"version":3,"sources":["../src/buildTransaction.ts","../src/computeBudget.ts","../src/config.ts","../src/jito.ts","../src/sendTransaction.ts"],"sourcesContent":["import {\n Address,\n appendTransactionMessageInstructions,\n assertAccountDecoded,\n BlockhashLifetimeConstraint,\n compileTransaction,\n compressTransactionMessageUsingAddressLookupTables,\n createNoopSigner,\n createTransactionMessage,\n getBase64EncodedWireTransaction,\n getSolanaErrorFromTransactionError,\n Instruction,\n isSolanaError,\n MaybeAccount,\n pipe,\n Rpc,\n RpcSimulateTransactionResult,\n SendableTransaction,\n setTransactionMessageFeePayerSigner,\n setTransactionMessageLifetimeUsingBlockhash,\n signTransactionMessageWithSigners,\n SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT,\n SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT,\n SolanaError,\n SolanaRpcApi,\n Transaction,\n TransactionMessage,\n TransactionMessageWithFeePayer,\n TransactionMessageWithSigners,\n TransactionSigner,\n TransactionWithLifetime,\n} from \"@solana/kit\";\nimport { isTransactionMessageWithDurableNonceLifetime } from \"@solana/transaction-messages\";\nimport { AddressLookupTable } from \"@solana-program/address-lookup-table\";\n\nimport { processComputeBudgetForTxMessage } from \"./computeBudget.ts\";\nimport { TransactionConfig } from \"./config\";\nimport { processJitoTipForTxMessage } from \"./jito.ts\";\n\n/**\n * Builds and signs a transaction from the given instructions and configuration.\n *\n * @param {Rpc<SolanaRpcApi>} rpc - Solana Rpc client.\n * @param {TransactionConfig} config - The transaction config.\n * @param {Instruction[]} instructions - Array of instructions to include in the transaction\n * @param {TransactionSigner} feePayer - The signer that will pay for the transaction\n * @param {(Address | string)[]} [lookupTableAccounts] - Optional array of address lookup table accounts to compress the transaction\n *\n * @returns {Promise<Readonly<SendableTransaction & Transaction & TransactionWithLifetime>>} A signed and encoded transaction\n *\n * @example\n * const instructions = [createATAix, createTransferSolInstruction];\n * const feePayer = wallet.publicKey;\n * const message = await buildTransaction(\n * rpc,\n * instructions,\n * feePayer,\n * );\n */\nexport async function buildTransaction(\n rpc: Rpc<SolanaRpcApi>,\n instructions: Instruction[],\n feePayer: TransactionSigner | Address,\n config: TransactionConfig,\n lookupTableAccounts?: MaybeAccount<AddressLookupTable>[],\n): Promise<Readonly<SendableTransaction & Transaction & TransactionWithLifetime>> {\n return buildTransactionMessage(\n rpc,\n instructions,\n !(\"address\" in feePayer) ? createNoopSigner(feePayer) : feePayer,\n config,\n lookupTableAccounts,\n );\n}\n\nasync function buildTransactionMessage(\n rpc: Rpc<SolanaRpcApi>,\n instructions: Instruction[],\n signer: TransactionSigner,\n config: TransactionConfig,\n lookupTableAccounts?: MaybeAccount<AddressLookupTable>[],\n) {\n let blockhash = config.blockhash;\n if (!blockhash) {\n blockhash = (\n await rpc\n .getLatestBlockhash({\n commitment: \"confirmed\",\n })\n .send()\n ).value;\n }\n\n let message = await prepareTransactionMessage(instructions, signer, blockhash);\n\n let computeUnits = 1_400_000;\n let messageWithExtra = await addPriorityInstructions(rpc, message, signer, config, computeUnits);\n\n if (lookupTableAccounts?.length) {\n const tables = lookupTableAccounts.reduce(\n (prev, account) => {\n if (account.exists) {\n assertAccountDecoded(account);\n prev[account.address] = account.data.addresses;\n }\n return prev;\n },\n {} as { [address: Address]: Address[] },\n );\n messageWithExtra = compressTransactionMessageUsingAddressLookupTables(messageWithExtra, tables);\n }\n\n if (!config.skipSimulation) {\n try {\n computeUnits = await getComputeUnitsForTxMessage(rpc, messageWithExtra);\n\n // Rebuild the message\n messageWithExtra = await addPriorityInstructions(rpc, message, signer, config, computeUnits);\n\n if (lookupTableAccounts?.length) {\n const tables = lookupTableAccounts.reduce(\n (prev, account) => {\n if (account.exists) {\n assertAccountDecoded(account);\n prev[account.address] = account.data.addresses;\n }\n return prev;\n },\n {} as { [address: Address]: Address[] },\n );\n messageWithExtra = compressTransactionMessageUsingAddressLookupTables(messageWithExtra, tables);\n }\n } catch (e) {\n console.warn(\"Transaction simulation failed, using 1,400,000 compute units: \", e);\n }\n }\n\n return signTransactionMessageWithSigners(messageWithExtra);\n}\n\nasync function prepareTransactionMessage(\n instructions: Instruction[],\n signer: TransactionSigner,\n blockhash: BlockhashLifetimeConstraint,\n) {\n return pipe(\n createTransactionMessage({ version: 0 }),\n tx => setTransactionMessageLifetimeUsingBlockhash(blockhash, tx),\n tx => setTransactionMessageFeePayerSigner(signer, tx),\n tx => appendTransactionMessageInstructions(instructions, tx),\n );\n}\n\nasync function addPriorityInstructions(\n rpc: Rpc<SolanaRpcApi>,\n message: TransactionMessageWithFeePayer &\n TransactionMessageWithSigners &\n Exclude<TransactionMessage, { version: \"legacy\" }>,\n signer: TransactionSigner,\n config: TransactionConfig,\n computeUnits: number,\n) {\n if (config.jito && config.jito.type !== \"none\") {\n message = await processJitoTipForTxMessage(message, signer, config);\n }\n\n return processComputeBudgetForTxMessage(rpc, message, computeUnits, config);\n}\n\nasync function getComputeUnitsForTxMessage(\n rpc: Rpc<SolanaRpcApi>,\n message: TransactionMessageWithFeePayer &\n TransactionMessageWithSigners &\n Exclude<TransactionMessage, { version: \"legacy\" }>,\n) {\n const replaceRecentBlockhash = !isTransactionMessageWithDurableNonceLifetime(message);\n\n const transaction = pipe(message, compileTransaction);\n const wireTransactionBytes = getBase64EncodedWireTransaction(transaction);\n\n try {\n const response = await rpc\n .simulateTransaction(wireTransactionBytes, {\n encoding: \"base64\",\n replaceRecentBlockhash,\n sigVerify: false,\n })\n .send();\n // The API response type varies based on config (eg. `replacementBlockhash` is only\n // present when `replaceRecentBlockhash` is true), but `RpcSimulateTransactionResult`\n // is a flat superset. Cast through `unknown` to bridge the structural gap.\n const { err: transactionError, ...simulationResult } = response.value as unknown as RpcSimulateTransactionResult;\n\n if (simulationResult.unitsConsumed == null) {\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT);\n }\n\n if (transactionError) {\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT, {\n ...simulationResult,\n cause: getSolanaErrorFromTransactionError(transactionError),\n });\n }\n\n // Downcast from bigint to number, capping at u32 max.\n return simulationResult.unitsConsumed > 4_294_967_295n ? 4_294_967_295 : Number(simulationResult.unitsConsumed);\n } catch (e) {\n if (isSolanaError(e, SOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT)) {\n throw e;\n }\n throw new SolanaError(SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_COMPUTE_LIMIT, {\n cause: e,\n });\n }\n}\n","import {\n Address,\n Instruction,\n isWritableRole,\n prependTransactionMessageInstruction,\n Rpc,\n SolanaRpcApi,\n TransactionMessage,\n TransactionMessageWithFeePayer,\n TransactionMessageWithSigners,\n} from \"@solana/kit\";\nimport { getSetComputeUnitLimitInstruction, getSetComputeUnitPriceInstruction } from \"@solana-program/compute-budget\";\n\nimport type { Percentile, TransactionConfig } from \"./config\";\nimport { DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER } from \"./config\";\n\nexport async function processComputeBudgetForTxMessage(\n rpc: Rpc<SolanaRpcApi>,\n message: TransactionMessageWithFeePayer &\n TransactionMessageWithSigners &\n Exclude<TransactionMessage, { version: \"legacy\" }>,\n computeUnits: number,\n config: TransactionConfig,\n) {\n const computeUnitMarginMultiplier = config.computeUnitMarginMultiplier;\n let priorityFeeMicroLamports = 0n;\n\n const units = Math.min(\n 1_400_000,\n Math.ceil(computeUnits * (computeUnitMarginMultiplier ?? DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER)),\n );\n\n const priorityFee = config.priorityFee;\n if (priorityFee) {\n if (priorityFee.type === \"exact\") {\n priorityFeeMicroLamports = (priorityFee.amountLamports * 1_000_000n) / BigInt(units);\n } else if (priorityFee.type === \"dynamic\") {\n const estimatedPriorityFee = await calculateDynamicPriorityFees(\n rpc,\n message.instructions,\n priorityFee.priorityFeePercentile ?? \"50\",\n );\n\n if (!priorityFee.maxCapLamports) {\n priorityFeeMicroLamports = estimatedPriorityFee;\n } else {\n const maxCapMicroLamports = (priorityFee.maxCapLamports * 1_000_000n) / BigInt(units);\n priorityFeeMicroLamports =\n maxCapMicroLamports > estimatedPriorityFee ? estimatedPriorityFee : maxCapMicroLamports;\n }\n }\n }\n\n if (priorityFeeMicroLamports > 0) {\n message = prependTransactionMessageInstruction(\n getSetComputeUnitPriceInstruction({\n microLamports: priorityFeeMicroLamports,\n }),\n message,\n );\n }\n\n message = prependTransactionMessageInstruction(\n getSetComputeUnitLimitInstruction({\n units,\n }),\n message,\n );\n\n return message;\n}\n\nfunction getWritableAccounts(ixs: readonly Instruction[]) {\n const writable = new Set<Address>();\n ixs.forEach(ix => {\n if (ix.accounts) {\n ix.accounts.forEach(acc => {\n if (isWritableRole(acc.role)) writable.add(acc.address);\n });\n }\n });\n return Array.from(writable);\n}\n\nasync function calculateDynamicPriorityFees(\n rpc: Rpc<SolanaRpcApi>,\n instructions: readonly Instruction[],\n percentile: Percentile,\n) {\n const writableAccounts = getWritableAccounts(instructions);\n const recent = await rpc.getRecentPrioritizationFees(writableAccounts).send();\n const nonZero = recent.filter(pf => pf.prioritizationFee > 0).map(pf => pf.prioritizationFee);\n const sorted = nonZero.sort((a, b) => Number(a - b));\n return sorted[Math.floor(sorted.length * (parseInt(percentile) / 100))] || BigInt(0);\n}\n","import { BlockhashLifetimeConstraint } from \"@solana/kit\";\n\n/**\n * Default compute unit margin multiplier used to ensure sufficient compute budget.\n */\nexport const DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER = 1.15;\nexport const DEFAULT_JITO_BLOCK_ENGINE_URL = \"https://bundles.jito.wtf\";\n\ntype FeeSetting =\n | {\n type: \"dynamic\";\n maxCapLamports?: bigint;\n }\n | {\n type: \"exact\";\n amountLamports: bigint;\n }\n | {\n type: \"none\";\n };\n\n/**\n * Configuration for transaction fees, including Jito and priority fee settings.\n */\nexport type JitoFeeSetting = FeeSetting & {\n priorityFeePercentile?: Percentile | \"50ema\";\n};\n\nexport type PriorityFeeSetting = FeeSetting & {\n priorityFeePercentile?: Percentile;\n};\n\n/**\n * Defines a percentile value for priority fee selection.\n */\nexport type Percentile = \"25\" | \"50\" | \"75\" | \"95\" | \"99\";\n\nexport type TransactionConfig = {\n jito?: JitoFeeSetting;\n priorityFee?: PriorityFeeSetting;\n computeUnitMarginMultiplier?: number;\n jitoBlockEngineUrl?: string;\n skipSimulation?: boolean;\n blockhash?: BlockhashLifetimeConstraint;\n};\n","import {\n Address,\n address,\n appendTransactionMessageInstruction,\n getBase64EncodedWireTransaction,\n lamports,\n Rpc,\n SendableTransaction,\n SolanaRpcApi,\n Transaction,\n TransactionMessage,\n TransactionMessageWithFeePayer,\n TransactionMessageWithSigners,\n TransactionSigner,\n TransactionWithLifetime,\n} from \"@solana/kit\";\nimport { getTransferSolInstruction } from \"@solana-program/system\";\n\nimport { DEFAULT_JITO_BLOCK_ENGINE_URL, type Percentile, TransactionConfig } from \"./config\";\n\nconst JITO_BUNDLE_EXPIRY_TIME = 30_000;\n\nexport type AccountConfig = {\n accountIndex: number;\n addresses: string[];\n};\n\nexport type JitoAccountInfo = {\n executable: boolean;\n owner: string;\n lamports: number;\n data: string;\n rentEpoch: number;\n};\n\nexport type JitoRpcApi = SolanaRpcApi & {\n simulateBundle: (\n params: {\n encodedTransactions: string[];\n },\n config?: {\n preExecutionAccountsConfigs?: AccountConfig;\n postExecutionAccountsConfigs?: AccountConfig;\n skipSigVerify?: boolean;\n simulationBank?: {\n commitment?: {\n commitment: \"processed\" | \"confirmed\" | \"finalized\";\n };\n };\n transactionEncoding?: \"base64\";\n replaceRecentBlockhash?: boolean;\n },\n ) => SimulateBundleResponse;\n\n sendBundle: (\n params: string[],\n config?: {\n encoding?: \"base64\";\n },\n ) => string;\n\n getBundleStatuses: (params: string[]) => GetBundleStatusesResponse;\n};\n\nexport type SimulateBundleResponse = {\n context: {\n slot: number;\n apiVersion?: string;\n };\n value: {\n summary: \"succeeded\" | { failed: { error: unknown; tx_signature: string } };\n transactionResults: Array<{\n err: unknown;\n logs: string[] | null;\n unitsConsumed?: number;\n returnData: {\n programId: string;\n data: string;\n } | null;\n preExecutionAccounts: JitoAccountInfo[] | null;\n postExecutionAccounts: JitoAccountInfo[] | null;\n }>;\n };\n};\n\nexport type GetBundleStatusesResponse = {\n context: {\n slot: number;\n };\n value: Array<{\n bundleId: string;\n transactions: string[];\n slot: number;\n confirmation_status: \"processed\" | \"confirmed\" | \"finalized\";\n err:\n | {\n Ok: null;\n }\n | {\n Err: object;\n };\n }>;\n};\n\nexport enum JitoApiUrl {\n Amsterdam = \"https://amsterdam.mainnet.block-engine.jito.wtf\",\n Frankfurt = \"https://frankfurt.mainnet.block-engine.jito.wtf\",\n London = \"https://london.mainnet.block-engine.jito.wtf\",\n NY = \"https://ny.mainnet.block-engine.jito.wtf\",\n Singapore = \"https://singapore.mainnet.block-engine.jito.wtf\",\n SLC = \"https://slc.mainnet.block-engine.jito.wtf\",\n Tokyo = \"https://tokyo.mainnet.block-engine.jito.wtf\",\n Default = \"https://mainnet.block-engine.jito.wtf\",\n}\n\nexport async function processJitoTipForTxMessage(\n message: TransactionMessageWithFeePayer &\n TransactionMessageWithSigners &\n Exclude<TransactionMessage, { version: \"legacy\" }>,\n signer: TransactionSigner,\n config: TransactionConfig,\n) {\n const jito = config.jito;\n if (!jito) throw new Error(\"jito config is undefined\");\n\n let jitoTipLamports = BigInt(0);\n\n if (jito.type === \"exact\") {\n jitoTipLamports = jito.amountLamports;\n } else if (jito.type === \"dynamic\") {\n jitoTipLamports = await recentJitoTip(config);\n if (jito.maxCapLamports && jitoTipLamports > jito.maxCapLamports) {\n jitoTipLamports = jito.maxCapLamports;\n }\n }\n\n if (jitoTipLamports > 0) {\n return appendTransactionMessageInstruction(\n getTransferSolInstruction({\n source: signer,\n destination: getJitoTipAddress(),\n amount: jitoTipLamports,\n }),\n message,\n );\n } else {\n return message;\n }\n}\n\n// returns recent jito tip in lamports\nexport async function recentJitoTip(config: TransactionConfig) {\n const baseUrl = config.jitoBlockEngineUrl ?? DEFAULT_JITO_BLOCK_ENGINE_URL;\n const response = await fetch(`${baseUrl}/api/v1/bundles/tip_floor`);\n if (!response.ok) {\n return BigInt(0);\n }\n const data = await response.json().then(res => res[0]);\n\n const percentileToKey: Record<Percentile | \"50ema\", string> = {\n \"25\": \"landed_tips_25th_percentile\",\n \"50\": \"landed_tips_50th_percentile\",\n \"75\": \"landed_tips_75th_percentile\",\n \"95\": \"landed_tips_95th_percentile\",\n \"99\": \"landed_tips_99th_percentile\",\n \"50ema\": \"ema_landed_tips_50th_percentile\",\n };\n\n const key = percentileToKey[config.jito?.priorityFeePercentile ?? \"50\"];\n if (!key || !data[key]) {\n return BigInt(0);\n }\n return lamports(BigInt(Math.floor(Number(data[key]) * 10 ** 9))).valueOf();\n}\n\n// should we add an argument that dictates if we should use cached value in case fetch fails ?\n\n// below is taken from legacy sdk (no need to add the whole library)\n// https://jito-foundation.gitbook.io/mev/mev-payment-and-distribution/on-chain-addresses\nconst jitoTipAddresses = [\n \"96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5\",\n \"HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe\",\n \"Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY\",\n \"ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49\",\n \"DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh\",\n \"ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt\",\n \"DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL\",\n \"3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT\",\n];\n\nfunction getJitoTipAddress(): Address {\n // just pick a random one from the list. There are multiple addresses so that no single one can cause local congestion.\n return address(jitoTipAddresses[Math.floor(Math.random() * jitoTipAddresses.length)]);\n}\n\ninterface JsonRpcResult {\n jsonrpc: string;\n id: number;\n result?: string; // bundle id\n error?: {\n code: number;\n message: string;\n data?: unknown;\n };\n}\n\nexport async function sendJitoBundle(\n jitoApiUrl: JitoApiUrl,\n transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[],\n jitoUUID?: string,\n): Promise<string> {\n const encodedTransactions = transactions.map(tx => getBase64EncodedWireTransaction(tx)) as string[];\n\n const url = new URL(\"/api/v1/bundles\", jitoApiUrl);\n if (jitoUUID && jitoUUID.length > 0) {\n url.searchParams.set(\"uuid\", jitoUUID);\n }\n\n const request = {\n id: 1,\n jsonrpc: \"2.0\",\n method: \"sendBundle\",\n params: [\n encodedTransactions,\n {\n encoding: \"base64\",\n },\n ],\n };\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n throw new Error(`Jito HTTP error: ${response.status}`);\n }\n\n const data = (await response.json()) as JsonRpcResult;\n\n if (data.error) {\n throw new Error(`Jito bundle failed: ${data.error.code} ${data.error.message}`);\n }\n\n if (!data.result) {\n throw new Error(\"sendBundle did not return a bundle id\");\n }\n\n const bundleId = data.result;\n\n const expiryTime = Date.now() + JITO_BUNDLE_EXPIRY_TIME;\n\n while (Date.now() < expiryTime) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n const request = {\n jsonrpc: \"2.0\",\n id: 1,\n method: \"getInflightBundleStatuses\",\n params: [[bundleId]],\n };\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n throw new Error(`Jito HTTP error: ${response.status}`);\n }\n\n const data = await response.json();\n const result = data.result?.value?.[0];\n if (!result) {\n throw new Error(`getInflightBundleStatuses method returned undefined result`, { cause: { bundleId } });\n }\n\n switch (result.status) {\n case \"Landed\":\n return bundleId;\n case \"Pending\":\n case \"Invalid\":\n continue;\n case \"Failed\":\n throw new Error(`Bundle failed`, { cause: { bundleId } });\n default:\n throw new Error(`Bundle status is unknown`, { cause: { bundleId } });\n }\n }\n\n throw new Error(`Bundle expired`, { cause: { bundleId } });\n}\n\nexport async function simulateBundle(\n rpc: Rpc<JitoRpcApi>,\n transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[],\n): Promise<SimulateBundleResponse> {\n const encodedTransactions = transactions.map(tx => getBase64EncodedWireTransaction(tx));\n\n return rpc\n .simulateBundle({\n encodedTransactions,\n })\n .send();\n}\n\nexport async function sendBundle(\n rpc: Rpc<JitoRpcApi>,\n transactions: (SendableTransaction & Transaction & TransactionWithLifetime)[],\n): Promise<string> {\n const encodedTransactions = transactions.map(tx => getBase64EncodedWireTransaction(tx));\n\n const bundleId = await rpc\n .sendBundle(encodedTransactions, {\n encoding: \"base64\",\n })\n .send();\n\n if (!bundleId) throw new Error(`sendBundle method failed`);\n\n const expiryTime = Date.now() + JITO_BUNDLE_EXPIRY_TIME;\n\n while (Date.now() < expiryTime) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n const statuses = await rpc.getBundleStatuses([bundleId]).send();\n\n const bundleStatus = statuses?.value?.[0];\n if (!bundleStatus) continue;\n\n if (bundleStatus.err && \"Err\" in bundleStatus.err) {\n throw new Error(`Bundle failed`, { cause: { bundleId, error: bundleStatus.err.Err } });\n } else {\n const confirmation_status = bundleStatus.confirmation_status;\n if (confirmation_status == \"confirmed\") {\n return bundleId;\n }\n }\n }\n\n throw new Error(`Bundle expired`, { cause: { bundleId } });\n}\n","import {\n Commitment,\n getBase58Decoder,\n getBase64EncodedWireTransaction,\n Instruction,\n KeyPairSigner,\n MaybeAccount,\n Rpc,\n SendableTransaction,\n Signature,\n SolanaRpcApi,\n Transaction,\n TransactionWithLifetime,\n} from \"@solana/kit\";\nimport { AddressLookupTable } from \"@solana-program/address-lookup-table\";\n\nimport { buildTransaction } from \"./buildTransaction\";\nimport { TransactionConfig } from \"./config\";\n\n/**\n * Builds and sends a transaction with the given instructions, signers, and commitment level.\n *\n * @param {Rpc<SolanaRpcApi>} rpc - Solana Rpc client.\n * @param {Instruction[]} instructions - Array of instructions to include in the transaction.\n * @param {KeyPairSigner} payer - The fee payer for the transaction.\n * @param {TransactionConfig} config - The transaction config.\n * @param {Address[]} [lookupTableAccounts] - Optional array of address lookup table accounts to use.\n * @param {Commitment} [commitment=\"confirmed\"] - The commitment level for transaction confirmation.\n *\n * @returns {Promise<Signature>} A promise that resolves to the transaction signature.\n *\n * @throws {Error} If transaction building or sending fails.\n *\n * @example\n * ```ts\n * const signature = await sendTransaction(\n * instructions,\n * keypairSigner,\n * DEFAULT_TRANSACTION_CONFIG,\n * lookupTables,\n * \"finalized\"\n * );\n * ```\n */\nexport async function sendTransaction(\n rpc: Rpc<SolanaRpcApi>,\n instructions: Instruction[],\n payer: KeyPairSigner,\n config?: TransactionConfig,\n lookupTableAccounts?: MaybeAccount<AddressLookupTable>[],\n commitment: Commitment = \"confirmed\",\n): Promise<Signature> {\n const tx = await buildTransaction(rpc, instructions, payer, config ?? {}, lookupTableAccounts);\n return sendSignedTransaction(rpc, tx, config?.skipSimulation ?? false, commitment);\n}\n\n/**\n * Sends a signed transaction message to the Solana network with a specified commitment level.\n *\n * @param {Rpc<SolanaRpcApi>} rpc - Rpc client.\n * @param {SendableTransaction & Transaction & TransactionWithLifetime} transaction - The fully signed transaction to send.\n * @param {boolean} skipSimulation - True if skip simulation\n * @param {Commitment} [commitment=\"confirmed\"] - The commitment level for transaction confirmation.\n *\n * @returns {Promise<Signature>} A promise that resolves to the transaction signature.\n *\n * @throws {Error} If transaction sending fails, the RPC connection fails, or the transaction expires.\n *\n * @example\n * ```ts\n * const signature = await sendSignedTransaction(\n * rpc,\n * signedTransaction,\n * \"finalized\"\n * );\n * ```\n */\nexport async function sendSignedTransaction(\n rpc: Rpc<SolanaRpcApi>,\n transaction: SendableTransaction & Transaction & TransactionWithLifetime,\n skipSimulation: boolean = false,\n commitment: Commitment = \"confirmed\",\n): Promise<Signature> {\n const txSignature = getTxSignature(transaction);\n const encodedTransaction = getBase64EncodedWireTransaction(transaction);\n\n if (!skipSimulation) {\n // Simulate transaction first\n const simResult = await rpc\n .simulateTransaction(encodedTransaction, {\n encoding: \"base64\",\n })\n .send();\n\n if (simResult.value.err) {\n throw new Error(`Transaction simulation failed`, { cause: simResult.value });\n }\n }\n\n const expiryTime = Date.now() + 60_000;\n\n while (Date.now() < expiryTime) {\n await rpc\n .sendTransaction(encodedTransaction, {\n maxRetries: BigInt(0),\n skipPreflight: true,\n encoding: \"base64\",\n })\n .send();\n\n const { value } = await rpc.getSignatureStatuses([txSignature]).send();\n const status = value[0];\n if (status?.confirmationStatus === commitment) {\n if (status.err) {\n throw new Error(`Transaction failed`, { cause: status.err });\n }\n return txSignature;\n }\n }\n\n throw new Error(\"Transaction expired\");\n}\n\nexport function getTxSignature(transaction: Transaction) {\n const [signature] = Object.values(transaction.signatures);\n return getBase58Decoder().decode(signature!) as Signature;\n}\n"],"mappings":"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","names":["getBase64EncodedWireTransaction","JitoApiUrl","request","response","data","getBase64EncodedWireTransaction","getBase64EncodedWireTransaction","getBase64EncodedWireTransaction"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unio-aggregator/unio-tx-sender",
|
|
3
3
|
"description": "A TypeScript package for building and sending Solana transactions with support for priority fees and Jito tips.",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.4",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"@solana-program/compute-budget": "^0.15.0",
|
|
30
30
|
"@solana-program/system": "^0.11.0",
|
|
31
31
|
"@solana/kit": "^6.9.0",
|
|
32
|
+
"@solana/transaction-messages": "^6.9.0",
|
|
32
33
|
"@solana/rpc": "^6.9.0",
|
|
33
34
|
"@solana/rpc-api": "^6.9.0",
|
|
34
35
|
"bs58": "^6.0.0"
|
|
@@ -45,7 +46,8 @@
|
|
|
45
46
|
"rimraf": "^6.1.3",
|
|
46
47
|
"eslint": "^10.6.0",
|
|
47
48
|
"eslint-plugin-prettier": "^5.5.6",
|
|
48
|
-
"eslint-plugin-simple-import-sort": "^13.0.0"
|
|
49
|
+
"eslint-plugin-simple-import-sort": "^13.0.0",
|
|
50
|
+
"prettier-plugin-tailwindcss": "^0.8.0"
|
|
49
51
|
},
|
|
50
52
|
"scripts": {
|
|
51
53
|
"build": "tsup src/index.ts --format cjs,esm --dts --sourcemap",
|