@haven-fi/solauto-sdk 1.0.310 → 1.0.312

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.
Files changed (32) hide show
  1. package/dist/constants/solautoConstants.d.ts +1 -0
  2. package/dist/constants/solautoConstants.d.ts.map +1 -1
  3. package/dist/constants/solautoConstants.js +2 -7
  4. package/dist/transactions/transactionUtils.d.ts.map +1 -1
  5. package/dist/transactions/transactionUtils.js +4 -2
  6. package/dist/transactions/transactionsManager.d.ts +3 -1
  7. package/dist/transactions/transactionsManager.d.ts.map +1 -1
  8. package/dist/transactions/transactionsManager.js +35 -7
  9. package/dist/utils/jitoUtils.d.ts +5 -0
  10. package/dist/utils/jitoUtils.d.ts.map +1 -1
  11. package/dist/utils/jitoUtils.js +98 -151
  12. package/dist/utils/jupiterUtils.d.ts.map +1 -1
  13. package/dist/utils/jupiterUtils.js +0 -6
  14. package/dist/utils/priceUtils.d.ts +1 -6
  15. package/dist/utils/priceUtils.d.ts.map +1 -1
  16. package/dist/utils/priceUtils.js +3 -17
  17. package/dist/utils/solauto/generalUtils.d.ts +1 -1
  18. package/dist/utils/solauto/generalUtils.d.ts.map +1 -1
  19. package/dist/utils/solauto/generalUtils.js +10 -2
  20. package/dist/utils/switchboardUtils.d.ts +6 -0
  21. package/dist/utils/switchboardUtils.d.ts.map +1 -1
  22. package/dist/utils/switchboardUtils.js +27 -2
  23. package/package.json +2 -1
  24. package/src/constants/solautoConstants.ts +1 -6
  25. package/src/transactions/transactionUtils.ts +9 -3
  26. package/src/transactions/transactionsManager.ts +74 -7
  27. package/src/utils/jitoUtils.ts +166 -166
  28. package/src/utils/jupiterUtils.ts +0 -6
  29. package/src/utils/priceUtils.ts +5 -32
  30. package/src/utils/solauto/generalUtils.ts +23 -1
  31. package/src/utils/switchboardUtils.ts +58 -3
  32. package/tests/transactions/solautoMarginfi.ts +27 -26
