-
-
-
- You need to hold {activeGroup?.pool.quoteTokens[0].meta.tokenSymbol} to open a short position.{" "}
-
-
+ {connected &&
+ tradeState === "short" &&
+ activeGroup?.pool.quoteTokens[0].userInfo.tokenAccount.balance === 0 && (
+
+
+
+
+ You need to hold {activeGroup?.pool.quoteTokens[0].meta.tokenSymbol} to open a short position.{" "}
+
+
+
-
- )}
+ )}
{isActiveWithCollat ? (
<>
diff --git a/apps/marginfi-v2-trading/src/components/common/TradingBox/components/TradingBoxSettings/TradingBoxSettings.tsx b/apps/marginfi-v2-trading/src/components/common/TradingBox/components/TradingBoxSettings/TradingBoxSettings.tsx
index 6f31d1b87a..995286e5ee 100644
--- a/apps/marginfi-v2-trading/src/components/common/TradingBox/components/TradingBoxSettings/TradingBoxSettings.tsx
+++ b/apps/marginfi-v2-trading/src/components/common/TradingBox/components/TradingBoxSettings/TradingBoxSettings.tsx
@@ -3,7 +3,7 @@ import React from "react";
import { IconArrowLeft } from "@tabler/icons-react";
import { ToggleGroup, ToggleGroupItem } from "~/components/ui/toggle-group";
-import { Slippage, PriorityFees } from "./components";
+import { Slippage } from "./components";
type TradingBoxSettingsProps = {
toggleSettings: (mode: boolean) => void;
@@ -30,7 +30,7 @@ export const TradingBoxSettings = ({ toggleSettings, slippageBps, setSlippageBps
-
+ {/*
Slippage
@@ -40,12 +40,11 @@ export const TradingBoxSettings = ({ toggleSettings, slippageBps, setSlippageBps
Priority Fee
-
+
*/}
{settingsMode === SettingsState.Slippage && (
)}
- {settingsMode === SettingsState.PriorityFee &&
}
);
diff --git a/apps/marginfi-v2-trading/src/components/common/TradingBox/components/TradingBoxSettings/components/PriorityFees.tsx b/apps/marginfi-v2-trading/src/components/common/TradingBox/components/TradingBoxSettings/components/PriorityFees.tsx
deleted file mode 100644
index e47cbcb363..0000000000
--- a/apps/marginfi-v2-trading/src/components/common/TradingBox/components/TradingBoxSettings/components/PriorityFees.tsx
+++ /dev/null
@@ -1,113 +0,0 @@
-import React from "react";
-
-import { IconInfoCircle } from "@tabler/icons-react";
-import { cn } from "@mrgnlabs/mrgn-utils";
-
-import { useUiStore } from "~/store";
-
-import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "~/components/ui/tooltip";
-import { Button } from "~/components/ui/button";
-import { Input } from "~/components/ui/input";
-
-type PriorityFeesProps = {
- toggleSettings: (mode: boolean) => void;
-};
-
-const priorityFeeOptions = [
- {
- label: "Normal",
- value: 0,
- },
- {
- label: "High",
- value: 0.00005,
- },
- {
- label: "Mamas",
- value: 0.005,
- },
-];
-
-export const PriorityFees = ({ toggleSettings }: PriorityFeesProps) => {
- const [priorityFee, setPriorityFee] = useUiStore((state) => [state.priorityFee, state.setPriorityFee]);
- const [selectedPriorityFee, setSelectedPriorityFee] = React.useState
(priorityFee);
-
- const priorityFeeRef = React.useRef(null);
- const [isCustomPriorityFeeMode, setIsCustomPriorityFeeMode] = React.useState(false);
- const [customPriorityFee, setCustomPriorityFee] = React.useState(null);
-
- return (
-
-
- Set transaction priority{" "}
-
-
-
-
-
-
-
-
Priority fees are paid to the Solana network.
-
This additional fee helps boost how a transaction is prioritized.
-
-
-
-
-
-
- {priorityFeeOptions.map((option) => (
- -
-
-
- ))}
-
-
or set manually
-
- setIsCustomPriorityFeeMode(true)}
- onChange={() => setCustomPriorityFee(parseFloat(priorityFeeRef.current?.value || "0"))}
- />
- SOL
-
-
-
- );
-};
diff --git a/apps/marginfi-v2-trading/src/components/common/TradingBox/components/TradingBoxSettings/components/index.ts b/apps/marginfi-v2-trading/src/components/common/TradingBox/components/TradingBoxSettings/components/index.ts
index d14340f1a8..f2513227a3 100644
--- a/apps/marginfi-v2-trading/src/components/common/TradingBox/components/TradingBoxSettings/components/index.ts
+++ b/apps/marginfi-v2-trading/src/components/common/TradingBox/components/TradingBoxSettings/components/index.ts
@@ -1,2 +1 @@
-export * from "./PriorityFees";
export * from "./Slippage";
diff --git a/apps/marginfi-v2-trading/src/components/common/TradingBox/tradingBox.utils.tsx b/apps/marginfi-v2-trading/src/components/common/TradingBox/tradingBox.utils.tsx
index 7e9f69e6ae..38694707c9 100644
--- a/apps/marginfi-v2-trading/src/components/common/TradingBox/tradingBox.utils.tsx
+++ b/apps/marginfi-v2-trading/src/components/common/TradingBox/tradingBox.utils.tsx
@@ -10,7 +10,13 @@ import {
SimulationResult,
} from "@mrgnlabs/marginfi-client-v2";
import { AccountSummary, ExtendedBankInfo } from "@mrgnlabs/marginfi-v2-ui-state";
-import { Wallet, percentFormatter, tokenPriceFormatter, usdFormatter } from "@mrgnlabs/mrgn-common";
+import {
+ TransactionBroadcastType,
+ Wallet,
+ percentFormatter,
+ tokenPriceFormatter,
+ usdFormatter,
+} from "@mrgnlabs/mrgn-common";
import {
ActionMethod,
DYNAMIC_SIMULATION_ERRORS,
@@ -19,10 +25,8 @@ import {
LoopingOptions,
showErrorToast,
MultiStepToastHandle,
- STATIC_SIMULATION_ERRORS,
cn,
extractErrorString,
- isBankOracleStale,
} from "@mrgnlabs/mrgn-utils";
import { IconPyth, IconSwitchboard } from "~/components/ui/icons";
@@ -37,32 +41,37 @@ export async function looping({
depositAmount,
options,
priorityFee,
- isTxnSplit = false,
+ broadcastType,
}: {
marginfiClient: MarginfiClient | null;
marginfiAccount: MarginfiAccountWrapper;
bank: ExtendedBankInfo;
depositAmount: number;
options: LoopingOptions;
- priorityFee?: number;
- isTxnSplit?: boolean;
+ priorityFee: number;
+ broadcastType: TransactionBroadcastType;
}) {
if (marginfiClient === null) {
showErrorToast({ message: "Marginfi client not ready" });
return;
}
- const multiStepToast = new MultiStepToastHandle(
- "Looping",
- [{ label: `Executing looping ${bank.meta.tokenSymbol} with ${options.loopingBank.meta.tokenSymbol}` }]
- );
+ const multiStepToast = new MultiStepToastHandle("Looping", [
+ { label: `Executing looping ${bank.meta.tokenSymbol} with ${options.loopingBank.meta.tokenSymbol}` },
+ ]);
multiStepToast.start();
try {
let sigs: string[] = [];
if (options.loopingTxn) {
- sigs = await marginfiClient.processTransactions([...options.feedCrankTxs, options.loopingTxn]);
+ sigs = await marginfiClient.processTransactions(
+ [...options.feedCrankTxs, options.loopingTxn],
+ undefined,
+ undefined,
+ broadcastType,
+ true
+ );
} else {
const { flashloanTx, feedCrankTxs } = await loopingBuilder({
marginfiAccount,
@@ -70,9 +79,15 @@ export async function looping({
depositAmount,
options,
priorityFee,
- // isTxnSplit,
+ broadcastType,
});
- sigs = await marginfiClient.processTransactions([...feedCrankTxs, flashloanTx]);
+ sigs = await marginfiClient.processTransactions(
+ [...feedCrankTxs, flashloanTx],
+ undefined,
+ undefined,
+ broadcastType,
+ true
+ );
}
multiStepToast.setSuccessAndNext();
return sigs;
diff --git a/apps/marginfi-v2-trading/src/pages/_app.tsx b/apps/marginfi-v2-trading/src/pages/_app.tsx
index 67a3732e8d..a53d1867b4 100644
--- a/apps/marginfi-v2-trading/src/pages/_app.tsx
+++ b/apps/marginfi-v2-trading/src/pages/_app.tsx
@@ -12,10 +12,11 @@ import { TipLinkWalletAutoConnect } from "@tiplink/wallet-adapter-react-ui";
import { ToastContainer } from "react-toastify";
import { Analytics } from "@vercel/analytics/react";
import { BankMetadataRaw } from "@mrgnlabs/mrgn-common";
-import { Desktop, Mobile, init as initAnalytics } from "@mrgnlabs/mrgn-utils";
-import { AuthDialog } from "@mrgnlabs/mrgn-ui";
+import { DEFAULT_MAX_CAP, Desktop, Mobile, init as initAnalytics } from "@mrgnlabs/mrgn-utils";
+import { ActionProvider, AuthDialog } from "@mrgnlabs/mrgn-ui";
import config from "~/config";
+import { useUiStore } from "~/store";
import { TradePovider } from "~/context";
import { WALLET_ADAPTERS } from "~/config/wallets";
import { BANK_METADATA_MAP } from "~/config/trade";
@@ -39,6 +40,13 @@ export default function MrgnApp({ Component, pageProps, path, bank }: AppProps &
const { query, isReady } = useRouter();
const [ready, setReady] = React.useState(false);
+ const [broadcastType, priorityType, maxCap, maxCapType] = useUiStore((state) => [
+ state.broadcastType,
+ state.priorityType,
+ state.maxCap,
+ state.maxCapType,
+ ]);
+
React.useEffect(() => {
setReady(true);
initAnalytics();
@@ -52,31 +60,38 @@ export default function MrgnApp({ Component, pageProps, path, bank }: AppProps &
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/apps/marginfi-v2-trading/src/pages/api/bundles/tip.ts b/apps/marginfi-v2-trading/src/pages/api/bundles/tip.ts
new file mode 100644
index 0000000000..1790e42d29
--- /dev/null
+++ b/apps/marginfi-v2-trading/src/pages/api/bundles/tip.ts
@@ -0,0 +1,48 @@
+import { NextApiRequest, NextApiResponse } from "next";
+
+const JITO_API = "http://bundles-api-rest.jito.wtf";
+
+export interface TipFloorDataResponse {
+ time: string;
+ landed_tips_25th_percentile: number;
+ landed_tips_50th_percentile: number;
+ landed_tips_75th_percentile: number;
+ landed_tips_95th_percentile: number;
+ landed_tips_99th_percentile: number;
+ ema_landed_tips_50th_percentile: number;
+}
+
+/*
+ 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);
+
+ // Fetch from API and update cache
+ try {
+ const response = await fetch(`${JITO_API}/api/v1/bundles/tip_floor`, {
+ headers: {
+ Accept: "application/json",
+ },
+ signal: controller.signal,
+ });
+
+ clearTimeout(timeoutId);
+
+ if (!response.ok) {
+ throw new Error("Network response was not ok");
+ }
+ const data: TipFloorDataResponse = (await response.json())[0];
+
+ // cache for 4 minutes
+ res.setHeader("Cache-Control", "s-maxage=240, stale-while-revalidate=59");
+ res.status(200).json(data);
+ } catch (error) {
+ console.error("Error:", error);
+ res.status(500).json({ error: "Error fetching data" });
+ }
+}
diff --git a/apps/marginfi-v2-trading/src/store/actionBoxStore.ts b/apps/marginfi-v2-trading/src/store/actionBoxStore.ts
index e5c928e725..17686b426e 100644
--- a/apps/marginfi-v2-trading/src/store/actionBoxStore.ts
+++ b/apps/marginfi-v2-trading/src/store/actionBoxStore.ts
@@ -70,7 +70,7 @@ interface ActionBoxState {
slippageBps: number,
connection: Connection,
priorityFee: number,
- platformFeeBps?: number
+ platformFeeBps: number
) => void;
setIsLoading: (isLoading: boolean) => void;
}
@@ -226,7 +226,8 @@ const stateCreator: StateCreator = (set, get) => ({
slippageBps,
connection,
priorityFee,
- platformFeeBps
+ platformFeeBps,
+ "BUNDLE"
);
if (repayCollat && "repayTxn" in repayCollat) {
diff --git a/apps/marginfi-v2-trading/src/store/uiStore.ts b/apps/marginfi-v2-trading/src/store/uiStore.ts
index be61051ce0..0a0a3a4a8e 100644
--- a/apps/marginfi-v2-trading/src/store/uiStore.ts
+++ b/apps/marginfi-v2-trading/src/store/uiStore.ts
@@ -4,6 +4,13 @@ import { persist } from "zustand/middleware";
import { ActionType } from "@mrgnlabs/marginfi-v2-ui-state";
import { LendingModes, PreviousTxn } from "~/types";
+import {
+ MaxCapType,
+ TransactionBroadcastType,
+ TransactionPriorityType,
+ TransactionSettings,
+} from "@mrgnlabs/mrgn-common";
+import { DEFAULT_PRIORITY_SETTINGS } from "@mrgnlabs/mrgn-utils";
export enum WalletState {
DEFAULT = "default",
@@ -20,7 +27,6 @@ interface UiState {
isWalletAuthDialogOpen: boolean;
isWalletOpen: boolean;
lendingMode: LendingModes;
- priorityFee: number;
slippageBps: number;
platformFeeBps: number;
isActionComplete: boolean;
@@ -28,18 +34,22 @@ interface UiState {
isActionBoxInputFocussed: boolean;
walletState: WalletState;
isOnrampActive: boolean;
+ broadcastType: TransactionBroadcastType;
+ priorityType: TransactionPriorityType;
+ maxCapType: MaxCapType;
+ maxCap: number;
// Actions
setIsWalletAuthDialogOpen: (isOpen: boolean) => void;
setIsWalletOpen: (isOpen: boolean) => void;
setLendingMode: (lendingMode: LendingModes) => void;
- setPriorityFee: (priorityFee: number) => void;
setSlippageBps: (slippageBps: number) => void;
setIsActionComplete: (isActionSuccess: boolean) => void;
setPreviousTxn: (previousTxn: PreviousTxn) => void;
setWalletState: (walletState: WalletState) => void;
setIsActionBoxInputFocussed: (isFocussed: boolean) => void;
setIsOnrampActive: (isOnrampActive: boolean) => void;
+ setTransactionSettings: (settings: TransactionSettings) => void;
}
function createUiStore() {
@@ -47,11 +57,6 @@ function createUiStore() {
persist(stateCreator, {
name: "uiStore",
onRehydrateStorage: () => (state) => {
- // overwrite priority fee
- if (process.env.NEXT_PUBLIC_INIT_PRIO_FEE && process.env.NEXT_PUBLIC_INIT_PRIO_FEE !== "0") {
- state?.setPriorityFee(Number(process.env.NEXT_PUBLIC_INIT_PRIO_FEE));
- }
-
// overwrite wallet on mobile
// covers private key export modal when open
if (window.innerWidth < 768) {
@@ -71,12 +76,12 @@ const stateCreator: StateCreator = (set, get) => ({
actionMode: ActionType.Deposit,
platformFeeBps: 30,
selectedTokenBank: null,
- priorityFee: 0,
isActionComplete: false,
previousTxn: null,
isActionBoxInputFocussed: false,
walletState: WalletState.DEFAULT,
isOnrampActive: false,
+ ...DEFAULT_PRIORITY_SETTINGS,
// Actions
setIsWalletAuthDialogOpen: (isOpen: boolean) => set({ isWalletAuthDialogOpen: isOpen }),
@@ -85,13 +90,13 @@ const stateCreator: StateCreator = (set, get) => ({
set({
lendingMode: lendingMode,
}),
- setPriorityFee: (priorityFee: number) => set({ priorityFee: priorityFee }),
setSlippageBps: (slippageBps: number) => set({ slippageBps: slippageBps }),
setIsActionComplete: (isActionComplete: boolean) => set({ isActionComplete: isActionComplete }),
setPreviousTxn: (previousTxn: PreviousTxn) => set({ previousTxn: previousTxn }),
setWalletState: (walletState: WalletState) => set({ walletState: walletState }),
setIsActionBoxInputFocussed: (isFocussed: boolean) => set({ isActionBoxInputFocussed: isFocussed }),
setIsOnrampActive: (isOnrampActive: boolean) => set({ isOnrampActive: isOnrampActive }),
+ setTransactionSettings: (settings: TransactionSettings) => set({ ...settings }),
});
export { createUiStore };
diff --git a/apps/marginfi-v2-trading/src/utils/tradingActions.ts b/apps/marginfi-v2-trading/src/utils/tradingActions.ts
index 7126a31bc7..ec1e8047d9 100644
--- a/apps/marginfi-v2-trading/src/utils/tradingActions.ts
+++ b/apps/marginfi-v2-trading/src/utils/tradingActions.ts
@@ -30,6 +30,7 @@ import { ExtendedBankInfo, clearAccountCache, ActiveBankInfo } from "@mrgnlabs/m
import { TradeSide } from "~/components/common/TradingBox/tradingBox.utils";
import { WalletContextStateOverride } from "~/components/wallet-v2/hooks/use-wallet.hook";
+import { TransactionBroadcastType } from "@mrgnlabs/mrgn-common";
export async function createMarginfiGroup({
marginfiClient,
@@ -163,6 +164,7 @@ export async function executeLeverageAction({
loopingObject: _loopingObject,
priorityFee,
slippageBps,
+ broadcastType,
}: {
marginfiClient: MarginfiClient | null;
marginfiAccount: MarginfiAccountWrapper | null;
@@ -175,6 +177,7 @@ export async function executeLeverageAction({
loopingObject: LoopingObject | null;
priorityFee: number;
slippageBps: number;
+ broadcastType: TransactionBroadcastType;
}) {
if (marginfiClient === null) {
showErrorToast("Marginfi client not ready");
@@ -237,6 +240,7 @@ export async function executeLeverageAction({
loopObject: loopingObject,
priorityFee,
isTrading: true,
+ broadcastType: broadcastType,
});
if ("loopingTxn" in result) {
@@ -261,7 +265,13 @@ export async function executeLeverageAction({
let txnSig: string[] = [];
if (loopingObject.feedCrankTxs) {
- txnSig = await marginfiClient.processTransactions([...loopingObject.feedCrankTxs, loopingObject.loopingTxn]);
+ txnSig = await marginfiClient.processTransactions(
+ [...loopingObject.feedCrankTxs, loopingObject.loopingTxn],
+ undefined,
+ undefined,
+ broadcastType,
+ true
+ );
} else {
txnSig = [await marginfiClient.processTransaction(loopingObject.loopingTxn)];
}
diff --git a/apps/marginfi-v2-ui/src/components/common/Navbar/Navbar.tsx b/apps/marginfi-v2-ui/src/components/common/Navbar/Navbar.tsx
index 475cc3cb2b..e2eb24c698 100644
--- a/apps/marginfi-v2-ui/src/components/common/Navbar/Navbar.tsx
+++ b/apps/marginfi-v2-ui/src/components/common/Navbar/Navbar.tsx
@@ -5,11 +5,10 @@ import Image from "next/image";
import { useRouter } from "next/router";
import { PublicKey } from "@solana/web3.js";
-// import LipAccount from "@mrgnlabs/lip-client/src/account";
-import { IconBell, IconBrandTelegram } from "@tabler/icons-react";
+import { IconBell, IconBrandTelegram, IconSettings } from "@tabler/icons-react";
import { collectRewardsBatch, capture, cn } from "@mrgnlabs/mrgn-utils";
-import { Wallet } from "@mrgnlabs/mrgn-ui";
+import { Settings, Wallet } from "@mrgnlabs/mrgn-ui";
import { useMrgnlendStore, useUiStore, useUserProfileStore } from "~/store";
import { useFirebaseAccount } from "~/hooks/useFirebaseAccount";
@@ -52,7 +51,16 @@ export const Navbar: FC = () => {
state.fetchMrgnlendState,
]);
- const [isOraclesStale, priorityFee] = useUiStore((state) => [state.isOraclesStale, state.priorityFee]);
+ const { isOraclesStale, priorityType, broadcastType, maxCap, maxCapType, setTransactionSettings } = useUiStore(
+ (state) => ({
+ isOraclesStale: state.isOraclesStale,
+ priorityType: state.priorityType,
+ broadcastType: state.broadcastType,
+ maxCap: state.maxCap,
+ maxCapType: state.maxCapType,
+ setTransactionSettings: state.setTransactionSettings,
+ })
+ );
const [userPointsData] = useUserProfileStore((state) => [state.userPointsData]);
@@ -154,6 +162,7 @@ export const Navbar: FC = () => {
}`}
onClick={async () => {
if (!wallet || !selectedAccount || bankAddressesWithEmissions.length === 0) return;
+ const priorityFee = 0; // code has been removed on new collect rewards so temporary placeholder
await collectRewardsBatch(selectedAccount, bankAddressesWithEmissions, priorityFee);
}}
>
@@ -203,6 +212,23 @@ export const Navbar: FC = () => {
+
+
+
+
+
+
+
+
+
[state.setIsFetchingData, state.isOraclesStale]);
+ const [priorityType, broadcastType, maxCapType, maxCap, setIsFetchingData, isOraclesStale] = useUiStore((state) => [
+ state.priorityType,
+ state.broadcastType,
+ state.maxCapType,
+ state.maxCap,
+ state.setIsFetchingData,
+ state.isOraclesStale,
+ ]);
const [
isMrgnlendStoreInitialized,
isRefreshingMrgnlendStore,
@@ -105,47 +109,57 @@ export default function MrgnApp({ Component, pageProps, path }: AppProps & MrgnA
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/apps/marginfi-v2-ui/src/pages/api/bundles/tip.ts b/apps/marginfi-v2-ui/src/pages/api/bundles/tip.ts
new file mode 100644
index 0000000000..1790e42d29
--- /dev/null
+++ b/apps/marginfi-v2-ui/src/pages/api/bundles/tip.ts
@@ -0,0 +1,48 @@
+import { NextApiRequest, NextApiResponse } from "next";
+
+const JITO_API = "http://bundles-api-rest.jito.wtf";
+
+export interface TipFloorDataResponse {
+ time: string;
+ landed_tips_25th_percentile: number;
+ landed_tips_50th_percentile: number;
+ landed_tips_75th_percentile: number;
+ landed_tips_95th_percentile: number;
+ landed_tips_99th_percentile: number;
+ ema_landed_tips_50th_percentile: number;
+}
+
+/*
+ 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);
+
+ // Fetch from API and update cache
+ try {
+ const response = await fetch(`${JITO_API}/api/v1/bundles/tip_floor`, {
+ headers: {
+ Accept: "application/json",
+ },
+ signal: controller.signal,
+ });
+
+ clearTimeout(timeoutId);
+
+ if (!response.ok) {
+ throw new Error("Network response was not ok");
+ }
+ const data: TipFloorDataResponse = (await response.json())[0];
+
+ // cache for 4 minutes
+ res.setHeader("Cache-Control", "s-maxage=240, stale-while-revalidate=59");
+ res.status(200).json(data);
+ } catch (error) {
+ console.error("Error:", error);
+ res.status(500).json({ error: "Error fetching data" });
+ }
+}
diff --git a/apps/marginfi-v2-ui/src/pages/api/oracle/price.ts b/apps/marginfi-v2-ui/src/pages/api/oracle/price.ts
index 1c72dcff11..d4406da3aa 100644
--- a/apps/marginfi-v2-ui/src/pages/api/oracle/price.ts
+++ b/apps/marginfi-v2-ui/src/pages/api/oracle/price.ts
@@ -153,7 +153,7 @@ async function fetchCrossbarPrices(feedHashes: string[]): Promise
- {/*