@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.
- package/dist/constants/solautoConstants.d.ts +1 -0
- package/dist/constants/solautoConstants.d.ts.map +1 -1
- package/dist/constants/solautoConstants.js +2 -7
- package/dist/transactions/transactionUtils.d.ts.map +1 -1
- package/dist/transactions/transactionUtils.js +4 -2
- package/dist/transactions/transactionsManager.d.ts +3 -1
- package/dist/transactions/transactionsManager.d.ts.map +1 -1
- package/dist/transactions/transactionsManager.js +35 -7
- package/dist/utils/jitoUtils.d.ts +5 -0
- package/dist/utils/jitoUtils.d.ts.map +1 -1
- package/dist/utils/jitoUtils.js +98 -151
- package/dist/utils/jupiterUtils.d.ts.map +1 -1
- package/dist/utils/jupiterUtils.js +0 -6
- package/dist/utils/priceUtils.d.ts +1 -6
- package/dist/utils/priceUtils.d.ts.map +1 -1
- package/dist/utils/priceUtils.js +3 -17
- package/dist/utils/solauto/generalUtils.d.ts +1 -1
- package/dist/utils/solauto/generalUtils.d.ts.map +1 -1
- package/dist/utils/solauto/generalUtils.js +10 -2
- package/dist/utils/switchboardUtils.d.ts +6 -0
- package/dist/utils/switchboardUtils.d.ts.map +1 -1
- package/dist/utils/switchboardUtils.js +27 -2
- package/package.json +2 -1
- package/src/constants/solautoConstants.ts +1 -6
- package/src/transactions/transactionUtils.ts +9 -3
- package/src/transactions/transactionsManager.ts +74 -7
- package/src/utils/jitoUtils.ts +166 -166
- package/src/utils/jupiterUtils.ts +0 -6
- package/src/utils/priceUtils.ts +5 -32
- package/src/utils/solauto/generalUtils.ts +23 -1
- package/src/utils/switchboardUtils.ts +58 -3
- 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;
|
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.
|
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
|
-
|
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
|
-
|
670
|
-
|
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,
|
32
|
-
|
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
|
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
|
-
|
493
|
-
|
494
|
-
|
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
|
package/src/utils/jitoUtils.ts
CHANGED
@@ -1,68 +1,47 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
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(
|