@@ -1 +1 @@
1
- {"version":3,"file":"switchboardUtils.d.ts","sourceRoot":"","sources":["../../src/utils/switchboardUtils.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,UAAU,EACV,SAAS,EAGV,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAkB,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAEtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,MAAM,EAAsB,MAAM,0BAA0B,CAAC;AAMtE,wBAAgB,WAAW,CACzB,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,SAAS,EACf,MAAM,CAAC,EAAE,SAAS,YAsBnB;AAED,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAiB5C"}
1
+ {"version":3,"file":"switchboardUtils.d.ts","sourceRoot":"","sources":["../../src/utils/switchboardUtils.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,UAAU,EACV,SAAS,EAGV,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAkB,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAEtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,MAAM,EAAsB,MAAM,0BAA0B,CAAC;AAOtE,wBAAgB,WAAW,CACzB,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,SAAS,EACf,MAAM,CAAC,EAAE,SAAS,YAsBnB;AAED,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAsB5C;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,SAAS,EAAE,GACjB,OAAO,CAAC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,EAAE,CAAC,CAuB/D;AAED,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,SAAS,EAAE,GACjB,OAAO,CAAC,MAAM,EAAE,CAAC,CAiBnB"}
@@ -5,6 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.getPullFeed = getPullFeed;
7
7
  exports.buildSwbSubmitResponseTx = buildSwbSubmitResponseTx;
8
+ exports.getSwitchboardFeedData = getSwitchboardFeedData;
9
+ exports.getSwitchboardPrices = getSwitchboardPrices;
8
10
  const anchor_1 = require("@coral-xyz/anchor");
9
11
  const switchboard_json_1 = __importDefault(require("../idls/switchboard.json"));
10
12
  const web3_js_1 = require("@solana/web3.js");
@@ -12,6 +14,7 @@ const on_demand_1 = require("@switchboard-xyz/on-demand");
12
14
  const switchboardConstants_1 = require("../constants/switchboardConstants");
13
15
  const umi_1 = require("@metaplex-foundation/umi");
14
16
  const umi_web3js_adapters_1 = require("@metaplex-foundation/umi-web3js-adapters");
17
+ const generalUtils_1 = require("./generalUtils");
15
18
  function getPullFeed(conn, mint, wallet) {
16
19
  const dummyWallet = {
17
20
  publicKey: wallet ?? new web3_js_1.PublicKey("11111111111111111111111111111111"),
@@ -25,9 +28,9 @@ function getPullFeed(conn, mint, wallet) {
25
28
  async function buildSwbSubmitResponseTx(conn, signer, mint) {
26
29
  const crossbar = new on_demand_1.CrossbarClient("https://crossbar.switchboard.xyz");
27
30
  const feed = getPullFeed(conn, mint, (0, umi_web3js_adapters_1.toWeb3JsPublicKey)(signer.publicKey));
28
- const [pullIx, responses] = await feed.fetchUpdateIx({
31
+ const [pullIx, responses] = await (0, generalUtils_1.retryWithExponentialBackoff)(async () => await feed.fetchUpdateIx({
29
32
  crossbarClient: crossbar,
30
- });
33
+ }), 8, 200);
31
34
  return {
32
35
  tx: (0, umi_1.transactionBuilder)().add({
33
36
  bytesCreatedOnChain: 0,
@@ -39,3 +42,25 @@ async function buildSwbSubmitResponseTx(conn, signer, mint) {
39
42
  .map((x) => x.oracle.lut.key.toString()),
40
43
  };
41
44
  }
45
+ async function getSwitchboardFeedData(conn, mints) {
46
+ if (mints.length === 0) {
47
+ return [];
48
+ }
49
+ const currSlot = await (0, generalUtils_1.retryWithExponentialBackoff)(async () => await conn.getSlot("confirmed"), 5);
50
+ const results = await Promise.all(mints.map(async (mint) => {
51
+ const feed = getPullFeed(conn, mint);
52
+ const result = await feed.loadData();
53
+ const price = Number(result.result.value) / Math.pow(10, 18);
54
+ const stale = currSlot > result.result.slot.toNumber() + result.maxStaleness;
55
+ return { mint, price, stale };
56
+ }));
57
+ return results;
58
+ }
59
+ async function getSwitchboardPrices(mints) {
60
+ if (mints.length === 0) {
61
+ return [];
62
+ }
63
+ const crossbar = new on_demand_1.CrossbarClient("https://crossbar.switchboard.xyz");
64
+ const results = await (0, generalUtils_1.retryWithExponentialBackoff)(async () => await crossbar.simulateSolanaFeeds("mainnet", mints.map((x) => switchboardConstants_1.SWITCHBOARD_PRICE_FEED_IDS[x.toString()])), 8, 200);
65
+ return results.flatMap((x) => x.results[0]);
66
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haven-fi/solauto-sdk",
3
- "version": "1.0.310",
3
+ "version": "1.0.312",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "description": "Typescript SDK for the Solauto program on the Solana blockchain",
@@ -26,6 +26,7 @@
26
26
  "@solana/spl-token": "^0.4.0",
27
27
  "@solana/web3.js": "^1.95.4",
28
28
  "@switchboard-xyz/on-demand": "^1.2.51",
29
+ "axios": "^1.7.8",
29
30
  "bs58": "^5.0.0",
30
31
  "cross-fetch": "^4.0.0",
31
32
  "rpc-websockets": "7.11.0"
@@ -9,7 +9,6 @@ import {
9
9
  ASSOCIATED_TOKEN_PROGRAM_ID,
10
10
  TOKEN_PROGRAM_ID,
11
11
  } from "@solana/spl-token";
12
- // import { JitoRpcConnection } from "jito-ts";
13
12
  import { SOLAUTO_MANAGER } from "./generalAccounts";
14
13
  import { JUPITER_PROGRAM_ID } from "../jupiter-sdk";
15
14
 
@@ -46,8 +45,4 @@ export const STANDARD_LUT_ACCOUNTS = [
46
45
  JUPITER_PROGRAM_ID,
47
46
  ].map((x) => x.toString());
48
47
 
49
- // export const JITO_BLOCK_ENGINE = "ny.mainnet.block-engine.jito.wtf";
50
- // export const JITO_CONNECTION = new JitoRpcConnection(
51
- // `https://${JITO_BLOCK_ENGINE}`,
52
- // "finalized"
53
- // );
48
+ export const JITO_BLOCK_ENGINE = "https://mainnet.block-engine.jito.wtf";
@@ -646,6 +646,9 @@ export async function buildSolautoRebalanceTransaction(
646
646
  attemptNum?: number
647
647
  ): Promise<TransactionItemInputs | undefined> {
648
648
  client.solautoPositionState = await client.getFreshPositionState();
649
+ const supplyPrice = safeGetPrice(client.supplyMint) ?? 0;
650
+ const debtPrice = safeGetPrice(client.debtMint) ?? 0;
651
+
649
652
  if (
650
653
  (client.solautoPositionState?.supply.amountUsed.baseUnit === BigInt(0) &&
651
654
  client.livePositionUpdates.supplyAdjustment === BigInt(0)) ||
@@ -654,7 +657,10 @@ export async function buildSolautoRebalanceTransaction(
654
657
  client.solautoPositionState!,
655
658
  client.solautoPositionSettings(),
656
659
  client.solautoPositionActiveDca(),
657
- currentUnixSeconds()
660
+ currentUnixSeconds(),
661
+ supplyPrice,
662
+ debtPrice,
663
+ 0
658
664
  ))
659
665
  ) {
660
666
  client.log("Not eligible for a rebalance");
@@ -666,8 +672,8 @@ export async function buildSolautoRebalanceTransaction(
666
672
  client.solautoPositionSettings(),
667
673
  client.solautoPositionActiveDca(),
668
674
  currentUnixSeconds(),
669
- safeGetPrice(client.supplyMint)!,
670
- safeGetPrice(client.debtMint)!,
675
+ supplyPrice,
676
+ debtPrice,
671
677
  targetLiqUtilizationRateBps
672
678
  );
673
679
  client.log("Rebalance values: ", values);
@@ -28,8 +28,8 @@ import {
28
28
  TransactionExpiredBlockheightExceededError,
29
29
  } from "@solana/web3.js";
30
30
  import { SWITCHBOARD_PRICE_FEED_IDS } from "../constants/switchboardConstants";
31
- import { buildSwbSubmitResponseTx, getSwitchboardPrices } from "../utils";
32
- // import { sendJitoBundledTransactions } from "../utils/jitoUtils";
31
+ import { buildSwbSubmitResponseTx, getSwitchboardFeedData } from "../utils";
32
+ import { sendJitoBundledTransactions } from "../utils/jitoUtils";
33
33
 
34
34
  const CHORES_TX_NAME = "account chores";
35
35
 
@@ -220,6 +220,7 @@ export class TransactionsManager {
220
220
  private statusCallback?: (statuses: TransactionManagerStatuses) => void,
221
221
  private txType?: TransactionRunType,
222
222
  private priorityFeeSetting: PriorityFeeSetting = PriorityFeeSetting.Min,
223
+ private atomically: boolean = false,
223
224
  private errorsToThrow?: ErrorsToThrow,
224
225
  private retries: number = 4,
225
226
  private retryDelay: number = 150
@@ -404,7 +405,7 @@ export class TransactionsManager {
404
405
  (x) => SWITCHBOARD_PRICE_FEED_IDS[x] === swbOracle
405
406
  )!
406
407
  );
407
- const stale = (await getSwitchboardPrices(client.connection, [mint]))[0]
408
+ const stale = (await getSwitchboardFeedData(client.connection, [mint]))[0]
408
409
  .stale;
409
410
 
410
411
  if (stale) {
@@ -489,15 +490,81 @@ export class TransactionsManager {
489
490
  return [];
490
491
  }
491
492
 
492
- let currentIndex = 0;
493
- while (currentIndex < itemSets.length) {
494
- await this.processTransactionSet(itemSets, currentIndex);
495
- currentIndex++;
493
+ if (itemSets.length > 1 && this.atomically) {
494
+ await this.processTransactionsAtomically(itemSets);
495
+ } else {
496
+ let currentIndex = 0;
497
+ while (currentIndex < itemSets.length) {
498
+ await this.processTransactionSet(itemSets, currentIndex);
499
+ currentIndex++;
500
+ }
496
501
  }
497
502
 
498
503
  return this.statuses;
499
504
  }
500
505
 
506
+ private async processTransactionsAtomically(itemSets: TransactionSet[]) {
507
+ let num = 0;
508
+
509
+ await retryWithExponentialBackoff(
510
+ async (attemptNum) => {
511
+ num = attemptNum;
512
+
513
+ let transactions = [];
514
+ for (const set of itemSets) {
515
+ transactions.push(await set.getSingleTransaction());
516
+ }
517
+
518
+ itemSets.forEach((x) =>
519
+ this.updateStatus(x.name(), TransactionStatus.Processing, attemptNum)
520
+ );
521
+ const txSigs = await sendJitoBundledTransactions(
522
+ this.txHandler.umi,
523
+ this.txHandler.signer,
524
+ transactions,
525
+ false,
526
+ this.priorityFeeSetting
527
+ );
528
+ if (txSigs) {
529
+ itemSets.forEach((x, i) =>
530
+ this.updateStatus(
531
+ x.name(),
532
+ TransactionStatus.Successful,
533
+ attemptNum,
534
+ txSigs[i]
535
+ )
536
+ );
537
+ } else {
538
+ itemSets.forEach((x) =>
539
+ this.updateStatus(
540
+ x.name(),
541
+ TransactionStatus.Failed,
542
+ attemptNum,
543
+ undefined,
544
+ true
545
+ )
546
+ );
547
+ throw new Error("Unknown error");
548
+ }
549
+ },
550
+ this.retries,
551
+ this.retryDelay,
552
+ this.errorsToThrow
553
+ ).catch((e: Error) => {
554
+ itemSets.forEach((x) =>
555
+ this.updateStatus(
556
+ x.name(),
557
+ TransactionStatus.Failed,
558
+ num,
559
+ undefined,
560
+ true,
561
+ e.message
562
+ )
563
+ );
564
+ throw e;
565
+ });
566
+ }
567
+
501
568
  private async processTransactionSet(
502
569
  itemSets: TransactionSet[],
503
570
  currentIndex: number
@@ -1,68 +1,47 @@
1
- // import { SolautoClient } from "../clients/solautoClient";
2
- // import { Keypair, PublicKey, VersionedTransaction } from "@solana/web3.js";
3
- // import { SimulatedBundleTransactionResult } from "jito-ts";
4
- // import { toWeb3JsTransaction } from "@metaplex-foundation/umi-web3js-adapters";
5
- // import {
6
- // JITO_BLOCK_ENGINE,
7
- // JITO_CONNECTION,
8
- // UMI,
9
- // } from "../constants/solautoConstants";
10
- // import {
11
- // Signer,
12
- // TransactionBuilder,
13
- // WrappedInstruction,
14
- // } from "@metaplex-foundation/umi";
15
- // import {
16
- // assembleFinalTransaction,
17
- // getComputeUnitPriceEstimate,
18
- // getSecretKey,
19
- // systemTransferUmiIx,
20
- // } from "./solanaUtils";
21
- // import { Bundle } from "jito-ts/dist/sdk/block-engine/types";
22
- // import {
23
- // SearcherClient,
24
- // searcherClient,
25
- // } from "jito-ts/dist/sdk/block-engine/searcher";
26
- // import { BundleResult } from "jito-ts/dist/gen/block-engine/bundle";
27
-
28
- // export function getSearcherClient(): SearcherClient {
29
- // return searcherClient(
30
- // JITO_BLOCK_ENGINE,
31
- // Keypair.fromSecretKey(getSecretKey("jito-bundles"))
32
- // );
33
- // }
34
-
35
- // export async function getRandomTipAccount(): Promise<PublicKey> {
36
- // const tipAccounts = await getSearcherClient().getTipAccounts();
37
- // const randomInt = Math.floor(Math.random() * tipAccounts.length);
38
- // return new PublicKey(tipAccounts[randomInt]);
39
- // }
40
-
41
- // export async function waitUntilJitoNextLeader(
42
- // distanceFromJitoSlot: number = 5
43
- // ) {
44
- // let searcher = getSearcherClient();
45
- // let isLeaderSlot = false;
46
-
47
- // while (!isLeaderSlot) {
48
- // const nextLeader = await searcher.getNextScheduledLeader();
49
- // const numSlots = nextLeader.nextLeaderSlot - nextLeader.currentSlot;
50
- // isLeaderSlot = numSlots <= distanceFromJitoSlot && numSlots > 1;
51
- // consoleLog(`Next jito leader slot in ${numSlots} slots`);
52
- // await new Promise((r) => setTimeout(r, 500));
53
- // }
54
- // }
55
-
56
- // async function getTipInstruction(
57
- // client: SolautoClient,
58
- // tipLamports: number
59
- // ): Promise<WrappedInstruction> {
60
- // return systemTransferUmiIx(
61
- // client.signer,
62
- // await getRandomTipAccount(),
63
- // BigInt(tipLamports)
64
- // );
65
- // }
1
+ import { PublicKey, VersionedTransaction } from "@solana/web3.js";
2
+ import { toWeb3JsTransaction } from "@metaplex-foundation/umi-web3js-adapters";
3
+ import { JITO_BLOCK_ENGINE } from "../constants/solautoConstants";
4
+ import {
5
+ Signer,
6
+ TransactionBuilder,
7
+ Umi,
8
+ WrappedInstruction,
9
+ } from "@metaplex-foundation/umi";
10
+ import {
11
+ assembleFinalTransaction,
12
+ getComputeUnitPriceEstimate,
13
+ systemTransferUmiIx,
14
+ } from "./solanaUtils";
15
+ import { consoleLog } from "./generalUtils";
16
+ import { PriorityFeeSetting } from "../types";
17
+ import axios from "axios";
18
+ import base58 from "bs58";
19
+
20
+ export async function getRandomTipAccount(): Promise<PublicKey> {
21
+ const tipAccounts = [
22
+ "96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5",
23
+ "HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe",
24
+ "Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY",
25
+ "ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49",
26
+ "DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh",
27
+ "ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt",
28
+ "DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL",
29
+ "3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT",
30
+ ];
31
+ const randomInt = Math.floor(Math.random() * tipAccounts.length);
32
+ return new PublicKey(tipAccounts[randomInt]);
33
+ }
34
+
35
+ async function getTipInstruction(
36
+ signer: Signer,
37
+ tipLamports: number
38
+ ): Promise<WrappedInstruction> {
39
+ return systemTransferUmiIx(
40
+ signer,
41
+ await getRandomTipAccount(),
42
+ BigInt(tipLamports)
43
+ );
44
+ }
66
45
 
67
46
  // async function simulateJitoBundle(
68
47
  // txs: VersionedTransaction[]
@@ -85,104 +64,125 @@
85
64
  // return simulationResult.value.transactionResults;
86
65
  // }
87
66
 
88
- // async function umiToVersionedTransactions(
89
- // signer: Signer,
90
- // txs: TransactionBuilder[],
91
- // feeEstimates: number[],
92
- // computeUnitLimits?: number[]
93
- // ): Promise<VersionedTransaction[]> {
94
- // return await Promise.all(
95
- // txs.map(async (tx, i) => {
96
- // const versionedTx = toWeb3JsTransaction(
97
- // await (
98
- // await assembleFinalTransaction(
99
- // signer,
100
- // tx,
101
- // feeEstimates[i],
102
- // computeUnitLimits ? computeUnitLimits[i] : undefined
103
- // ).setLatestBlockhash(UMI)
104
- // ).buildAndSign(UMI)
105
- // );
106
- // return versionedTx;
107
- // })
108
- // );
109
- // }
110
-
111
- // async function sendJitoBundle(bundle: Bundle): Promise<BundleResult> {
112
- // await waitUntilJitoNextLeader();
113
- // let searcher = getSearcherClient();
114
-
115
- // consoleLog("Sending bundle...");
116
- // try {
117
- // const resp = await searcher.sendBundle(bundle);
118
- // consoleLog("Send bundle response:", resp);
119
- // } catch (e) {
120
- // console.error("Error sending bundle:", e);
121
- // }
122
-
123
- // return await new Promise((resolve, reject) => {
124
- // searcher.onBundleResult(
125
- // (res) => {
126
- // if (res.accepted || res.processed || res.finalized) {
127
- // resolve(res);
128
- // } else {
129
- // consoleLog(res);
130
- // return reject("Bundle not accepted");
131
- // }
132
- // },
133
- // (err) => {
134
- // consoleLog("Error: ", err);
135
- // return reject(err);
136
- // }
137
- // );
138
- // });
139
- // }
140
-
141
- // interface JitoTransactionsResult {
142
- // bundleResult: BundleResult;
143
- // txSigs: Uint8Array[];
144
- // }
145
-
146
- // export async function sendJitoBundledTransactions(
147
- // client: SolautoClient,
148
- // txs: TransactionBuilder[],
149
- // simulateOnly?: boolean
150
- // ): Promise<JitoTransactionsResult | undefined> {
151
- // client.log("Sending Jito bundle...");
152
- // client.log("Transactions: ", txs.length);
153
- // client.log(
154
- // "Transaction sizes: ",
155
- // txs.map((x) => x.getTransactionSize(UMI))
156
- // );
157
-
158
- // txs[0] = txs[0].prepend(await getTipInstruction(client, 1000000));
159
- // const feeEstimates = await Promise.all(txs.map(getComputeUnitPriceEstimate));
160
-
161
- // let builtTxs = await umiToVersionedTransactions(
162
- // client.signer,
163
- // txs,
164
- // feeEstimates,
165
- // // Array(txs.length).fill(1_400_000)
166
- // );
167
- // // // TODO: Skip over this for now, and instead don't specify a compute unit limit in the final bundle transactions
168
- // // const simulationResults = await simulateJitoBundle(builtTxs);
169
-
170
- // if (!simulateOnly) {
171
- // // let builtTxs = await umiToVersionedTransactions(
172
- // // client.signer,
173
- // // txs,
174
- // // feeEstimates,
175
- // // simulationResults.map((x) => x.unitsConsumed! * 1.15)
176
- // // );
177
-
178
- // const bundleResult = await sendJitoBundle(
179
- // new Bundle(builtTxs, 100)
180
- // );
181
- // return {
182
- // bundleResult,
183
- // txSigs: builtTxs.map((x) => x.signatures).flat(),
184
- // };
185
- // }
186
-
187
- // return undefined;
188
- // }
67
+ async function umiToVersionedTransactions(
68
+ umi: Umi,
69
+ signer: Signer,
70
+ txs: TransactionBuilder[],
71
+ feeEstimates: number[],
72
+ computeUnitLimits?: number[]
73
+ ): Promise<VersionedTransaction[]> {
74
+ return await Promise.all(
75
+ txs.map(async (tx, i) => {
76
+ const versionedTx = toWeb3JsTransaction(
77
+ await (
78
+ await assembleFinalTransaction(
79
+ signer,
80
+ tx,
81
+ feeEstimates[i],
82
+ computeUnitLimits ? computeUnitLimits[i] : undefined
83
+ ).setLatestBlockhash(umi)
84
+ ).buildAndSign(umi)
85
+ );
86
+ return versionedTx;
87
+ })
88
+ );
89
+ }
90
+
91
+ async function getBundleStatus(bundleId: string) {
92
+ const res = await axios.post(`${JITO_BLOCK_ENGINE}/api/v1/bundles`, {
93
+ jsonrpc: "2.0",
94
+ id: 1,
95
+ method: "getBundleStatuses",
96
+ params: [[bundleId]],
97
+ });
98
+ if (res.data.error) {
99
+ throw new Error(`Failed to get bundle status: ${res.data.error}`);
100
+ }
101
+
102
+ return res.data.result;
103
+ }
104
+
105
+ async function pollBundleStatus(
106
+ bundleId: string,
107
+ interval = 1000,
108
+ timeout = 40000
109
+ ): Promise<string[]> {
110
+ const endTime = Date.now() + timeout;
111
+ while (Date.now() < endTime) {
112
+ await new Promise((resolve) => setTimeout(resolve, interval));
113
+ const statuses = await getBundleStatus(bundleId);
114
+ if (statuses?.value?.length > 0) {
115
+ const status = statuses.value[0].confirmation_status;
116
+ if (status === "confirmed") {
117
+ return statuses?.value[0].transactions as string[];
118
+ }
119
+ }
120
+ }
121
+ return [];
122
+ }
123
+
124
+ async function sendJitoBundle(transactions: string[]): Promise<string[]> {
125
+ consoleLog("Sending bundle...");
126
+ const resp = await axios.post<{ result: string }>(
127
+ `${JITO_BLOCK_ENGINE}/api/v1/bundles`,
128
+ {
129
+ jsonrpc: "2.0",
130
+ id: 1,
131
+ method: "sendBundle",
132
+ params: [transactions],
133
+ }
134
+ );
135
+
136
+ const bundleId = resp.data.result;
137
+ return await pollBundleStatus(bundleId);
138
+ }
139
+
140
+ export async function sendJitoBundledTransactions(
141
+ umi: Umi,
142
+ signer: Signer,
143
+ txs: TransactionBuilder[],
144
+ simulateOnly?: boolean,
145
+ priorityFeeSetting: PriorityFeeSetting = PriorityFeeSetting.Min
146
+ ): Promise<string[] | undefined> {
147
+ consoleLog("Sending Jito bundle...");
148
+ consoleLog("Transactions: ", txs.length);
149
+ consoleLog(
150
+ "Transaction sizes: ",
151
+ txs.map((x) => x.getTransactionSize(umi))
152
+ );
153
+
154
+ txs[0] = txs[0].prepend(await getTipInstruction(signer, 150_000));
155
+ const feeEstimates = await Promise.all(
156
+ txs.map(
157
+ async (x) =>
158
+ (await getComputeUnitPriceEstimate(umi, x, priorityFeeSetting)) ??
159
+ 1000000
160
+ )
161
+ );
162
+
163
+ let builtTxs = await umiToVersionedTransactions(
164
+ umi,
165
+ signer,
166
+ txs,
167
+ feeEstimates
168
+ // Array(txs.length).fill(1_400_000)
169
+ );
170
+ // // TODO: Skip over this for now, and instead don't specify a compute unit limit in the final bundle transactions
171
+ // const simulationResults = await simulateJitoBundle(builtTxs);
172
+
173
+ if (!simulateOnly) {
174
+ // let builtTxs = await umiToVersionedTransactions(
175
+ // client.signer,
176
+ // txs,
177
+ // feeEstimates,
178
+ // simulationResults.map((x) => x.unitsConsumed! * 1.15)
179
+ // );
180
+
181
+ const txSigs = await sendJitoBundle(
182
+ builtTxs.map((x) => base58.encode(x.serialize()))
183
+ );
184
+ return txSigs.length > 0 ? txSigs : undefined;
185
+ }
186
+
187
+ return undefined;
188
+ }
@@ -94,12 +94,6 @@ export async function getJupSwapTransaction(
94
94
  )
95
95
  ).toString();
96
96
  }
97
- // else {
98
- // quoteResponse.inAmount = (
99
- // parseInt(quoteResponse.inAmount) +
100
- // Math.ceil(parseInt(quoteResponse.inAmount) * fromBps(priceImpactBps))
101
- // ).toString();
102
- // }
103
97
 
104
98
  consoleLog("Getting jup instructions...");
105
99
  const instructions = await retryWithExponentialBackoff(