diff --git a/src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx b/src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx index 313eb6ff17..0aab5dd828 100644 --- a/src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +++ b/src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx @@ -38,10 +38,10 @@ import { createWrapOrUnwrapTxn } from "domain/synthetics/orders/createWrapOrUnwr import { formatLeverage, formatLiquidationPrice, getTriggerNameByOrderType } from "domain/synthetics/positions"; import { convertToTokenAmount, + convertToUsd, formatTokensRatio, getNeedTokenApprove, useTokensAllowanceData, - convertToUsd, } from "domain/synthetics/tokens"; import { TriggerThresholdType, applySlippageToMinOut, applySlippageToPrice } from "domain/synthetics/trade"; import { getIsEquivalentTokens, getSpread } from "domain/tokens"; @@ -55,13 +55,14 @@ import { useSettings } from "context/SettingsContext/SettingsContextProvider"; import { useSubaccount, useSubaccountCancelOrdersDetailsMessage } from "context/SubaccountContext/SubaccountContext"; import { useTokensData } from "context/SyntheticsStateContext/hooks/globalsHooks"; import { - useSidecarOrders, - SidecarOrderEntryGroup, - SidecarSlTpOrderEntryValid, - SidecarLimitOrderEntryValid, SidecarLimitOrderEntry, + SidecarLimitOrderEntryValid, + SidecarOrderEntryGroup, SidecarSlTpOrderEntry, + SidecarSlTpOrderEntryValid, + useSidecarOrders, } from "domain/synthetics/sidecarOrders/useSidecarOrders"; +import { PERCENTAGE_DECEMALS } from "domain/synthetics/sidecarOrders/utils"; import { useHighExecutionFeeConsent } from "domain/synthetics/trade/useHighExecutionFeeConsent"; import { usePriceImpactWarningState } from "domain/synthetics/trade/usePriceImpactWarningState"; import { helperToast } from "lib/helperToast"; @@ -86,19 +87,20 @@ import { AcceptablePriceImpactInputRow } from "../AcceptablePriceImpactInputRow/ import { HighPriceImpactWarning } from "../HighPriceImpactWarning/HighPriceImpactWarning"; import { NetworkFeeRow } from "../NetworkFeeRow/NetworkFeeRow"; import { TradeFeesRow } from "../TradeFeesRow/TradeFeesRow"; +import { useTradeboxPoolWarnings } from "../TradeboxPoolWarnings/TradeboxPoolWarnings"; import { SideOrderEntries } from "./SideOrderEntries"; -import { PERCENTAGE_DECEMALS } from "domain/synthetics/sidecarOrders/utils"; import { AllowedSlippageRow } from "./rows/AllowedSlippageRow"; -import { useTradeboxPoolWarnings } from "../TradeboxPoolWarnings/TradeboxPoolWarnings"; import { selectGasLimits, selectGasPrice } from "context/SyntheticsStateContext/selectors/globalSelectors"; import { makeSelectOrdersByPositionKey } from "context/SyntheticsStateContext/selectors/orderSelectors"; import { + selectTradeboxAutoCancel, selectTradeboxAvailableMarketsOptions, selectTradeboxCollateralToken, selectTradeboxDecreasePositionAmounts, selectTradeboxDefaultTriggerAcceptablePriceImpactBps, selectTradeboxExecutionFee, + selectTradeboxExecutionPrice, selectTradeboxFees, selectTradeboxFixedTriggerOrderType, selectTradeboxFixedTriggerThresholdType, @@ -109,8 +111,10 @@ import { selectTradeboxLiquidity, selectTradeboxMarkPrice, selectTradeboxMarketInfo, + selectTradeboxMaxLiquidityPath, selectTradeboxNextPositionValues, selectTradeboxSelectedPosition, + selectTradeboxSelectedPositionKey, selectTradeboxSelectedTriggerAcceptablePriceImpactBps, selectTradeboxSetKeepLeverage, selectTradeboxSetSelectedAcceptablePriceImpactBps, @@ -119,16 +123,14 @@ import { selectTradeboxTradeFlags, selectTradeboxTradeRatios, selectTradeboxTriggerPrice, - selectTradeboxSelectedPositionKey, - selectTradeboxMaxLiquidityPath, - selectTradeboxExecutionPrice, } from "context/SyntheticsStateContext/selectors/tradeboxSelectors"; import { useSelector } from "context/SyntheticsStateContext/utils"; -import "./ConfirmationBox.scss"; -import { bigMath } from "lib/bigmath"; import { estimateOrderOraclePriceCount } from "domain/synthetics/fees/utils/estimateOraclePriceCount"; +import { bigMath } from "lib/bigmath"; import { ExecutionPriceRow } from "../ExecutionPriceRow"; +import "./ConfirmationBox.scss"; + export type Props = { isVisible: boolean; error: string | undefined; @@ -169,6 +171,7 @@ export function ConfirmationBox(p: Props) { const fixedTriggerThresholdType = useSelector(selectTradeboxFixedTriggerThresholdType); const fixedTriggerOrderType = useSelector(selectTradeboxFixedTriggerOrderType); const { longLiquidity, shortLiquidity } = useSelector(selectTradeboxLiquidity); + const { autoCancel, setAutoCancel } = useSelector(selectTradeboxAutoCancel); const { element: highExecutionFeeAcknowledgement, isHighFeeConsentError } = useHighExecutionFeeConsent( executionFee?.feeUsd @@ -620,6 +623,7 @@ export function ConfirmationBox(p: Props) { receiveTokenAddress: collateralToken.address, isLong, indexToken: marketInfo.indexToken, + autoCancel: false, }; return createIncreaseOrderTxn({ @@ -649,6 +653,7 @@ export function ConfirmationBox(p: Props) { setPendingTxns: p.setPendingTxns, setPendingOrder, setPendingPosition, + autoCancel: isLimit ? autoCancel : false, }, createDecreaseOrderParams: createSltpEntries.map((entry) => { return { @@ -737,6 +742,7 @@ export function ConfirmationBox(p: Props) { skipSimulation: true, indexToken: marketInfo.indexToken, tokensData, + autoCancel, }, { setPendingTxns, @@ -1251,6 +1257,11 @@ export function ConfirmationBox(p: Props) { /> )} {isLimit && increaseAmounts && renderAcceptablePriceImpactInput()} + {(isLimit || isTrigger) && ( + + Auto Cancel + + )} @@ -1542,6 +1553,13 @@ export function ConfirmationBox(p: Props) { {decreaseAmounts && decreaseAmounts.triggerOrderType !== OrderType.StopLossDecrease && ( {renderAcceptablePriceImpactInput()} )} + {(isLimit || isTrigger) && ( + + + Auto Cancel + + + )} )} + + Auto Cancel + + { const minCollateralFactor = q((s) => selectMarketsInfoData(s)?.[order.marketAddress]?.minCollateralFactor); return getMaxAllowedLeverageByMinCollateralFactor(minCollateralFactor); }); + +export const selectOrderEditorAutoCancel = createSelector((q) => { + return { + autoCancel: q((state) => state.orderEditor.autoCancel), + setAutoCancel: q((state) => state.orderEditor.setAutoCancel), + }; +}); diff --git a/src/context/SyntheticsStateContext/selectors/tradeboxSelectors/index.ts b/src/context/SyntheticsStateContext/selectors/tradeboxSelectors/index.ts index f776cac92b..9b2c7f14aa 100644 --- a/src/context/SyntheticsStateContext/selectors/tradeboxSelectors/index.ts +++ b/src/context/SyntheticsStateContext/selectors/tradeboxSelectors/index.ts @@ -72,7 +72,7 @@ export const selectTradeboxMarketInfo = (s: SyntheticsState) => s.tradebox.marke export const selectTradeboxCollateralTokenAddress = (s: SyntheticsState) => selectOnlyOnTradeboxPage(s, s.tradebox.collateralAddress); export const selectTradeboxCollateralToken = (s: SyntheticsState) => s.tradebox.collateralToken; -export const selectTradeboxAvailableTradeModes = (s: SyntheticsState) => s.tradebox.avaialbleTradeModes; +export const selectTradeboxAvailableTradeModes = (s: SyntheticsState) => s.tradebox.availableTradeModes; export const selectTradeboxAvailableTokensOptions = (s: SyntheticsState) => s.tradebox.availableTokensOptions; export const selectTradeboxFromTokenInputValue = (s: SyntheticsState) => s.tradebox.fromTokenInputValue; export const selectTradeboxToTokenInputValue = (s: SyntheticsState) => s.tradebox.toTokenInputValue; @@ -815,3 +815,10 @@ export const selectTradeboxMarketsSortMap = createSelector((q) => { return acc; }, {}); }); + +export const selectTradeboxAutoCancel = createSelector((q) => { + return { + autoCancel: q((state) => state.tradebox.autoCancel), + setAutoCancel: q((state) => state.tradebox.setAutoCancel), + }; +}); diff --git a/src/domain/synthetics/orders/createDecreaseOrderTxn.ts b/src/domain/synthetics/orders/createDecreaseOrderTxn.ts index 40644e67f6..8f23b9482f 100644 --- a/src/domain/synthetics/orders/createDecreaseOrderTxn.ts +++ b/src/domain/synthetics/orders/createDecreaseOrderTxn.ts @@ -39,6 +39,7 @@ export type DecreaseOrderParams = { referralCode?: string; indexToken: Token; tokensData: TokensData; + autoCancel: boolean; }; export type DecreaseOrderCallbacks = { @@ -204,7 +205,7 @@ export function createDecreaseEncodedPayload({ decreasePositionSwapType: p.decreasePositionSwapType, isLong: p.isLong, shouldUnwrapNativeToken: isNativeReceive, - autoCancel: false, + autoCancel: p.autoCancel, referralCode: p.referralCode || ethers.ZeroHash, }; diff --git a/src/domain/synthetics/orders/createIncreaseOrderTxn.ts b/src/domain/synthetics/orders/createIncreaseOrderTxn.ts index 304499f76a..8cb4ce04b5 100644 --- a/src/domain/synthetics/orders/createIncreaseOrderTxn.ts +++ b/src/domain/synthetics/orders/createIncreaseOrderTxn.ts @@ -41,6 +41,7 @@ type IncreaseOrderParams = { referralCode: string | undefined; indexToken: TokenData; tokensData: TokensData; + autoCancel: boolean; setPendingTxns: (txns: any) => void; setPendingOrder: SetPendingOrder; setPendingPosition: SetPendingPosition; @@ -191,6 +192,7 @@ export async function createIncreaseOrderTxn({ acceptablePrice, triggerPrice, minOutputAmount, + autoCancel: false, }), ]; }, @@ -328,7 +330,7 @@ function createOrderParams({ decreasePositionSwapType: DecreasePositionSwapType.NoSwap, isLong: p.isLong, shouldUnwrapNativeToken: isNativePayment, - autoCancel: false, + autoCancel: p.autoCancel, referralCode: p.referralCode || ethers.ZeroHash, }; } diff --git a/src/domain/synthetics/orders/types.ts b/src/domain/synthetics/orders/types.ts index 28d7854368..2461eabeec 100644 --- a/src/domain/synthetics/orders/types.ts +++ b/src/domain/synthetics/orders/types.ts @@ -63,6 +63,7 @@ export type Order = { isLong: boolean; orderType: OrderType; shouldUnwrapNativeToken: boolean; + autoCancel: boolean; data: string; }; @@ -89,6 +90,7 @@ export type PositionOrderInfo = Order & { acceptablePrice: bigint; triggerPrice: bigint; triggerThresholdType: TriggerThresholdType; + autoCancel: boolean; }; export type OrderInfo = SwapOrderInfo | PositionOrderInfo; diff --git a/src/domain/synthetics/orders/updateOrderTxn.ts b/src/domain/synthetics/orders/updateOrderTxn.ts index 2d8cc7255f..42f85bf1ac 100644 --- a/src/domain/synthetics/orders/updateOrderTxn.ts +++ b/src/domain/synthetics/orders/updateOrderTxn.ts @@ -18,6 +18,7 @@ export type UpdateOrderParams = { minOutputAmount: bigint; // used to top-up execution fee for frozen orders executionFee?: bigint; + autoCancel: boolean; setPendingTxns: (txns: any) => void; }; @@ -36,6 +37,7 @@ export function updateOrderTxn( executionFee, setPendingTxns, indexToken, + autoCancel, } = p; const router = subaccount @@ -52,6 +54,7 @@ export function updateOrderTxn( acceptablePrice, triggerPrice, minOutputAmount, + autoCancel, }); return callContract(chainId, router, "multicall", [encodedPayload], { @@ -75,6 +78,7 @@ export function createUpdateEncodedPayload({ acceptablePrice, triggerPrice, minOutputAmount, + autoCancel, }: { chainId: number; router: ethers.Contract; @@ -85,6 +89,7 @@ export function createUpdateEncodedPayload({ acceptablePrice: bigint; triggerPrice: bigint; minOutputAmount: bigint; + autoCancel: boolean; }) { const orderVaultAddress = getContract(chainId, "OrderVault"); @@ -101,7 +106,7 @@ export function createUpdateEncodedPayload({ convertToContractPrice(acceptablePrice, indexToken?.decimals || 0), convertToContractPrice(triggerPrice, indexToken?.decimals || 0), minOutputAmount, - false, // autoCancel + autoCancel, ], }); diff --git a/src/domain/synthetics/orders/useOrderEditorState.ts b/src/domain/synthetics/orders/useOrderEditorState.ts index e0eeec62da..b7554b5bdc 100644 --- a/src/domain/synthetics/orders/useOrderEditorState.ts +++ b/src/domain/synthetics/orders/useOrderEditorState.ts @@ -15,6 +15,7 @@ export function useOrderEditorState(ordersInfoData: OrdersInfoData | undefined) const [sizeInputValue, setSizeInputValue] = useState(""); const [triggerPriceInputValue, setTriggerPriceInputValue] = useState(""); const [triggerRatioInputValue, setTriggerRatioInputValue] = useState(""); + const [autoCancel, setAutoCancel] = useState(false); useEffect( function resetOrderEditorState() { @@ -22,6 +23,7 @@ export function useOrderEditorState(ordersInfoData: OrdersInfoData | undefined) setSizeInputValue(""); setTriggerPriceInputValue(""); setTriggerRatioInputValue(""); + setAutoCancel(false); }; if (!editingOrderKey) { @@ -53,10 +55,15 @@ export function useOrderEditorState(ordersInfoData: OrdersInfoData | undefined) acceptablePriceImpactBps, initialAcceptablePriceImpactBps, setAcceptablePriceImpactBps, + + autoCancel, + setAutoCancel, }), [ acceptablePrice, acceptablePriceImpactBps, + autoCancel, + setAutoCancel, cancellingOrdersKeys, editingOrderKey, initialAcceptablePriceImpactBps, diff --git a/src/domain/synthetics/orders/useOrders.ts b/src/domain/synthetics/orders/useOrders.ts index dcb6b0151f..cf6aa410d3 100644 --- a/src/domain/synthetics/orders/useOrders.ts +++ b/src/domain/synthetics/orders/useOrders.ts @@ -208,6 +208,7 @@ function parseResponse(res: MulticallResult(""); const [triggerRatioInputValue, setTriggerRatioInputValue] = useState(""); + const [autoCancel, setAutoCancel] = useState(false); const { swapTokens } = availableTokensOptions; @@ -216,7 +217,7 @@ export function useTradeboxState( const [isLeverageEnabled, setIsLeverageEnabled] = useLocalStorageSerializeKey(getLeverageEnabledKey(chainId), true); const [keepLeverage, setKeepLeverage] = useLocalStorageSerializeKey(getKeepLeverageKey(chainId), true); - const avaialbleTradeModes = useMemo(() => { + const availableTradeModes = useMemo(() => { if (!tradeType) { return []; } @@ -502,11 +503,11 @@ export function useTradeboxState( useEffect( function updateTradeMode() { - if (tradeType && tradeMode && !avaialbleTradeModes.includes(tradeMode)) { - setTradeMode(avaialbleTradeModes[0]); + if (tradeType && tradeMode && !availableTradeModes.includes(tradeMode)) { + setTradeMode(availableTradeModes[0]); } }, - [tradeType, tradeMode, avaialbleTradeModes, setTradeMode] + [tradeType, tradeMode, availableTradeModes, setTradeMode] ); useEffect( @@ -541,7 +542,7 @@ export function useTradeboxState( collateralAddress, collateralToken, availableTokensOptions, - avaialbleTradeModes, + availableTradeModes, setActivePosition, setFromTokenAddress, setToTokenAddress, @@ -579,6 +580,8 @@ export function useTradeboxState( setIsLeverageEnabled, keepLeverage, setKeepLeverage, + autoCancel, + setAutoCancel, }; } diff --git a/src/locales/de/messages.po b/src/locales/de/messages.po index 420e777c61..0aba6fc4f5 100644 --- a/src/locales/de/messages.po +++ b/src/locales/de/messages.po @@ -4767,6 +4767,12 @@ msgstr "Min. erforderliches Kollateral" msgid "Search Pool" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "Auto Cancel" +msgstr "" + #: src/components/TokenCard/TokenCard.tsx msgid "{arbitrumLink} and {avalancheLink} GM Pools are <0>incentivized{sparkle}." msgstr "" diff --git a/src/locales/en/messages.po b/src/locales/en/messages.po index 70f660aced..398fc02dd6 100644 --- a/src/locales/en/messages.po +++ b/src/locales/en/messages.po @@ -4770,6 +4770,12 @@ msgstr "Min. required Collateral" msgid "Search Pool" msgstr "Search Pool" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "Auto Cancel" +msgstr "Auto Cancel" + #: src/components/TokenCard/TokenCard.tsx msgid "{arbitrumLink} and {avalancheLink} GM Pools are <0>incentivized{sparkle}." msgstr "{arbitrumLink} and {avalancheLink} GM Pools are <0>incentivized{sparkle}." diff --git a/src/locales/es/messages.po b/src/locales/es/messages.po index 8ae8805c4d..8c8bc21aeb 100644 --- a/src/locales/es/messages.po +++ b/src/locales/es/messages.po @@ -4767,6 +4767,12 @@ msgstr "Garantía mínima requerida" msgid "Search Pool" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "Auto Cancel" +msgstr "" + #: src/components/TokenCard/TokenCard.tsx msgid "{arbitrumLink} and {avalancheLink} GM Pools are <0>incentivized{sparkle}." msgstr "" diff --git a/src/locales/fr/messages.po b/src/locales/fr/messages.po index 6d395de36b..d64876a16c 100644 --- a/src/locales/fr/messages.po +++ b/src/locales/fr/messages.po @@ -4767,6 +4767,12 @@ msgstr "Collatéral min. requis" msgid "Search Pool" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "Auto Cancel" +msgstr "" + #: src/components/TokenCard/TokenCard.tsx msgid "{arbitrumLink} and {avalancheLink} GM Pools are <0>incentivized{sparkle}." msgstr "" diff --git a/src/locales/ja/messages.po b/src/locales/ja/messages.po index bb873ef0a9..62a442a13b 100644 --- a/src/locales/ja/messages.po +++ b/src/locales/ja/messages.po @@ -4767,6 +4767,12 @@ msgstr "最低必要担保" msgid "Search Pool" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "Auto Cancel" +msgstr "" + #: src/components/TokenCard/TokenCard.tsx msgid "{arbitrumLink} and {avalancheLink} GM Pools are <0>incentivized{sparkle}." msgstr "" diff --git a/src/locales/ko/messages.po b/src/locales/ko/messages.po index 295e273838..c70eafb019 100644 --- a/src/locales/ko/messages.po +++ b/src/locales/ko/messages.po @@ -4767,6 +4767,12 @@ msgstr "최소 필요 담보" msgid "Search Pool" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "Auto Cancel" +msgstr "" + #: src/components/TokenCard/TokenCard.tsx msgid "{arbitrumLink} and {avalancheLink} GM Pools are <0>incentivized{sparkle}." msgstr "" diff --git a/src/locales/pseudo/messages.po b/src/locales/pseudo/messages.po index 7636bc24e7..60e95828f5 100644 --- a/src/locales/pseudo/messages.po +++ b/src/locales/pseudo/messages.po @@ -4767,6 +4767,12 @@ msgstr "" msgid "Search Pool" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "Auto Cancel" +msgstr "" + #: src/components/TokenCard/TokenCard.tsx msgid "{arbitrumLink} and {avalancheLink} GM Pools are <0>incentivized{sparkle}." msgstr "" diff --git a/src/locales/ru/messages.po b/src/locales/ru/messages.po index ff788a8a00..509878595a 100644 --- a/src/locales/ru/messages.po +++ b/src/locales/ru/messages.po @@ -4767,6 +4767,12 @@ msgstr "Минимально требуемый залог" msgid "Search Pool" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "Auto Cancel" +msgstr "" + #: src/components/TokenCard/TokenCard.tsx msgid "{arbitrumLink} and {avalancheLink} GM Pools are <0>incentivized{sparkle}." msgstr "" diff --git a/src/locales/zh/messages.po b/src/locales/zh/messages.po index c55418d3a8..5c933bf2ed 100644 --- a/src/locales/zh/messages.po +++ b/src/locales/zh/messages.po @@ -4767,6 +4767,12 @@ msgstr "最低要求抵押品" msgid "Search Pool" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "Auto Cancel" +msgstr "" + #: src/components/TokenCard/TokenCard.tsx msgid "{arbitrumLink} and {avalancheLink} GM Pools are <0>incentivized{sparkle}." msgstr ""