@unio-aggregator/unio-tx-sender 1.0.1 → 1.0.2
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 +198 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +103 -20
- package/dist/index.d.ts +103 -20
- package/dist/index.js +179 -56
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -20,15 +20,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
var index_exports = {};
|
|
21
21
|
__export(index_exports, {
|
|
22
22
|
DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER: () => DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER,
|
|
23
|
-
|
|
23
|
+
DEFAULT_JITO_BLOCK_ENGINE_URL: () => DEFAULT_JITO_BLOCK_ENGINE_URL,
|
|
24
|
+
JitoApiUrl: () => JitoApiUrl,
|
|
24
25
|
buildTransaction: () => buildTransaction,
|
|
26
|
+
getTxSignature: () => getTxSignature,
|
|
27
|
+
processJitoTipForTxMessage: () => processJitoTipForTxMessage,
|
|
28
|
+
recentJitoTip: () => recentJitoTip,
|
|
29
|
+
sendBundle: () => sendBundle,
|
|
30
|
+
sendJitoBundle: () => sendJitoBundle,
|
|
25
31
|
sendSignedTransaction: () => sendSignedTransaction,
|
|
26
|
-
sendTransaction: () => sendTransaction
|
|
32
|
+
sendTransaction: () => sendTransaction,
|
|
33
|
+
simulateBundle: () => simulateBundle
|
|
27
34
|
});
|
|
28
35
|
module.exports = __toCommonJS(index_exports);
|
|
29
36
|
|
|
30
37
|
// src/buildTransaction.ts
|
|
31
|
-
var
|
|
38
|
+
var import_kit4 = require("@solana/kit");
|
|
32
39
|
|
|
33
40
|
// src/computeBudget.ts
|
|
34
41
|
var import_kit = require("@solana/kit");
|
|
@@ -36,38 +43,34 @@ var import_compute_budget = require("@solana-program/compute-budget");
|
|
|
36
43
|
|
|
37
44
|
// src/config.ts
|
|
38
45
|
var DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER = 1.15;
|
|
39
|
-
var
|
|
40
|
-
priorityFee: {
|
|
41
|
-
type: "none",
|
|
42
|
-
priorityFeePercentile: "50"
|
|
43
|
-
},
|
|
44
|
-
jito: {
|
|
45
|
-
type: "none",
|
|
46
|
-
priorityFeePercentile: "50"
|
|
47
|
-
},
|
|
48
|
-
computeUnitMarginMultiplier: DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER,
|
|
49
|
-
jitoBlockEngineUrl: "https://bundles.jito.wtf",
|
|
50
|
-
skipSimulation: false
|
|
51
|
-
};
|
|
46
|
+
var DEFAULT_JITO_BLOCK_ENGINE_URL = "https://bundles.jito.wtf";
|
|
52
47
|
|
|
53
48
|
// src/computeBudget.ts
|
|
54
49
|
async function processComputeBudgetForTxMessage(rpc, message, computeUnits, config) {
|
|
55
|
-
const priorityFee = config.priorityFee;
|
|
56
50
|
const computeUnitMarginMultiplier = config.computeUnitMarginMultiplier;
|
|
57
51
|
let priorityFeeMicroLamports = 0n;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (
|
|
67
|
-
priorityFeeMicroLamports =
|
|
68
|
-
} else {
|
|
69
|
-
const
|
|
70
|
-
|
|
52
|
+
const units = BigInt(
|
|
53
|
+
Math.min(
|
|
54
|
+
14e5,
|
|
55
|
+
Math.ceil(computeUnits * (computeUnitMarginMultiplier ?? DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER))
|
|
56
|
+
)
|
|
57
|
+
);
|
|
58
|
+
const priorityFee = config.priorityFee;
|
|
59
|
+
if (priorityFee) {
|
|
60
|
+
if (priorityFee.type === "exact") {
|
|
61
|
+
priorityFeeMicroLamports = priorityFee.amountLamports * 1000000n / units;
|
|
62
|
+
} else if (priorityFee.type === "dynamic") {
|
|
63
|
+
const estimatedPriorityFee = await calculateDynamicPriorityFees(
|
|
64
|
+
rpc,
|
|
65
|
+
message.instructions,
|
|
66
|
+
priorityFee.priorityFeePercentile ?? "50"
|
|
67
|
+
);
|
|
68
|
+
if (!priorityFee.maxCapLamports) {
|
|
69
|
+
priorityFeeMicroLamports = estimatedPriorityFee;
|
|
70
|
+
} else {
|
|
71
|
+
const maxCapMicroLamports = priorityFee.maxCapLamports * 1000000n / units;
|
|
72
|
+
priorityFeeMicroLamports = maxCapMicroLamports > estimatedPriorityFee ? estimatedPriorityFee : maxCapMicroLamports;
|
|
73
|
+
}
|
|
71
74
|
}
|
|
72
75
|
}
|
|
73
76
|
if (priorityFeeMicroLamports > 0) {
|
|
@@ -80,7 +83,7 @@ async function processComputeBudgetForTxMessage(rpc, message, computeUnits, conf
|
|
|
80
83
|
}
|
|
81
84
|
message = (0, import_kit.prependTransactionMessageInstruction)(
|
|
82
85
|
(0, import_compute_budget.getSetComputeUnitLimitInstruction)({
|
|
83
|
-
units:
|
|
86
|
+
units: computeUnits
|
|
84
87
|
}),
|
|
85
88
|
message
|
|
86
89
|
);
|
|
@@ -107,17 +110,34 @@ async function calculateDynamicPriorityFees(rpc, instructions, percentile) {
|
|
|
107
110
|
|
|
108
111
|
// src/jito.ts
|
|
109
112
|
var import_kit2 = require("@solana/kit");
|
|
113
|
+
var import_kit3 = require("@solana/kit");
|
|
110
114
|
var import_system = require("@solana-program/system");
|
|
115
|
+
var JITO_BUNDLE_EXPIRY_TIME = 3e4;
|
|
116
|
+
var JitoApiUrl = /* @__PURE__ */ ((JitoApiUrl2) => {
|
|
117
|
+
JitoApiUrl2["Amsterdam"] = "https://amsterdam.mainnet.block-engine.jito.wtf";
|
|
118
|
+
JitoApiUrl2["Frankfurt"] = "https://frankfurt.mainnet.block-engine.jito.wtf";
|
|
119
|
+
JitoApiUrl2["London"] = "https://london.mainnet.block-engine.jito.wtf";
|
|
120
|
+
JitoApiUrl2["NY"] = "https://ny.mainnet.block-engine.jito.wtf";
|
|
121
|
+
JitoApiUrl2["Singapore"] = "https://singapore.mainnet.block-engine.jito.wtf";
|
|
122
|
+
JitoApiUrl2["SLC"] = "https://slc.mainnet.block-engine.jito.wtf";
|
|
123
|
+
JitoApiUrl2["Tokyo"] = "https://tokyo.mainnet.block-engine.jito.wtf";
|
|
124
|
+
JitoApiUrl2["Default"] = "https://mainnet.block-engine.jito.wtf";
|
|
125
|
+
return JitoApiUrl2;
|
|
126
|
+
})(JitoApiUrl || {});
|
|
111
127
|
async function processJitoTipForTxMessage(message, signer, config) {
|
|
112
|
-
let jitoTipLamports = BigInt(0);
|
|
113
128
|
const jito = config.jito;
|
|
129
|
+
if (!jito) throw new Error("jito config is undefined");
|
|
130
|
+
let jitoTipLamports = BigInt(0);
|
|
114
131
|
if (jito.type === "exact") {
|
|
115
132
|
jitoTipLamports = jito.amountLamports;
|
|
116
133
|
} else if (jito.type === "dynamic") {
|
|
117
134
|
jitoTipLamports = await recentJitoTip(config);
|
|
135
|
+
if (jito.maxCapLamports && jitoTipLamports > jito.maxCapLamports) {
|
|
136
|
+
jitoTipLamports = jito.maxCapLamports;
|
|
137
|
+
}
|
|
118
138
|
}
|
|
119
139
|
if (jitoTipLamports > 0) {
|
|
120
|
-
return (0, import_kit2.
|
|
140
|
+
return (0, import_kit2.appendTransactionMessageInstruction)(
|
|
121
141
|
(0, import_system.getTransferSolInstruction)({
|
|
122
142
|
source: signer,
|
|
123
143
|
destination: getJitoTipAddress(),
|
|
@@ -130,7 +150,8 @@ async function processJitoTipForTxMessage(message, signer, config) {
|
|
|
130
150
|
}
|
|
131
151
|
}
|
|
132
152
|
async function recentJitoTip(config) {
|
|
133
|
-
const
|
|
153
|
+
const baseUrl = config.jitoBlockEngineUrl ?? DEFAULT_JITO_BLOCK_ENGINE_URL;
|
|
154
|
+
const response = await fetch(`${baseUrl}/api/v1/bundles/tip_floor`);
|
|
134
155
|
if (!response.ok) {
|
|
135
156
|
return BigInt(0);
|
|
136
157
|
}
|
|
@@ -143,11 +164,11 @@ async function recentJitoTip(config) {
|
|
|
143
164
|
"99": "landed_tips_99th_percentile",
|
|
144
165
|
"50ema": "ema_landed_tips_50th_percentile"
|
|
145
166
|
};
|
|
146
|
-
const key = percentileToKey[config.
|
|
167
|
+
const key = percentileToKey[config.jito?.priorityFeePercentile ?? "50"];
|
|
147
168
|
if (!key || !data[key]) {
|
|
148
169
|
return BigInt(0);
|
|
149
170
|
}
|
|
150
|
-
return (0,
|
|
171
|
+
return (0, import_kit3.lamports)(BigInt(Math.floor(Number(data[key]) * 10 ** 9))).valueOf();
|
|
151
172
|
}
|
|
152
173
|
var jitoTipAddresses = [
|
|
153
174
|
"96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5",
|
|
@@ -160,50 +181,155 @@ var jitoTipAddresses = [
|
|
|
160
181
|
"3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT"
|
|
161
182
|
];
|
|
162
183
|
function getJitoTipAddress() {
|
|
163
|
-
return (0,
|
|
184
|
+
return (0, import_kit3.address)(jitoTipAddresses[Math.floor(Math.random() * jitoTipAddresses.length)]);
|
|
185
|
+
}
|
|
186
|
+
async function sendJitoBundle(jitoApiUrl, transactions, jitoUUID) {
|
|
187
|
+
const encodedTransactions = transactions.map((tx) => (0, import_kit2.getBase64EncodedWireTransaction)(tx));
|
|
188
|
+
const url = new URL("/api/v1/bundles", jitoApiUrl);
|
|
189
|
+
if (jitoUUID && jitoUUID.length > 0) {
|
|
190
|
+
url.searchParams.set("uuid", jitoUUID);
|
|
191
|
+
}
|
|
192
|
+
const request = {
|
|
193
|
+
id: 1,
|
|
194
|
+
jsonrpc: "2.0",
|
|
195
|
+
method: "sendBundle",
|
|
196
|
+
params: [
|
|
197
|
+
encodedTransactions,
|
|
198
|
+
{
|
|
199
|
+
encoding: "base64"
|
|
200
|
+
}
|
|
201
|
+
]
|
|
202
|
+
};
|
|
203
|
+
const response = await fetch(url, {
|
|
204
|
+
method: "POST",
|
|
205
|
+
headers: {
|
|
206
|
+
"Content-Type": "application/json"
|
|
207
|
+
},
|
|
208
|
+
body: JSON.stringify(request)
|
|
209
|
+
});
|
|
210
|
+
if (!response.ok) {
|
|
211
|
+
throw new Error(`Jito HTTP error: ${response.status}`);
|
|
212
|
+
}
|
|
213
|
+
const data = await response.json();
|
|
214
|
+
if (data.error) {
|
|
215
|
+
throw new Error(`Jito bundle failed: ${data.error.code} ${data.error.message}`);
|
|
216
|
+
}
|
|
217
|
+
if (!data.result) {
|
|
218
|
+
throw new Error("sendBundle did not return a bundle id");
|
|
219
|
+
}
|
|
220
|
+
const bundleId = data.result;
|
|
221
|
+
const expiryTime = Date.now() + JITO_BUNDLE_EXPIRY_TIME;
|
|
222
|
+
while (Date.now() < expiryTime) {
|
|
223
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
224
|
+
const request2 = {
|
|
225
|
+
jsonrpc: "2.0",
|
|
226
|
+
id: 1,
|
|
227
|
+
method: "getInflightBundleStatuses",
|
|
228
|
+
params: [[bundleId]]
|
|
229
|
+
};
|
|
230
|
+
const response2 = await fetch(url, {
|
|
231
|
+
method: "POST",
|
|
232
|
+
headers: {
|
|
233
|
+
"Content-Type": "application/json"
|
|
234
|
+
},
|
|
235
|
+
body: JSON.stringify(request2)
|
|
236
|
+
});
|
|
237
|
+
if (!response2.ok) {
|
|
238
|
+
throw new Error(`Jito HTTP error: ${response2.status}`);
|
|
239
|
+
}
|
|
240
|
+
const data2 = await response2.json();
|
|
241
|
+
const result = data2.result?.value?.[0];
|
|
242
|
+
if (!result) {
|
|
243
|
+
throw new Error(`getInflightBundleStatuses method returned undefined result`, { cause: { bundleId } });
|
|
244
|
+
}
|
|
245
|
+
switch (result.status) {
|
|
246
|
+
case "Landed":
|
|
247
|
+
return bundleId;
|
|
248
|
+
case "Pending":
|
|
249
|
+
case "Invalid":
|
|
250
|
+
continue;
|
|
251
|
+
case "Failed":
|
|
252
|
+
throw new Error(`Bundle failed`, { cause: { bundleId } });
|
|
253
|
+
default:
|
|
254
|
+
throw new Error(`Bundle status is unknown`, { cause: { bundleId } });
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
throw new Error(`Bundle expired`, { cause: { bundleId } });
|
|
258
|
+
}
|
|
259
|
+
async function simulateBundle(rpc, transactions) {
|
|
260
|
+
const encodedTransactions = transactions.map((tx) => (0, import_kit2.getBase64EncodedWireTransaction)(tx));
|
|
261
|
+
return rpc.simulateBundle({
|
|
262
|
+
encodedTransactions
|
|
263
|
+
}).send();
|
|
264
|
+
}
|
|
265
|
+
async function sendBundle(rpc, transactions) {
|
|
266
|
+
const encodedTransactions = transactions.map((tx) => (0, import_kit2.getBase64EncodedWireTransaction)(tx));
|
|
267
|
+
const bundleId = await rpc.sendBundle(encodedTransactions, {
|
|
268
|
+
encoding: "base64"
|
|
269
|
+
}).send();
|
|
270
|
+
if (!bundleId) throw new Error(`sendBundle method failed`);
|
|
271
|
+
const expiryTime = Date.now() + JITO_BUNDLE_EXPIRY_TIME;
|
|
272
|
+
while (Date.now() < expiryTime) {
|
|
273
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
274
|
+
const statuses = await rpc.getBundleStatuses([bundleId]).send();
|
|
275
|
+
const bundleStatus = statuses?.value?.[0];
|
|
276
|
+
if (!bundleStatus) continue;
|
|
277
|
+
if (bundleStatus.err && "Err" in bundleStatus.err) {
|
|
278
|
+
throw new Error(`Bundle failed`, { cause: { bundleId, error: bundleStatus.err.Err } });
|
|
279
|
+
} else {
|
|
280
|
+
const confirmation_status = bundleStatus.confirmation_status;
|
|
281
|
+
if (confirmation_status == "confirmed") {
|
|
282
|
+
return bundleId;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
throw new Error(`Bundle expired`, { cause: { bundleId } });
|
|
164
287
|
}
|
|
165
288
|
|
|
166
289
|
// src/buildTransaction.ts
|
|
167
|
-
async function buildTransaction(rpc,
|
|
290
|
+
async function buildTransaction(rpc, instructions, feePayer, config, lookupTableAccounts) {
|
|
168
291
|
return buildTransactionMessage(
|
|
169
292
|
rpc,
|
|
170
|
-
config,
|
|
171
293
|
instructions,
|
|
172
|
-
!("address" in feePayer) ? (0,
|
|
294
|
+
!("address" in feePayer) ? (0, import_kit4.createNoopSigner)(feePayer) : feePayer,
|
|
295
|
+
config,
|
|
173
296
|
lookupTableAccounts
|
|
174
297
|
);
|
|
175
298
|
}
|
|
176
|
-
async function buildTransactionMessage(rpc,
|
|
177
|
-
let
|
|
299
|
+
async function buildTransactionMessage(rpc, instructions, signer, config, lookupTableAccounts) {
|
|
300
|
+
let blockhash = config.blockhash;
|
|
301
|
+
if (!blockhash) {
|
|
302
|
+
blockhash = (await rpc.getLatestBlockhash({
|
|
303
|
+
commitment: "confirmed"
|
|
304
|
+
}).send()).value;
|
|
305
|
+
}
|
|
306
|
+
let message = await prepareTransactionMessage(instructions, signer, blockhash);
|
|
178
307
|
if (lookupTableAccounts?.length) {
|
|
179
308
|
const tables = lookupTableAccounts.reduce(
|
|
180
309
|
(prev, account) => {
|
|
181
310
|
if (account.exists) {
|
|
182
|
-
(0,
|
|
311
|
+
(0, import_kit4.assertAccountDecoded)(account);
|
|
183
312
|
prev[account.address] = account.data.addresses;
|
|
184
313
|
}
|
|
185
314
|
return prev;
|
|
186
315
|
},
|
|
187
316
|
{}
|
|
188
317
|
);
|
|
189
|
-
message = (0,
|
|
318
|
+
message = (0, import_kit4.compressTransactionMessageUsingAddressLookupTables)(message, tables);
|
|
190
319
|
}
|
|
191
320
|
const messageWithExtraInstructions = await addPriorityInstructions(rpc, message, signer, config);
|
|
192
|
-
return (0,
|
|
321
|
+
return (0, import_kit4.signTransactionMessageWithSigners)(messageWithExtraInstructions);
|
|
193
322
|
}
|
|
194
|
-
async function prepareTransactionMessage(instructions,
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
(0,
|
|
200
|
-
(tx) => (0, import_kit3.setTransactionMessageLifetimeUsingBlockhash)(blockhash, tx),
|
|
201
|
-
(tx) => (0, import_kit3.setTransactionMessageFeePayerSigner)(signer, tx),
|
|
202
|
-
(tx) => (0, import_kit3.appendTransactionMessageInstructions)(instructions, tx)
|
|
323
|
+
async function prepareTransactionMessage(instructions, signer, blockhash) {
|
|
324
|
+
return (0, import_kit4.pipe)(
|
|
325
|
+
(0, import_kit4.createTransactionMessage)({ version: 0 }),
|
|
326
|
+
(tx) => (0, import_kit4.setTransactionMessageLifetimeUsingBlockhash)(blockhash, tx),
|
|
327
|
+
(tx) => (0, import_kit4.setTransactionMessageFeePayerSigner)(signer, tx),
|
|
328
|
+
(tx) => (0, import_kit4.appendTransactionMessageInstructions)(instructions, tx)
|
|
203
329
|
);
|
|
204
330
|
}
|
|
205
331
|
async function addPriorityInstructions(rpc, message, signer, config) {
|
|
206
|
-
if (config.jito.type !== "none") {
|
|
332
|
+
if (config.jito && config.jito.type !== "none") {
|
|
207
333
|
message = await processJitoTipForTxMessage(message, signer, config);
|
|
208
334
|
}
|
|
209
335
|
let computeUnits = 14e5;
|
|
@@ -217,25 +343,19 @@ async function addPriorityInstructions(rpc, message, signer, config) {
|
|
|
217
343
|
return processComputeBudgetForTxMessage(rpc, message, computeUnits, config);
|
|
218
344
|
}
|
|
219
345
|
async function getComputeUnitsForTxMessage(rpc, txMessage) {
|
|
220
|
-
return await (0,
|
|
346
|
+
return await (0, import_kit4.estimateComputeUnitLimitFactory)({ rpc })(txMessage);
|
|
221
347
|
}
|
|
222
348
|
|
|
223
349
|
// src/sendTransaction.ts
|
|
224
|
-
var
|
|
350
|
+
var import_kit5 = require("@solana/kit");
|
|
225
351
|
async function sendTransaction(rpc, instructions, payer, config, lookupTableAccounts, commitment = "confirmed") {
|
|
226
|
-
const tx = await buildTransaction(
|
|
227
|
-
|
|
228
|
-
config ?? DEFAULT_TRANSACTION_CONFIG,
|
|
229
|
-
instructions,
|
|
230
|
-
payer,
|
|
231
|
-
lookupTableAccounts
|
|
232
|
-
);
|
|
233
|
-
return sendSignedTransaction(rpc, tx, config ?? DEFAULT_TRANSACTION_CONFIG, commitment);
|
|
352
|
+
const tx = await buildTransaction(rpc, instructions, payer, config ?? {}, lookupTableAccounts);
|
|
353
|
+
return sendSignedTransaction(rpc, tx, config?.skipSimulation ?? false, commitment);
|
|
234
354
|
}
|
|
235
|
-
async function sendSignedTransaction(rpc, transaction,
|
|
355
|
+
async function sendSignedTransaction(rpc, transaction, skipSimulation = false, commitment = "confirmed") {
|
|
236
356
|
const txSignature = getTxSignature(transaction);
|
|
237
|
-
const encodedTransaction = (0,
|
|
238
|
-
if (!
|
|
357
|
+
const encodedTransaction = (0, import_kit5.getBase64EncodedWireTransaction)(transaction);
|
|
358
|
+
if (!skipSimulation) {
|
|
239
359
|
const simResult = await rpc.simulateTransaction(encodedTransaction, {
|
|
240
360
|
encoding: "base64"
|
|
241
361
|
}).send();
|
|
@@ -263,14 +383,21 @@ async function sendSignedTransaction(rpc, transaction, config, commitment = "con
|
|
|
263
383
|
}
|
|
264
384
|
function getTxSignature(transaction) {
|
|
265
385
|
const [signature] = Object.values(transaction.signatures);
|
|
266
|
-
return (0,
|
|
386
|
+
return (0, import_kit5.getBase58Decoder)().decode(signature);
|
|
267
387
|
}
|
|
268
388
|
// Annotate the CommonJS export names for ESM import in node:
|
|
269
389
|
0 && (module.exports = {
|
|
270
390
|
DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER,
|
|
271
|
-
|
|
391
|
+
DEFAULT_JITO_BLOCK_ENGINE_URL,
|
|
392
|
+
JitoApiUrl,
|
|
272
393
|
buildTransaction,
|
|
394
|
+
getTxSignature,
|
|
395
|
+
processJitoTipForTxMessage,
|
|
396
|
+
recentJitoTip,
|
|
397
|
+
sendBundle,
|
|
398
|
+
sendJitoBundle,
|
|
273
399
|
sendSignedTransaction,
|
|
274
|
-
sendTransaction
|
|
400
|
+
sendTransaction,
|
|
401
|
+
simulateBundle
|
|
275
402
|
});
|
|
276
403
|
//# sourceMappingURL=index.cjs.map
|
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 \"./sendTransaction\";\n","import {\n Address,\n appendTransactionMessageInstructions,\n assertAccountDecoded,\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 config: TransactionConfig,\n instructions: Instruction[],\n feePayer: TransactionSigner | Address,\n lookupTableAccounts?: MaybeAccount<AddressLookupTable>[],\n): Promise<Readonly<SendableTransaction & Transaction & TransactionWithLifetime>> {\n return buildTransactionMessage(\n rpc,\n config,\n instructions,\n !(\"address\" in feePayer) ? createNoopSigner(feePayer) : feePayer,\n lookupTableAccounts,\n );\n}\n\nasync function buildTransactionMessage(\n rpc: Rpc<SolanaRpcApi>,\n config: TransactionConfig,\n instructions: Instruction[],\n signer: TransactionSigner,\n lookupTableAccounts?: MaybeAccount<AddressLookupTable>[],\n) {\n let message = await prepareTransactionMessage(instructions, rpc, signer);\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 rpc: Rpc<SolanaRpcApi>,\n signer: TransactionSigner,\n) {\n const { value: blockhash } = await rpc\n .getLatestBlockhash({\n commitment: \"confirmed\",\n })\n .send();\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.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 priorityFee = config.priorityFee;\n const computeUnitMarginMultiplier = config.computeUnitMarginMultiplier;\n let priorityFeeMicroLamports = 0n;\n\n if (priorityFee.type === \"exact\") {\n priorityFeeMicroLamports = (priorityFee.amountLamports * 1_000_000n) / BigInt(computeUnits);\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(computeUnits);\n\n priorityFeeMicroLamports =\n maxCapMicroLamports > estimatedPriorityFee ? estimatedPriorityFee : maxCapMicroLamports;\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: Math.ceil(computeUnits * (computeUnitMarginMultiplier ?? DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER)),\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","/**\n * Default compute unit margin multiplier used to ensure sufficient compute budget.\n */\nexport const DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER = 1.15;\n\n/**\n * Default prioritization settings, including priority fees and Jito tips.\n */\nexport const DEFAULT_TRANSACTION_CONFIG: TransactionConfig = {\n priorityFee: {\n type: \"none\",\n priorityFeePercentile: \"50\",\n },\n jito: {\n type: \"none\",\n priorityFeePercentile: \"50\",\n },\n computeUnitMarginMultiplier: DEFAULT_COMPUTE_UNIT_MARGIN_MULTIPLIER,\n jitoBlockEngineUrl: \"https://bundles.jito.wtf\",\n skipSimulation: false,\n};\n\n/*\nasync function getChainIdFromGenesisHash(rpc: Rpc<SolanaRpcApi>): Promise<ChainId> {\n // not all rpc endpoints support getGenesisHash\n try {\n const genesisHash = await rpc.getGenesisHash().send();\n const genesisHashToChainId: Record<string, ChainId> = {\n \"5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d\": \"solana\",\n EAQLJCV2mh23BsK2P9oYpV5CHVLDNHTxYss3URrNmg3s: \"eclipse\",\n EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG: \"solana-devnet\",\n CX4huckiV9QNAkKNVKi5Tj8nxzBive5kQimd94viMKsU: \"eclipse-testnet\",\n };\n return genesisHashToChainId[genesisHash] || \"unknown\";\n } catch (error) {\n console.warn(\"Error getting chain ID from genesis hash\", error);\n return \"unknown\";\n }\n}\n */\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\nexport type TransactionConfig = {\n jito: JitoFeeSetting;\n priorityFee: PriorityFeeSetting;\n computeUnitMarginMultiplier: number;\n jitoBlockEngineUrl: string;\n skipSimulation: boolean;\n};\n\n/**\n * Defines a percentile value for priority fee selection.\n */\nexport type Percentile = \"25\" | \"50\" | \"75\" | \"95\" | \"99\";\n\n/**\n * Represents a supported blockchain network chain ID.\n */\nexport type ChainId = \"solana\" | \"eclipse\" | \"solana-devnet\" | \"eclipse-testnet\" | \"unknown\";\n","import { Address, TransactionMessage, TransactionMessageWithFeePayer, TransactionSigner } from \"@solana/kit\";\nimport { address, lamports, prependTransactionMessageInstruction } from \"@solana/kit\";\nimport { getTransferSolInstruction } from \"@solana-program/system\";\n\nimport { type Percentile, TransactionConfig } from \"./config\";\n\nexport async function processJitoTipForTxMessage(\n message: TransactionMessage & TransactionMessageWithFeePayer,\n signer: TransactionSigner,\n config: TransactionConfig,\n) {\n let jitoTipLamports = BigInt(0);\n const jito = config.jito;\n\n if (jito.type === \"exact\") {\n jitoTipLamports = jito.amountLamports;\n } else if (jito.type === \"dynamic\") {\n jitoTipLamports = await recentJitoTip(config);\n }\n if (jitoTipLamports > 0) {\n return prependTransactionMessageInstruction(\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 response = await fetch(`${config.jitoBlockEngineUrl}/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.priorityFee.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\n // can cause local congestion.\n return address(jitoTipAddresses[Math.floor(Math.random() * jitoTipAddresses.length)]);\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 { DEFAULT_TRANSACTION_CONFIG, 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(\n rpc,\n config ?? DEFAULT_TRANSACTION_CONFIG,\n instructions,\n payer,\n lookupTableAccounts,\n );\n return sendSignedTransaction(rpc, tx, config ?? DEFAULT_TRANSACTION_CONFIG, 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 {TransactionConfig} config - The transaction config.\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 config: TransactionConfig,\n commitment: Commitment = \"confirmed\",\n): Promise<Signature> {\n const txSignature = getTxSignature(transaction);\n const encodedTransaction = getBase64EncodedWireTransaction(transaction);\n\n if (!config.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\nfunction 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;;;ACAA,IAAAA,cAsBO;;;ACdP,iBAAqE;AACrE,4BAAqF;;;ACN9E,IAAM,yCAAyC;AAK/C,IAAM,6BAAgD;AAAA,EAC3D,aAAa;AAAA,IACX,MAAM;AAAA,IACN,uBAAuB;AAAA,EACzB;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,uBAAuB;AAAA,EACzB;AAAA,EACA,6BAA6B;AAAA,EAC7B,oBAAoB;AAAA,EACpB,gBAAgB;AAClB;;;ADNA,eAAsB,iCACpB,KACA,SACA,cACA,QACA;AACA,QAAM,cAAc,OAAO;AAC3B,QAAM,8BAA8B,OAAO;AAC3C,MAAI,2BAA2B;AAE/B,MAAI,YAAY,SAAS,SAAS;AAChC,+BAA4B,YAAY,iBAAiB,WAAc,OAAO,YAAY;AAAA,EAC5F,WAAW,YAAY,SAAS,WAAW;AACzC,UAAM,uBAAuB,MAAM;AAAA,MACjC;AAAA,MACA,QAAQ;AAAA,MACR,YAAY,yBAAyB;AAAA,IACvC;AAEA,QAAI,CAAC,YAAY,gBAAgB;AAC/B,iCAA2B;AAAA,IAC7B,OAAO;AACL,YAAM,sBAAuB,YAAY,iBAAiB,WAAc,OAAO,YAAY;AAE3F,iCACE,sBAAsB,uBAAuB,uBAAuB;AAAA,IACxE;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,KAAK,KAAK,gBAAgB,+BAA+B,uCAAuC;AAAA,IACzG,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;;;AEnFA,IAAAC,cAAwE;AACxE,oBAA0C;AAI1C,eAAsB,2BACpB,SACA,QACA,QACA;AACA,MAAI,kBAAkB,OAAO,CAAC;AAC9B,QAAM,OAAO,OAAO;AAEpB,MAAI,KAAK,SAAS,SAAS;AACzB,sBAAkB,KAAK;AAAA,EACzB,WAAW,KAAK,SAAS,WAAW;AAClC,sBAAkB,MAAM,cAAc,MAAM;AAAA,EAC9C;AACA,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,WAAW,MAAM,MAAM,GAAG,OAAO,kBAAkB,2BAA2B;AACpF,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,YAAY,yBAAyB,IAAI;AAC5E,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;AAGpC,aAAO,qBAAQ,iBAAiB,KAAK,MAAM,KAAK,OAAO,IAAI,iBAAiB,MAAM,CAAC,CAAC;AACtF;;;AH3BA,eAAsB,iBACpB,KACA,QACA,cACA,UACA,qBACgF;AAChF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,EAAE,aAAa,gBAAY,8BAAiB,QAAQ,IAAI;AAAA,IACxD;AAAA,EACF;AACF;AAEA,eAAe,wBACb,KACA,QACA,cACA,QACA,qBACA;AACA,MAAI,UAAU,MAAM,0BAA0B,cAAc,KAAK,MAAM;AAEvE,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,KACA,QACA;AACA,QAAM,EAAE,OAAO,UAAU,IAAI,MAAM,IAChC,mBAAmB;AAAA,IAClB,YAAY;AAAA,EACd,CAAC,EACA,KAAK;AAER,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,KAAK,SAAS,QAAQ;AAC/B,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;;;AI5IA,IAAAC,cAaO;AA+BP,eAAsB,gBACpB,KACA,cACA,OACA,QACA,qBACA,aAAyB,aACL;AACpB,QAAM,KAAK,MAAM;AAAA,IACf;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,SAAO,sBAAsB,KAAK,IAAI,UAAU,4BAA4B,UAAU;AACxF;AAuBA,eAAsB,sBACpB,KACA,aACA,QACA,aAAyB,aACL;AACpB,QAAM,cAAc,eAAe,WAAW;AAC9C,QAAM,yBAAqB,6CAAgC,WAAW;AAEtE,MAAI,CAAC,OAAO,gBAAgB;AAE1B,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;AAEA,SAAS,eAAe,aAA0B;AAChD,QAAM,CAAC,SAAS,IAAI,OAAO,OAAO,YAAY,UAAU;AACxD,aAAO,8BAAiB,EAAE,OAAO,SAAU;AAC7C;","names":["import_kit","import_kit","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 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":"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","names":["import_kit","import_kit","JitoApiUrl","request","response","data","import_kit"]}
|