From 81c6f4afbf5ecab10682a490f248672405a7598e Mon Sep 17 00:00:00 2001 From: borcherd Date: Fri, 13 Dec 2024 12:52:59 +0100 Subject: [PATCH] feat: updated onComplete and added short-long restriction check --- .../hooks/use-trade-simulation.ts | 6 +- .../common/trade-box-v2/trade-box.tsx | 56 +++++++++++-------- .../trade-box-v2/utils/trade-box.utils.ts | 20 +++++++ 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/apps/marginfi-v2-trading/src/components/common/trade-box-v2/hooks/use-trade-simulation.ts b/apps/marginfi-v2-trading/src/components/common/trade-box-v2/hooks/use-trade-simulation.ts index e9b3934f0..777ba1a0e 100644 --- a/apps/marginfi-v2-trading/src/components/common/trade-box-v2/hooks/use-trade-simulation.ts +++ b/apps/marginfi-v2-trading/src/components/common/trade-box-v2/hooks/use-trade-simulation.ts @@ -32,6 +32,7 @@ export type TradeSimulationProps = { simulationResult: SimulationResult | null; wrappedAccount: MarginfiAccountWrapper | null; accountSummary?: AccountSummary; + isEnabled: boolean; slippageBps: number; platformFeeBps: number; @@ -55,7 +56,7 @@ export function useTradeSimulation({ slippageBps, platformFeeBps, accountSummary, - + isEnabled, setActionTxns, setErrorMessage, setIsLoading, @@ -188,13 +189,14 @@ export function useTradeSimulation({ }, [selectedBank, selectedSecondaryBank, setErrorMessage, setMaxLeverage]); React.useEffect(() => { + // console.log("isEnabled", isEnabled); if (prevDebouncedAmount !== debouncedAmount || prevDebouncedLeverage !== debouncedLeverage) { // Only set to PREPARING if we're actually going to simulate if (debouncedAmount > 0 && debouncedLeverage > 0) { fetchTradeTxns(debouncedAmount, debouncedLeverage); } } - }, [debouncedAmount, debouncedLeverage, fetchTradeTxns, prevDebouncedAmount, prevDebouncedLeverage]); + }, [debouncedAmount, debouncedLeverage, fetchTradeTxns, prevDebouncedAmount, prevDebouncedLeverage, isEnabled]); React.useEffect(() => { // Only run simulation if we have transactions to simulate diff --git a/apps/marginfi-v2-trading/src/components/common/trade-box-v2/trade-box.tsx b/apps/marginfi-v2-trading/src/components/common/trade-box-v2/trade-box.tsx index 080576672..9f0fa2b3b 100644 --- a/apps/marginfi-v2-trading/src/components/common/trade-box-v2/trade-box.tsx +++ b/apps/marginfi-v2-trading/src/components/common/trade-box-v2/trade-box.tsx @@ -153,7 +153,7 @@ export const TradeBoxV2 = ({ activePool, side = "long" }: TradeBoxV2Props) => { ); // Memos - const numberFormater = React.useMemo(() => new Intl.NumberFormat("en-US", { maximumFractionDigits: 10 }), []); // The fuck is this lol? + const numberFormater = React.useMemo(() => new Intl.NumberFormat("en-US", { maximumFractionDigits: 10 }), []); const leveragedAmount = React.useMemo(() => { if (tradeState === "long") { @@ -163,6 +163,20 @@ export const TradeBoxV2 = ({ activePool, side = "long" }: TradeBoxV2Props) => { } }, [tradeState, actionTxns]); + const actionMethods = React.useMemo( + () => + checkTradeActionAvailable({ + amount, + connected, + collateralBank: selectedBank, + secondaryBank: selectedSecondaryBank, + actionQuote: actionTxns.actionQuote, + tradeState, + }), + + [amount, connected, activePoolExtended, actionTxns, tradeState, selectedSecondaryBank, selectedBank] + ); + // Effects React.useEffect(() => { if (activePoolExtended) { @@ -205,6 +219,7 @@ export const TradeBoxV2 = ({ activePool, side = "long" }: TradeBoxV2Props) => { actionTxns: actionTxns, simulationResult: null, accountSummary: accountSummary ?? undefined, + isEnabled: !actionMethods.concat(additionalActionMessages).filter((value) => value.isEnabled === false).length, setActionTxns: setActionTxns, setErrorMessage: setErrorMessage, setIsLoading: setIsSimulating, @@ -212,20 +227,13 @@ export const TradeBoxV2 = ({ activePool, side = "long" }: TradeBoxV2Props) => { setMaxLeverage, }); - const isActiveWithCollat = true; // TODO: figure out what this does? - - const actionMethods = React.useMemo( - () => - checkTradeActionAvailable({ - amount, - connected, - collateralBank: selectedBank, - secondaryBank: selectedSecondaryBank, - actionQuote: actionTxns.actionQuote, - }), + React.useEffect(() => { + console.log("actionMethods", actionMethods); + console.log("additionalActionMessages", additionalActionMessages); + console.log(!actionMethods.concat(additionalActionMessages).filter((value) => value.isEnabled === false).length); + }, [actionMethods]); - [amount, connected, activePoolExtended, actionTxns, tradeState] - ); + const isActiveWithCollat = true; // TODO: figure out what this does? const handleAmountChange = React.useCallback( (amountRaw: string) => { @@ -279,18 +287,22 @@ export const TradeBoxV2 = ({ activePool, side = "long" }: TradeBoxV2Props) => { callbacks.onComplete && callbacks.onComplete({ txn: txnSigs[txnSigs.length - 1] ?? "", - txnType: "LEND", - lendingOptions: { - amount: params.depositAmount, - type: ActionType.Loop, - bank: params.depositBank as ActiveBankInfo, + txnType: "TRADING", + tradingOptions: { + depositBank: params.depositBank as ActiveBankInfo, + borrowBank: params.borrowBank as ActiveBankInfo, + initDepositAmount: params.depositAmount.toString(), + depositAmount: params.actualDepositAmount, + borrowAmount: params.borrowAmount.toNumber(), + leverage: leverage, + type: tradeState, + quote: _actionTxns.actionQuote!, + entryPrice: activePoolExtended.tokenBank.info.oraclePrice.priceRealtime.price.toNumber(), }, }); }, setError: (error: IndividualFlowError) => { - // TODO: update the messaging within the toast. Might need tailored functions in the sdk for trading - console.log("error", error); - const toast = error.multiStepToast as MultiStepToastHandle; // TODO: check if this works, not sure it does + const toast = error.multiStepToast as MultiStepToastHandle; if (!toast) { return; } diff --git a/apps/marginfi-v2-trading/src/components/common/trade-box-v2/utils/trade-box.utils.ts b/apps/marginfi-v2-trading/src/components/common/trade-box-v2/utils/trade-box.utils.ts index 518af41a6..bf5d4573c 100644 --- a/apps/marginfi-v2-trading/src/components/common/trade-box-v2/utils/trade-box.utils.ts +++ b/apps/marginfi-v2-trading/src/components/common/trade-box-v2/utils/trade-box.utils.ts @@ -1,5 +1,6 @@ import { QuoteResponse } from "@jup-ag/api"; import { OperationalState } from "@mrgnlabs/marginfi-client-v2"; +import { ActiveBankInfo } from "@mrgnlabs/marginfi-v2-ui-state"; import { ActionMessageType, DYNAMIC_SIMULATION_ERRORS, isBankOracleStale } from "@mrgnlabs/mrgn-utils"; import { ArenaBank } from "~/store/tradeStoreV2"; @@ -9,6 +10,7 @@ interface CheckTradeActionAvailableProps { collateralBank: ArenaBank | null; secondaryBank: ArenaBank | null; actionQuote: QuoteResponse | null; + tradeState: "long" | "short"; } export function checkTradeActionAvailable({ @@ -17,6 +19,7 @@ export function checkTradeActionAvailable({ collateralBank, secondaryBank, actionQuote, + tradeState, }: CheckTradeActionAvailableProps): ActionMessageType[] { let checks: ActionMessageType[] = []; @@ -26,6 +29,9 @@ export function checkTradeActionAvailable({ const generalChecks = getGeneralChecks(amount ?? 0); if (generalChecks) checks.push(...generalChecks); + const tradeSpecificChecks = getTradeSpecificChecks(tradeState, secondaryBank); + if (tradeSpecificChecks) checks.push(...tradeSpecificChecks); + // allert checks if (collateralBank) { const tradeChecks = canBeTraded(collateralBank, secondaryBank, actionQuote); @@ -99,6 +105,20 @@ function canBeTraded( if ((repayBankInfo && isBankOracleStale(repayBankInfo)) || (targetBankInfo && isBankOracleStale(targetBankInfo))) { checks.push(DYNAMIC_SIMULATION_ERRORS.STALE_CHECK("Trading")); } + return checks; +} + +function getTradeSpecificChecks(tradeState: "long" | "short", secondaryBank: ArenaBank | null): ActionMessageType[] { + let checks: ActionMessageType[] = []; + + if (secondaryBank?.isActive && (secondaryBank as ActiveBankInfo)?.position.isLending) { + checks.push({ + isEnabled: false, + description: `You cannot ${tradeState} while you have an active ${ + tradeState === "long" ? "short" : "long" + } position for this token.`, + }); + } return checks; }