Skip to content

Commit

Permalink
fix: arena improvements & better cu limit for flashloans
Browse files Browse the repository at this point in the history
  • Loading branch information
k0beLeenders committed Nov 25, 2024
1 parent 618a5cc commit 634b679
Show file tree
Hide file tree
Showing 12 changed files with 175 additions and 180 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Image from "next/image";
import { IconMinus, IconX, IconPlus, IconLoader2 } from "@tabler/icons-react";
import { Transaction, VersionedTransaction } from "@solana/web3.js";

import { MultiStepToastHandle, cn, extractErrorString, capture, fetchPriorityFee } from "@mrgnlabs/mrgn-utils";
import { MultiStepToastHandle, cn, extractErrorString, capture, ClosePositionActionTxns } from "@mrgnlabs/mrgn-utils";
import { ActiveBankInfo, ActionType } from "@mrgnlabs/marginfi-v2-ui-state";

import { useConnection } from "~/hooks/use-connection";
Expand Down Expand Up @@ -41,11 +41,8 @@ export const PositionActionButtons = ({
const { connection } = useConnection();
const { wallet, connected } = useWallet();
const [platformFeeBps] = useUiStore((state) => [state.platformFeeBps]);
const [actionTransaction, setActionTransaction] = React.useState<{
closeTxn: VersionedTransaction | Transaction;
feedCrankTxs: VersionedTransaction[];
quote?: QuoteResponse;
} | null>(null);
const [actionTransaction, setActionTransaction] = React.useState<ClosePositionActionTxns | null>(null);

const [isLoading, setIsLoading] = React.useState(false);
const [multiStepToast, setMultiStepToast] = React.useState<MultiStepToastHandle | null>(null);
const [isClosing, setIsClosing] = React.useState(false);
Expand All @@ -56,16 +53,13 @@ export const PositionActionButtons = ({
state.setIsRefreshingStore,
state.nativeSolBalance,
]);
const [slippageBps, priorityType, broadcastType, maxCap, maxCapType, setIsActionComplete, setPreviousTxn] =
useUiStore((state) => [
state.slippageBps,
state.priorityType,
state.broadcastType,
state.maxCap,
state.maxCapType,
state.setIsActionComplete,
state.setPreviousTxn,
]);
const [slippageBps, priorityFees, broadcastType, setIsActionComplete, setPreviousTxn] = useUiStore((state) => [
state.slippageBps,
state.priorityFees,
state.broadcastType,
state.setIsActionComplete,
state.setPreviousTxn,
]);

const depositBanks = React.useMemo(() => {
const tokenBank = activeGroup.pool.token.isActive ? activeGroup.pool.token : null;
Expand Down Expand Up @@ -107,21 +101,18 @@ export const PositionActionButtons = ({
throw new Error("Invalid client");
}

const priorityFees = await fetchPriorityFee(maxCapType, maxCap, broadcastType, priorityType, connection);

const txns = await calculateClosePositions({
marginfiAccount: activeGroup.selectedAccount,
depositBanks: depositBanks,
borrowBank: borrowBank,
slippageBps,
connection: connection,
priorityFees,
platformFeeBps,
});

if ("description" in txns) {
throw new Error(txns?.description ?? "Something went wrong.");
} else if ("closeTxn" in txns) {
} else if ("actionTxn" in txns) {
setActionTransaction(txns);
}
} catch (error: any) {
Expand All @@ -134,38 +125,19 @@ export const PositionActionButtons = ({
setMultiStepToast(multiStepToast);
}
setIsClosing(false);
}, [
activeGroup,
borrowBank,
depositBanks,
maxCapType,
maxCap,
broadcastType,
priorityType,
connection,
slippageBps,
platformFeeBps,
]);
}, [activeGroup, borrowBank, depositBanks, connection, slippageBps, platformFeeBps]);

const processTransaction = React.useCallback(async () => {
try {
setIsLoading(true);
let txnSig: string | string[] = "";

if (!actionTransaction || !multiStepToast) throw new Error("Action not ready");
if (actionTransaction.closeTxn instanceof Transaction) {
txnSig = await activeGroup.client.processTransaction(actionTransaction.closeTxn, {
broadcastType: broadcastType,
});
multiStepToast.setSuccessAndNext();
} else {
const priorityFees = await fetchPriorityFee(maxCapType, maxCap, broadcastType, priorityType, connection);
txnSig = await activeGroup.client.processTransactions(
[...actionTransaction.feedCrankTxs, actionTransaction.closeTxn],
{ broadcastType: broadcastType, ...priorityFees }
);
multiStepToast.setSuccessAndNext();
}
if (!actionTransaction?.actionTxn || !multiStepToast) throw new Error("Action not ready");
txnSig = await activeGroup.client.processTransactions(
[...actionTransaction.additionalTxns, actionTransaction.actionTxn],
{ broadcastType: broadcastType, ...priorityFees }
);
multiStepToast.setSuccessAndNext();

if (txnSig) {
setActionTransaction(null);
Expand Down Expand Up @@ -220,14 +192,12 @@ export const PositionActionButtons = ({
activeGroup.pool.quoteTokens,
activeGroup?.groupPk,
broadcastType,
maxCapType,
maxCap,
priorityType,
connection,
priorityFees,
setIsActionComplete,
setPreviousTxn,
setIsRefreshingStore,
refreshGroup,
connection,
wallet,
]);

Expand Down Expand Up @@ -431,40 +401,43 @@ export const PositionActionButtons = ({
</>
)}

{actionTransaction?.quote?.priceImpactPct && (
{actionTransaction?.actionQuote?.priceImpactPct && (
<>
<dt>Price impact</dt>
<dd
className={cn(
Number(actionTransaction.quote.priceImpactPct) > 0.05
Number(actionTransaction.actionQuote.priceImpactPct) > 0.05
? "text-mrgn-error"
: Number(actionTransaction.quote.priceImpactPct) > 0.01
: Number(actionTransaction.actionQuote.priceImpactPct) > 0.01
? "text-alert-foreground"
: "text-mrgn-success",
"text-right"
)}
>
{percentFormatter.format(Number(actionTransaction.quote.priceImpactPct))}
{percentFormatter.format(Number(actionTransaction.actionQuote.priceImpactPct))}
</dd>
</>
)}

{actionTransaction?.quote?.slippageBps && (
{actionTransaction?.actionQuote?.slippageBps && (
<>
<dt>Slippage</dt>
<dd
className={cn(actionTransaction.quote.slippageBps > 500 && "text-alert-foreground", "text-right")}
className={cn(
actionTransaction.actionQuote.slippageBps > 500 && "text-alert-foreground",
"text-right"
)}
>
{percentFormatter.format(Number(actionTransaction.quote.slippageBps) / 10000)}
{percentFormatter.format(Number(actionTransaction.actionQuote.slippageBps) / 10000)}
</dd>
</>
)}

<dt>Platform fee</dt>
{actionTransaction?.quote?.platformFee?.feeBps && (
{actionTransaction?.actionQuote?.platformFee?.feeBps && (
<>
<dd className="text-right">
{percentFormatter.format(actionTransaction.quote.platformFee.feeBps / 10000)}
{percentFormatter.format(actionTransaction.actionQuote.platformFee.feeBps / 10000)}
</dd>
</>
)}
Expand Down
3 changes: 2 additions & 1 deletion apps/marginfi-v2-trading/src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { ToastContainer } from "react-toastify";
import { Analytics } from "@vercel/analytics/react";
import { BankMetadataRaw } from "@mrgnlabs/mrgn-common";
import { DEFAULT_MAX_CAP, Desktop, Mobile, init as initAnalytics } from "@mrgnlabs/mrgn-utils";
import { ActionProvider, AuthDialog } from "@mrgnlabs/mrgn-ui";
import { ActionProvider } from "~/components/action-box-v2";
import { generateEndpoint } from "~/rpc.utils";

import config from "~/config";
Expand All @@ -30,6 +30,7 @@ import { Header } from "~/components/common/Header";
import { Footer } from "~/components/desktop/Footer";

import "react-toastify/dist/ReactToastify.min.css";
import { AuthDialog } from "~/components/wallet-v2";

require("~/styles/globals.css");
require("~/styles/fonts.css");
Expand Down
44 changes: 44 additions & 0 deletions apps/marginfi-v2-trading/src/pages/api/priorityFees.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { getCalculatedPrioritizationFeeByPercentile } from "@mrgnlabs/mrgn-common";
import { Connection } from "@solana/web3.js";
import { NextApiRequest, NextApiResponse } from "next";

const enum PriotitizationFeeLevels {
LOW = 2500,
MEDIAN = 5000,
HIGH = 7500,
MAX = 10000,
}
/*
Get jito tip data for at least 50 percentile result
*/
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
// use abort controller to restrict fetch to 5 seconds
const controller = new AbortController();
const timeoutId = setTimeout(() => {
controller.abort();
}, 5000);

const connection = new Connection(process.env.PRIVATE_RPC_ENDPOINT_OVERRIDE || "");

// Fetch from API and update cache
try {
const data = await getCalculatedPrioritizationFeeByPercentile(
connection,
{
lockedWritableAccounts: [], // TODO: investigate this
percentile: PriotitizationFeeLevels.HIGH,
fallback: false,
},
20
);

clearTimeout(timeoutId);

// cache for 4 minutes
res.setHeader("Cache-Control", "s-maxage=30, stale-while-revalidate=59");
res.status(200).json(data);
} catch (error) {
console.error("Error:", error);
res.status(500).json({ error: "Error fetching data" });
}
}
22 changes: 7 additions & 15 deletions apps/marginfi-v2-trading/src/utils/tradingActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
STATIC_SIMULATION_ERRORS,
extractErrorString,
LoopActionTxns,
ClosePositionActionTxns,
} from "@mrgnlabs/mrgn-utils";
import { ExtendedBankInfo, clearAccountCache, ActiveBankInfo } from "@mrgnlabs/marginfi-v2-ui-state";

Expand Down Expand Up @@ -301,33 +302,23 @@ export async function calculateClosePositions({
depositBanks,
slippageBps,
connection,
priorityFees,
platformFeeBps,
}: {
marginfiAccount: MarginfiAccountWrapper;
borrowBank: ActiveBankInfo | null;
depositBanks: ActiveBankInfo[];
slippageBps: number;
connection: Connection;
priorityFees: PriorityFees;
platformFeeBps?: number;
}): Promise<
| {
closeTxn: VersionedTransaction | Transaction;
feedCrankTxs: VersionedTransaction[];
quote?: QuoteResponse;
}
| ActionMessageType
> {
platformFeeBps: number;
}): Promise<ClosePositionActionTxns | ActionMessageType> {
// user is borrowing and depositing
if (borrowBank && depositBanks.length === 1) {
return calculateBorrowLendPositionParams({
marginfiAccount,
borrowBank,
depositBank: depositBanks[0],
slippageBps,
connection,
priorityFees,
slippageBps,
platformFeeBps,
});
}
Expand All @@ -341,8 +332,9 @@ export async function calculateClosePositions({
}))
);
return {
closeTxn: txn,
feedCrankTxs: [],
actionTxn: txn,
additionalTxns: [],
actionQuote: null,
};
}

Expand Down
10 changes: 8 additions & 2 deletions packages/marginfi-client-v2/src/models/account/wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,10 @@ class MarginfiAccountWrapper {

// creates atas if needed
const setupIxs = await this.makeSetupIx([borrowBankAddress, depositBankAddress]);
const cuRequestIxs = this.makeComputeBudgetIx();
const cuRequestIxs =
this.makeComputeBudgetIx().length > 0
? this.makeComputeBudgetIx()
: [ComputeBudgetProgram.setComputeUnitLimit({ units: 500_000 })];
// tiny priority fee just in case bundle fails
const [priorityFeeIx] = makePriorityFeeIx(0.00001);
const withdrawIxs = await this.makeWithdrawIx(
Expand Down Expand Up @@ -587,7 +590,10 @@ class MarginfiAccountWrapper {

// creates atas if needed
const setupIxs = await this.makeSetupIx([borrowBankAddress, depositBankAddress]);
const cuRequestIxs = this.makeComputeBudgetIx();
const cuRequestIxs =
this.makeComputeBudgetIx().length > 0
? this.makeComputeBudgetIx()
: [ComputeBudgetProgram.setComputeUnitLimit({ units: 500_000 })];
// tiny priority fee just in case bundle fails
const [priorityFeeIx] = makePriorityFeeIx(0.00001);
const borrowIxs = await this.makeBorrowIx(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export function formatTransactions(

transactions.forEach((tx, idx) => {
const cu = tx.unitsConsumed ? Math.min(tx.unitsConsumed + 50_000, 1_400_000) : getComputeBudgetUnits(tx);

const priorityFeeUi = microLamportsToUi(priorityFeeMicro, cu);

let updatedFees = priorityFeeMicro;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,6 @@ export function replaceV0TxInstructions(
const updatedCuLimitIx = additionalIxs.find(
(a) => decodeComputeBudgetInstruction(a).instructionType === "SetComputeUnitLimit"
);

// replace priority fee instruction
if (decoded.instructionType === "SetComputeUnitPrice" && updatedCuPriceIx) {
//subtract the additional instruction from the additional instructions array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,9 @@ export const ActionProvider: React.FC<ActionContextType & { children: React.Reac

export const useActionContext = () => {
const context = React.useContext(ActionContext);

if (!context) {
console.warn("useActionContext called outside provider or with null context");
}
return context;
};
Loading

0 comments on commit 634b679

Please sign in to comment.