diff --git a/.env b/.env index 4f79a0f8e2..abf9075dd6 100644 --- a/.env +++ b/.env @@ -1 +1,2 @@ -GENERATE_SOURCEMAP=false \ No newline at end of file +GENERATE_SOURCEMAP=false +REACT_APP_UI_FEE_RECEIVER=0xff00000000000000000000000000000000000001 diff --git a/.eslintrc.json b/.eslintrc.json index 125cbe13e7..46a0121107 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,26 +1,47 @@ { - "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:react-hooks/recommended"], + "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:react-hooks/recommended", "plugin:react/recommended", "plugin:react-perf/recommended"], "rules": { - "curly": "off", "no-undef": "error", + "no-console": "warn", + "no-var": "error", + "no-case-declarations": "error", + "@typescript-eslint/no-empty-function": "error", + "no-extra-boolean-cast": "error", + "no-prototype-builtins": "error", + "no-empty": "error", + "@typescript-eslint/no-inferrable-types": "error", + "@typescript-eslint/no-non-null-asserted-optional-chain": "error", + "react/no-unused-prop-types": "error", + "react-hooks/rules-of-hooks": "warn", + "react/hook-use-state": "warn", + "@typescript-eslint/no-unused-vars": "warn", + "react/jsx-fragments": "warn", + "react-perf/jsx-no-new-array-as-prop": "warn", + "react-perf/jsx-no-new-object-as-prop": "warn", + "react-perf/jsx-no-new-function-as-prop": "off", + + /* might be useful */ "@typescript-eslint/no-non-null-assertion": "off", + "curly": "off", "@typescript-eslint/no-explicit-any": "off", "prefer-const": "off", - "no-console": "warn", "no-irregular-whitespace": "off", - "@typescript-eslint/no-inferrable-types": "error", "@typescript-eslint/ban-ts-comment": "off", - "@typescript-eslint/no-unused-vars": "warn", - "no-var": "error", "no-async-promise-executor": "off", - "@typescript-eslint/no-non-null-asserted-optional-chain": "error", "@typescript-eslint/ban-types": "off", - "@typescript-eslint/no-empty-function": "error", - "no-case-declarations": "error", "@typescript-eslint/no-empty-interface": "off", - "no-extra-boolean-cast": "error", - "no-prototype-builtins": "error", - "no-empty": "error" + "react/react-in-jsx-scope": "off", + "react/no-unescaped-entities": "off", + "react/prop-types": "off", + "react/jsx-no-bind": "off", + "react/jsx-no-leaked-render": "off", + "react/no-multi-comp": "off", + "react/no-array-index-key": "off", + "react/no-unstable-nested-components": "off", + "react/jsx-no-useless-fragment": "off", + "react/require-default-props": "off", + "react/jsx-handler-names": "off", + "react/display-name": "off" }, "env": { "browser": true, @@ -30,5 +51,10 @@ "globals": { "process": true, "TradingView": true + }, + "settings": { + "react": { + "version": "detect" + } } } \ No newline at end of file diff --git a/package.json b/package.json index b2341dff59..5990213f7d 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@lingui/core": "3.13.3", "@lingui/react": "3.13.3", "@rainbow-me/rainbowkit": "0.12.18", + "@taskworld.com/rereselect": "0.3.0", "@testing-library/jest-dom": "5.16.1", "@testing-library/react": "11.2.7", "@testing-library/user-event": "12.8.3", @@ -53,6 +54,7 @@ "react-toastify": "6.0.9", "react-use": "17.3.1", "recharts": "2.1.8", + "reselect": "5.1.0", "sass": "1.55.0", "shallowequal": "1.1.0", "swr": "2.2.1", @@ -124,7 +126,9 @@ "buffer": "6.0.3", "eslint": "^8.41.0", "eslint-config-react-app": "^7.0.1", + "eslint-plugin-react": "7.33.2", "eslint-plugin-react-hooks": "4.6.0", + "eslint-plugin-react-perf": "3.3.2", "husky": "7.0.4", "lint-staged": "12.3.4", "prettier": "2.5.1", diff --git a/src/App/App.js b/src/App/App.js index 4425b5f768..b26a19be1b 100644 --- a/src/App/App.js +++ b/src/App/App.js @@ -6,7 +6,6 @@ import "@wagmi/connectors"; import { Redirect, Route, Switch, useHistory, useLocation } from "react-router-dom"; -import { BASIS_POINTS_DIVISOR } from "config/factors"; import { getAppBaseUrl, isHomeSite, REFERRAL_CODE_QUERY_PARAM } from "lib/legacy"; import { decodeReferralCode, encodeReferralCode } from "domain/referrals"; @@ -28,9 +27,8 @@ import Referrals from "pages/Referrals/Referrals"; import ReferralsTier from "pages/ReferralsTier/ReferralsTier"; import Stake from "pages/Stake/Stake"; import Stats from "pages/Stats/Stats"; +import { PriceImpactRebatesStatsPage } from "pages/PriceImpactRebatesStats/PriceImpactRebatesStats"; -import Checkbox from "components/Checkbox/Checkbox"; -import Modal from "components/Modal/Modal"; import { cssTransition, ToastContainer } from "react-toastify"; import "react-toastify/dist/ReactToastify.css"; @@ -42,7 +40,6 @@ import "./App.scss"; import SEO from "components/Common/SEO"; import EventToastContainer from "components/EventToast/EventToastContainer"; import useEventToast from "components/EventToast/useEventToast"; -import Tooltip from "components/Tooltip/Tooltip"; import useRouteQuery from "lib/useRouteQuery"; import PositionRouter from "abis/PositionRouter.json"; @@ -58,40 +55,33 @@ import TermsAndConditions from "pages/TermsAndConditions/TermsAndConditions"; import { useLocalStorage } from "react-use"; import { i18n } from "@lingui/core"; -import { t, Trans } from "@lingui/macro"; +import { Trans } from "@lingui/macro"; import { I18nProvider } from "@lingui/react"; -import Button from "components/Button/Button"; import ExternalLink from "components/ExternalLink/ExternalLink"; import { Header } from "components/Header/Header"; -import { ARBITRUM, DEFAULT_ALLOWED_SLIPPAGE_BPS, EXECUTION_FEE_CONFIG_V2, getExplorerUrl } from "config/chains"; -import { isDevelopment } from "config/env"; +import { ARBITRUM, getExplorerUrl } from "config/chains"; import { getIsSyntheticsSupported } from "config/features"; import { CURRENT_PROVIDER_LOCALSTORAGE_KEY, - DISABLE_ORDER_VALIDATION_KEY, - IS_PNL_IN_LEVERAGE_KEY, LANGUAGE_LOCALSTORAGE_KEY, REFERRAL_CODE_KEY, SHOULD_EAGER_CONNECT_LOCALSTORAGE_KEY, - SHOULD_SHOW_POSITION_LINES_KEY, - SHOW_PNL_AFTER_FEES_KEY, } from "config/localStorage"; import { TOAST_AUTO_CLOSE_TIME, WS_LOST_FOCUS_TIMEOUT } from "config/ui"; import { SettingsContextProvider, useSettings } from "context/SettingsContext/SettingsContextProvider"; +import { SyntheticsStateContextProvider } from "context/SyntheticsStateContext/SyntheticsStateContextProvider"; import { SyntheticsEventsProvider } from "context/SyntheticsEvents"; import { useWebsocketProvider, WebsocketContextProvider } from "context/WebsocketContext/WebsocketContextProvider"; import { useChainId } from "lib/chains"; import { helperToast } from "lib/helperToast"; import { defaultLocale, dynamicActivate } from "lib/i18n"; import { useLocalStorageSerializeKey } from "lib/localStorage"; -import { roundToTwoDecimals } from "lib/numbers"; import { useHasLostFocus } from "lib/useHasPageLostFocus"; import { MarketPoolsPage } from "pages/MarketPoolsPage/MarketPoolsPage"; import SyntheticsActions from "pages/SyntheticsActions/SyntheticsActions"; import { SyntheticsFallbackPage } from "pages/SyntheticsFallbackPage/SyntheticsFallbackPage"; import { SyntheticsPage } from "pages/SyntheticsPage/SyntheticsPage"; import { SyntheticsStats } from "pages/SyntheticsStats/SyntheticsStats"; -import NumberInput from "components/NumberInput/NumberInput"; import { watchNetwork } from "@wagmi/core"; import { useDisconnect } from "wagmi"; import useWallet from "lib/wallets/useWallet"; @@ -99,6 +89,7 @@ import { swrGCMiddleware } from "lib/swrMiddlewares"; import useTradeRedirect from "lib/useTradeRedirect"; import { SubaccountContextProvider } from "context/SubaccountContext/SubaccountContext"; import { SubaccountModal } from "components/Synthetics/SubaccountModal/SubaccountModal"; +import { SettingsModal } from "components/SettingsModal/SettingsModal"; if (window?.ethereum?.autoRefreshOnNetworkChange) { window.ethereum.autoRefreshOnNetworkChange = false; @@ -113,8 +104,7 @@ const Zoom = cssTransition({ duration: 200, }); -function FullApp() { - const { signer } = useWallet(); +function FullApp({ pendingTxns, setPendingTxns }) { const { disconnect } = useDisconnect(); const isHome = isHomeSite(); const exchangeRef = useRef(); @@ -172,98 +162,9 @@ function FullApp() { const settings = useSettings(); const [isSettingsVisible, setIsSettingsVisible] = useState(false); - const [slippageAmount, setSlippageAmount] = useState(0); - const [executionFeeBufferBps, setExecutionFeeBufferBps] = useState(0); - const [isPnlInLeverage, setIsPnlInLeverage] = useState(false); - const [shouldDisableValidationForTesting, setShouldDisableValidationForTesting] = useState(false); - - const [showPnlAfterFees, setShowPnlAfterFees] = useState(true); - const [showDebugValues, setShowDebugValues] = useState(false); - - const [savedIsPnlInLeverage, setSavedIsPnlInLeverage] = useLocalStorageSerializeKey( - [chainId, IS_PNL_IN_LEVERAGE_KEY], - false - ); - - const [savedShowPnlAfterFees, setSavedShowPnlAfterFees] = useLocalStorageSerializeKey( - [chainId, SHOW_PNL_AFTER_FEES_KEY], - true - ); - - let [savedShouldDisableValidationForTesting, setSavedShouldDisableValidationForTesting] = useLocalStorageSerializeKey( - [chainId, DISABLE_ORDER_VALIDATION_KEY], - false - ); - if (!isDevelopment()) { - savedShouldDisableValidationForTesting = false; - } - - const [savedShouldShowPositionLines, setSavedShouldShowPositionLines] = useLocalStorageSerializeKey( - [chainId, SHOULD_SHOW_POSITION_LINES_KEY], - false - ); - const openSettings = useCallback(() => { - const slippage = parseInt(settings.savedAllowedSlippage); - setSlippageAmount(roundToTwoDecimals((slippage / BASIS_POINTS_DIVISOR) * 100)); - if (settings.executionFeeBufferBps !== undefined) { - const bps = settings.executionFeeBufferBps; - setExecutionFeeBufferBps(roundToTwoDecimals((bps / BASIS_POINTS_DIVISOR) * 100)); - } - setIsPnlInLeverage(savedIsPnlInLeverage); - setShowPnlAfterFees(savedShowPnlAfterFees); - setShowDebugValues(settings.showDebugValues); - setShouldDisableValidationForTesting(savedShouldDisableValidationForTesting); setIsSettingsVisible(true); - }, [ - savedIsPnlInLeverage, - savedShouldDisableValidationForTesting, - savedShowPnlAfterFees, - settings.executionFeeBufferBps, - settings.savedAllowedSlippage, - settings.showDebugValues, - ]); - - const saveAndCloseSettings = () => { - const slippage = parseFloat(slippageAmount); - if (isNaN(slippage)) { - helperToast.error(t`Invalid slippage value`); - return; - } - if (slippage > 5) { - helperToast.error(t`Slippage should be less than 5%`); - return; - } - const basisPoints = roundToTwoDecimals((slippage * BASIS_POINTS_DIVISOR) / 100); - if (parseInt(basisPoints) !== parseFloat(basisPoints)) { - helperToast.error(t`Max slippage precision is 0.01%`); - return; - } - - settings.setSavedAllowedSlippage(basisPoints); - - if (settings.shouldUseExecutionFeeBuffer) { - const executionFeeBuffer = parseFloat(executionFeeBufferBps); - if (isNaN(executionFeeBuffer) || executionFeeBuffer < 0) { - helperToast.error(t`Invalid execution fee buffer value`); - return; - } - const nextExecutionBufferFeeBps = roundToTwoDecimals((executionFeeBuffer * BASIS_POINTS_DIVISOR) / 100); - - if (parseInt(nextExecutionBufferFeeBps) !== parseFloat(nextExecutionBufferFeeBps)) { - helperToast.error(t`Max execution fee buffer precision is 0.01%`); - return; - } - - settings.setExecutionFeeBufferBps(nextExecutionBufferFeeBps); - } - - setSavedIsPnlInLeverage(isPnlInLeverage); - setSavedShowPnlAfterFees(showPnlAfterFees); - setSavedShouldDisableValidationForTesting(shouldDisableValidationForTesting); - setIsSettingsVisible(false); - settings.setShowDebugValues(showDebugValues); - }; + }, []); const localStorageCode = window.localStorage.getItem(REFERRAL_CODE_KEY); const baseUrl = getAppBaseUrl(); @@ -275,8 +176,6 @@ function FullApp() { } } - const [pendingTxns, setPendingTxns] = useState([]); - const showRedirectModal = (to) => { setRedirectModalVisible(true); setSelectedToPage(to); @@ -284,55 +183,6 @@ function FullApp() { useTradeRedirect({ chainId, tradePageVersion, setTradePageVersion }); - useEffect(() => { - const checkPendingTxns = async () => { - const updatedPendingTxns = []; - for (let i = 0; i < pendingTxns.length; i++) { - const pendingTxn = pendingTxns[i]; - const receipt = await signer.provider.getTransactionReceipt(pendingTxn.hash); - if (receipt) { - if (receipt.status === 0) { - const txUrl = getExplorerUrl(chainId) + "tx/" + pendingTxn.hash; - helperToast.error( -
- - Txn failed. View - -
-
- ); - } - - if (receipt.status === 1 && pendingTxn.message) { - const txUrl = getExplorerUrl(chainId) + "tx/" + pendingTxn.hash; - helperToast.success( -
- {pendingTxn.message}{" "} - - View - -
- {pendingTxn.messageDetails &&
} - {pendingTxn.messageDetails} -
- ); - } - continue; - } - updatedPendingTxns.push(pendingTxn); - } - - if (updatedPendingTxns.length !== pendingTxns.length) { - setPendingTxns(updatedPendingTxns); - } - }; - - const interval = setInterval(() => { - checkPendingTxns(); - }, 2 * 1000); - return () => clearInterval(interval); - }, [signer, pendingTxns, chainId]); - const { wsProvider } = useWebsocketProvider(); const vaultAddress = getContract(chainId, "Vault"); @@ -413,18 +263,21 @@ function FullApp() { + + + {getIsSyntheticsSupported(chainId) ? ( - + + + ) : ( )} @@ -459,19 +319,24 @@ function FullApp() { {getIsSyntheticsSupported(chainId) ? ( - + + + ) : ( )} @@ -481,7 +346,7 @@ function FullApp() { @@ -510,20 +375,31 @@ function FullApp() { - + - + + + - + + + {({ match }) => } @@ -574,118 +450,73 @@ function FullApp() { setShouldHideRedirectModal={setShouldHideRedirectModal} shouldHideRedirectModal={shouldHideRedirectModal} /> - -
-
- Allowed Slippage -
-
- setSlippageAmount(e.target.value)} - placeholder="0.3" - /> -
%
-
- {parseFloat(slippageAmount) < (DEFAULT_ALLOWED_SLIPPAGE_BPS / BASIS_POINTS_DIVISOR) * 100 && ( -
- - Allowed Slippage below {(DEFAULT_ALLOWED_SLIPPAGE_BPS / BASIS_POINTS_DIVISOR) * 100}% may result in - failed orders. - -
- )} -
- {settings.shouldUseExecutionFeeBuffer && ( -
-
- Max Execution Fee Buffer} - renderContent={() => ( -
- - The Max Execution Fee is set to a higher value to handle potential increases in gas price during - order execution. Any excess execution fee will be refunded to your account when the order is - executed. Only applicable to GMX V2. - -
-
- Read more -
- )} - /> -
-
- setExecutionFeeBufferBps(e.target.value)} - placeholder="10" - /> -
%
-
- {parseFloat(executionFeeBufferBps) < - (EXECUTION_FEE_CONFIG_V2[chainId].defaultBufferBps / BASIS_POINTS_DIVISOR) * 100 && ( -
- - Max Execution Fee buffer below{" "} - {(EXECUTION_FEE_CONFIG_V2[chainId].defaultBufferBps / BASIS_POINTS_DIVISOR) * 100}% may result in - failed orders. - -
- )} -
- )} -
- - Display PnL after fees - -
-
- - Include PnL in leverage display - -
-
- - - Chart positions - - -
- {isDevelopment() && ( -
- - Disable order validations - -
- )} - - {isDevelopment() && ( -
- - Show debug values - -
- )} - - -
+ ); } +const SWRConfigProp = { + refreshInterval: 5000, + refreshWhenHidden: false, + refreshWhenOffline: false, + use: [swrGCMiddleware], +}; + function App() { const { disconnect } = useDisconnect(); + const { signer } = useWallet(); + const { chainId } = useChainId(); + const [pendingTxns, setPendingTxns] = useState([]); + + useEffect(() => { + const checkPendingTxns = async () => { + const updatedPendingTxns = []; + for (let i = 0; i < pendingTxns.length; i++) { + const pendingTxn = pendingTxns[i]; + const receipt = await signer.provider.getTransactionReceipt(pendingTxn.hash); + if (receipt) { + if (receipt.status === 0) { + const txUrl = getExplorerUrl(chainId) + "tx/" + pendingTxn.hash; + helperToast.error( +
+ + Txn failed. View + +
+
+ ); + } + + if (receipt.status === 1 && pendingTxn.message) { + const txUrl = getExplorerUrl(chainId) + "tx/" + pendingTxn.hash; + helperToast.success( +
+ {pendingTxn.message}{" "} + + View + +
+ {pendingTxn.messageDetails &&
} + {pendingTxn.messageDetails} +
+ ); + } + continue; + } + updatedPendingTxns.push(pendingTxn); + } + + if (updatedPendingTxns.length !== pendingTxns.length) { + setPendingTxns(updatedPendingTxns); + } + }; + + const interval = setInterval(() => { + checkPendingTxns(); + }, 2 * 1000); + return () => clearInterval(interval); + }, [signer, pendingTxns, chainId]); useScrollToTop(); @@ -705,20 +536,14 @@ function App() { return () => unwatch(); }, [disconnect]); - let app = ; + let app = ; app = {app}; app = {app}; - app = {app}; + app = {app}; app = {app}; app = {app}; app = {app}; - app = ( - - {app} - - ); + app = {app}; return app; } diff --git a/src/App/App.scss b/src/App/App.scss index c9193b86e0..9976a841e0 100644 --- a/src/App/App.scss +++ b/src/App/App.scss @@ -162,6 +162,12 @@ $app-card-padding: 1.5rem; font-size: var(--font-base); } +.App-card-space-between { + display: flex; + flex-direction: column; + justify-content: space-between; +} + .App-card-bottom-placeholder { visibility: hidden; } @@ -407,6 +413,10 @@ button.App-connect-wallet:hover { height: 1px; background: #23263b; margin: 1.05rem -1.5rem; + + &:last-child { + display: none; + } } .line-divider { @@ -458,10 +468,6 @@ button.App-connect-wallet:hover { justify-content: flex-end; } -.settings-modal-error { - padding-bottom: 0.7rem; -} - .section-title-content .section-title-content__title { font-size: var(--font-lg); line-height: 3.1rem; @@ -921,41 +927,6 @@ button.App-button-option:disabled { align-items: center; } -.App-settings-row { - margin-bottom: 0.8rem; - font-size: var(--font-base); -} - -.App-settings .App-cta { - margin-top: 1.5rem; -} - -.App-settings { - .Modal-content { - width: 40rem; - } -} - -.App-slippage-tolerance-input-container { - position: relative; -} - -.App-slippage-tolerance-input { - border: 1px solid rgba(255, 255, 255, 0.1); - margin-top: 0.8rem; - margin-bottom: 0.8rem; - width: 100%; -} - -.App-slippage-tolerance-input-percent { - position: absolute; - right: 1.1rem; - width: 3.1rem; - top: 2.325rem; - bottom: 0; - text-align: right; -} - .Network-icon { vertical-align: middle; width: 1.85rem; diff --git a/src/abis/RewardRouter.json b/src/abis/RewardRouter.json index df9ed4ca3b..753059af32 100644 --- a/src/abis/RewardRouter.json +++ b/src/abis/RewardRouter.json @@ -280,6 +280,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "maxBoostBasisPoints", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "gmx", diff --git a/src/components/APRLabel/APRLabel.js b/src/components/APRLabel/APRLabel.js index 462b3c5e46..9c873795b4 100644 --- a/src/components/APRLabel/APRLabel.js +++ b/src/components/APRLabel/APRLabel.js @@ -18,9 +18,11 @@ import Token from "abis/Token.json"; import GlpManager from "abis/GlpManager.json"; import { useGmxPrice } from "domain/legacy"; +import { useMaxBoostBasicPoints } from "domain/rewards/useMaxBoostBasisPoints"; import { getContract } from "config/contracts"; import { getServerUrl } from "config/backend"; +import { BASIS_POINTS_DIVISOR } from "config/factors"; import { contractFetcher } from "lib/contracts"; import { formatKeyAmount } from "lib/numbers"; import useWallet from "lib/wallets/useWallet"; @@ -125,6 +127,8 @@ export default function APRLabel({ chainId, label }) { const { gmxPrice } = useGmxPrice(chainId, {}, active); + const maxBoostBasicPoints = useMaxBoostBasicPoints(); + const gmxSupplyUrl = getServerUrl(chainId, "/gmx_supply"); const { data: gmxSupply } = useSWR(gmxSupplyUrl, { fetcher: (url) => fetch(url).then((res) => res.text()), @@ -150,7 +154,8 @@ export default function APRLabel({ chainId, label }) { nativeTokenPrice, stakedGmxSupply, gmxPrice, - gmxSupply + gmxSupply, + maxBoostBasicPoints?.div(BASIS_POINTS_DIVISOR) ); return <>{`${formatKeyAmount(processedData, label, 2, 2, true)}%`}; diff --git a/src/components/AlertInfo/AlertInfo.scss b/src/components/AlertInfo/AlertInfo.scss new file mode 100644 index 0000000000..fa5eb5eb8b --- /dev/null +++ b/src/components/AlertInfo/AlertInfo.scss @@ -0,0 +1,21 @@ +.AlertInfo.compact { + margin-bottom: 0.8rem; +} + +.AlertInfo { + display: flex; + margin-bottom: 1.6rem; + + &-icon { + padding-right: 0.6rem; + padding-top: 0.2rem; + + img { + display: block; + } + } + + &-text { + font-size: 1.3rem; + } +} diff --git a/src/components/AlertInfo/AlertInfo.tsx b/src/components/AlertInfo/AlertInfo.tsx new file mode 100644 index 0000000000..4043006bf3 --- /dev/null +++ b/src/components/AlertInfo/AlertInfo.tsx @@ -0,0 +1,25 @@ +import { ReactNode } from "react"; +import cx from "classnames"; + +import infoIcon from "img/ic_info.svg"; +import warningIcon from "img/ic_warn.svg"; + +import "./AlertInfo.scss"; + +interface Props { + type: "warning" | "info"; + children: ReactNode; + compact?: boolean; +} + +export function AlertInfo({ compact = false, children, type }: Props) { + const icon = type === "warning" ? warningIcon : infoIcon; + return ( +
+
+ Alert Icon +
+
{children}
+
+ ); +} diff --git a/src/components/Banner/Banner.tsx b/src/components/Banner/Banner.tsx index 12d9bc71d3..e1217ba8a2 100644 --- a/src/components/Banner/Banner.tsx +++ b/src/components/Banner/Banner.tsx @@ -11,7 +11,7 @@ function Banner({ className }) { sparkle

) { @@ -65,7 +65,10 @@ export default function BuyInputSection(props: Props) { const labelElement = target.closest("[data-label]"); const labelClicked = labelElement ? labelElement.getAttribute("data-label") : null; - if (!(preventFocusOnLabelClick === labelClicked || preventFocusOnLabelClick === "both") && inputRef.current) { + const shouldPreventFocus = preventFocusOnLabelClick === labelClicked || preventFocusOnLabelClick === "both"; + const isMaxButtonClicked = target.classList.contains("Exchange-swap-max"); + + if (!shouldPreventFocus && !isMaxButtonClicked && inputRef.current) { inputRef.current.focus(); } } diff --git a/src/components/Common/SpinningLoader.js b/src/components/Common/SpinningLoader.js index f084e7f424..68efd515c4 100644 --- a/src/components/Common/SpinningLoader.js +++ b/src/components/Common/SpinningLoader.js @@ -1,9 +1,11 @@ import "./SpinningLoader.css"; import { ImSpinner2 } from "react-icons/im"; +import { useMemo } from "react"; function SpinningLoader({ size = "1.25rem" }) { - return ; + const style = useMemo(() => ({ fontSize: size }), [size]); + return ; } export default SpinningLoader; diff --git a/src/components/EventToast/EventToastContainer.js b/src/components/EventToast/EventToastContainer.js index 4c9438b581..e84b712845 100644 --- a/src/components/EventToast/EventToastContainer.js +++ b/src/components/EventToast/EventToastContainer.js @@ -1,25 +1,32 @@ import { Toaster } from "react-hot-toast"; +import { useMemo } from "react"; import { useWindowScroll, createBreakpoint } from "react-use"; +const TOAST_OPTIONS = { + duration: Infinity, +}; + function EventToastContainer() { let { y: scrollY } = useWindowScroll(); const useBreakpoint = createBreakpoint({ XL: 1033, L: 768, S: 350 }); const breakpoint = useBreakpoint(); + const containerStyle = useMemo( + () => ({ + zIndex: 2, + transition: "all 200ms", + top: scrollY > 60 ? "30px" : `${93 - scrollY}px`, + right: breakpoint === "XL" ? "30px" : "1rem", + }), + [breakpoint, scrollY] + ); return ( 60 ? "30px" : `${93 - scrollY}px`, - right: breakpoint === "XL" ? "30px" : "1rem", - }} - toastOptions={{ - duration: Infinity, - }} + containerStyle={containerStyle} + toastOptions={TOAST_OPTIONS} /> ); } diff --git a/src/components/EventToast/useEventToast.js b/src/components/EventToast/useEventToast.js index e585bc7a21..ff2af97e95 100644 --- a/src/components/EventToast/useEventToast.js +++ b/src/components/EventToast/useEventToast.js @@ -6,7 +6,7 @@ import EventToast from "./EventToast"; import { isFuture, parse } from "date-fns"; import { isHomeSite } from "lib/legacy"; import { useChainId } from "lib/chains"; -import { useMarketsInfo } from "domain/synthetics/markets"; +import { useMarketsInfoRequest } from "domain/synthetics/markets"; import useIncentiveStats from "domain/synthetics/common/useIncentiveStats"; import { ARBITRUM } from "config/chains"; import { getProvider } from "lib/rpc"; @@ -15,7 +15,7 @@ function useEventToast() { const isHome = isHomeSite(); const [visited, setVisited] = useLocalStorage("visited-announcements", []); const { chainId } = useChainId(); - const { marketsInfoData } = useMarketsInfo(chainId); + const { marketsInfoData } = useMarketsInfoRequest(chainId); const incentiveStats = useIncentiveStats(ARBITRUM); const [isArbitrumDown, setIsArbitrumDown] = useState(false); @@ -47,12 +47,9 @@ function useEventToast() { }, [marketsInfoData]); useEffect(() => { - const allIncentivesOn = Boolean( - incentiveStats?.lp?.isActive && incentiveStats?.migration?.isActive && incentiveStats?.trading?.isActive - ); + const allIncentivesOn = Boolean(incentiveStats?.lp?.isActive && incentiveStats?.trading?.isActive); const someIncentivesOn = - !allIncentivesOn && - Boolean(incentiveStats?.lp?.isActive || incentiveStats?.migration?.isActive || incentiveStats?.trading?.isActive); + !allIncentivesOn && Boolean(incentiveStats?.lp?.isActive || incentiveStats?.trading?.isActive); const validationParams = { "v2-adaptive-funding": isAdaptiveFundingActiveSomeMarkets, "v2-adaptive-funding-coming-soon": diff --git a/src/components/Exchange/ConfirmationBox.css b/src/components/Exchange/ConfirmationBox.css index 764f1e21cd..5b36e6c631 100644 --- a/src/components/Exchange/ConfirmationBox.css +++ b/src/components/Exchange/ConfirmationBox.css @@ -2,6 +2,8 @@ list-style: none; padding: 0; margin: 1rem 0; + display: grid; + grid-row-gap: 0.5rem; } .order-list li { display: flex; @@ -9,9 +11,14 @@ align-items: center; background: var(--dark-blue-hover); border-radius: var(--border-radius-sm); + padding: 0.5rem 0.5rem 0.5rem 1rem; + font-size: 1.3rem; +} + +.order-list li:not(:first-child) { margin-bottom: 0.5rem; - padding: 1rem; } + .order-list li p { margin: 0; } @@ -21,6 +28,8 @@ border: none; color: white; opacity: 0.8; + display: inline-flex; + padding: 0; } .order-list li button:hover { opacity: 1; diff --git a/src/components/Exchange/ConfirmationBox.js b/src/components/Exchange/ConfirmationBox.js index cf95aa2326..f5618c7e61 100644 --- a/src/components/Exchange/ConfirmationBox.js +++ b/src/components/Exchange/ConfirmationBox.js @@ -1,42 +1,49 @@ -import React, { useCallback, useState, useMemo, useRef, useEffect } from "react"; +import { Plural, Trans, t } from "@lingui/macro"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { BsArrowRight } from "react-icons/bs"; import { useKey } from "react-use"; -import "./ConfirmationBox.css"; + +import { cancelDecreaseOrder, handleCancelOrder } from "domain/legacy"; +import { getTokenInfo, getUsd } from "domain/tokens"; + +import { getConstant } from "config/chains"; +import { getContract } from "config/contracts"; import { - USD_DECIMALS, - PRECISION, + BASIS_POINTS_DIVISOR, + DEFAULT_HIGHER_SLIPPAGE_AMOUNT, + DEFAULT_SLIPPAGE_AMOUNT, + EXCESSIVE_SLIPPAGE_AMOUNT, +} from "config/factors"; +import { SLIPPAGE_BPS_KEY } from "config/localStorage"; +import { getPriceDecimals, getToken, getWrappedToken } from "config/tokens"; +import { TRIGGER_PREFIX_ABOVE, TRIGGER_PREFIX_BELOW } from "config/ui"; +import { + DECREASE, + INCREASE, LIMIT, MIN_PROFIT_TIME, - INCREASE, + PRECISION, + USD_DECIMALS, + calculatePositionDelta, getExchangeRate, getExchangeRateDisplay, - calculatePositionDelta, - DECREASE, } from "lib/legacy"; -import { DEFAULT_SLIPPAGE_AMOUNT, DEFAULT_HIGHER_SLIPPAGE_AMOUNT, EXCESSIVE_SLIPPAGE_AMOUNT } from "config/factors"; -import { BASIS_POINTS_DIVISOR } from "config/factors"; -import { getConstant } from "config/chains"; -import { getContract } from "config/contracts"; - -import { BsArrowRight } from "react-icons/bs"; -import Modal from "../Modal/Modal"; -import Tooltip from "../Tooltip/Tooltip"; -import Checkbox from "../Checkbox/Checkbox"; -import ExchangeInfoRow from "./ExchangeInfoRow"; -import { cancelDecreaseOrder, handleCancelOrder } from "domain/legacy"; -import StatsTooltipRow from "../StatsTooltip/StatsTooltipRow"; -import { TRIGGER_PREFIX_ABOVE, TRIGGER_PREFIX_BELOW } from "config/ui"; import { useLocalStorageSerializeKey } from "lib/localStorage"; -import { SLIPPAGE_BPS_KEY } from "config/localStorage"; import { bigNumberify, expandDecimals, formatAmount, formatPercentage } from "lib/numbers"; -import { getPriceDecimals, getToken, getWrappedToken } from "config/tokens"; -import { Plural, t, Trans } from "@lingui/macro"; +import useWallet from "lib/wallets/useWallet"; + import Button from "components/Button/Button"; -import FeesTooltip from "./FeesTooltip"; -import { getTokenInfo, getUsd } from "domain/tokens"; import PercentageInput from "components/PercentageInput/PercentageInput"; -import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; -import useWallet from "lib/wallets/useWallet"; import TokenWithIcon from "components/TokenIcon/TokenWithIcon"; +import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; +import Checkbox from "../Checkbox/Checkbox"; +import Modal from "../Modal/Modal"; +import StatsTooltipRow from "../StatsTooltip/StatsTooltipRow"; +import Tooltip from "../Tooltip/Tooltip"; +import ExchangeInfoRow from "./ExchangeInfoRow"; +import FeesTooltip from "./FeesTooltip"; + +import "./ConfirmationBox.css"; const HIGH_SPREAD_THRESHOLD = expandDecimals(1, USD_DECIMALS).div(100); // 1%; @@ -58,7 +65,7 @@ function getSwapSpreadInfo(fromTokenInfo, toTokenInfo, isLong, nativeTokenAddres } } -function renderAllowedSlippage(setAllowedSlippage, defaultSlippage) { +function renderAllowedSlippage(setAllowedSlippage, defaultSlippage, allowedSlippage) { return ( +
  • {type === INCREASE ? t`Increase` : t`Decrease`} {indexToken.symbol} {isLong ? t`Long` : t`Short`}{" "}  {triggerPricePrefix} ${formatAmount(triggerPrice, USD_DECIMALS, 2, true)} @@ -470,7 +478,7 @@ export default function ConfirmationBox(props) { const triggerPricePrefix = triggerAboveThreshold ? TRIGGER_PREFIX_ABOVE : TRIGGER_PREFIX_BELOW; const indexToken = getToken(chainId, order.indexToken); return ( -

  • +
  • {type === INCREASE ? t`Increase` : t`Decrease`} {indexToken.symbol} {isLong ? t`Long` : t`Short`}  {triggerPricePrefix} ${formatAmount(triggerPrice, USD_DECIMALS, 2, true)} @@ -623,6 +631,14 @@ export default function ConfirmationBox(props) { ); }, [toTokenInfo, shortCollateralToken, isShort, isLong, isSwap, toAmount, toUsdMax]); + const currentExecutionFees = useMemo( + () => ({ + fee: currentExecutionFee, + feeUsd: currentExecutionFeeUsd, + }), + [currentExecutionFee, currentExecutionFeeUsd] + ); + const renderMarginSection = useCallback(() => { const collateralToken = getToken(chainId, collateralTokenAddress); return ( @@ -656,7 +672,7 @@ export default function ConfirmationBox(props) { {!toAmount && leverage && leverage.gt(0) && `-`} {leverage && leverage.eq(0) && `-`} - {isMarketOrder && renderAllowedSlippage(setAllowedSlippage, savedSlippageAmount)} + {isMarketOrder && renderAllowedSlippage(setAllowedSlippage, savedSlippageAmount, allowedSlippage)} {showCollateralSpread && ( {formatAmount(collateralSpreadInfo.value.mul(100), USD_DECIMALS, 2, true)}% @@ -705,7 +721,7 @@ export default function ConfirmationBox(props) { renderContent={() => { return ( <> - Your position's collateral after deducting fees. + Your position's collateral after deducting fees:

    @@ -723,10 +739,7 @@ export default function ConfirmationBox(props) { @@ -745,44 +758,46 @@ export default function ConfirmationBox(props) { ); }, [ - renderMain, - nextAveragePrice, - toAmount, - hasExistingPosition, - existingPosition, - isMarketOrder, - triggerPriceUsd, - displayLiquidationPrice, - existingLiquidationPrice, - feesUsd, - leverage, chainId, + collateralTokenAddress, + renderMain, + renderCollateralSpreadWarning, renderFeeWarning, - hasPendingProfit, - isProfitWarningAccepted, - renderAvailableLiquidity, - orderOption, - fromUsdMin, - collateralAfterFees, renderExistingOrderWarning, - renderExistingTriggerWarning, renderExistingTriggerErrors, - isTriggerWarningAccepted, - decreaseOrdersThatWillBeExecuted, + renderExistingTriggerWarning, minExecutionFeeErrorMessage, - collateralTokenAddress, - entryMarkPrice, - positionFee, - swapFees, - currentExecutionFee, - currentExecutionFeeUsd, - renderCollateralSpreadWarning, - collateralSpreadInfo, - showCollateralSpread, + hasPendingProfit, + isMarketOrder, + isProfitWarningAccepted, + orderOption, + renderAvailableLiquidity, + hasExistingPosition, + toAmount, + existingPosition.leverage, + existingPosition.averagePrice, + leverage, savedSlippageAmount, - fundingRate, + showCollateralSpread, + collateralSpreadInfo.isHigh, + collateralSpreadInfo.value, existingPositionPriceDecimal, + nextAveragePrice, + entryMarkPrice, toTokenPriceDecimal, + triggerPriceUsd, + existingLiquidationPrice, + displayLiquidationPrice, + collateralAfterFees, + fundingRate, + currentExecutionFees, + positionFee, + swapFees, + decreaseOrdersThatWillBeExecuted.length, + isTriggerWarningAccepted, + fromUsdMin, + feesUsd, + allowedSlippage, ]); const renderSwapSection = useCallback(() => { @@ -797,7 +812,7 @@ export default function ConfirmationBox(props) { )} {orderOption === LIMIT && renderAvailableLiquidity()} - {isMarketOrder && renderAllowedSlippage(setAllowedSlippage, savedSlippageAmount)} + {isMarketOrder && renderAllowedSlippage(setAllowedSlippage, savedSlippageAmount, allowedSlippage)} {getExchangeRateDisplay(getExchangeRate(fromTokenInfo, toTokenInfo), fromTokenInfo, toTokenInfo)} @@ -827,15 +842,7 @@ export default function ConfirmationBox(props) { )} - + @@ -845,23 +852,24 @@ export default function ConfirmationBox(props) { ); }, [ renderMain, + renderFeeWarning, renderSwapSpreadWarning, + showSwapSpread, + spreadInfo.isHigh, + spreadInfo.value, + orderOption, + renderAvailableLiquidity, + isMarketOrder, + savedSlippageAmount, fromTokenInfo, toTokenInfo, - orderOption, - showSwapSpread, - spreadInfo, - feesUsd, + triggerRatio, fromTokenUsd, toTokenUsd, - triggerRatio, - isMarketOrder, + currentExecutionFees, + feesUsd, minOut, - renderFeeWarning, - renderAvailableLiquidity, - currentExecutionFee, - currentExecutionFeeUsd, - savedSlippageAmount, + allowedSlippage, ]); const submitButtonRef = useRef(null); diff --git a/src/components/Exchange/ExchangeInfo.tsx b/src/components/Exchange/ExchangeInfo.tsx new file mode 100644 index 0000000000..80235e0362 --- /dev/null +++ b/src/components/Exchange/ExchangeInfo.tsx @@ -0,0 +1,63 @@ +import React, { ReactNode } from "react"; + +interface ExchangeInfoProps { + children?: ReactNode; + divider?: ReactNode; + className?: string; +} + +interface ExchangeInfoGroupProps { + children?: ReactNode; +} + +const LINE_DIVIDER =

    ; + +function ExchangeInfo({ children, className, divider = LINE_DIVIDER }: ExchangeInfoProps) { + const childrenArr = React.Children.toArray(children) as React.ReactElement[]; + + return ( +
    + {childrenArr + .reduce((acc, child, index) => { + if (isExchangeInfoGroup(child)) { + const groupChildren = React.Children.toArray(child.props.children).filter(Boolean) as React.ReactElement[]; + + if (groupChildren.length) { + acc.push( + React.cloneElement(child, { + key: child.props.key ?? index, + children: groupChildren, + }) + ); + } + } else { + acc.push(child); + } + + return acc; + }, [] as React.ReactElement[]) + .map((child, index, arr) => { + const isLast = index === arr.length - 1; + + return ( + <> + {child} + {!isLast && divider} + + ); + })} +
    + ); +} + +function ExchangeInfoGroup({ children }: ExchangeInfoGroupProps) { + return <>{children}; +} + +function isExchangeInfoGroup(child: ReactNode) { + return React.isValidElement(child) && child.type === ExchangeInfoGroup; +} + +ExchangeInfo.Group = ExchangeInfoGroup; + +export { ExchangeInfo }; diff --git a/src/components/Exchange/ExchangeInfoRow.js b/src/components/Exchange/ExchangeInfoRow.js index 4bd4d5a12a..6280ecce01 100644 --- a/src/components/Exchange/ExchangeInfoRow.js +++ b/src/components/Exchange/ExchangeInfoRow.js @@ -6,7 +6,7 @@ export default function ExchangeInfoRow(props) { return (
    {label}
    -
    {children || value}
    +
    {children || value}
    ); } diff --git a/src/components/Exchange/ExchangeTVChart.js b/src/components/Exchange/ExchangeTVChart.js index 5ac8159d93..e64405c0ce 100644 --- a/src/components/Exchange/ExchangeTVChart.js +++ b/src/components/Exchange/ExchangeTVChart.js @@ -72,6 +72,7 @@ export default function ExchangeTVChart(props) { period = DEFAULT_PERIOD; } + // eslint-disable-next-line react/hook-use-state const [currentSeries] = useState(); const dataProvider = useRef(); diff --git a/src/components/Exchange/NetValueTooltip.tsx b/src/components/Exchange/NetValueTooltip.tsx index 514ca0d1f1..5457c5079c 100644 --- a/src/components/Exchange/NetValueTooltip.tsx +++ b/src/components/Exchange/NetValueTooltip.tsx @@ -4,6 +4,7 @@ import Tooltip from "components/Tooltip/Tooltip"; import { Position } from "domain/positions/types"; import { USD_DECIMALS } from "lib/legacy"; import { formatAmount } from "lib/numbers"; +import { useMemo } from "react"; type Props = { position: Position; @@ -11,6 +12,11 @@ type Props = { }; export default function NetValueTooltip({ position, isMobile }: Props) { + const pnlAfterFees = useMemo( + () => [position.deltaAfterFeesStr, `(${position.deltaAfterFeesPercentageStr})`], + [position.deltaAfterFeesPercentageStr, position.deltaAfterFeesStr] + ); + return ( diff --git a/src/components/Exchange/OrdersList.js b/src/components/Exchange/OrdersList.js index 0438f63d2a..ce3060f2c9 100644 --- a/src/components/Exchange/OrdersList.js +++ b/src/components/Exchange/OrdersList.js @@ -559,7 +559,7 @@ export default function OrdersList(props) { }, [orders, onEditClick, onCancelClick, infoTokens, positionsMap, hideActions, chainId, account]); return ( - + <> {renderHead()} @@ -589,6 +589,6 @@ export default function OrdersList(props) { savedShouldDisableValidationForTesting={savedShouldDisableValidationForTesting} /> )} - + ); } diff --git a/src/components/Exchange/PositionEditor.js b/src/components/Exchange/PositionEditor.js index 5b83befa65..fe5f5fe29f 100644 --- a/src/components/Exchange/PositionEditor.js +++ b/src/components/Exchange/PositionEditor.js @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState, useMemo } from "react"; import useSWR from "swr"; import { Trans, t } from "@lingui/macro"; import { ethers } from "ethers"; @@ -38,6 +38,15 @@ const EDIT_OPTIONS = [DEPOSIT, WITHDRAW]; const MIN_ORDER_USD = expandDecimals(10, USD_DECIMALS); const { AddressZero } = ethers.constants; +const EDIT_OPTIONS_LABELS = { + [DEPOSIT]: t`Deposit`, + [WITHDRAW]: t`Withdraw`, +}; +const ERROR_TOOLTIP_MSG = { + [ErrorCode.InvalidLiqPrice]: t`Liquidation price would cross mark price.`, + [ErrorCode.InsufficientDepositAmount]: t`Deposit amount is insufficient to bring leverage below the max allowed leverage of 100x`, +}; + export default function PositionEditor(props) { const { pendingPositions, @@ -480,15 +489,6 @@ export default function PositionEditor(props) { withdrawCollateral(); }; - const EDIT_OPTIONS_LABELS = { - [DEPOSIT]: t`Deposit`, - [WITHDRAW]: t`Withdraw`, - }; - const ERROR_TOOLTIP_MSG = { - [ErrorCode.InvalidLiqPrice]: t`Liquidation price would cross mark price.`, - [ErrorCode.InsufficientDepositAmount]: t`Deposit amount is insufficient to bring leverage below the max allowed leverage of 100x`, - }; - function renderPrimaryButton() { const [errorMessage, errorType, errorCode] = getError(); const primaryTextMessage = getPrimaryText(); @@ -514,6 +514,14 @@ export default function PositionEditor(props) { ); } + const minExecutionFees = useMemo( + () => ({ + fee: minExecutionFee, + feeUsd: minExecutionFeeUSD, + }), + [minExecutionFee, minExecutionFeeUSD] + ); + return (
    {position && ( @@ -683,13 +691,7 @@ export default function PositionEditor(props) { Fees
    - +
    diff --git a/src/components/Exchange/PositionSeller.js b/src/components/Exchange/PositionSeller.js index 05bbd218cf..fb94f4e449 100644 --- a/src/components/Exchange/PositionSeller.js +++ b/src/components/Exchange/PositionSeller.js @@ -6,11 +6,21 @@ import { BsArrowRight } from "react-icons/bs"; import PositionRouter from "abis/PositionRouter.json"; import Button from "components/Button/Button"; +import BuyInputSection from "components/BuyInputSection/BuyInputSection"; import PercentageInput from "components/PercentageInput/PercentageInput"; import ToggleSwitch from "components/ToggleSwitch/ToggleSwitch"; import TokenSelector from "components/TokenSelector/TokenSelector"; +import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; import { ARBITRUM, IS_NETWORK_DISABLED, getChainName, getConstant } from "config/chains"; import { getContract } from "config/contracts"; +import { + BASIS_POINTS_DIVISOR, + DEFAULT_HIGHER_SLIPPAGE_AMOUNT, + DEFAULT_SLIPPAGE_AMOUNT, + EXCESSIVE_SLIPPAGE_AMOUNT, + MAX_ALLOWED_LEVERAGE, + MAX_LEVERAGE, +} from "config/factors"; import { CLOSE_POSITION_RECEIVE_TOKEN_KEY, SLIPPAGE_BPS_KEY } from "config/localStorage"; import { getPriceDecimals, getV1Tokens, getWrappedToken } from "config/tokens"; import { TRIGGER_PREFIX_ABOVE, TRIGGER_PREFIX_BELOW } from "config/ui"; @@ -35,8 +45,6 @@ import { getProfitPrice, isAddressZero, } from "lib/legacy"; -import { DEFAULT_HIGHER_SLIPPAGE_AMOUNT, DEFAULT_SLIPPAGE_AMOUNT, EXCESSIVE_SLIPPAGE_AMOUNT } from "config/factors"; -import { BASIS_POINTS_DIVISOR, MAX_ALLOWED_LEVERAGE, MAX_LEVERAGE } from "config/factors"; import { useLocalStorageByChainId, useLocalStorageSerializeKey } from "lib/localStorage"; import { bigNumberify, @@ -58,14 +66,17 @@ import ExchangeInfoRow from "./ExchangeInfoRow"; import FeesTooltip from "./FeesTooltip"; import "./PositionSeller.css"; import { ErrorCode, ErrorDisplayType } from "./constants"; -import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; -import BuyInputSection from "components/BuyInputSection/BuyInputSection"; const { AddressZero } = ethers.constants; const ORDER_SIZE_DUST_USD = expandDecimals(1, USD_DECIMALS - 1); // $0.10 const HIGH_SPREAD_THRESHOLD = expandDecimals(1, USD_DECIMALS).div(100); // 1%; +const ORDER_OPTION_LABELS = { + [MARKET]: t`Market`, + [STOP]: t`Trigger`, +}; + function applySpread(amount, spread) { if (!amount || !spread) { return amount; @@ -239,11 +250,8 @@ export default function PositionSeller(props) { savedRecieveTokenAddress ? toTokens.find((token) => token.address === savedRecieveTokenAddress) : undefined ); - const ORDER_OPTIONS = [MARKET, STOP]; - const ORDER_OPTION_LABELS = { - [MARKET]: t`Market`, - [STOP]: t`Trigger`, - }; + const ORDER_OPTIONS = useMemo(() => [MARKET, STOP], []); + let [orderOption, setOrderOption] = useState(MARKET); if (!flagOrdersEnabled) { @@ -365,8 +373,20 @@ export default function PositionSeller(props) { setSavedRecieveTokenAddress, ]); - let executionFee = orderOption === STOP ? getConstant(chainId, "DECREASE_ORDER_EXECUTION_GAS_FEE") : minExecutionFee; - let executionFeeUsd = getUsd(executionFee, nativeTokenAddress, false, infoTokens) || bigNumberify(0); + const executionFee = + orderOption === STOP ? getConstant(chainId, "DECREASE_ORDER_EXECUTION_GAS_FEE") : minExecutionFee; + const executionFeeUsd = useMemo( + () => getUsd(executionFee, nativeTokenAddress, false, infoTokens) || bigNumberify(0), + [executionFee, infoTokens, nativeTokenAddress] + ); + + const executionFees = useMemo( + () => ({ + fee: executionFee, + feeUsd: executionFeeUsd, + }), + [executionFee, executionFeeUsd] + ); const collateralToken = position.collateralToken; const collateralTokenInfo = getTokenInfo(infoTokens, collateralToken.address); @@ -429,7 +449,7 @@ export default function PositionSeller(props) { a position has profit or loss and how much fees it has. The following logic counters the backend logic and determines the exact collateralDelta to be passed so that ultimately the nextCollateral value generated will keep leverage the same. - + The backend logic can be found in reduceCollateral function at https://github.com/gmx-io/gmx-contracts/blob/master/contracts/core/Vault.sol#L992 */ @@ -1123,6 +1143,7 @@ export default function PositionSeller(props) { > @@ -1285,7 +1303,7 @@ export default function PositionSeller(props) { {formatAmount(receiveSpreadInfo.value.mul(100), USD_DECIMALS, 2, true)}% )} -
    +
    Receive
    @@ -1346,6 +1364,7 @@ export default function PositionSeller(props) {
    ( const { code, success } = userAffiliateCode; const positionPriceDecimal = getPriceDecimals(chainId, indexToken.symbol); const homeURL = getHomeUrl(); + const style = useMemo(() => ({ backgroundImage: `url(${sharePositionBgImg})` }), [sharePositionBgImg]); return (
    -
    +
    GMX Logo
    • {isLong ? "LONG" : "SHORT"}
    • diff --git a/src/components/Exchange/SwapBox.js b/src/components/Exchange/SwapBox.js index b63ba606aa..70328c59d3 100644 --- a/src/components/Exchange/SwapBox.js +++ b/src/components/Exchange/SwapBox.js @@ -114,6 +114,14 @@ function getNextAveragePrice({ size, sizeDelta, hasProfit, delta, nextPrice, isL return nextAveragePrice; } +const SWAP_LABELS = { + [LONG]: t`Long`, + [SHORT]: t`Short`, + [SWAP]: t`Swap`, +}; + +const ORDER_OPTION_LABELS = { [STOP]: t`Trigger`, [MARKET]: t`Market`, [LIMIT]: t`Limit` }; + export default function SwapBox(props) { const { pendingPositions, @@ -203,6 +211,7 @@ export default function SwapBox(props) { [chainId, "Exchange-swap-leverage-option"], "2" ); + const [isLeverageSliderEnabled, setIsLeverageSliderEnabled] = useLocalStorageSerializeKey( [chainId, "Exchange-swap-leverage-slider-enabled"], true @@ -223,7 +232,6 @@ export default function SwapBox(props) { const isMarketOrder = orderOption === MARKET; const orderOptions = isSwap ? SWAP_ORDER_OPTIONS : LEVERAGE_ORDER_OPTIONS; - const orderOptionLabels = { [STOP]: t`Trigger`, [MARKET]: t`Market`, [LIMIT]: t`Limit` }; const [triggerPriceValue, setTriggerPriceValue] = useState(""); const triggerPriceUsd = isMarketOrder ? 0 : parseValue(triggerPriceValue, USD_DECIMALS); @@ -1710,6 +1718,36 @@ export default function SwapBox(props) { feeBps = feeBasisPoints; } + const maxInValue = useMemo( + () => [ + `${formatAmount(maxFromTokenIn, fromTokenInfo.decimals, 0, true)} ${fromTokenInfo.symbol}`, + `($${formatAmount(maxFromTokenInUSD, USD_DECIMALS, 0, true)})`, + ], + [fromTokenInfo.decimals, fromTokenInfo.symbol, maxFromTokenIn, maxFromTokenInUSD] + ); + const maxOutValue = useMemo( + () => [ + `${formatAmount(maxToTokenOut, toTokenInfo.decimals, 0, true)} ${toTokenInfo.symbol}`, + `($${formatAmount(maxToTokenOutUSD, USD_DECIMALS, 0, true)})`, + ], + [maxToTokenOut, maxToTokenOutUSD, toTokenInfo.decimals, toTokenInfo.symbol] + ); + + const SWAP_ORDER_EXECUTION_GAS_FEE = getConstant(chainId, "SWAP_ORDER_EXECUTION_GAS_FEE"); + const INCREASE_ORDER_EXECUTION_GAS_FEE = getConstant(chainId, "INCREASE_ORDER_EXECUTION_GAS_FEE"); + const executionFee = isSwap ? SWAP_ORDER_EXECUTION_GAS_FEE : INCREASE_ORDER_EXECUTION_GAS_FEE; + const executionFeeUsd = getUsd(executionFee, nativeTokenAddress, false, infoTokens); + const currentExecutionFee = isMarketOrder ? minExecutionFee : executionFee; + const currentExecutionFeeUsd = isMarketOrder ? minExecutionFeeUSD : executionFeeUsd; + + const executionFees = useMemo( + () => ({ + fee: currentExecutionFee, + feeUsd: currentExecutionFeeUsd, + }), + [currentExecutionFee, currentExecutionFeeUsd] + ); + if (!fromToken || !toToken) { return null; } @@ -1873,19 +1911,6 @@ export default function SwapBox(props) { ), }; - const SWAP_LABELS = { - [LONG]: t`Long`, - [SHORT]: t`Short`, - [SWAP]: t`Swap`, - }; - - const SWAP_ORDER_EXECUTION_GAS_FEE = getConstant(chainId, "SWAP_ORDER_EXECUTION_GAS_FEE"); - const INCREASE_ORDER_EXECUTION_GAS_FEE = getConstant(chainId, "INCREASE_ORDER_EXECUTION_GAS_FEE"); - const executionFee = isSwap ? SWAP_ORDER_EXECUTION_GAS_FEE : INCREASE_ORDER_EXECUTION_GAS_FEE; - const executionFeeUsd = getUsd(executionFee, nativeTokenAddress, false, infoTokens); - const currentExecutionFee = isMarketOrder ? minExecutionFee : executionFee; - const currentExecutionFeeUsd = isMarketOrder ? minExecutionFeeUSD : executionFeeUsd; - const existingCurrentIndexShortPosition = isShort && positions @@ -1949,7 +1974,7 @@ export default function SwapBox(props) { {flagOrdersEnabled && ( {showFromAndToSection && ( - + <> - + )} {showTriggerRatioSection && (
      {!fees && "-"} - {fees && ( - - )} + {fees && }
    @@ -2221,10 +2236,7 @@ export default function SwapBox(props) { {feesUsd && ( {collateralToken.symbol} is required for collateral.} @@ -2288,20 +2300,8 @@ export default function SwapBox(props) { renderContent={() => { return (
    - - + +
    ); }} diff --git a/src/components/Glp/GlpSwap.js b/src/components/Glp/GlpSwap.js index 46dfd3da6a..fbbaae6d9b 100644 --- a/src/components/Glp/GlpSwap.js +++ b/src/components/Glp/GlpSwap.js @@ -137,6 +137,7 @@ function getTooltipContent(managedUsd, tokenInfo, token) { <> { const shouldShowIncentivesNote = useLpIncentivesIsActive(); const daysConsidered = useDaysConsideredInMarketsApr(); + const walletTotalValue = useMemo( + () => [ + formatTokenAmount(balance, 18, "GM", { + useCommas: true, + fallbackToZero: true, + }), + `(${formatUsd(balanceUsd)})`, + ], + [balance, balanceUsd] + ); + + const renderTooltipContent = useCallback(() => { + return ( + <> + + {userEarnings && ( + <> + + + {userEarnings.allMarkets.expected365d.gt(0) && ( + <> + +
    +
    + Expected 365d Fees are projected based on past {daysConsidered}d base APR. +
    + {shouldShowIncentivesNote && ( + <> +
    +
    + Fee values do not include incentives. +
    + + )} + + )} + + )} + + ); + }, [daysConsidered, shouldShowIncentivesNote, userEarnings, walletTotalValue]); + return balance && balanceUsd ? ( ( - <> - - {userEarnings && ( - <> - - - {userEarnings.allMarkets.expected365d.gt(0) && ( - <> - -
    -
    - Expected 365d Fees are projected based on past {daysConsidered}d base APR. -
    - {shouldShowIncentivesNote && ( - <> -
    -
    - Fee values do not include incentives. -
    - - )} - - )} - - )} - - )} + renderContent={renderTooltipContent} /> ) : ( <>{label} diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index a3223b9929..33ab82d903 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -20,16 +20,18 @@ const AnimatePresence = (props: React.ComponentProps ); -const fadeVariants = { +const FADE_VARIANTS = { hidden: { opacity: 0 }, visible: { opacity: 1 }, }; -const slideVariants = { +const SLIDE_VARIANTS = { hidden: { x: "-100%" }, visible: { x: 0 }, }; +const TRANSITION = { duration: 0.2 }; + type Props = { disconnectAccountAndCloseSettings: () => void; openSettings: () => void; @@ -70,8 +72,8 @@ export function Header({ initial="hidden" animate="visible" exit="hidden" - variants={fadeVariants} - transition={{ duration: 0.2 }} + variants={FADE_VARIANTS} + transition={TRANSITION} onClick={() => setIsDrawerVisible(!isDrawerVisible)} > )} @@ -85,8 +87,8 @@ export function Header({ initial="hidden" animate="visible" exit="hidden" - variants={fadeVariants} - transition={{ duration: 0.2 }} + variants={FADE_VARIANTS} + transition={TRANSITION} onClick={() => setIsNativeSelectorModalVisible(!isNativeSelectorModalVisible)} > )} @@ -152,8 +154,8 @@ export function Header({ initial="hidden" animate="visible" exit="hidden" - variants={slideVariants} - transition={{ duration: 0.2 }} + variants={SLIDE_VARIANTS} + transition={TRANSITION} > {isHomeSite() ? ( void; redirectPopupTimestamp: number; onClick?: MouseEventHandler; diff --git a/src/components/LeverageSlider/LeverageSlider.tsx b/src/components/LeverageSlider/LeverageSlider.tsx index 076a77b389..6fc4dc2954 100644 --- a/src/components/LeverageSlider/LeverageSlider.tsx +++ b/src/components/LeverageSlider/LeverageSlider.tsx @@ -1,30 +1,64 @@ import cx from "classnames"; -import { BASIS_POINTS_DIVISOR, MAX_ALLOWED_LEVERAGE } from "config/factors"; import Slider, { SliderTooltip, Handle } from "rc-slider"; import "rc-slider/assets/index.css"; import "./LeverageSlider.scss"; +import { range } from "lodash"; +import { useCallback, useEffect, useMemo } from "react"; -const leverageMarks = { - 2: "2x", - 5: "5x", - 10: "10x", - 15: "15x", - 20: "20x", - 25: "25x", - 30: "30x", - 35: "35x", - 40: "40x", - 45: "45x", - 50: "50x", -}; +const defaultMarks = [1.1, 2, 5, 10, 15, 20, 25, 30, 35, 40, 50]; +const DEFAULT_LEVERAGE_KEY = 20; type Props = { isPositive?: boolean; value?: number; onChange: (value: number) => void; + marks: number[]; +}; + +type HandleProps = { + value: number; + dragging: boolean; + index: number; + keyValueMap: { [key: number]: number }; }; +function getMarksWithLabel(marks: number[]) { + return marks.reduce((marks, value, index) => { + marks[index * 10] = `${value}x`; + return marks; + }, {} as { [key: number]: string }); +} + export function LeverageSlider(p: Props) { + const { onChange, value, marks } = p; + const finalMarks = marks ?? defaultMarks; + + const { marksLabel, keyValueMap, valueKeyMap } = useMemo(() => { + const marksLabel = getMarksWithLabel(finalMarks); + const { keyValueMap, valueKeyMap } = generateKeyValueMap(finalMarks); + return { marksLabel, keyValueMap, valueKeyMap }; + }, [finalMarks]); + + const defaultValue = valueKeyMap[value ?? 0] ?? DEFAULT_LEVERAGE_KEY; + const max = (finalMarks.length - 1) * 10; + + const handleChange = useCallback( + (value: number) => { + onChange(keyValueMap[value ?? 0] ?? DEFAULT_LEVERAGE_KEY); + }, + [onChange, keyValueMap] + ); + + useEffect(() => { + if (value !== defaultValue) { + handleChange(defaultValue); + } + }, [value, defaultValue, handleChange]); + + const customHandle = useMemo(() => { + return (props: any) => ; + }, [keyValueMap]); + return (
    ); } -function LeverageSliderHandle({ value, dragging, index, ...restProps }: any) { +function LeverageSliderHandle({ value, dragging, index, keyValueMap, ...restProps }: HandleProps) { + const displayValue = keyValueMap[value || 0] ?? DEFAULT_LEVERAGE_KEY; + + useEffect(() => { + if (dragging) { + document.body.classList.add("dragging"); + } else { + document.body.classList.remove("dragging"); + } + }, [dragging]); + return ( ); } + +function generateEquallySpacedArray(min: number, max: number, shouldIncludeMax?: boolean): number[] { + const step = (max - min) / 10; + let array = range(min, max, step).map((num) => parseFloat(num.toFixed(1))); + + if (shouldIncludeMax && array[array.length - 1] !== max) { + array.push(max); + } + + return array; +} + +function generateKeyValueMap(marks: number[]) { + const values = marks.slice(0, -1).flatMap((mark, index) => { + const shouldIncludeMax = index === marks.length - 2; + return generateEquallySpacedArray(mark, marks[index + 1], shouldIncludeMax); + }); + + const keyValueMap = Object.fromEntries(values.map((value, index) => [index, value])); + const valueKeyMap = Object.fromEntries(values.map((value, index) => [value, index])); + + return { keyValueMap, valueKeyMap }; +} diff --git a/src/components/MarketSelector/MarketSelector.tsx b/src/components/MarketSelector/MarketSelector.tsx index 01363f1f2b..8b020c14f3 100644 --- a/src/components/MarketSelector/MarketSelector.tsx +++ b/src/components/MarketSelector/MarketSelector.tsx @@ -1,6 +1,6 @@ import { t } from "@lingui/macro"; import cx from "classnames"; -import { MarketInfo, MarketsInfoData, getMarketIndexName } from "domain/synthetics/markets"; +import { MarketInfo, getMarketIndexName } from "domain/synthetics/markets"; import { TokensData, convertToUsd } from "domain/synthetics/tokens"; import { BigNumber } from "ethers"; import { importImage } from "lib/legacy"; @@ -18,9 +18,7 @@ type Props = { className?: string; selectedIndexName?: string; markets: MarketInfo[]; - marketsInfoData?: MarketsInfoData; marketTokensData?: TokensData; - disabled?: boolean; showBalances?: boolean; selectedMarketLabel?: ReactNode | string; isSideMenu?: boolean; diff --git a/src/components/MarketSelector/PoolSelector.tsx b/src/components/MarketSelector/PoolSelector.tsx index e065129230..c5ca835c03 100644 --- a/src/components/MarketSelector/PoolSelector.tsx +++ b/src/components/MarketSelector/PoolSelector.tsx @@ -1,6 +1,9 @@ import { t } from "@lingui/macro"; import cx from "classnames"; -import { MarketInfo, MarketsInfoData, getMarketIndexName, getMarketPoolName } from "domain/synthetics/markets"; +import SearchInput from "components/SearchInput/SearchInput"; +import TokenIcon from "components/TokenIcon/TokenIcon"; +import { getNormalizedTokenSymbol } from "config/tokens"; +import { MarketInfo, getMarketIndexName, getMarketPoolName } from "domain/synthetics/markets"; import { TokensData, convertToUsd } from "domain/synthetics/tokens"; import { BigNumber } from "ethers"; import { formatTokenAmount, formatUsd } from "lib/numbers"; @@ -10,9 +13,6 @@ import { BiChevronDown } from "react-icons/bi"; import Modal from "../Modal/Modal"; import TooltipWithPortal from "../Tooltip/TooltipWithPortal"; import "./MarketSelector.scss"; -import SearchInput from "components/SearchInput/SearchInput"; -import TokenIcon from "components/TokenIcon/TokenIcon"; -import { getNormalizedTokenSymbol } from "config/tokens"; type Props = { label?: string; @@ -20,9 +20,7 @@ type Props = { selectedMarketAddress?: string; selectedIndexName?: string; markets: MarketInfo[]; - marketsInfoData?: MarketsInfoData; marketTokensData?: TokensData; - disabled?: boolean; showBalances?: boolean; isSideMenu?: boolean; getMarketState?: (market: MarketInfo) => MarketState | undefined; diff --git a/src/components/Modal/Modal.css b/src/components/Modal/Modal.css index ef5a2f85b0..5054f6ee72 100644 --- a/src/components/Modal/Modal.css +++ b/src/components/Modal/Modal.css @@ -84,8 +84,3 @@ .Modal-close-icon:hover { opacity: 0.9; } - -.Modal-note { - margin-bottom: 1.5rem; - margin-top: 0.8rem; -} diff --git a/src/components/Modal/Modal.js b/src/components/Modal/Modal.tsx similarity index 64% rename from src/components/Modal/Modal.js rename to src/components/Modal/Modal.tsx index 318f140a85..b840d94cc0 100644 --- a/src/components/Modal/Modal.js +++ b/src/components/Modal/Modal.tsx @@ -1,17 +1,45 @@ -import "./Modal.css"; -import React, { useRef, useEffect } from "react"; +import React, { useRef, useEffect, useMemo, PropsWithChildren } from "react"; import cx from "classnames"; import { motion, AnimatePresence } from "framer-motion"; import { RemoveScroll } from "react-remove-scroll"; import { MdClose } from "react-icons/md"; -export default function Modal(props) { +import "./Modal.css"; + +const FADE_VARIANTS = { + hidden: { opacity: 0 }, + visible: { opacity: 1 }, +}; + +const VISIBLE_STYLES: React.CSSProperties = { + overflow: "hidden", + position: "fixed", +}; + +const HIDDEN_STYLES: React.CSSProperties = { + overflow: "visible", + position: "fixed", +}; + +const TRANSITION = { duration: 0.2 }; + +export type ModalProps = PropsWithChildren<{ + isVisible?: boolean; + setIsVisible: (isVisible: boolean) => void; + className?: string; + zIndex?: number; + onAfterOpen?: () => void; + label?: React.ReactNode; + headerContent?: () => React.ReactNode; +}>; + +export default function Modal(props: ModalProps) { const { isVisible, setIsVisible, className, zIndex, onAfterOpen } = props; const modalRef = useRef(null); useEffect(() => { - function close(e) { + function close(e: KeyboardEvent) { if (e.keyCode === 27 && setIsVisible) { setIsVisible(false); } @@ -24,29 +52,24 @@ export default function Modal(props) { if (typeof onAfterOpen === "function") onAfterOpen(); }, [onAfterOpen]); - const fadeVariants = { - hidden: { opacity: 0 }, - visible: { opacity: 1 }, - }; + const style = useMemo(() => ({ zIndex }), [zIndex]); return ( + // @ts-ignore {isVisible && (
    setIsVisible(false)} >
    diff --git a/src/components/Modal/ModalWithPortal.js b/src/components/Modal/ModalWithPortal.tsx similarity index 50% rename from src/components/Modal/ModalWithPortal.js rename to src/components/Modal/ModalWithPortal.tsx index 001e24d843..2b7e77efd7 100644 --- a/src/components/Modal/ModalWithPortal.js +++ b/src/components/Modal/ModalWithPortal.tsx @@ -1,7 +1,7 @@ import Portal from "../Common/Portal"; -import Modal from "./Modal"; +import Modal, { type ModalProps } from "./Modal"; -export default function ModalWithPortal(props) { +export default function ModalWithPortal(props: ModalProps) { return ( diff --git a/src/components/NetworkDropdown/NetworkDropdown.tsx b/src/components/NetworkDropdown/NetworkDropdown.tsx index de78fa753b..805b2fe9b1 100644 --- a/src/components/NetworkDropdown/NetworkDropdown.tsx +++ b/src/components/NetworkDropdown/NetworkDropdown.tsx @@ -1,20 +1,26 @@ -import React, { useRef, useState } from "react"; import { Menu } from "@headlessui/react"; -import ModalWithPortal from "../Modal/ModalWithPortal"; -import { t, Trans } from "@lingui/macro"; +import { Trans, t } from "@lingui/macro"; import cx from "classnames"; +import noop from "lodash/noop"; +import { useRef, useState } from "react"; import { HiDotsVertical } from "react-icons/hi"; -import "./NetworkDropdown.css"; -import language24Icon from "img/ic_language24.svg"; -import settingsIcon from "img/ic_settings_16.svg"; -import { defaultLocale } from "lib/i18n"; + +import { getIcon } from "config/icons"; import { LANGUAGE_LOCALSTORAGE_KEY } from "config/localStorage"; -import LanguageModalContent from "./LanguageModalContent"; import { useChainId } from "lib/chains"; -import { getIcon } from "config/icons"; +import { defaultLocale } from "lib/i18n"; import { switchNetwork } from "lib/wallets"; import useWallet from "lib/wallets/useWallet"; +import type { ModalProps } from "components/Modal/Modal"; +import ModalWithPortal from "../Modal/ModalWithPortal"; +import LanguageModalContent from "./LanguageModalContent"; + +import language24Icon from "img/ic_language24.svg"; +import settingsIcon from "img/ic_settings_16.svg"; + +import "./NetworkDropdown.css"; + const LANGUAGE_MODAL_KEY = "LANGUAGE"; const NETWORK_MODAL_KEY = "NETWORK"; @@ -40,7 +46,7 @@ export default function NetworkDropdown(props) { } } - function getModalProps(modalName) { + function getModalProps(modalName: string | null): ModalProps { switch (modalName) { case LANGUAGE_MODAL_KEY: return { @@ -57,7 +63,9 @@ export default function NetworkDropdown(props) { label: t`Networks and Settings`, }; default: - return {}; + return { + setIsVisible: noop, + }; } } diff --git a/src/components/PercentageInput/PercentageInput.scss b/src/components/PercentageInput/PercentageInput.scss index 3290982587..ffecfd500b 100644 --- a/src/components/PercentageInput/PercentageInput.scss +++ b/src/components/PercentageInput/PercentageInput.scss @@ -8,7 +8,7 @@ right: 0; padding: 0; top: 1.25rem; - z-index: 1; + z-index: 2; background: #212540; li { @@ -58,24 +58,6 @@ opacity: 0.7; } } - - .Percentage-input-error { - display: none; - } - - &:hover .Percentage-input-error { - display: block; - } - - &:hover .Percentage-input-error::before { - content: ""; - position: absolute; - top: -1rem; - left: 0; - width: 100%; - height: 1rem; - background: transparent; - } } .Percentage-input-negative-sign { diff --git a/src/components/PercentageInput/PercentageInput.tsx b/src/components/PercentageInput/PercentageInput.tsx index c8d5020ee6..46bdeb3d8a 100644 --- a/src/components/PercentageInput/PercentageInput.tsx +++ b/src/components/PercentageInput/PercentageInput.tsx @@ -1,10 +1,15 @@ import cx from "classnames"; +import { ChangeEvent, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from "react"; + import { BASIS_POINTS_DIVISOR } from "config/factors"; import { roundToTwoDecimals } from "lib/numbers"; -import { ChangeEvent, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from "react"; + +import type { TooltipPosition } from "components/Tooltip/Tooltip"; +import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; + import "./PercentageInput.scss"; -const validDecimalRegex = /^\d+(\.\d{0,2})?$/; // 0.00 ~ 99.99 +export const NUMBER_WITH_TWO_DECIMALS = /^\d+(\.\d{0,2})?$/; // 0.00 ~ 99.99 function getValueText(value: number) { return roundToTwoDecimals((value / BASIS_POINTS_DIVISOR) * 100).toString(); @@ -21,6 +26,8 @@ type Props = { highValueWarningText?: ReactNode; negativeSign?: boolean; highValueCheckStrategy?: "gte" | "gt"; + value?: number; + tooltipPosition?: TooltipPosition; }; const DEFAULT_SUGGESTIONS = [0.3, 0.5, 1, 1.5]; @@ -28,6 +35,7 @@ const DEFAULT_SUGGESTIONS = [0.3, 0.5, 1, 1.5]; export default function PercentageInput({ onChange, defaultValue, + value, maxValue = 99 * 100, highValue, lowValue, @@ -36,18 +44,19 @@ export default function PercentageInput({ lowValueWarningText, negativeSign, highValueCheckStrategy: checkStrategy = "gte", + tooltipPosition, }: Props) { - const [inputValue, setInputvalue] = useState(() => getValueText(defaultValue)); const [isPanelVisible, setIsPanelVisible] = useState(false); - - useEffect(() => { - setInputvalue(getValueText(defaultValue)); - }, [defaultValue]); + const [inputValue, setInputValue] = useState(() => (value === undefined ? "" : getValueText(value))); + const inputRef = useRef(null); + const handleSignClick = useCallback(() => { + inputRef.current?.focus(); + }, []); function handleChange(event: ChangeEvent) { const { value } = event.target; if (value === "") { - setInputvalue(value); + setInputValue(""); onChange(defaultValue); return; } @@ -59,16 +68,36 @@ export default function PercentageInput({ if (parsedValue >= maxValue) { onChange(maxValue); - setInputvalue(getValueText(maxValue)); + setInputValue(getValueText(maxValue)); return; } - if (validDecimalRegex.test(value)) { + if (NUMBER_WITH_TWO_DECIMALS.test(value)) { onChange(parsedValue); - setInputvalue(value); + setInputValue(value); } } + useEffect(() => { + if (value === undefined) { + if (inputValue !== "") { + setInputValue(""); + } + + return; + } + + if ( + // When the value is changed from outside we want to keep input empty + // if the value is the same as the default value as it means the user + // just cleared the input + Number.parseFloat(inputValue) !== Number.parseFloat(getValueText(value)) && + !(getValueText(value) === getValueText(defaultValue) && inputValue === "") + ) { + setInputValue(getValueText(value)); + } + }, [defaultValue, inputValue, value]); + const error = useMemo(() => { const parsedValue = Math.round(Number.parseFloat(inputValue) * 100); @@ -88,43 +117,43 @@ export default function PercentageInput({ const shouldShowPanel = isPanelVisible && Boolean(suggestions.length); - const inputRef = useRef(null); - const handleSignClick = useCallback(() => { - inputRef.current?.focus(); - }, []); - return (
    -
    - {negativeSign && ( - - - - - )} - setIsPanelVisible(true)} - onBlur={() => setIsPanelVisible(false)} - value={inputValue ? inputValue : ""} - placeholder={inputValue || getValueText(defaultValue)} - autoComplete="off" - onChange={handleChange} - /> - -
    - {error && !shouldShowPanel && ( -
    {error}
    - )} +
    {error}
    } + position={tooltipPosition} + > +
    + {negativeSign && ( + + - + + )} + setIsPanelVisible(true)} + onBlur={() => setIsPanelVisible(false)} + value={inputValue} + placeholder={getValueText(defaultValue)} + autoComplete="off" + onChange={handleChange} + /> + +
    +
    + {shouldShowPanel && (
      {suggestions.map((slippage) => (
    • { - setInputvalue(String(slippage)); + setInputValue(String(slippage)); onChange(slippage * 100); setIsPanelVisible(false); }} diff --git a/src/components/Radio/Radio.js b/src/components/Radio/Radio.js index 44f95397b5..d3ccd49619 100644 --- a/src/components/Radio/Radio.js +++ b/src/components/Radio/Radio.js @@ -10,6 +10,7 @@ export default function Radio(props) { return (
      {options.map((opt) => ( + // eslint-disable-next-line react/jsx-key
      setOption(opt)}>
      diff --git a/src/components/Referrals/AffiliatesStats.tsx b/src/components/Referrals/AffiliatesStats.tsx index 30cb0d5d45..301952c666 100644 --- a/src/components/Referrals/AffiliatesStats.tsx +++ b/src/components/Referrals/AffiliatesStats.tsx @@ -8,7 +8,7 @@ import { ARBITRUM, AVALANCHE, AVALANCHE_FUJI, getExplorerUrl } from "config/chai import { isDevelopment } from "config/env"; import { getNativeToken, getToken, getTokenBySymbol } from "config/tokens"; import { RebateDistributionType, ReferralCodeStats, TotalReferralsStats, useTiers } from "domain/referrals"; -import { useMarketsInfo } from "domain/synthetics/markets"; +import { useMarketsInfoRequest } from "domain/synthetics/markets"; import { useAffiliateRewards } from "domain/synthetics/referrals/useAffiliateRewards"; import { getTotalClaimableAffiliateRewardsUsd } from "domain/synthetics/referrals/utils"; import { BigNumber } from "ethers"; @@ -59,7 +59,7 @@ function AffiliatesStats({ const [isAddReferralCodeModalOpen, setIsAddReferralCodeModalOpen] = useState(false); const addNewModalRef = useRef(null); - const { marketsInfoData } = useMarketsInfo(chainId); + const { marketsInfoData } = useMarketsInfoRequest(chainId); const { affiliateRewardsData } = useAffiliateRewards(chainId); const esGmxAddress = getTokenBySymbol(chainId, "esGMX").address; diff --git a/src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx b/src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx index 579c5a656d..2db1cebe57 100644 --- a/src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx +++ b/src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx @@ -3,7 +3,7 @@ import Button from "components/Button/Button"; import ExchangeInfoRow from "components/Exchange/ExchangeInfoRow"; import Modal from "components/Modal/Modal"; import Tooltip from "components/Tooltip/Tooltip"; -import { getMarketIndexName, getMarketPoolName, useMarketsInfo } from "domain/synthetics/markets"; +import { getMarketIndexName, getMarketPoolName, useMarketsInfoRequest } from "domain/synthetics/markets"; import { AffiliateReward } from "domain/synthetics/referrals/types"; import { useAffiliateRewards } from "domain/synthetics/referrals/useAffiliateRewards"; import { getTotalClaimableAffiliateRewardsUsd } from "domain/synthetics/referrals/utils"; @@ -28,7 +28,7 @@ export function ClaimAffiliatesModal(p: Props) { const { account, signer } = useWallet(); const { chainId } = useChainId(); - const { marketsInfoData } = useMarketsInfo(chainId); + const { marketsInfoData } = useMarketsInfoRequest(chainId); const { affiliateRewardsData } = useAffiliateRewards(chainId); const [isSubmitting, setIsSubmitting] = useState(false); diff --git a/src/components/SearchInput/SearchInput.tsx b/src/components/SearchInput/SearchInput.tsx index 60d2bad491..f4b66fb0c5 100644 --- a/src/components/SearchInput/SearchInput.tsx +++ b/src/components/SearchInput/SearchInput.tsx @@ -12,6 +12,10 @@ type Props = { placeholder?: string; }; +const STYLE = { + backgroundImage: `url(${searchIcon})`, +}; + export default function SearchInput({ value, setValue, onKeyDown, className, placeholder }: Props) { const isSmallerScreen = useMedia("(max-width: 700px)"); const classNames = cx("Search-input", className); @@ -25,9 +29,7 @@ export default function SearchInput({ value, setValue, onKeyDown, className, pla onKeyDown={onKeyDown} autoFocus={!isSmallerScreen} className="Tokenselector-search-input" - style={{ - backgroundImage: `url(${searchIcon})`, - }} + style={STYLE} />
      ); diff --git a/src/components/Select/Select.tsx b/src/components/Select/Select.tsx index 30fb03f598..111809f4db 100644 --- a/src/components/Select/Select.tsx +++ b/src/components/Select/Select.tsx @@ -15,7 +15,11 @@ export default function Select(props: SelectProps) { return ( ); diff --git a/src/components/SettingsModal/SettingsModal.scss b/src/components/SettingsModal/SettingsModal.scss new file mode 100644 index 0000000000..ac2b73d3e5 --- /dev/null +++ b/src/components/SettingsModal/SettingsModal.scss @@ -0,0 +1,48 @@ +.App-settings-row { + margin-bottom: 0.8rem; + font-size: var(--font-base); +} + +.App-settings .App-cta { + margin-top: 1.5rem; +} + +.App-settings { + .Modal-content { + width: 40rem; + } +} + +.App-slippage-tolerance-input-container { + position: relative; +} + +.App-slippage-tolerance-input { + border: 1px solid rgba(255, 255, 255, 0.1); + margin-top: 0.8rem; + margin-bottom: 0.8rem; + width: 100%; + + &.with-minus { + padding-left: 2.5rem; + } +} + +.App-slippage-tolerance-input-minus { + position: absolute; + left: 1.1rem; + top: 2.325rem; +} + +.App-slippage-tolerance-input-percent { + position: absolute; + right: 1.1rem; + width: 3.1rem; + top: 2.325rem; + bottom: 0; + text-align: right; +} + +.settings-modal-error { + padding-bottom: 0.7rem; +} diff --git a/src/components/SettingsModal/SettingsModal.tsx b/src/components/SettingsModal/SettingsModal.tsx new file mode 100644 index 0000000000..fe44c08654 --- /dev/null +++ b/src/components/SettingsModal/SettingsModal.tsx @@ -0,0 +1,207 @@ +import { t, Trans } from "@lingui/macro"; +import { useEffect, useState } from "react"; + +import { DEFAULT_ALLOWED_SLIPPAGE_BPS, EXECUTION_FEE_CONFIG_V2 } from "config/chains"; +import { isDevelopment } from "config/env"; +import { BASIS_POINTS_DIVISOR } from "config/factors"; +import { useSettings } from "context/SettingsContext/SettingsContextProvider"; +import { useChainId } from "lib/chains"; +import { helperToast } from "lib/helperToast"; +import { roundToTwoDecimals } from "lib/numbers"; + +import { AlertInfo } from "components/AlertInfo/AlertInfo"; +import Button from "components/Button/Button"; +import Checkbox from "components/Checkbox/Checkbox"; +import ExternalLink from "components/ExternalLink/ExternalLink"; +import Modal from "components/Modal/Modal"; +import NumberInput from "components/NumberInput/NumberInput"; +import Tooltip from "components/Tooltip/Tooltip"; + +import "./SettingsModal.scss"; + +export function SettingsModal({ + isSettingsVisible, + setIsSettingsVisible, +}: { + isSettingsVisible: boolean; + setIsSettingsVisible: (value: boolean) => void; +}) { + const settings = useSettings(); + const { chainId } = useChainId(); + + const [slippageAmount, setSlippageAmount] = useState("0"); + const [executionFeeBufferBps, setExecutionFeeBufferBps] = useState("0"); + const [isPnlInLeverage, setIsPnlInLeverage] = useState(false); + const [showPnlAfterFees, setShowPnlAfterFees] = useState(true); + const [shouldDisableValidationForTesting, setShouldDisableValidationForTesting] = useState(false); + const [showDebugValues, setShowDebugValues] = useState(false); + + useEffect(() => { + if (!isSettingsVisible) return; + + const slippage = parseInt(String(settings.savedAllowedSlippage)); + setSlippageAmount(String(roundToTwoDecimals((slippage / BASIS_POINTS_DIVISOR) * 100))); + if (settings.executionFeeBufferBps !== undefined) { + const bps = settings.executionFeeBufferBps; + setExecutionFeeBufferBps(String(roundToTwoDecimals((bps / BASIS_POINTS_DIVISOR) * 100))); + } + setIsPnlInLeverage(settings.isPnlInLeverage); + setShowPnlAfterFees(settings.showPnlAfterFees); + setShowDebugValues(settings.showDebugValues); + setShouldDisableValidationForTesting(settings.shouldDisableValidationForTesting); + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isSettingsVisible]); + + const saveAndCloseSettings = () => { + const slippage = parseFloat(String(slippageAmount)); + if (isNaN(slippage)) { + helperToast.error(t`Invalid slippage value`); + return; + } + if (slippage > 5) { + helperToast.error(t`Slippage should be less than -5%`); + return; + } + const basisPoints = roundToTwoDecimals((slippage * BASIS_POINTS_DIVISOR) / 100); + if (parseInt(String(basisPoints)) !== parseFloat(String(basisPoints))) { + helperToast.error(t`Max slippage precision is -0.01%`); + return; + } + + settings.setSavedAllowedSlippage(basisPoints); + + if (settings.shouldUseExecutionFeeBuffer) { + const executionFeeBuffer = parseFloat(String(executionFeeBufferBps)); + if (isNaN(executionFeeBuffer) || executionFeeBuffer < 0) { + helperToast.error(t`Invalid execution fee buffer value`); + return; + } + const nextExecutionBufferFeeBps = roundToTwoDecimals((executionFeeBuffer * BASIS_POINTS_DIVISOR) / 100); + + if (parseInt(String(nextExecutionBufferFeeBps)) !== parseFloat(String(nextExecutionBufferFeeBps))) { + helperToast.error(t`Max execution fee buffer precision is 0.01%`); + return; + } + + settings.setExecutionFeeBufferBps(nextExecutionBufferFeeBps); + } + + settings.setIsPnlInLeverage(isPnlInLeverage); + settings.setShowPnlAfterFees(showPnlAfterFees); + settings.setShouldDisableValidationForTesting(shouldDisableValidationForTesting); + settings.setShowDebugValues(showDebugValues); + setIsSettingsVisible(false); + }; + + return ( + +
      +
      + Allowed Slippage +
      +
      +
      -
      + setSlippageAmount(e.target.value)} + placeholder="0.3" + /> +
      %
      +
      + {parseFloat(slippageAmount) < (DEFAULT_ALLOWED_SLIPPAGE_BPS / BASIS_POINTS_DIVISOR) * 100 && ( +
      + + Allowed Slippage below {(DEFAULT_ALLOWED_SLIPPAGE_BPS / BASIS_POINTS_DIVISOR) * 100}% may result in failed + orders. + +
      + )} +
      + {settings.shouldUseExecutionFeeBuffer && ( +
      +
      + Max Execution Fee Buffer} + renderContent={() => ( +
      + + The Max Execution Fee is set to a higher value to handle potential increases in gas price during + order execution. Any excess execution fee will be refunded to your account when the order is + executed. Only applicable to GMX V2. + +
      +
      + Read more +
      + )} + /> +
      +
      + setExecutionFeeBufferBps(e.target.value)} + placeholder="10" + /> +
      %
      +
      + {parseFloat(executionFeeBufferBps) < + (EXECUTION_FEE_CONFIG_V2[chainId].defaultBufferBps! / BASIS_POINTS_DIVISOR) * 100 && ( +
      + + + Max Execution Fee buffer below{" "} + {(EXECUTION_FEE_CONFIG_V2[chainId].defaultBufferBps! / BASIS_POINTS_DIVISOR) * 100}% may result in + failed orders. + + +
      + )} +
      + )} +
      + + Display PnL after fees + +
      +
      + + Include PnL in leverage display + +
      +
      + + + Chart positions + + +
      + {isDevelopment() && ( +
      + + Disable order validations + +
      + )} + + {isDevelopment() && ( +
      + + Show debug values + +
      + )} + + +
      + ); +} diff --git a/src/components/ShareBar/ShareBar.tsx b/src/components/ShareBar/ShareBar.tsx index 80401f6a7e..41d229deaf 100644 --- a/src/components/ShareBar/ShareBar.tsx +++ b/src/components/ShareBar/ShareBar.tsx @@ -22,6 +22,7 @@ export function ShareBar(p: Props) { return (
      + {/* eslint-disable-next-line react-perf/jsx-no-new-object-as-prop */}
      ); diff --git a/src/components/Stake/GMXAprTooltip.tsx b/src/components/Stake/GMXAprTooltip.tsx index 90c9969657..3b427d336f 100644 --- a/src/components/Stake/GMXAprTooltip.tsx +++ b/src/components/Stake/GMXAprTooltip.tsx @@ -1,16 +1,22 @@ import { t, Trans } from "@lingui/macro"; +import ExternalLink from "components/ExternalLink/ExternalLink"; import StatsTooltipRow from "components/StatsTooltip/StatsTooltipRow"; +import { DOCS_LINKS } from "config/links"; +import { useAccumulatedBnGMXAmount } from "domain/rewards/useAccumulatedBnGMXAmount"; import { BigNumber } from "ethers"; -import { formatKeyAmount } from "lib/numbers"; +import { formatKeyAmount, formatAmount } from "lib/numbers"; type Props = { processedData: { gmxAprForEsGmx: BigNumber; gmxAprForNativeToken: BigNumber; + maxGmxAprForNativeToken: BigNumber; gmxAprForNativeTokenWithBoost: BigNumber; gmxBoostAprForNativeToken?: BigNumber; }; nativeTokenSymbol: string; + isUserConnected: boolean; + recommendStakeGmx?: BigNumber; }; function renderEscrowedGMXApr(processedData) { @@ -24,56 +30,80 @@ function renderEscrowedGMXApr(processedData) { ); } -export default function GMXAprTooltip({ processedData, nativeTokenSymbol }: Props) { +export default function GMXAprTooltip({ + processedData, + nativeTokenSymbol, + recommendStakeGmx, + isUserConnected = false, +}: Props) { + const accumulatedBnGMXAmount = useAccumulatedBnGMXAmount(); const escrowedGMXApr = renderEscrowedGMXApr(processedData); - return ( - <> - {(!processedData.gmxBoostAprForNativeToken || processedData.gmxBoostAprForNativeToken.eq(0)) && ( + const gmxAprPercentage = formatKeyAmount(processedData, "gmxAprForNativeToken", 2, 2, true); + const maxGmxAprPercentage = formatKeyAmount(processedData, "maxGmxAprForNativeToken", 2, 2, true); + const maxGmxAprPercentageDifference = processedData.maxGmxAprForNativeToken.sub( + processedData.gmxAprForNativeTokenWithBoost + ); + + const aprUpdateMsg = t`APRs are updated weekly on Wednesday and will depend on the fees collected for the week.`; + + if (!isUserConnected) { + return ( + <> + - )} - {processedData?.gmxBoostAprForNativeToken?.gt(0) ? ( -
      - - -
      - - {escrowedGMXApr && ( - <> -
      {escrowedGMXApr} - - )} -
      - The Boosted APR is from your staked Multiplier Points. -
      - ) : ( - escrowedGMXApr - )} -

      - APRs are updated weekly on Wednesday and will depend on the fees collected for the week. + + Max. {nativeTokenSymbol} APR is calculated with the max. 200% Boost Percentage by staking{" "} + Multiplier Points. +

      + {aprUpdateMsg} + + ); + } - - Max. {nativeTokenSymbol} APR with 200% Boost for this week:{" "} - {formatKeyAmount(processedData, "maxGmxAprForNativeToken", 2, 2, true)}%. - + return ( + <> +
      + + +
      + + {escrowedGMXApr && ( + <> +
      {escrowedGMXApr} + + )} +
      + {recommendStakeGmx?.gt(0) ? ( + + You have reached the maximum Boost Percentage. Stake an additional{" "} + {formatAmount(recommendStakeGmx, 18, 2, true)} GMX or esGMX to be able to stake your unstaked{" "} + {formatAmount(accumulatedBnGMXAmount, 18, 4, true)} Multiplier Points using the "Compound" button. + + ) : ( + + Earn an extra {formatAmount(maxGmxAprPercentageDifference, 2, 2, true)}% {nativeTokenSymbol} Boosted APR by + increasing your staked Multiplier Points. + + )} +
      +
      +
      + {aprUpdateMsg}
      ); diff --git a/src/components/SubaccountNavigationButton/SubaccountNavigationButton.tsx b/src/components/SubaccountNavigationButton/SubaccountNavigationButton.tsx index a00e89a237..b3e67a3814 100644 --- a/src/components/SubaccountNavigationButton/SubaccountNavigationButton.tsx +++ b/src/components/SubaccountNavigationButton/SubaccountNavigationButton.tsx @@ -10,13 +10,13 @@ import { useSubaccountModalOpen, } from "context/SubaccountContext/SubaccountContext"; import { SUBACCOUNT_DOCS_URL } from "domain/synthetics/subaccount/constants"; -import { TradeFlags } from "domain/synthetics/trade/useTradeFlags"; import { BigNumber } from "ethers"; import { useChainId } from "lib/chains"; import { useLocalStorageSerializeKey } from "lib/localStorage"; import { ReactNode, memo, useCallback } from "react"; import "./SubaccountNavigationButton.scss"; import { ONE_CLICK_TRADING_NATIVE_TOKEN_WARN_HIDDEN, ONE_CLICK_TRADING_OFFER_HIDDEN } from "config/localStorage"; +import { TradeFlags } from "domain/synthetics/trade"; export const SubaccountNavigationButton = memo( ({ diff --git a/src/components/SuggestionInput/SuggestionInput.scss b/src/components/SuggestionInput/SuggestionInput.scss new file mode 100644 index 0000000000..17a33f1628 --- /dev/null +++ b/src/components/SuggestionInput/SuggestionInput.scss @@ -0,0 +1,57 @@ +.Suggestion-input-wrapper { + position: relative; + .Suggestion-list { + position: absolute; + display: flex; + list-style: none; + border-radius: var(--border-radius-sm); + right: 0; + padding: 0; + top: 1.25rem; + background: #212540; + z-index: 1002; + + li { + padding: 0.5rem 0.75rem; + cursor: pointer; + border-radius: var(--border-radius-sm); + text-align: center; + &:hover { + background: rgba(58, 63, 121, 0.5607843137254902); + } + } + } + .Suggestion-input { + border: 1px solid #212540; + border-radius: var(--border-radius-sm); + padding-right: 0.5rem; + line-height: 1; + background: #212540; + + label { + cursor: pointer; + } + + &:hover, + &:focus { + border-color: #3a3f798f; + } + &:focus-within { + border-color: #3a3f79; + } + + &.input-error { + border-color: #f3b50e; + } + + input { + padding: 0.2rem 0.5rem 0.35rem; + font-size: 1.4rem; + border-radius: 4px; + max-width: 7rem; + } + span { + opacity: 0.7; + } + } +} diff --git a/src/components/SuggestionInput/SuggestionInput.tsx b/src/components/SuggestionInput/SuggestionInput.tsx new file mode 100644 index 0000000000..9a6a12cb85 --- /dev/null +++ b/src/components/SuggestionInput/SuggestionInput.tsx @@ -0,0 +1,54 @@ +import "./SuggestionInput.scss"; +import { ChangeEvent, useState } from "react"; +import cx from "classnames"; +import NumberInput from "components/NumberInput/NumberInput"; + +type Props = { + value?: string; + setValue?: (value: string) => void; + placeholder?: string; + suggestionList?: number[]; + symbol?: string; +}; + +export default function SuggestionInput({ placeholder, value, setValue, suggestionList, symbol }: Props) { + const [isPanelVisible, setIsPanelVisible] = useState(false); + + function handleChange(event: ChangeEvent) { + if (setValue) { + setValue(event.target.value); + } + } + function handleSuggestionClick(suggestion: number) { + if (setValue) { + setValue(suggestion.toString()); + setIsPanelVisible(false); + } + } + + return ( +
      +
      + setIsPanelVisible(true)} + onBlur={() => setIsPanelVisible(false)} + value={value ?? ""} + placeholder={placeholder} + onValueChange={handleChange} + /> + +
      + {suggestionList && isPanelVisible && ( +
        + {suggestionList.map((suggestion) => ( +
      • handleSuggestionClick(suggestion)}> + {suggestion}% +
      • + ))} +
      + )} +
      + ); +} diff --git a/src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx b/src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx index 21f8aa5a18..92bd8046ba 100644 --- a/src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx +++ b/src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx @@ -1,84 +1,81 @@ import { Trans, t } from "@lingui/macro"; -import ExchangeInfoRow from "components/Exchange/ExchangeInfoRow"; -import PercentageInput from "components/PercentageInput/PercentageInput"; -import { HIGH_POSITION_IMPACT_BPS } from "config/factors"; -import { TradeFees } from "domain/synthetics/trade"; import { BigNumber } from "ethers"; +import { memo, useCallback, useMemo } from "react"; + +import { HIGH_POSITION_IMPACT_BPS } from "config/factors"; import { formatPercentage } from "lib/numbers"; -import { memo, useCallback, useEffect, useMemo, useState } from "react"; + +import ExchangeInfoRow from "components/Exchange/ExchangeInfoRow"; +import PercentageInput from "components/PercentageInput/PercentageInput"; + import "./AcceptablePriceImpactInputRow.scss"; type Props = { - defaultAcceptablePriceImpactBps: BigNumber | undefined; - fees: TradeFees | undefined; - setSelectedAcceptablePriceImpactBps: (value: BigNumber) => void; + acceptablePriceImpactBps?: BigNumber; + recommendedAcceptablePriceImpactBps?: BigNumber; + initialPriceImpactFeeBps?: BigNumber; + priceImpactFeeBps?: BigNumber; + setAcceptablePriceImpactBps: (value: BigNumber) => void; notAvailable?: boolean; }; const EMPTY_SUGGESTIONS: number[] = []; function AcceptablePriceImpactInputRowImpl({ - defaultAcceptablePriceImpactBps, - fees, - setSelectedAcceptablePriceImpactBps, + acceptablePriceImpactBps, + recommendedAcceptablePriceImpactBps = acceptablePriceImpactBps, + initialPriceImpactFeeBps = acceptablePriceImpactBps, + priceImpactFeeBps, + setAcceptablePriceImpactBps, notAvailable = false, }: Props) { const setValue = useCallback( - (value) => { - setSelectedAcceptablePriceImpactBps(BigNumber.from(value)); + (value: number | undefined) => { + setAcceptablePriceImpactBps(BigNumber.from(value)); }, - [setSelectedAcceptablePriceImpactBps] + [setAcceptablePriceImpactBps] ); - const defaultValue = defaultAcceptablePriceImpactBps?.toNumber(); - - // calculated Acceptable Price value is not refreshing to the new percentage - // when size field is changed. - useEffect(() => { - if (defaultValue) { - setValue(defaultValue); - } - }, [defaultValue, setValue]); - - const [key, setKey] = useState(0); + const recommendedValue = recommendedAcceptablePriceImpactBps?.toNumber(); + const initialValue = initialPriceImpactFeeBps?.toNumber(); + const value = acceptablePriceImpactBps?.toNumber(); // if current price impact is 0.01%, the message will be shown // only if acceptable price impact is set to more than 0.51% const highValue = useMemo(() => { - if (!fees) { + if (!priceImpactFeeBps) { return undefined; } - if (fees.positionPriceImpact?.bps.lte(0)) { - return HIGH_POSITION_IMPACT_BPS + fees.positionPriceImpact?.bps.abs().toNumber(); + if (priceImpactFeeBps.lte(0)) { + return HIGH_POSITION_IMPACT_BPS + priceImpactFeeBps.abs().toNumber(); } else { return HIGH_POSITION_IMPACT_BPS; } - }, [fees]); + }, [priceImpactFeeBps]); const handleRecommendedValueClick = useCallback(() => { - setKey((key) => key + 1); - setValue(defaultValue); - }, [defaultValue, setValue]); + setValue(recommendedValue); + }, [recommendedValue, setValue]); - if (!defaultAcceptablePriceImpactBps || !fees || defaultValue === undefined) { + if (recommendedValue === undefined || initialValue === undefined || !priceImpactFeeBps) { return null; } const recommendedHandle = ( - Set Recommended Impact: {formatPercentage(BigNumber.from(defaultValue).mul(-1), { signed: true })} + Set Recommended Impact: {formatPercentage(BigNumber.from(recommendedValue).mul(-1), { signed: true })} . ); - const lowValueWarningText = fees.positionPriceImpact?.bps.gte(0) ? ( + const lowValueWarningText = priceImpactFeeBps.gte(0) ? (

      - The current Price Impact is {formatPercentage(fees.positionPriceImpact?.bps, { signed: true })}. Consider using - -0.30% Acceptable Price Impact so the order is more likely to be processed. + The current Price Impact is {formatPercentage(priceImpactFeeBps, { signed: true })}. Consider using -0.30% + Acceptable Price Impact so the order is more likely to be processed.

      @@ -87,8 +84,8 @@ function AcceptablePriceImpactInputRowImpl({ ) : (

      - The Current Price Impact is {formatPercentage(fees.positionPriceImpact?.bps, { signed: true })}. Consider adding - a buffer of 0.30% to it so the order is more likely to be processed. + The Current Price Impact is {formatPercentage(priceImpactFeeBps, { signed: true })}. Consider adding a buffer of + 0.30% to it so the order is more likely to be processed.

      @@ -100,7 +97,7 @@ function AcceptablePriceImpactInputRowImpl({

      You have set a high Acceptable Price Impact. The current Price Impact is{" "} - {formatPercentage(fees.positionPriceImpact?.bps, { signed: true })}. + {formatPercentage(priceImpactFeeBps, { signed: true })}.

      @@ -112,16 +109,17 @@ function AcceptablePriceImpactInputRowImpl({ t`NA` ) : ( ); diff --git a/src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx b/src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx new file mode 100644 index 0000000000..d41e815c95 --- /dev/null +++ b/src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx @@ -0,0 +1,164 @@ +import { Trans, t } from "@lingui/macro"; +import Modal from "components/Modal/Modal"; +import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; +import { useMarketsInfoData, useTokensData } from "context/SyntheticsStateContext/hooks/globalsHooks"; +import { RebateInfoItem } from "domain/synthetics/fees/useRebatesInfo"; +import { getMarketIndexName, getMarketPoolName } from "domain/synthetics/markets"; +import { getTokenData } from "domain/synthetics/tokens"; +import { BigNumber } from "ethers"; +import { expandDecimals, formatDeltaUsd, formatTokenAmount } from "lib/numbers"; +import { getByKey } from "lib/objects"; +import { memo, useCallback, useMemo } from "react"; +import { calcTotalRebateUsd } from "../Claims/utils"; + +export function AccruedPositionPriceImpactRebateModal({ + isVisible, + onClose, + accruedPositionPriceImpactFees, +}: { + isVisible: boolean; + onClose: () => void; + accruedPositionPriceImpactFees: RebateInfoItem[]; +}) { + const tokensData = useTokensData(); + const totalUsd = useMemo( + () => formatDeltaUsd(calcTotalRebateUsd(accruedPositionPriceImpactFees, tokensData, true)), + [accruedPositionPriceImpactFees, tokensData] + ); + const reducedByMarketItemGroups = useMemo(() => { + const groupedMarkets: Record = {}; + return accruedPositionPriceImpactFees.reduce((acc, rebateItem) => { + const key = rebateItem.marketAddress; + + if (typeof groupedMarkets[key] === "number") { + const index = groupedMarkets[key]; + acc[index].push(rebateItem); + } else { + groupedMarkets[key] = acc.length; + acc.push([rebateItem]); + } + + return acc; + }, [] as RebateInfoItem[][]); + }, [accruedPositionPriceImpactFees]); + + return ( + +

      +
      Total {totalUsd}
      +
      +
      +
      +
      +
      +
      + MARKET +
      +
      + REBATE +
      +
      + {reducedByMarketItemGroups.map((rebateItems) => ( + + ))} +
      +
      + + ); +} + +const Row = memo(({ rebateItems }: { rebateItems: RebateInfoItem[] }) => { + const marketsInfoData = useMarketsInfoData(); + const market = getByKey(marketsInfoData, rebateItems[0].marketAddress); + const label = useMemo(() => { + if (!market) return ""; + const indexName = getMarketIndexName(market); + const poolName = getMarketPoolName(market); + return ( +
      + {indexName} + [{poolName}] +
      + ); + }, [market]); + const tokensData = useTokensData(); + + const reducedByTokenItems = useMemo(() => { + const groupedMarkets: Record = {}; + const reduced = rebateItems.reduce((acc, rebateItem) => { + const key = rebateItem.marketAddress + rebateItem.tokenAddress; + if (typeof groupedMarkets[key] === "number") { + const index = groupedMarkets[key]; + acc[index].value = acc[index].value.add(rebateItem.value); + } else { + groupedMarkets[key] = acc.length; + acc.push({ ...rebateItem }); + } + + return acc; + }, [] as RebateInfoItem[]); + + if (reduced.length !== 2) return reduced; + + reduced.sort((a, b) => { + let ax = 0; + let bx = 0; + + if (a.tokenAddress === market?.longTokenAddress) ax = 1; + else if (a.tokenAddress === market?.shortTokenAddress) ax = -1; + + if (b.tokenAddress === market?.longTokenAddress) bx = 1; + else if (b.tokenAddress === market?.shortTokenAddress) bx = -1; + + return bx - ax; + }); + + return reduced; + }, [market?.longTokenAddress, market?.shortTokenAddress, rebateItems]); + + const usd = useMemo(() => { + let total = BigNumber.from(0); + + rebateItems.forEach((rebateItem) => { + const tokenData = getTokenData(tokensData, rebateItem.tokenAddress); + const price = tokenData?.prices.minPrice; + const decimals = tokenData?.decimals; + const usd = price && decimals ? rebateItem.value.mul(price).div(expandDecimals(1, decimals)) : null; + if (!usd) return; + total = total.add(usd); + }); + + return formatDeltaUsd(total); + }, [rebateItems, tokensData]); + + const renderContent = useCallback( + () => + reducedByTokenItems.map((rebateItem) => { + const tokenData = getTokenData(tokensData, rebateItem.tokenAddress); + if (!tokenData) return null; + return ( +
      {formatTokenAmount(rebateItem.value, tokenData?.decimals, tokenData?.symbol)}
      + ); + }), + [reducedByTokenItems, tokensData] + ); + + return ( +
      +
      {label}
      +
      + +
      +
      + ); +}); diff --git a/src/components/Synthetics/BridgingInfo/BridgingInfo.tsx b/src/components/Synthetics/BridgingInfo/BridgingInfo.tsx index 3b9230ed5b..ecb4a0dc74 100644 --- a/src/components/Synthetics/BridgingInfo/BridgingInfo.tsx +++ b/src/components/Synthetics/BridgingInfo/BridgingInfo.tsx @@ -27,9 +27,13 @@ export default function BridgingInfo(props: Props) {

      - {bridgingOptions.map((option) => { + {bridgingOptions.map((option, i) => { const bridgeLink = option.generateLink(chainId); - return {option?.name}; + return ( + + {option?.name} + + ); })} )} diff --git a/src/components/Synthetics/ChartTokenSelector/ChartTokenSelector.tsx b/src/components/Synthetics/ChartTokenSelector/ChartTokenSelector.tsx index cdea40c759..1666268152 100644 --- a/src/components/Synthetics/ChartTokenSelector/ChartTokenSelector.tsx +++ b/src/components/Synthetics/ChartTokenSelector/ChartTokenSelector.tsx @@ -1,20 +1,20 @@ -import React, { useMemo, useState } from "react"; import { Popover } from "@headlessui/react"; +import { t } from "@lingui/macro"; import cx from "classnames"; -import groupBy from "lodash/groupBy"; -import { FaChevronDown } from "react-icons/fa"; -import "./ChartTokenSelector.scss"; -import { Token } from "domain/tokens"; import SearchInput from "components/SearchInput/SearchInput"; import TokenIcon from "components/TokenIcon/TokenIcon"; -import { t } from "@lingui/macro"; -import { TradeFlags } from "domain/synthetics/trade/useTradeFlags"; -import { AvailableTokenOptions, TradeType } from "domain/synthetics/trade"; +import { convertTokenAddress } from "config/tokens"; import { getAvailableUsdLiquidityForPosition } from "domain/synthetics/markets"; +import { PositionsInfoData } from "domain/synthetics/positions"; +import { AvailableTokenOptions, TradeType } from "domain/synthetics/trade"; +import { Token } from "domain/tokens"; import { BigNumber } from "ethers"; import { formatUsd } from "lib/numbers"; -import { PositionsInfoData } from "domain/synthetics/positions"; -import { convertTokenAddress } from "config/tokens"; +import groupBy from "lodash/groupBy"; +import { useMemo, useState } from "react"; +import { FaChevronDown } from "react-icons/fa"; +import "./ChartTokenSelector.scss"; +import { useTradeboxTradeFlags } from "context/SyntheticsStateContext/hooks/tradeboxHooks"; type TokenOption = Token & { maxLongLiquidity: BigNumber; @@ -27,17 +27,15 @@ type Props = { chainId: number; selectedToken: Token | undefined; onSelectToken: (address: string, marketAddress?: string, tradeType?: TradeType) => void; - tradeFlags?: TradeFlags; options: Token[] | undefined; - className?: string; avaialbleTokenOptions: AvailableTokenOptions; positionsInfo?: PositionsInfoData; }; export default function ChartTokenSelector(props: Props) { - const { chainId, options, selectedToken, onSelectToken, tradeFlags, avaialbleTokenOptions, positionsInfo } = props; + const { chainId, options, selectedToken, onSelectToken, avaialbleTokenOptions, positionsInfo } = props; const { sortedAllMarkets } = avaialbleTokenOptions; - const { isSwap, isLong, isShort } = tradeFlags || {}; + const { isSwap, isLong, isShort } = useTradeboxTradeFlags(); const [searchKeyword, setSearchKeyword] = useState(""); const onSelect = (token: { indexTokenAddress: string; marketTokenAddress?: string; tradeType?: TradeType }) => { @@ -77,7 +75,7 @@ export default function ChartTokenSelector(props: Props) { if (tokenAddress === selectedToken?.address) return; - if (tradeFlags?.isSwap) { + if (isSwap) { onSelect({ indexTokenAddress: token.address, }); diff --git a/src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx b/src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx index 6e2ab6034d..e62fdaf858 100644 --- a/src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx +++ b/src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx @@ -26,7 +26,7 @@ type ClaimFundingFeesHistoryRowProps = { const claimCollateralEventTitles: Record = { [ClaimType.ClaimFunding]: t`Claim Funding Fees`, - [ClaimType.ClaimPriceImpact]: t`Claim Price Impact`, + [ClaimType.ClaimPriceImpact]: t`Claim Price Impact Rebates`, }; export function ClaimHistoryRow({ claimAction }: ClaimHistoryRowProps) { diff --git a/src/components/Synthetics/ClaimModal/ClaimModal.tsx b/src/components/Synthetics/ClaimModal/ClaimModal.tsx index e78a134214..c2acb3473f 100644 --- a/src/components/Synthetics/ClaimModal/ClaimModal.tsx +++ b/src/components/Synthetics/ClaimModal/ClaimModal.tsx @@ -2,7 +2,6 @@ import { Trans, t } from "@lingui/macro"; import Modal from "components/Modal/Modal"; import { MarketInfo, - MarketsInfoData, getMarketIndexName, getMarketPoolName, getTotalClaimableFundingUsd, @@ -13,24 +12,25 @@ import { useChainId } from "lib/chains"; import { formatDeltaUsd, formatTokenAmount } from "lib/numbers"; import Tooltip from "components/Tooltip/Tooltip"; -import { claimCollateralTxn } from "domain/synthetics/markets/claimCollateralTxn"; +import { claimFundingFeesTxn } from "domain/synthetics/markets/claimFundingFeesTxn"; import Button from "components/Button/Button"; +import { useMarketsInfoData } from "context/SyntheticsStateContext/hooks/globalsHooks"; +import useWallet from "lib/wallets/useWallet"; import { useState } from "react"; import "./ClaimModal.scss"; -import useWallet from "lib/wallets/useWallet"; type Props = { isVisible: boolean; - marketsInfoData?: MarketsInfoData; onClose: () => void; setPendingTxns: (txns: any) => void; }; export function ClaimModal(p: Props) { - const { isVisible, onClose, setPendingTxns, marketsInfoData } = p; + const { isVisible, onClose, setPendingTxns } = p; const { account, signer } = useWallet(); const { chainId } = useChainId(); + const marketsInfoData = useMarketsInfoData(); const [isSubmitting, setIsSubmitting] = useState(false); @@ -114,7 +114,7 @@ export function ClaimModal(p: Props) { setIsSubmitting(true); - claimCollateralTxn(chainId, signer, { + claimFundingFeesTxn(chainId, signer, { account, fundingFees: { marketAddresses: fundingMarketAddresses, diff --git a/src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx b/src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx new file mode 100644 index 0000000000..6ab0d79b5e --- /dev/null +++ b/src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx @@ -0,0 +1,206 @@ +import { Trans, t } from "@lingui/macro"; +import Button from "components/Button/Button"; +import Modal from "components/Modal/Modal"; +import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; +import { createClaimCollateralTxn } from "domain/synthetics/claimHistory/claimPriceImpactRebate"; +import { MarketsInfoData, getMarketIndexName, getMarketPoolName } from "domain/synthetics/markets"; +import { getTokenData } from "domain/synthetics/tokens"; +import { BigNumber } from "ethers"; +import { useChainId } from "lib/chains"; +import { expandDecimals, formatDeltaUsd, formatTokenAmount } from "lib/numbers"; +import { getByKey } from "lib/objects"; +import useWallet from "lib/wallets/useWallet"; +import { memo, useCallback, useMemo, useState } from "react"; +import { calcTotalRebateUsd } from "../Claims/utils"; +import { RebateInfoItem } from "domain/synthetics/fees/useRebatesInfo"; +import { useMarketsInfoData, useTokensData } from "context/SyntheticsStateContext/hooks/globalsHooks"; + +export function ClaimablePositionPriceImpactRebateModal({ + isVisible, + onClose, + claimablePositionPriceImpactFees, +}: { + isVisible: boolean; + onClose: () => void; + claimablePositionPriceImpactFees: RebateInfoItem[]; +}) { + const [isSubmitting, setIsSubmitting] = useState(false); + const { chainId } = useChainId(); + const tokensData = useTokensData(); + const marketsInfoData = useMarketsInfoData(); + const totalUsd = useMemo( + () => formatDeltaUsd(calcTotalRebateUsd(claimablePositionPriceImpactFees, tokensData, false)), + [claimablePositionPriceImpactFees, tokensData] + ); + const { signer, account } = useWallet(); + + const reducedByMarketItemGroups = useMemo(() => { + const groupedMarkets: Record = {}; + return claimablePositionPriceImpactFees.reduce((acc, rebateItem) => { + const key = rebateItem.marketAddress; + + if (typeof groupedMarkets[key] === "number") { + const index = groupedMarkets[key]; + acc[index].push(rebateItem); + } else { + groupedMarkets[key] = acc.length; + acc.push([rebateItem]); + } + + return acc; + }, [] as RebateInfoItem[][]); + }, [claimablePositionPriceImpactFees]); + + const [buttonText, buttonDisabled] = useMemo(() => { + if (isSubmitting) return [t`Claiming...`, true]; + return [t`Claim`, false]; + }, [isSubmitting]); + + const handleSubmit = useCallback(async () => { + if (!signer) throw new Error("No signer"); + if (!account) throw new Error("No account"); + + setIsSubmitting(true); + + try { + await createClaimCollateralTxn(chainId, signer, { + account, + claimablePositionPriceImpactFees, + }); + onClose(); + } finally { + setIsSubmitting(false); + } + }, [account, chainId, claimablePositionPriceImpactFees, onClose, signer]); + + return ( + +
      +
      + Claim {totalUsd} +
      +
      +
      +
      +
      +
      +
      + MARKET +
      +
      + REBATE +
      +
      + {marketsInfoData + ? reducedByMarketItemGroups.map((rebateItems) => ( + + )) + : null} +
      +
      + + + ); +} + +const Row = memo( + ({ rebateItems, marketsInfoData }: { rebateItems: RebateInfoItem[]; marketsInfoData: MarketsInfoData }) => { + const market = getByKey(marketsInfoData, rebateItems[0].marketAddress); + const label = useMemo(() => { + if (!market) return ""; + const indexName = getMarketIndexName(market); + const poolName = getMarketPoolName(market); + return ( +
      + {indexName} + [{poolName}] +
      + ); + }, [market]); + + const tokensData = useTokensData(); + + const reducedByTokenItems = useMemo(() => { + const groupedTokens: Record = {}; + const reduced = rebateItems.reduce((acc, rebateItem) => { + const key = rebateItem.marketAddress + rebateItem.tokenAddress; + if (typeof groupedTokens[key] === "number") { + const index = groupedTokens[key]; + acc[index].value = acc[index].value.add(rebateItem.value); + acc[index].valueByFactor = acc[index].valueByFactor.add(rebateItem.valueByFactor); + } else { + groupedTokens[key] = acc.length; + acc.push({ ...rebateItem }); + } + + return acc; + }, [] as RebateInfoItem[]); + if (reduced.length !== 2) return reduced; + + reduced.sort((a, b) => { + let ax = 0; + let bx = 0; + + if (a.tokenAddress === market?.longTokenAddress) ax = 1; + else if (a.tokenAddress === market?.shortTokenAddress) ax = -1; + + if (b.tokenAddress === market?.longTokenAddress) bx = 1; + else if (b.tokenAddress === market?.shortTokenAddress) bx = -1; + + return bx - ax; + }); + + return reduced; + }, [market?.longTokenAddress, market?.shortTokenAddress, rebateItems]); + + const usd = useMemo(() => { + let total = BigNumber.from(0); + + rebateItems.forEach((rebateItem) => { + const tokenData = getTokenData(tokensData, rebateItem.tokenAddress); + const price = tokenData?.prices.minPrice; + const decimals = tokenData?.decimals; + const usd = price && decimals ? rebateItem.valueByFactor.mul(price).div(expandDecimals(1, decimals)) : null; + if (!usd) return; + total = total.add(usd); + }); + + return formatDeltaUsd(total); + }, [rebateItems, tokensData]); + + const renderContent = useCallback( + () => + reducedByTokenItems.map((rebateItem) => { + const tokenData = getTokenData(tokensData, rebateItem.tokenAddress); + if (!tokenData) return null; + return ( +
      + {formatTokenAmount(rebateItem.valueByFactor, tokenData?.decimals, tokenData?.symbol)} +
      + ); + }), + [reducedByTokenItems, tokensData] + ); + + return ( +
      +
      {label}
      +
      + +
      +
      + ); + } +); diff --git a/src/components/Synthetics/Claims/ClaimableCard.tsx b/src/components/Synthetics/Claims/ClaimableCard.tsx index ed4f85714e..f131bbb4cc 100644 --- a/src/components/Synthetics/Claims/ClaimableCard.tsx +++ b/src/components/Synthetics/Claims/ClaimableCard.tsx @@ -1,30 +1,61 @@ -import { t } from "@lingui/macro"; -import { MarketsInfoData, getTotalClaimableFundingUsd } from "domain/synthetics/markets"; +import { Trans, t } from "@lingui/macro"; +import ExternalLink from "components/ExternalLink/ExternalLink"; +import { useMarketsInfoData, useTokensData } from "context/SyntheticsStateContext/hooks/globalsHooks"; +import { RebateInfoItem } from "domain/synthetics/fees/useRebatesInfo"; +import { getTotalClaimableFundingUsd } from "domain/synthetics/markets"; +import { CSSProperties, useMemo } from "react"; import { ClaimableCardUI } from "./ClaimableCardUI"; -import { CSSProperties } from "react"; +import { calcTotalRebateUsd } from "./utils"; type Props = { onClaimClick: () => void; - marketsInfoData: MarketsInfoData | undefined; + onClaimablePositionPriceImpactFeesClick: () => void; style?: CSSProperties; + claimablePositionPriceImpactFees: RebateInfoItem[]; }; const tooltipText = t`Positive Funding Fees for a Position become claimable after the Position is increased, decreased or closed; or settled its fees with the option under "Accrued".`; const buttonText = t`Claim`; const title = t`Claimable`; -export function ClaimableCard({ marketsInfoData, onClaimClick, style }: Props) { +export function ClaimableCard({ + onClaimClick, + style, + claimablePositionPriceImpactFees, + onClaimablePositionPriceImpactFeesClick, +}: Props) { + const marketsInfoData = useMarketsInfoData(); const markets = Object.values(marketsInfoData ?? {}); - const totalClaimableFundingUsd = getTotalClaimableFundingUsd(markets); + const totalClaimableFundingUsd = useMemo(() => getTotalClaimableFundingUsd(markets), [markets]); + const tokensData = useTokensData(); + const priceImpactRebateUsd = useMemo( + () => calcTotalRebateUsd(claimablePositionPriceImpactFees, tokensData, false), + [claimablePositionPriceImpactFees, tokensData] + ); - return ( - + const sections = useMemo( + () => + [ + { buttonText, tooltipText, onButtonClick: onClaimClick, usd: totalClaimableFundingUsd }, + { + buttonText, + tooltipText: ( + + Claimable Price Impact Rebates. +
      +
      + + Read more + + . +
      + ), + onButtonClick: onClaimablePositionPriceImpactFeesClick, + usd: priceImpactRebateUsd, + }, + ] as const, + [onClaimClick, onClaimablePositionPriceImpactFeesClick, priceImpactRebateUsd, totalClaimableFundingUsd] ); + + return ; } diff --git a/src/components/Synthetics/Claims/ClaimableCardUI.tsx b/src/components/Synthetics/Claims/ClaimableCardUI.tsx index 6d5439b579..0e7124cfb3 100644 --- a/src/components/Synthetics/Claims/ClaimableCardUI.tsx +++ b/src/components/Synthetics/Claims/ClaimableCardUI.tsx @@ -1,40 +1,75 @@ -import { Trans } from "@lingui/macro"; +import { t } from "@lingui/macro"; +import cx from "classnames"; import Tooltip from "components/Tooltip/Tooltip"; import { BigNumber } from "ethers"; import { formatDeltaUsd } from "lib/numbers"; -import { CSSProperties, useCallback, useMemo } from "react"; +import { CSSProperties, ReactNode, useCallback, useMemo } from "react"; +import { useMedia } from "react-use"; + +type Section = { + buttonText: ReactNode; + tooltipText: ReactNode; + onButtonClick: () => void; + usd: BigNumber; + buttonStyle?: "primary" | "secondary"; +}; type Props = { - fundingFees: BigNumber; - buttonText: string; title: string; - onButtonClick: () => void; - tooltipText: string; style?: CSSProperties; + sections: Readonly<[Section, Section]>; }; -export function ClaimableCardUI({ buttonText, fundingFees, onButtonClick, title, tooltipText, style }: Props) { - const totalUsd = useMemo(() => formatDeltaUsd(fundingFees), [fundingFees]); +export function ClaimableCardUI({ title, style, sections }: Props) { + const [section1, section2] = sections; + const isHorizontal = useMedia("(min-width: 600px) and (max-width: 1100px)"); + + return ( +
      +
      {title}
      +
      +
      + {!isHorizontal &&
      } + {isHorizontal &&
      } +
      +
      +
      + ); +} + +function Section({ + buttonStyle = "primary", + buttonText, + onButtonClick, + tooltipText, + title, + usd, +}: Section & { title: string }) { const renderTooltipContent = useCallback(() => tooltipText, [tooltipText]); + const usdFormatted = useMemo(() => formatDeltaUsd(usd), [usd]); + const buttonClassname = buttonStyle === "primary" ? "primary App-button-option App-card-option" : "secondary"; return ( -
      -
      -
      {title}
      -
      - - Funding fees - - - - -
      - {fundingFees.gt(0) && ( - - )} +
      +
      + {title} + + {tooltipText ? ( + + ) : ( + usdFormatted + )} +
      + {usd.gt(0) && ( + + )}
      ); } diff --git a/src/components/Synthetics/Claims/Claims.scss b/src/components/Synthetics/Claims/Claims.scss index 0cd3c69da8..2c6b231634 100644 --- a/src/components/Synthetics/Claims/Claims.scss +++ b/src/components/Synthetics/Claims/Claims.scss @@ -1,29 +1,107 @@ .Claims-row { - display: flex; - flex-direction: row; + display: flex; + flex-direction: row; + padding: 0.1rem 1.5rem; + align-items: center; + flex: 1; +} + +.Claims-card { + background: #16182e; + font-size: var(--font-base); + margin-bottom: 0.8rem; + padding-bottom: 1rem; + border-radius: 0.4rem; +} + +.Claims-title { + border-bottom: 1px solid #23263b; + padding: 1rem 1.5rem; + font-size: 1.5rem; } .Claims-col { - justify-content: center; - align-items: flex-start; - display: flex; - flex-direction: column; + justify-content: center; + align-items: flex-start; + display: flex; + flex-direction: column; + padding: 1rem 0; } .Claims-col + .Claims-col { - margin-left: 3rem; + margin-left: 3rem; } .Claims-col .muted { - margin-bottom: 0.2rem; + margin-bottom: 0.2rem; } -.Claims-claim-button { - margin-left: auto; +.Claims-claim-button.primary { + cursor: pointer; + border-radius: 4px; + font-size: var(--font-sm); + line-height: 2rem; + font-weight: normal; + letter-spacing: 0px; + color: white; + padding-left: 16px; + padding-right: 16px; + text-decoration: none; + box-sizing: border-box; + position: relative; + min-height: 36px; + display: inline-flex !important; + align-items: center; + border: none; + background: rgb(43, 55, 94); + margin-left: auto; + height: 0; +} + +.Claims-claim-button.secondary { + cursor: pointer; + font-size: var(--font-sm); + font-weight: normal; + letter-spacing: 0px; + text-decoration: none; + box-sizing: border-box; + position: relative; + min-height: 36px; + display: inline-flex !important; + align-items: center; + border: none; + margin-left: auto; + height: 0; + background-color: transparent; + + color: rgba(255, 255, 255, 0.7); + &:hover { + color: rgba(255, 255, 255); + } } .Claims-col-title { - white-space: nowrap; - margin-bottom: 1.8rem; - width: 7rem; -} \ No newline at end of file + white-space: nowrap; + margin-bottom: 1.8rem; + width: 7rem; +} + +.Claims-rows { + display: flex; + flex-direction: column; +} + +.Claims-rows-horizontal.Claims-rows { + display: flex; + flex-direction: row; +} + +.Claims-hr { + margin: 0.4rem 1.4rem 0; + border-bottom: 1px solid #23263b; +} + +.Claims-hr-horizontal { + margin: 0.8rem 0 0; + border-left: 1px solid #23263b; +} diff --git a/src/components/Synthetics/Claims/Claims.tsx b/src/components/Synthetics/Claims/Claims.tsx index 095ded1f55..e964ce8e66 100644 --- a/src/components/Synthetics/Claims/Claims.tsx +++ b/src/components/Synthetics/Claims/Claims.tsx @@ -1,110 +1,167 @@ -import cx from "classnames"; import { Trans } from "@lingui/macro"; +import cx from "classnames"; +import { useClaimCollateralHistory } from "domain/synthetics/claimHistory"; +import { RebateInfoItem } from "domain/synthetics/fees/useRebatesInfo"; +import { PositionsInfoData } from "domain/synthetics/positions"; import { useChainId } from "lib/chains"; +import useWallet from "lib/wallets/useWallet"; import { useCallback, useState } from "react"; -import { useClaimCollateralHistory } from "domain/synthetics/claimHistory"; +import { useMedia } from "react-use"; +import { AccruedPositionPriceImpactRebateModal } from "../AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal"; import { ClaimHistoryRow } from "../ClaimHistoryRow/ClaimHistoryRow"; -import { MarketsInfoData } from "domain/synthetics/markets"; -import { TokensData } from "domain/synthetics/tokens"; -import useWallet from "lib/wallets/useWallet"; +import { ClaimModal } from "../ClaimModal/ClaimModal"; +import { ClaimablePositionPriceImpactRebateModal } from "../ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal"; +import { SettleAccruedFundingFeeModal } from "../SettleAccruedFundingFeeModal/SettleAccruedFundingFeeModal"; import { ClaimableCard } from "./ClaimableCard"; - import "./Claims.scss"; -import { useMedia } from "react-use"; import { SettleAccruedCard } from "./SettleAccruedCard"; -import { PositionsInfoData } from "domain/synthetics/positions"; const PAGE_SIZE = 100; -type Props = { - shouldShowPaginationButtons: boolean; - marketsInfoData: MarketsInfoData | undefined; - tokensData: TokensData | undefined; - setIsClaiming: (isClaiming: boolean) => void; - setIsSettling: (isSettling: boolean) => void; - positionsInfoData: PositionsInfoData | undefined; -}; +const MARGIN_RIGHT = { marginRight: 4 }; +const MARGIN_LEFT = { marginLeft: 4 }; export function Claims({ shouldShowPaginationButtons, - marketsInfoData, - tokensData, - setIsClaiming, + isSettling, setIsSettling, positionsInfoData, -}: Props) { + gettingPendingFeePositionKeys, + setGettingPendingFeePositionKeys, + setPendingTxns, + allowedSlippage, + accruedPositionPriceImpactFees, + claimablePositionPriceImpactFees, +}: { + shouldShowPaginationButtons: boolean; + isSettling: boolean; + setIsSettling: (v: boolean) => void; + positionsInfoData: PositionsInfoData | undefined; + gettingPendingFeePositionKeys: string[]; + setGettingPendingFeePositionKeys: (keys: string[]) => void; + setPendingTxns: (txns: any) => void; + allowedSlippage: number; + accruedPositionPriceImpactFees: RebateInfoItem[]; + claimablePositionPriceImpactFees: RebateInfoItem[]; +}) { const { chainId } = useChainId(); const { account } = useWallet(); const [pageIndex, setPageIndex] = useState(0); + const [isClaiming, setIsClaiming] = useState(false); + + const [isAccruedPositionPriceImpactRebateModalVisible, setIsAccruedPositionPriceImpactRebateModalVisible] = + useState(false); + const [isClaimablePositionPriceImpactFeesModalVisible, setIsClaimablePositionPriceImpactFeesModalVisible] = + useState(false); const { claimActions, isLoading } = useClaimCollateralHistory(chainId, { - marketsInfoData, - tokensData, pageIndex, pageSize: PAGE_SIZE, }); const isEmpty = !account || claimActions?.length === 0; - const handleClaimClick = useCallback(() => { - setIsClaiming(true); - }, [setIsClaiming]); + const handleClaimClick = useCallback(() => setIsClaiming(true), [setIsClaiming]); + const handleSettleClick = useCallback(() => setIsSettling(true), [setIsSettling]); + const handleAccruedPositionPriceImpactRebateClick = useCallback( + () => setIsAccruedPositionPriceImpactRebateModalVisible(true), + [setIsAccruedPositionPriceImpactRebateModalVisible] + ); + const handleClaimablePositionPriceImpactFeesClick = useCallback( + () => setIsClaimablePositionPriceImpactFeesModalVisible(true), + [setIsClaimablePositionPriceImpactFeesModalVisible] + ); + + const handleSettleCloseClick = useCallback(() => { + setGettingPendingFeePositionKeys([]); + setIsSettling(false); + }, [setGettingPendingFeePositionKeys, setIsSettling]); - const handleSettleClick = useCallback(() => { - setIsSettling(true); - }, [setIsSettling]); + const handleAccruedPositionPriceImpactRebateCloseClick = useCallback(() => { + setIsAccruedPositionPriceImpactRebateModalVisible(false); + }, []); + + const handleClaimablePositionPriceImpactFeesCloseClick = useCallback(() => { + setIsClaimablePositionPriceImpactFeesModalVisible(false); + }, []); const isMobile = useMedia("(max-width: 1100px)"); return ( -
      - {account && isLoading && ( -
      - Loading... -
      - )} -
      - {account && !isLoading && ( - - )} - {account && !isLoading && ( - + <> + setIsClaiming(false)} setPendingTxns={setPendingTxns} /> + + + + + +
      + {account && isLoading && ( +
      + Loading... +
      )} -
      - {isEmpty && ( -
      - No claims yet -
      - )} - {claimActions?.map((claimAction) => ( - - ))} - {shouldShowPaginationButtons && ( -
      - {pageIndex > 0 && ( - +
      + {account && !isLoading && ( + )} - {claimActions && claimActions.length >= PAGE_SIZE && ( - + {account && !isLoading && ( + )}
      - )} -
      + {isEmpty && ( +
      + No claims yet +
      + )} + {claimActions?.map((claimAction) => ( + + ))} + {shouldShowPaginationButtons && ( +
      + {pageIndex > 0 && ( + + )} + {claimActions && claimActions.length >= PAGE_SIZE && ( + + )} +
      + )} +
      + ); } diff --git a/src/components/Synthetics/Claims/SettleAccruedCard.tsx b/src/components/Synthetics/Claims/SettleAccruedCard.tsx index febe980906..1a0370ce2c 100644 --- a/src/components/Synthetics/Claims/SettleAccruedCard.tsx +++ b/src/components/Synthetics/Claims/SettleAccruedCard.tsx @@ -1,31 +1,64 @@ -import { t } from "@lingui/macro"; +import { Trans, t } from "@lingui/macro"; +import ExternalLink from "components/ExternalLink/ExternalLink"; +import { useTokensData } from "context/SyntheticsStateContext/hooks/globalsHooks"; +import { RebateInfoItem } from "domain/synthetics/fees/useRebatesInfo"; import { getTotalAccruedFundingUsd } from "domain/synthetics/markets"; import { PositionsInfoData } from "domain/synthetics/positions"; import { CSSProperties, useMemo } from "react"; import { ClaimableCardUI } from "./ClaimableCardUI"; +import { calcTotalRebateUsd } from "./utils"; type Props = { onSettleClick: () => void; + onAccruedPositionPriceImpactRebateClick: () => void; positionsInfoData: PositionsInfoData | undefined; style?: CSSProperties; + accruedPositionPriceImpactFees: RebateInfoItem[]; }; const tooltipText = t`Accrued Positive Funding Fees for Positions not yet claimable. They will become available to claim by using the "Settle" button, or after the Position is increased, decreased or closed.`; const buttonText = t`Settle`; +const button2Text = t`Show details`; const title = t`Accrued`; -export function SettleAccruedCard({ onSettleClick, style, positionsInfoData }: Props) { +export function SettleAccruedCard({ + accruedPositionPriceImpactFees, + onAccruedPositionPriceImpactRebateClick, + onSettleClick, + positionsInfoData, + style, +}: Props) { const positions = useMemo(() => Object.values(positionsInfoData || {}), [positionsInfoData]); const fundingFees = useMemo(() => getTotalAccruedFundingUsd(positions), [positions]); - - return ( - + const tokensData = useTokensData(); + const priceImpactDifference = useMemo( + () => calcTotalRebateUsd(accruedPositionPriceImpactFees, tokensData, true), + [accruedPositionPriceImpactFees, tokensData] + ); + const sections = useMemo( + () => + [ + { usd: fundingFees, buttonText, tooltipText, onButtonClick: onSettleClick }, + { + usd: priceImpactDifference, + buttonText: button2Text, + tooltipText: ( + + Accrued Price Impact Rebates. They will become Claimable after some time. +
      +
      + + Read more + + . +
      + ), + onButtonClick: onAccruedPositionPriceImpactRebateClick, + buttonStyle: "secondary", + }, + ] as const, + [fundingFees, onAccruedPositionPriceImpactRebateClick, onSettleClick, priceImpactDifference] ); + + return ; } diff --git a/src/components/Synthetics/Claims/utils.ts b/src/components/Synthetics/Claims/utils.ts new file mode 100644 index 0000000000..532a9f8c5e --- /dev/null +++ b/src/components/Synthetics/Claims/utils.ts @@ -0,0 +1,28 @@ +import { RebateInfoItem } from "domain/synthetics/fees/useRebatesInfo"; +import { TokensData, getTokenData } from "domain/synthetics/tokens"; +import { BigNumber } from "ethers"; +import { expandDecimals } from "lib/numbers"; + +export function calcTotalRebateUsd( + rebates: RebateInfoItem[], + tokensData: TokensData | undefined, + ignoreFactor: boolean +) { + if (!tokensData) { + return BigNumber.from(0); + } + + return rebates.reduce((total, rebate) => { + const token = getTokenData(tokensData, rebate.tokenAddress); + + if (!token) { + return total; + } + + const price = token.prices.minPrice; + const value = ignoreFactor ? rebate.value : rebate.valueByFactor; + const rebateUsd = value.mul(price).div(expandDecimals(1, token.decimals)); + + return total.add(rebateUsd); + }, BigNumber.from(0)); +} diff --git a/src/components/Synthetics/ConfirmationBox/ConfirmationBox.scss b/src/components/Synthetics/ConfirmationBox/ConfirmationBox.scss index c2a086f4ac..1c645f646a 100644 --- a/src/components/Synthetics/ConfirmationBox/ConfirmationBox.scss +++ b/src/components/Synthetics/ConfirmationBox/ConfirmationBox.scss @@ -3,6 +3,31 @@ flex-direction: column; } +.trade-info-wrapper { + display: grid; + grid-template-columns: 48.5% 3% 48.5%; + align-items: center; + margin-top: 0; + + .arrow-icon { + margin-top: 0.5rem; + } + + .trade-token-amount { + color: white; + font-size: 1.8rem; + } + + .trade-amount-usd { + font-size: 1.6rem; + color: var(--text-gray); + } +} + +.Existing-limit-order { + font-size: 1.4rem; +} + .Confirmation-box { .Modal-body { overflow-x: hidden; @@ -24,3 +49,8 @@ margin-top: 0; } } + +.SLTP-pnl-tooltip .Tooltip-popup { + white-space: nowrap; + min-width: fit-content; +} diff --git a/src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx b/src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx index e0d014a22c..52ace7d9e9 100644 --- a/src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +++ b/src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx @@ -6,22 +6,29 @@ import Checkbox from "components/Checkbox/Checkbox"; import ExchangeInfoRow from "components/Exchange/ExchangeInfoRow"; import Modal from "components/Modal/Modal"; import StatsTooltipRow from "components/StatsTooltip/StatsTooltipRow"; +import ToggleSwitch from "components/ToggleSwitch/ToggleSwitch"; import Tooltip from "components/Tooltip/Tooltip"; import { ValueTransition } from "components/ValueTransition/ValueTransition"; import { getContract } from "config/contracts"; import { BASIS_POINTS_DIVISOR, - DEFAULT_SLIPPAGE_AMOUNT, - EXCESSIVE_SLIPPAGE_AMOUNT, + COLLATERAL_SPREAD_SHOW_AFTER_INITIAL_ZERO_THRESHOLD, HIGH_SPREAD_THRESHOLD, } from "config/factors"; import { useSyntheticsEvents } from "context/SyntheticsEvents"; import { useUserReferralCode } from "domain/referrals/hooks"; -import { ExecutionFee, getBorrowingFactorPerPeriod, getFundingFactorPerPeriod } from "domain/synthetics/fees"; -import { MarketInfo } from "domain/synthetics/markets"; import { + ExecutionFee, + estimateExecuteDecreaseOrderGasLimit, + getBorrowingFactorPerPeriod, + getExecutionFee, + getFundingFactorPerPeriod, + useGasLimits, + useGasPrice, +} from "domain/synthetics/fees"; +import { + DecreasePositionSwapType, OrderType, - OrdersInfoData, PositionOrderInfo, createDecreaseOrderTxn, createIncreaseOrderTxn, @@ -41,9 +48,6 @@ import { getTriggerNameByOrderType, } from "domain/synthetics/positions"; import { - TokenData, - TokensData, - TokensRatio, convertToTokenAmount, formatTokensRatio, getNeedTokenApprove, @@ -51,36 +55,44 @@ import { } from "domain/synthetics/tokens"; import { DecreasePositionAmounts, - IncreasePositionAmounts, - NextPositionValues, - SwapAmounts, TradeFees, TriggerThresholdType, applySlippageToMinOut, applySlippageToPrice, getExecutionPriceForDecrease, } from "domain/synthetics/trade"; -import { TradeFlags } from "domain/synthetics/trade/useTradeFlags"; import { getIsEquivalentTokens, getSpread } from "domain/tokens"; import { BigNumber } from "ethers"; import { useChainId } from "lib/chains"; import { CHART_PERIODS, USD_DECIMALS } from "lib/legacy"; import { useConnectModal } from "@rainbow-me/rainbowkit"; -import PercentageInput from "components/PercentageInput/PercentageInput"; +import { AlertInfo } from "components/AlertInfo/AlertInfo"; import { SubaccountNavigationButton } from "components/SubaccountNavigationButton/SubaccountNavigationButton"; -import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; import { useSettings } from "context/SettingsContext/SettingsContextProvider"; import { useIsLastSubaccountAction, useSubaccount, useSubaccountCancelOrdersDetailsMessage, } from "context/SubaccountContext/SubaccountContext"; +import { useOrdersInfoData, useTokensData } from "context/SyntheticsStateContext/hooks/globalsHooks"; +import { useTradeRatios } from "context/SyntheticsStateContext/hooks/tradeHooks"; +import { + useTradeboxDecreasePositionAmounts, + useTradeboxIncreasePositionAmounts, + useTradeboxNextPositionValuesForDecrease, + useTradeboxNextPositionValuesForIncrease, + useTradeboxState, + useTradeboxSwapAmounts, + useTradeboxTradeFlags, +} from "context/SyntheticsStateContext/hooks/tradeboxHooks"; +import useSLTPEntries from "domain/synthetics/orders/useSLTPEntries"; import { AvailableMarketsOptions } from "domain/synthetics/trade/useAvailableMarketsOptions"; +import { useHighExecutionFeeConsent } from "domain/synthetics/trade/useHighExecutionFeeConsent"; import { usePriceImpactWarningState } from "domain/synthetics/trade/usePriceImpactWarningState"; import { helperToast } from "lib/helperToast"; import { - bigNumberify, + expandDecimals, formatAmount, formatDeltaUsd, formatPercentage, @@ -88,38 +100,27 @@ import { formatTokenAmountWithUsd, formatUsd, } from "lib/numbers"; +import { getByKey } from "lib/objects"; import { usePrevious } from "lib/usePrevious"; import { getPlusOrMinusSymbol, getPositiveOrNegativeClass } from "lib/utils"; import useWallet from "lib/wallets/useWallet"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { FaArrowRight } from "react-icons/fa"; +import { IoClose } from "react-icons/io5"; import { useKey, useLatest } from "react-use"; import { AcceptablePriceImpactInputRow } from "../AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow"; import { HighPriceImpactWarning } from "../HighPriceImpactWarning/HighPriceImpactWarning"; import { TradeFeesRow } from "../TradeFeesRow/TradeFeesRow"; import "./ConfirmationBox.scss"; +import SLTPEntries from "./SLTPEntries"; +import { AllowedSlippageRow } from "./rows/AllowedSlippageRow"; export type Props = { isVisible: boolean; - tradeFlags: TradeFlags; - isWrapOrUnwrap: boolean; - fromToken?: TokenData; - toToken?: TokenData; - markPrice?: BigNumber; - markRatio?: TokensRatio; triggerPrice?: BigNumber; fixedTriggerThresholdType?: TriggerThresholdType; fixedTriggerOrderType?: OrderType.LimitDecrease | OrderType.StopLossDecrease; - selectedTriggerAcceptablePriceImpactBps?: BigNumber; - defaultTriggerAcceptablePriceImpactBps?: BigNumber; - triggerRatio?: TokensRatio; - marketInfo?: MarketInfo; - collateralToken?: TokenData; - swapAmounts?: SwapAmounts; marketsOptions?: AvailableMarketsOptions; - increaseAmounts?: IncreasePositionAmounts; - decreaseAmounts?: DecreasePositionAmounts; - nextPositionValues?: NextPositionValues; - keepLeverage?: boolean; swapLiquidityUsd?: BigNumber; longLiquidityUsd?: BigNumber; shortLiquidityUsd?: BigNumber; @@ -128,54 +129,77 @@ export type Props = { error?: string; existingPosition?: PositionInfo; shouldDisableValidation: boolean; - isHigherSlippageAllowed?: boolean; - ordersData?: OrdersInfoData; - tokensData?: TokensData; - setSelectedTriggerAcceptablePriceImapctBps: (value: BigNumber) => void; - setIsHigherSlippageAllowed: (isHigherSlippageAllowed: boolean) => void; - setKeepLeverage: (keepLeverage: boolean) => void; + selectedTriggerAcceptablePriceImpactBps?: BigNumber; + setSelectedTriggerAcceptablePriceImpactBps: (value: BigNumber) => void; onClose: () => void; onSubmitted: () => void; setPendingTxns: (txns: any) => void; + triggerRatioValue: BigNumber | undefined; + markPrice: BigNumber | undefined; }; export function ConfirmationBox(p: Props) { const { - tradeFlags, - isWrapOrUnwrap, - fromToken, - toToken, - markPrice, - markRatio, triggerPrice, fixedTriggerThresholdType, fixedTriggerOrderType, - defaultTriggerAcceptablePriceImpactBps, - triggerRatio, - marketInfo, - collateralToken, - swapAmounts, - increaseAmounts, - decreaseAmounts, - nextPositionValues, swapLiquidityUsd, longLiquidityUsd, shortLiquidityUsd, - keepLeverage, fees, executionFee, error, existingPosition, shouldDisableValidation, marketsOptions, - ordersData, - tokensData, - setSelectedTriggerAcceptablePriceImapctBps, - setKeepLeverage, + selectedTriggerAcceptablePriceImpactBps, + setSelectedTriggerAcceptablePriceImpactBps, onClose, onSubmitted, setPendingTxns, + triggerRatioValue, + markPrice, } = p; + const { + isWrapOrUnwrap, + fromTokenAddress, + toTokenAddress, + defaultTriggerAcceptablePriceImpactBps, + marketInfo, + collateralToken, + keepLeverage, + setKeepLeverage, + tradeMode, + tradeType, + } = useTradeboxState(); + + const { element: highExecutionFeeAcknowledgement, isHighFeeConsentError } = useHighExecutionFeeConsent( + executionFee?.feeUsd + ); + + const { markRatio, triggerRatio } = useTradeRatios({ + fromTokenAddress, + toTokenAddress, + tradeMode, + tradeType, + triggerRatioValue, + }); + + const tokensData = useTokensData(); + const ordersData = useOrdersInfoData(); + const swapAmounts = useTradeboxSwapAmounts(); + const increaseAmounts = useTradeboxIncreasePositionAmounts(); + const decreaseAmounts = useTradeboxDecreasePositionAmounts(); + const nextPositionValuesForIncrease = useTradeboxNextPositionValuesForIncrease(); + const nextPositionValuesForDecrease = useTradeboxNextPositionValuesForDecrease(); + const tradeFlags = useTradeboxTradeFlags(); + + const nextPositionValues = useMemo(() => { + return tradeFlags.isIncrease ? nextPositionValuesForIncrease : nextPositionValuesForDecrease; + }, [nextPositionValuesForDecrease, nextPositionValuesForIncrease, tradeFlags.isIncrease]); + + const fromToken = getByKey(tokensData, fromTokenAddress); + const toToken = getByKey(tokensData, toTokenAddress); const { isLong, isShort, isPosition, isSwap, isMarket, isLimit, isTrigger, isIncrease } = tradeFlags; const { indexToken } = marketInfo || {}; @@ -185,17 +209,32 @@ export function ConfirmationBox(p: Props) { const { openConnectModal } = useConnectModal(); const { setPendingPosition, setPendingOrder } = useSyntheticsEvents(); const { savedAllowedSlippage } = useSettings(); - + const { gasLimits } = useGasLimits(chainId); + const { gasPrice } = useGasPrice(chainId); const prevIsVisible = usePrevious(p.isVisible); const { referralCodeForTxn } = useUserReferralCode(signer, chainId, account); const [isTriggerWarningAccepted, setIsTriggerWarningAccepted] = useState(false); - const [isLimitOrdersVisible, setIsLimitOrdersVisible] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); const [allowedSlippage, setAllowedSlippage] = useState(savedAllowedSlippage); const submitButtonRef = useRef(null); + const { stopLoss, takeProfit } = useSLTPEntries({ + marketInfo, + tradeFlags, + collateralToken, + increaseAmounts, + nextPositionValues, + triggerPrice, + }); + + const { sltpEntries, sltpAmounts } = useMemo(() => { + const entries = (stopLoss?.entries || []).concat(takeProfit?.entries || []); + const amounts = entries.map((entry) => entry.amounts).filter(Boolean) as DecreasePositionAmounts[]; + return { sltpEntries: entries, sltpAmounts: amounts }; + }, [stopLoss, takeProfit]); + useEffect(() => { setAllowedSlippage(savedAllowedSlippage); }, [savedAllowedSlippage, p.isVisible]); @@ -237,6 +276,20 @@ export function ConfirmationBox(p: Props) { return Object.values(ordersData).filter((order) => isOrderForPosition(order, positionKey)) as PositionOrderInfo[]; }, [ordersData, positionKey]); + const getDecreaseExecutionFee = useCallback( + (decreaseAmounts?: DecreasePositionAmounts) => { + if (!decreaseAmounts || !gasLimits || !tokensData || !gasPrice) return; + const swapsCount = decreaseAmounts.decreaseSwapType === DecreasePositionSwapType.NoSwap ? 0 : 1; + + const estimatedGas = estimateExecuteDecreaseOrderGasLimit(gasLimits, { + swapsCount, + }); + + return getExecutionFee(chainId, gasLimits, tokensData, estimatedGas, gasPrice); + }, + [gasLimits, tokensData, gasPrice, chainId] + ); + const existingLimitOrders = useMemo( () => positionOrders.filter((order) => isLimitOrderType(order.orderType)), [positionOrders] @@ -326,8 +379,8 @@ export function ConfirmationBox(p: Props) { const priceImpactWarningState = usePriceImpactWarningState({ positionPriceImpact: fees?.positionPriceImpact, swapPriceImpact: fees?.swapPriceImpact, - tradeFlags, place: "confirmationBox", + tradeFlags, }); const setIsHighPositionImpactAcceptedRef = useLatest(priceImpactWarningState.setIsHighPositionImpactAccepted); @@ -341,7 +394,14 @@ export function ConfirmationBox(p: Props) { const submitButtonState = useMemo(() => { if (priceImpactWarningState.validationError) { return { - text: "Price Impact not yet acknowledged", + text: t`Price Impact not yet acknowledged`, + disabled: true, + }; + } + + if (isHighFeeConsentError) { + return { + text: t`High Execution Fee not yet acknowledged`, disabled: true, }; } @@ -385,13 +445,21 @@ export function ConfirmationBox(p: Props) { text = t`Confirm ${getTriggerNameByOrderType(fixedTriggerOrderType)} Order`; } + if (sltpEntries.length > 0) { + const isError = sltpEntries.some((entry) => entry.error); + return { + text, + disabled: isError, + }; + } + return { text, disabled: false, }; }, [ - isLimit, priceImpactWarningState.validationError, + isHighFeeConsentError, isSubmitting, error, needPayTokenApproval, @@ -399,11 +467,13 @@ export function ConfirmationBox(p: Props) { decreaseOrdersThatWillBeExecuted.length, isTriggerWarningAccepted, isMarket, + isLimit, fromToken?.assetSymbol, fromToken?.symbol, isSwap, isLong, fixedTriggerOrderType, + sltpEntries, ]); useKey( @@ -418,9 +488,15 @@ export function ConfirmationBox(p: Props) { [p.isVisible, submitButtonState.disabled] ); - const subaccountRequiredBalance = p.executionFee?.feeTokenAmount ?? null; - const subaccount = useSubaccount(subaccountRequiredBalance); - const isLastSubaccountAction = useIsLastSubaccountAction(1); + const subaccountRequiredBalance = + p.executionFee?.feeTokenAmount.add( + sltpAmounts.reduce( + (acc, amount) => acc.add(getDecreaseExecutionFee(amount)?.feeTokenAmount || 0), + BigNumber.from(0) + ) + ) ?? null; + const subaccount = useSubaccount(subaccountRequiredBalance, 1 + sltpAmounts.length); + const isLastSubaccountAction = useIsLastSubaccountAction(1 + sltpAmounts.length); const cancelOrdersDetailsMessage = useSubaccountCancelOrdersDetailsMessage(subaccountRequiredBalance ?? undefined, 1); function onCancelOrderClick(key: string): void { @@ -493,30 +569,59 @@ export function ConfirmationBox(p: Props) { return Promise.resolve(); } - return createIncreaseOrderTxn(chainId, signer, subaccount, { - account, - marketAddress: marketInfo.marketTokenAddress, - initialCollateralAddress: fromToken?.address, - initialCollateralAmount: increaseAmounts.initialCollateralAmount, - targetCollateralAddress: collateralToken.address, - collateralDeltaAmount: increaseAmounts.collateralDeltaAmount, - swapPath: increaseAmounts.swapPathStats?.swapPath || [], - sizeDeltaUsd: increaseAmounts.sizeDeltaUsd, - sizeDeltaInTokens: increaseAmounts.sizeDeltaInTokens, - triggerPrice: isLimit ? triggerPrice : undefined, - acceptablePrice: increaseAmounts.acceptablePrice, - isLong, - orderType: isLimit ? OrderType.LimitIncrease : OrderType.MarketIncrease, - executionFee: executionFee.feeTokenAmount, - allowedSlippage, - referralCode: referralCodeForTxn, - indexToken: marketInfo.indexToken, - tokensData, - skipSimulation: isLimit || shouldDisableValidation, - setPendingTxns: p.setPendingTxns, - setPendingOrder, - setPendingPosition, - }); + return createIncreaseOrderTxn( + chainId, + signer, + subaccount, + { + account, + marketAddress: marketInfo.marketTokenAddress, + initialCollateralAddress: fromToken?.address, + initialCollateralAmount: increaseAmounts.initialCollateralAmount, + targetCollateralAddress: collateralToken.address, + collateralDeltaAmount: increaseAmounts.collateralDeltaAmount, + swapPath: increaseAmounts.swapPathStats?.swapPath || [], + sizeDeltaUsd: increaseAmounts.sizeDeltaUsd, + sizeDeltaInTokens: increaseAmounts.sizeDeltaInTokens, + triggerPrice: isLimit ? triggerPrice : undefined, + acceptablePrice: increaseAmounts.acceptablePrice, + isLong, + orderType: isLimit ? OrderType.LimitIncrease : OrderType.MarketIncrease, + executionFee: executionFee.feeTokenAmount, + allowedSlippage, + referralCode: referralCodeForTxn, + indexToken: marketInfo.indexToken, + tokensData, + skipSimulation: isLimit || shouldDisableValidation, + setPendingTxns: p.setPendingTxns, + setPendingOrder, + setPendingPosition, + }, + sltpAmounts.map((entry) => { + return { + account, + marketAddress: marketInfo.marketTokenAddress, + initialCollateralAddress: collateralToken?.address, + initialCollateralDeltaAmount: entry.collateralDeltaAmount || BigNumber.from(0), + receiveTokenAddress: collateralToken.address, + swapPath: [], + sizeDeltaUsd: entry.sizeDeltaUsd, + sizeDeltaInTokens: entry.sizeDeltaInTokens, + isLong, + acceptablePrice: entry.acceptablePrice, + triggerPrice: entry.triggerPrice, + minOutputUsd: BigNumber.from(0), + decreasePositionSwapType: entry.decreaseSwapType, + orderType: entry.triggerOrderType!, + referralCode: referralCodeForTxn, + executionFee: getDecreaseExecutionFee(entry)?.feeTokenAmount || BigNumber.from(0), + allowedSlippage, + indexToken: marketInfo.indexToken, + tokensData, + skipSimulation: isLimit || shouldDisableValidation, + }; + }) + ); } function onSubmitDecreaseOrder() { @@ -604,9 +709,11 @@ export function ConfirmationBox(p: Props) { function reset() { if (p.isVisible !== prevIsVisible) { setIsTriggerWarningAccepted(false); + stopLoss?.reset(); + takeProfit?.reset(); } }, - [p.isVisible, prevIsVisible] + [p.isVisible, prevIsVisible, takeProfit, stopLoss] ); function renderSubaccountNavigationButton() { @@ -624,28 +731,30 @@ export function ConfirmationBox(p: Props) { if (isSwap) { return ( <> -
      -
      - Pay{" "} - {formatTokenAmountWithUsd( - swapAmounts?.amountIn, - swapAmounts?.usdIn, - fromToken?.symbol, - fromToken?.decimals - )} +
      +
      +
      + Pay{" "} + + {formatTokenAmount(swapAmounts?.amountIn, fromToken?.decimals, fromToken?.symbol, { + useCommas: true, + })} + +
      +
      {formatUsd(swapAmounts?.usdIn)}
      -
      -
      - Receive{" "} - {formatTokenAmountWithUsd( - swapAmounts?.amountOut, - swapAmounts?.usdOut, - toToken?.symbol, - toToken?.decimals - )} + +
      +
      + Receive{" "} + + {formatTokenAmount(swapAmounts?.amountOut, toToken?.decimals, toToken?.symbol, { useCommas: true })} + +
      +
      {formatUsd(swapAmounts?.usdOut)}
      - {renderSubaccountNavigationButton()} +
      {renderSubaccountNavigationButton()}
      ); } @@ -653,28 +762,32 @@ export function ConfirmationBox(p: Props) { if (isIncrease) { return ( <> -
      - - Pay{" "} - {formatTokenAmountWithUsd( - increaseAmounts?.initialCollateralAmount, - increaseAmounts?.initialCollateralUsd, - fromToken?.symbol, - fromToken?.decimals - )} - -
      -
      - {isLong ? t`Long` : t`Short`}{" "} - {formatTokenAmountWithUsd( - increaseAmounts?.sizeDeltaInTokens, - increaseAmounts?.sizeDeltaUsd, - toToken?.symbol, - toToken?.decimals - )} +
      +
      +
      + Pay{" "} + + {formatTokenAmount(increaseAmounts?.initialCollateralAmount, fromToken?.decimals, fromToken?.symbol, { + useCommas: true, + })} + +
      +
      {formatUsd(increaseAmounts?.initialCollateralUsd)}
      +
      + +
      +
      + {isLong ? t`Long` : t`Short`}{" "} + + {formatTokenAmount(increaseAmounts?.sizeDeltaInTokens, toToken?.decimals, toToken?.symbol, { + useCommas: true, + })} + +
      +
      {formatUsd(increaseAmounts?.sizeDeltaUsd)}
      - {renderSubaccountNavigationButton()} +
      {renderSubaccountNavigationButton()}
      ); } @@ -691,24 +804,22 @@ export function ConfirmationBox(p: Props) { function renderOrderItem(order: PositionOrderInfo) { return ( -
    • +
    • - {isLimitOrderType(order.orderType) ? t`Increase` : t`Decrease`} {order.indexToken?.symbol}{" "} - {formatUsd(order.sizeDeltaUsd)} {order.isLong ? t`Long` : t`Short`}   + {order.isLong ? t`Long` : t`Short`} {order.indexToken?.symbol} ({order.targetCollateralToken.symbol}):{" "} + {formatUsd(order.sizeDeltaUsd)} at price   {order.triggerThresholdType} {formatUsd(order.triggerPrice, { displayDecimals: toToken?.priceDecimals, })}{" "}

    • ); } - const longShortText = isLong ? t`Long` : t`Short`; - function renderDifferentTokensWarning() { if (!isPosition || !fromToken || !toToken) { return null; @@ -719,34 +830,34 @@ export function ConfirmationBox(p: Props) { if (isCollateralTokenNonStable && collateralTokenSymbol !== indexTokenSymbol) { return ( -
      + You have selected {collateralTokenSymbol} as Collateral, the Liquidation Price will vary based on the price of {collateralTokenSymbol}. -
      + ); } if (isLong && isCollateralTokenNonStable && collateralTokenSymbol === indexTokenSymbol) { return ( -
      + You have selected {collateralTokenSymbol} as collateral, the Liquidation Price is higher compared to using a stablecoin as collateral since the worth of the collateral will change with its price. If required, you can change the collateral type using the Collateral In option in the trade box. -
      + ); } if (isShort && isCollateralTokenNonStable && collateralTokenSymbol === indexTokenSymbol) { return ( -
      + You have selected {collateralTokenSymbol} as collateral to short {indexTokenSymbol}. -
      + ); } } @@ -777,22 +888,22 @@ export function ConfirmationBox(p: Props) { if (isMarket) { return ( -
      + You have an existing position with {marketsOptions?.collateralWithPosition?.symbol} as collateral. This action will not apply for that position. -
      + ); } return ( -
      + You have an existing position with {marketsOptions?.collateralWithPosition?.symbol} as collateral. This Order will not be valid for that Position. -
      + ); } @@ -800,42 +911,19 @@ export function ConfirmationBox(p: Props) { if (!existingLimitOrders?.length || !toToken) { return; } - - if (existingLimitOrders.length === 1) { - const order = existingLimitOrders[0]; - - const sizeText = formatUsd(order.sizeDeltaUsd); - - return ( -
      - - You have an active Limit Order to Increase {longShortText} {order.indexToken?.symbol} {sizeText} at price{" "} - {formatUsd(order.triggerPrice, { - displayDecimals: toToken.priceDecimals, - })} - . - -
      - ); - } else { - return ( -
      -
      - - - You have multiple existing Increase {longShortText} {toToken.symbol} limit orders{" "} - - - setIsLimitOrdersVisible((p) => !p)} className="view-orders"> - ({isLimitOrdersVisible ? t`hide` : t`view`}) - -
      - {isLimitOrdersVisible &&
        {existingLimitOrders.map(renderOrderItem)}
      } -
      - ); - } + return ( +
      + + + +
        {existingLimitOrders.map(renderOrderItem)}
      +
      + ); } - function renderExistingTriggerErrors() { if (!decreaseOrdersThatWillBeExecuted?.length) { return; @@ -844,13 +932,13 @@ export function ConfirmationBox(p: Props) { const existingTriggerOrderLength = decreaseOrdersThatWillBeExecuted.length; return ( <> -
      + -
      +
        {decreaseOrdersThatWillBeExecuted.map(renderOrderItem)}
      ); @@ -868,13 +956,13 @@ export function ConfirmationBox(p: Props) { const existingTriggerOrderLength = existingTriggerOrders.length; return ( -
      + -
      + ); } @@ -938,74 +1026,93 @@ export function ConfirmationBox(p: Props) { if (swapSpreadInfo.spread && swapSpreadInfo.isHigh) { return ( -
      - The spread is {`>`} 1%, please ensure the trade details are acceptable before comfirming +
      + + The spread is {`>`} 1%, please ensure the trade details are acceptable before comfirming +
      ); } } - function renderLimitPriceWarning() { - return ( -
      - Limit Order Price will vary based on Fees and Price Impact to guarantee the Min. Receive amount. -
      - ); - } - const renderCollateralSpreadWarning = useCallback(() => { if (collateralSpreadInfo && collateralSpreadInfo.isHigh) { return ( -
      + Transacting with a depegged stable coin is subject to spreads reflecting the worse of current market price or $1.00, with transactions involving multiple stablecoins may have multiple spreads. -
      + ); } }, [collateralSpreadInfo]); - function renderAllowedSlippage(defaultSlippage, setSlippage) { + function renderSLTP(type: "stopLoss" | "takeProfit") { + const isStopLoss = type === "stopLoss"; + const entriesInfo = isStopLoss ? stopLoss : takeProfit; + + if (existingPosition || !entriesInfo) return; + + const label = isStopLoss ? t`Stop-Loss` : t`Take-Profit`; + const labelPnl = isStopLoss ? t`Stop-Loss PnL` : t`Take-Profit PnL`; + return ( - { - return ( -
      - - You can edit the default Allowed Slippage in the settings menu on the top right of the page. -
      -
      - Note that a low allowed slippage, e.g. less than{" "} - {formatPercentage(bigNumberify(DEFAULT_SLIPPAGE_AMOUNT), { signed: false })}, may result in failed - orders if prices are volatile. -
      -
      - ); - }} - /> - } - > - + + +
      + } /> - + + {entriesInfo?.totalPnL?.isZero() ? ( + "-" + ) : ( + + entriesInfo?.entries?.map((entry, index) => { + if (!entry || !entry.amounts) return; + return ( +
      + + At ${entry.price}, SL {entry?.percentage}%: + + + {formatUsd(entry.amounts?.realizedPnl)} ( + {formatPercentage(entry.amounts?.realizedPnlPercentage, { + signed: true, + })} + ) + +
      + ); + }) + } + /> + )} +
      +
      ); } function renderAcceptablePriceImpactInput() { return ( ); } @@ -1015,17 +1122,25 @@ export function ConfirmationBox(p: Props) { return ; } - function renderLeverage(from: BigNumber | undefined, to: BigNumber | undefined, emptyValue = false) { - return ( - <> - } - /> -
      - - ); - } + const hasWarning = + renderExistingLimitOrdersWarning() || + renderDifferentCollateralWarning() || + renderCollateralSpreadWarning() || + renderExistingTriggerErrors() || + renderExistingTriggerWarning() || + renderDifferentTokensWarning(); + + const [initialCollateralSpread, setInitialCollateralSpread] = useState(); + + const collateralSpreadPercent = collateralSpreadInfo?.spread + ?.mul(BASIS_POINTS_DIVISOR) + ?.div(expandDecimals(1, USD_DECIMALS)); + + useEffect(() => { + if (collateralSpreadPercent && !initialCollateralSpread) { + setInitialCollateralSpread(collateralSpreadPercent); + } + }, [collateralSpreadPercent, initialCollateralSpread]); function renderIncreaseOrderSection() { if (!marketInfo || !fromToken || !collateralToken || !toToken) { @@ -1044,24 +1159,63 @@ export function ConfirmationBox(p: Props) { ? applySlippageToPrice(allowedSlippage, increaseAmounts.acceptablePrice, true, isLong) : increaseAmounts?.acceptablePrice; + const isNearZeroFromStart = + initialCollateralSpread?.eq(0) && + collateralSpreadPercent?.lt(COLLATERAL_SPREAD_SHOW_AFTER_INITIAL_ZERO_THRESHOLD); + + const showCollateralSpread = isMarket && !isNearZeroFromStart; + return ( <>
      {renderMain()} - {renderDifferentCollateralWarning()} - {renderCollateralSpreadWarning()} - {renderExistingLimitOrdersWarning()} - {renderExistingTriggerErrors()} - {renderExistingTriggerWarning()} - {renderDifferentTokensWarning()} - {isLimit && renderAvailableLiquidity()} + {hasWarning &&
      } + {hasWarning && ( + <> + {renderDifferentCollateralWarning()} + {renderCollateralSpreadWarning()} + {renderExistingLimitOrdersWarning()} + {renderExistingTriggerErrors()} + {renderExistingTriggerWarning()} + {renderDifferentTokensWarning()} + + )} + {renderSLTP("takeProfit")} + {renderSLTP("stopLoss")} + +
      {renderLeverage(existingPosition?.leverage, nextPositionValues?.nextLeverage)} - {isMarket && renderAllowedSlippage(savedAllowedSlippage, setAllowedSlippage)} - {isMarket && collateralSpreadInfo?.spread && ( - - {formatAmount(collateralSpreadInfo.spread.mul(100), USD_DECIMALS, 2, true)}% + +
      + + {isLimit && renderAvailableLiquidity()} + {showCollateralSpread && ( + + {formatPercentage(collateralSpreadPercent)} )} + {isMarket && ( + + )} + {isLimit && increaseAmounts && renderAcceptablePriceImpactInput()} + +
      + + {isLimit && ( + + )} - {isLimit && ( - - )} - - {isLimit && increaseAmounts && renderAcceptablePriceImpactInput()} } /> -
      +
      + {p.existingPosition?.sizeInUsd.gt(0) && ( + + } + /> + )} +
      {isCollateralSwap ? (
      + } position="right-top" renderContent={() => { return ( <> - Your position's collateral after deducting fees. + Your position's collateral after deducting fees:

      + {existingPosition && ( + + )}
      @@ -1224,22 +1389,31 @@ export function ConfirmationBox(p: Props) { } function renderSwapSection() { + const hasWarning = renderSwapSpreadWarining() || (isLimit && renderLimitPriceWarning()); return ( <>
      {renderMain()} {renderSwapSpreadWarining()} {isLimit && renderLimitPriceWarning()} + {hasWarning &&
      } + {isLimit && renderAvailableLiquidity()} {swapSpreadInfo.showSpread && swapSpreadInfo.spread && ( {formatAmount(swapSpreadInfo.spread.mul(100), USD_DECIMALS, 2, true)}% )} - {isLimit && renderAvailableLiquidity()} - {isMarket && renderAllowedSlippage(savedAllowedSlippage, setAllowedSlippage)} - - {formatTokensRatio(fromToken, toToken, markRatio)} - + + {isMarket && ( + + )} + +
      + {isLimit && ( )} + {formatTokensRatio(fromToken, toToken, markRatio)} + {formatUsd(swapAmounts?.priceIn, { displayDecimals: fromToken?.priceDecimals, @@ -1264,7 +1440,7 @@ export function ConfirmationBox(p: Props) { })} - {!p.isWrapOrUnwrap && } + {!isWrapOrUnwrap && } {isMarket && swapAmounts?.minOutputAmount @@ -1288,13 +1464,29 @@ export function ConfirmationBox(p: Props) {
      {renderMain()} {renderDifferentCollateralWarning()} + {existingPosition?.leverage && !decreaseAmounts?.isFullClose && ( + <> + {renderLeverage( + existingPosition?.leverage, + nextPositionValues?.nextLeverage, + nextPositionValues?.nextSizeUsd?.lte(0) + )} + {isTrigger && ( + + + Keep leverage at {formatLeverage(existingPosition.leverage)} + + + )} +
      + + )} - {isTrigger && existingPosition?.leverage && ( - - - Keep leverage at {formatLeverage(existingPosition.leverage)} - - + {decreaseAmounts && decreaseAmounts.triggerOrderType !== OrderType.StopLossDecrease && ( + <> + {renderAcceptablePriceImpactInput()} +
      + )} - - {existingPosition && ( - {renderAcceptablePriceImpactInput()} )} + + {p.existingPosition && ( - {!p.existingPosition && } - - {p.existingPosition && ( - - } - /> - )} - - {!p.keepLeverage && - p.existingPosition?.leverage && - renderLeverage( - existingPosition?.leverage, - nextPositionValues?.nextLeverage, - nextPositionValues?.nextSizeUsd?.lte(0) - )} {existingPosition && ( )} + {!p.existingPosition && } + + {p.existingPosition && ( + + } + /> + )} + {existingPosition && decreaseAmounts?.receiveUsd && ( - + {isSwap && renderSwapSection()} {isIncrease && renderIncreaseOrderSection()} {isTrigger && renderTriggerDecreaseSection()} {hasCheckboxesSection &&
      } {renderHighPriceImpactWarning()} + {highExecutionFeeAcknowledgement} {needPayTokenApproval && fromToken && ( <> @@ -1495,3 +1680,20 @@ export function ConfirmationBox(p: Props) {
      ); } + +function renderLeverage(from: BigNumber | undefined, to: BigNumber | undefined, emptyValue = false) { + return ( + } + /> + ); +} + +function renderLimitPriceWarning() { + return ( + + Limit Order Price will vary based on Fees and Price Impact to guarantee the Min. Receive amount. + + ); +} diff --git a/src/components/Synthetics/ConfirmationBox/SLTPEntries.scss b/src/components/Synthetics/ConfirmationBox/SLTPEntries.scss new file mode 100644 index 0000000000..f977d7652a --- /dev/null +++ b/src/components/Synthetics/ConfirmationBox/SLTPEntries.scss @@ -0,0 +1,160 @@ +.SLTPEntries-wrapper { + display: grid; + grid-row-gap: 0.35rem; + + .SLTPEntry-row { + display: grid; + grid-template-columns: auto auto auto; + grid-column-gap: 1rem; + + &:not(:last-child) { + margin-bottom: 1rem; + } + + .SLTP-price { + border: 1px solid #212540; + border-radius: var(--border-radius-sm); + padding-left: 0.5rem; + line-height: 1; + background: #212540; + position: relative; + + .price-input { + padding: 0.2rem 0.5rem 0.2rem; + font-size: 1.4rem; + border-radius: 4px; + max-width: 7rem; + border-radius: var(--border-radius-sm); + text-align: right; + } + + &:hover, + &:focus { + border-color: #3a3f798f; + } + &:focus-within { + border-color: #3a3f79; + } + + &.input-error { + border-color: var(--error-red); + } + .price-symbol { + cursor: pointer; + opacity: 0.7; + } + .SLTP-price-error { + display: none; + &.Tooltip-popup { + min-width: 0; + width: max-content; + } + } + + &:hover { + .SLTP-price-error { + display: block; + } + } + } + .SLTP-percentage { + position: relative; + + &.input-error { + .Suggestion-input { + border-color: var(--error-red); + } + } + + .Suggestion-input { + input { + width: 4.8rem; + } + } + + .SLTP-percent-info { + display: none; + &.Tooltip-popup { + min-width: 25rem; + } + } + + &:focus-within { + .SLTP-percent-info { + display: none; + } + } + + &:hover { + .SLTP-percent-info { + display: block; + } + } + .SLTP-percent-error { + display: none; + &.Tooltip-popup { + min-width: 0; + width: max-content; + } + } + + &:hover { + .SLTP-percent-error { + display: block; + } + } + } + } + .error { + opacity: 0.7; + color: var(--error-red); + font-size: 1.3rem; + text-align: right; + padding-right: 0.5rem; + } + + .SLTP-actions { + display: flex; + align-items: center; + height: 100%; + button { + border: none; + padding: 0.5rem; + border-radius: var(--border-radius-sm); + display: inline-flex; + align-items: center; + justify-content: center; + } + + .action-remove { + background-color: rgba(231, 78, 93, 0.15); + opacity: 0.7; + + &:hover:not(:disabled) { + opacity: 1; + } + } + + .action-add { + background-color: rgba(94, 201, 137, 0.15); + opacity: 0.7; + + &:hover:not(:disabled) { + opacity: 1; + } + } + } + + .rotate-45 { + transform: rotate(45deg); + } +} + +.SLTP-helper-text .Tooltip-popup { + min-width: min-content; + text-wrap: nowrap; + + span { + line-height: 1; + } +} diff --git a/src/components/Synthetics/ConfirmationBox/SLTPEntries.tsx b/src/components/Synthetics/ConfirmationBox/SLTPEntries.tsx new file mode 100644 index 0000000000..0cc21b414f --- /dev/null +++ b/src/components/Synthetics/ConfirmationBox/SLTPEntries.tsx @@ -0,0 +1,126 @@ +import "./SLTPEntries.scss"; +import NumberInput from "components/NumberInput/NumberInput"; +import { NUMBER_WITH_TWO_DECIMALS } from "components/PercentageInput/PercentageInput"; +import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; +import { FaPlus } from "react-icons/fa"; +import cx from "classnames"; +import { formatUsd } from "lib/numbers"; +import SuggestionInput from "components/SuggestionInput/SuggestionInput"; +import { MarketInfo } from "domain/synthetics/markets"; +import { t } from "@lingui/macro"; +import { useRef } from "react"; +import { SLTPInfo } from "domain/synthetics/orders/useSLTPEntries"; + +const SUGGESTION_PERCENTAGE_LIST = [10, 25, 50, 75, 100]; + +type Props = { + entriesInfo: SLTPInfo; + marketInfo?: MarketInfo; +}; + +function SLTPEntries({ entriesInfo, marketInfo }: Props) { + const { addEntry, updateEntry, canAddEntry, deleteEntry } = entriesInfo; + const sltpRef = useRef(null); + + function handleAddEntry() { + addEntry(); + setTimeout(() => { + const inputs = sltpRef.current?.querySelectorAll(".SLTP-price input"); + (inputs && (inputs[inputs.length - 1] as HTMLInputElement))?.focus(); + }); + } + + return ( +
      + {entriesInfo.entries.map((entry) => { + const indexToken = marketInfo?.indexToken; + const entrySizeUsd = entry.amounts?.sizeDeltaUsd; + const priceTooltipMsg = + !entry.error && + entry.price && + indexToken && + entrySizeUsd && + t`Decrease ${indexToken?.symbol} Long by ${formatUsd(entrySizeUsd)} at $${entry.price}.`; + + return ( +
      +
      +
      + $ + + updateEntry(entry.id, { ...entry, price: e.target.value })} + placeholder="Price" + className="price-input" + /> + + {entry.error?.price && ( +
      + {entry.error?.price} +
      + )} +
      +
      + { + if (NUMBER_WITH_TWO_DECIMALS.test(value) || value.length === 0) { + updateEntry(entry.id, { ...entry, percentage: value }); + } + }} + placeholder="Size" + suggestionList={SUGGESTION_PERCENTAGE_LIST} + symbol="%" + /> + {entry.error?.percentage && ( +
      + {entry.error?.percentage} +
      + )} + {entrySizeUsd && priceTooltipMsg ? ( +
      + {priceTooltipMsg} +
      + ) : ( + "" + )} +
      +
      + + + + } + portalClassName="SLTP-helper-text" + handleClassName="mr-xs" + position="right-center" + renderContent={() => Add Row} + openDelay={1500} + /> + deleteEntry(entry.id)} + disabled={entriesInfo.entries.length === 1 && !entry.percentage && !entry.price} + > + + + } + portalClassName="SLTP-helper-text" + position="right-center" + renderContent={() => Remove Row} + openDelay={1500} + /> +
      +
      +
      + ); + })} +
      + ); +} + +export default SLTPEntries; diff --git a/src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx b/src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx new file mode 100644 index 0000000000..a394d03602 --- /dev/null +++ b/src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx @@ -0,0 +1,52 @@ +import { Trans, t } from "@lingui/macro"; + +import { DEFAULT_SLIPPAGE_AMOUNT, EXCESSIVE_SLIPPAGE_AMOUNT } from "config/factors"; +import { bigNumberify, formatPercentage } from "lib/numbers"; + +import ExchangeInfoRow from "components/Exchange/ExchangeInfoRow"; +import PercentageInput from "components/PercentageInput/PercentageInput"; +import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; + +export function AllowedSlippageRow({ + defaultSlippage, + allowedSlippage, + setSlippage, +}: { + defaultSlippage: number; + allowedSlippage: number; + setSlippage: (value: number) => void; +}) { + return ( + { + return ( +
      + + You can edit the default Allowed Slippage in the settings menu on the top right of the page. +
      +
      + Note that a low allowed slippage, e.g. less than - + {formatPercentage(bigNumberify(DEFAULT_SLIPPAGE_AMOUNT), { signed: false })}, may result in failed + orders if prices are volatile. +
      +
      + ); + }} + /> + } + > + +
      + ); +} diff --git a/src/components/Synthetics/GmList/GmList.tsx b/src/components/Synthetics/GmList/GmList.tsx index 3e9a74e34d..b444871afe 100644 --- a/src/components/Synthetics/GmList/GmList.tsx +++ b/src/components/Synthetics/GmList/GmList.tsx @@ -204,13 +204,13 @@ export function GmList({
      ({formatUsd(totalSupplyUsd)})
    {indexTokensStats.length ? ( - indexTokensStats.map((stats) => { + indexTokensStats.map((stats, index) => { const largestPool = stats.marketsStats.sort((a, b) => { return b.poolValueUsd.gt(a.poolValueUsd) ? 1 : -1; })[0]; + const tooltipPositionNetFee = index < indexTokensStats.length / 2 ? "right-bottom" : "right-top"; + const netFeePerHourLong = largestPool.fundingRateLong.add(largestPool.borrowingRateLong); + const netFeePerHourShort = largestPool.fundingRateShort.add(largestPool.borrowingRateShort); return ( @@ -265,11 +243,13 @@ export function MarketsList() { /> @@ -288,75 +268,86 @@ export function MarketsList() { <>
    - {indexTokensStats.map((stats) => ( -
    -
    -
    - {stats.token.symbol} -
    {stats.token.symbol}
    -
    - -
    -
    -
    -
    -
    -
    -
    - Price -
    -
    {formatUsd(stats.token.prices?.minPrice)}
    -
    -
    -
    - Pools -
    -
    - ( - <> - {stats.marketsStats.map(({ marketInfo, poolValueUsd }) => ( - - ))} - - )} + {indexTokensStats.map((stats, index) => { + const largestPool = stats.marketsStats.sort((a, b) => { + return b.poolValueUsd.gt(a.poolValueUsd) ? 1 : -1; + })[0]; + + const tooltipPositionNetFee = index < indexTokensStats.length / 2 ? "right-bottom" : "right-top"; + const netFeePerHourLong = largestPool.fundingRateLong.add(largestPool.borrowingRateLong); + const netFeePerHourShort = largestPool.fundingRateShort.add(largestPool.borrowingRateShort); + + return ( +
    +
    +
    + {stats.token.symbol} +
    {stats.token.symbol}
    +
    + +
    -
    -
    - Funding Rate / 1h +
    +
    +
    +
    + Price +
    +
    {formatUsd(stats.token.prices?.minPrice)}
    -
    - +
    +
    + Pools +
    +
    + ( + <> + {stats.marketsStats.map(({ marketInfo, poolValueUsd }) => ( + + ))} + + )} + /> +
    -
    -
    -
    - Utilization +
    +
    + Net Fee / 1h +
    +
    + +
    +
    +
    +
    + Utilization +
    +
    {formatAmount(stats.totalUtilization, 2, 2, false)}%
    -
    {formatAmount(stats.totalUtilization, 2, 2, false)}%
    -
    - ))} + ); + })}
    )} diff --git a/src/components/Synthetics/OrderEditor/OrderEditor.scss b/src/components/Synthetics/OrderEditor/OrderEditor.scss index 36cb45155c..5bc45973f1 100644 --- a/src/components/Synthetics/OrderEditor/OrderEditor.scss +++ b/src/components/Synthetics/OrderEditor/OrderEditor.scss @@ -1,3 +1,7 @@ .PositionEditor-tabs { margin-top: 0; } + +.PositionEditor-fees-tooltip .Tooltip-popup { + width: 23em; +} diff --git a/src/components/Synthetics/OrderEditor/OrderEditor.tsx b/src/components/Synthetics/OrderEditor/OrderEditor.tsx index e334e1f201..7414782be8 100644 --- a/src/components/Synthetics/OrderEditor/OrderEditor.tsx +++ b/src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -1,8 +1,18 @@ import { Trans, t } from "@lingui/macro"; -import cx from "classnames"; -import BuyInputSection from "components/BuyInputSection/BuyInputSection"; -import Modal from "components/Modal/Modal"; -import { MarketsInfoData } from "domain/synthetics/markets"; +import { BigNumber } from "ethers"; +import { useEffect, useMemo, useState } from "react"; + +import { UserReferralInfo } from "domain/referrals"; +import { + estimateExecuteDecreaseOrderGasLimit, + estimateExecuteIncreaseOrderGasLimit, + estimateExecuteSwapOrderGasLimit, + getExecutionFee, + getFeeItem, + useGasLimits, + useGasPrice, +} from "domain/synthetics/fees"; +import useUiFeeFactor from "domain/synthetics/fees/utils/useUiFeeFactor"; import { OrderInfo, OrderType, @@ -14,18 +24,19 @@ import { isSwapOrderType, isTriggerDecreaseOrderType, } from "domain/synthetics/orders"; +import { updateOrderTxn } from "domain/synthetics/orders/updateOrderTxn"; import { - PositionsInfoData, - formatLeverage, + PositionInfo, formatAcceptablePrice, + formatLeverage, formatLiquidationPrice, getPositionKey, getTriggerNameByOrderType, } from "domain/synthetics/positions"; import { - TokensData, TokensRatio, convertToTokenAmount, + convertToUsd, getAmountByRatio, getTokenData, getTokensRatioByPrice, @@ -37,53 +48,63 @@ import { formatAmountFree, formatDeltaUsd, formatTokenAmount, + formatTokenAmountWithUsd, formatUsd, getBasisPoints, parseValue, } from "lib/numbers"; -import { useEffect, useMemo, useState } from "react"; +import { ExchangeInfo } from "components/Exchange/ExchangeInfo"; import ExchangeInfoRow from "components/Exchange/ExchangeInfoRow"; import { ValueTransition } from "components/ValueTransition/ValueTransition"; -import { getWrappedToken } from "config/tokens"; -import { usePositionsConstants } from "domain/synthetics/positions"; import { BASIS_POINTS_DIVISOR, MAX_ALLOWED_LEVERAGE } from "config/factors"; +import { getWrappedToken } from "config/tokens"; import { - estimateExecuteDecreaseOrderGasLimit, - estimateExecuteIncreaseOrderGasLimit, - estimateExecuteSwapOrderGasLimit, - getExecutionFee, - useGasLimits, - useGasPrice, -} from "domain/synthetics/fees"; -import { updateOrderTxn } from "domain/synthetics/orders/updateOrderTxn"; -import { applySlippageToPrice, getSwapPathOutputAddresses, useSwapRoutes } from "domain/synthetics/trade"; -import { BigNumber } from "ethers"; -import { getByKey } from "lib/objects"; -import { getIncreasePositionAmounts, getNextPositionValuesForIncreaseTrade } from "domain/synthetics/trade"; -import useUiFeeFactor from "domain/synthetics/fees/utils/useUiFeeFactor"; -import { useLocalStorageSerializeKey } from "lib/localStorage"; -import { IS_PNL_IN_LEVERAGE_KEY } from "config/localStorage"; -import { useUserReferralInfo } from "domain/referrals/hooks"; + TradeMode, + TradeType, + applySlippageToPrice, + getAcceptablePriceInfo, + getDecreasePositionAmounts, + getIncreasePositionAmounts, + getSwapPathOutputAddresses, +} from "domain/synthetics/trade"; import Button from "components/Button/Button"; -import useWallet from "lib/wallets/useWallet"; +import StatsTooltipRow from "components/StatsTooltip/StatsTooltipRow"; +import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; +import { getKeepLeverageKey } from "config/localStorage"; +import { useSettings } from "context/SettingsContext/SettingsContextProvider"; import { useSubaccount } from "context/SubaccountContext/SubaccountContext"; +import { + useMarketsInfoData, + usePositionsConstants, + usePositionsInfoData, + useTokensData, + useUserReferralInfo, +} from "context/SyntheticsStateContext/hooks/globalsHooks"; +import { useNextPositionValuesForIncrease, useSwapRoutes } from "context/SyntheticsStateContext/hooks/tradeHooks"; +import { useLocalStorageSerializeKey } from "lib/localStorage"; +import { getByKey } from "lib/objects"; +import useWallet from "lib/wallets/useWallet"; + +import BuyInputSection from "components/BuyInputSection/BuyInputSection"; +import Modal from "components/Modal/Modal"; +import { AcceptablePriceImpactInputRow } from "components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow"; + import "./OrderEditor.scss"; type Props = { - positionsData?: PositionsInfoData; - marketsInfoData?: MarketsInfoData; - tokensData?: TokensData; order: OrderInfo; onClose: () => void; setPendingTxns: (txns: any) => void; }; export function OrderEditor(p: Props) { - const { marketsInfoData, tokensData } = p; const { chainId } = useChainId(); - const { signer, account } = useWallet(); + const { signer } = useWallet(); + const tokensData = useTokensData(); + const marketsInfoData = useMarketsInfoData(); + const positionsData = usePositionsInfoData(); const { gasPrice } = useGasPrice(chainId); const { gasLimits } = useGasLimits(chainId); @@ -94,38 +115,8 @@ export function OrderEditor(p: Props) { const [sizeInputValue, setSizeInputValue] = useState(""); const sizeDeltaUsd = parseValue(sizeInputValue || "0", USD_DECIMALS); - const [triggerPirceInputValue, setTriggerPriceInputValue] = useState(""); - const triggerPrice = parseValue(triggerPirceInputValue || "0", USD_DECIMALS)!; - - const uiFeeFactor = useUiFeeFactor(chainId); - const { minCollateralUsd } = usePositionsConstants(chainId); - const userReferralInfo = useUserReferralInfo(signer, chainId, account); - - const [savedIsPnlInLeverage] = useLocalStorageSerializeKey([chainId, IS_PNL_IN_LEVERAGE_KEY], false); - - const acceptablePrice = useMemo(() => { - if (isSwapOrderType(p.order.orderType)) { - return BigNumber.from(0); - } - - const positionOrder = p.order as PositionOrderInfo; - - // For SL orders Acceptable Price is not applicable and set to 0 or MaxUnit256 - if (p.order.orderType === OrderType.StopLossDecrease) { - return positionOrder.acceptablePrice; - } - - const oldAcceptablePrice = positionOrder.acceptablePrice; - const oldTriggerPrice = positionOrder.triggerPrice; - const priceDelta = oldAcceptablePrice?.sub(oldTriggerPrice || 0).abs() || 0; - const acceptablePriceImpactBps = getBasisPoints(priceDelta, oldTriggerPrice); - return applySlippageToPrice( - acceptablePriceImpactBps.toNumber(), - triggerPrice || oldTriggerPrice, - p.order.isLong, - isIncreaseOrderType(p.order.orderType) - ); - }, [p.order, triggerPrice]); + const [triggerPriceInputValue, setTriggerPriceInputValue] = useState(""); + const triggerPrice = parseValue(triggerPriceInputValue || "0", USD_DECIMALS)!; // Swaps const fromToken = getTokenData(tokensData, p.order.initialCollateralTokenAddress); @@ -211,10 +202,10 @@ export function OrderEditor(p: Props) { p.order.isLong ); - const existingPosition = getByKey(p.positionsData, positionKey); + const existingPosition = getByKey(positionsData, positionKey); const executionFee = useMemo(() => { - if (!p.order.isFrozen || !gasLimits || !gasPrice || !tokensData) return undefined; + if (!gasLimits || !gasPrice || !tokensData) return undefined; let estimatedGas: BigNumber | undefined; @@ -239,26 +230,65 @@ export function OrderEditor(p: Props) { if (!estimatedGas) return undefined; return getExecutionFee(chainId, gasLimits, tokensData, estimatedGas, gasPrice); - }, [chainId, gasLimits, gasPrice, p.order.isFrozen, p.order.orderType, p.order.swapPath, tokensData]); + }, [chainId, gasLimits, gasPrice, p.order.orderType, p.order.swapPath, tokensData]); - const subaccount = useSubaccount(executionFee?.feeTokenAmount ?? null); - const swapRoute = useSwapRoutes({ - marketsInfoData, - fromTokenAddress: p.order.initialCollateralTokenAddress, - toTokenAddress: existingPosition ? existingPosition.collateralTokenAddress : toTokenAddress, - }); + const additionalExecutionFee = useMemo(() => { + if (!executionFee || p.order.executionFee?.gte(executionFee.feeTokenAmount)) { + return undefined; + } + + const feeTokenData = getTokenData(tokensData, executionFee.feeToken.address); + const additionalTokenAmount = executionFee.feeTokenAmount.sub(p.order.executionFee ?? 0); + + return { + feeUsd: convertToUsd(additionalTokenAmount, executionFee.feeToken.decimals, feeTokenData?.prices.minPrice), + feeTokenAmount: additionalTokenAmount, + feeToken: executionFee.feeToken, + }; + }, [executionFee, tokensData, p.order.executionFee]); + + const subaccount = useSubaccount(additionalExecutionFee?.feeTokenAmount ?? null); const isLimitIncreaseOrder = p.order.orderType === OrderType.LimitIncrease; + const positionOrder = p.order as PositionOrderInfo | undefined; + const positionIndexToken = positionOrder?.indexToken; + const indexTokenAmount = useMemo( + () => + positionIndexToken ? convertToTokenAmount(sizeDeltaUsd, positionIndexToken.decimals, triggerPrice) : undefined, + [positionIndexToken, sizeDeltaUsd, triggerPrice] + ); + const nextPositionValuesForIncrease = useNextPositionValuesForIncrease({ + collateralTokenAddress: positionOrder?.targetCollateralToken.address, + fixedAcceptablePriceImpactBps: undefined, + indexTokenAddress: positionIndexToken?.address, + indexTokenAmount, + initialCollateralAmount: positionOrder?.initialCollateralDeltaAmount ?? BigNumber.from(0), + initialCollateralTokenAddress: fromToken?.address, + leverage: existingPosition?.leverage, + marketAddress: positionOrder?.marketAddress, + positionKey: existingPosition?.key, + strategy: "independent", + tradeMode: isLimitOrderType(p.order.orderType) ? TradeMode.Limit : TradeMode.Trigger, + tradeType: positionOrder?.isLong ? TradeType.Long : TradeType.Short, + triggerPrice: isLimitOrderType(p.order.orderType) ? triggerPrice : undefined, + tokenTypeForSwapRoute: existingPosition ? "collateralToken" : "indexToken", + }); + + const swapRoute = useSwapRoutes(p.order.initialCollateralTokenAddress, toTokenAddress); + + const userReferralInfo = useUserReferralInfo(); + const uiFeeFactor = useUiFeeFactor(chainId); + + const { acceptablePrice, acceptablePriceImpactBps, initialAcceptablePriceImpactBps, setAcceptablePriceImpactBps } = + useAcceptablePrice(p.order, triggerPrice); + const increaseAmounts = useMemo(() => { if (!isLimitIncreaseOrder || !toToken || !fromToken || !market || !triggerPrice?.gt(0)) { return undefined; } - const positionOrder = p.order as PositionOrderInfo; - const indexTokenAmount = convertToTokenAmount(sizeDeltaUsd, positionOrder.indexToken.decimals, triggerPrice); - return getIncreasePositionAmounts({ marketInfo: market, indexToken: positionOrder.indexToken, @@ -289,38 +319,33 @@ export function OrderEditor(p: Props) { userReferralInfo, ]); - const nextPositionValues = useMemo(() => { - if (!isLimitIncreaseOrder || !minCollateralUsd || !market) { - return undefined; - } - - if (increaseAmounts?.acceptablePrice && sizeDeltaUsd?.gt(0)) { - return getNextPositionValuesForIncreaseTrade({ - marketInfo: market, - collateralToken: p.order.targetCollateralToken, - existingPosition, - isLong: p.order.isLong, - collateralDeltaUsd: increaseAmounts.collateralDeltaUsd, - collateralDeltaAmount: increaseAmounts.collateralDeltaAmount, - sizeDeltaUsd: increaseAmounts?.sizeDeltaUsd, - sizeDeltaInTokens: increaseAmounts.sizeDeltaInTokens, - indexPrice: increaseAmounts.indexPrice, - showPnlInLeverage: savedIsPnlInLeverage ?? false, - minCollateralUsd: minCollateralUsd!, - userReferralInfo, - }); - } - }, [ - increaseAmounts, - isLimitIncreaseOrder, - market, - minCollateralUsd, - p.order, - savedIsPnlInLeverage, + const decreaseAmounts = useDecreaseAmounts({ + order: p.order, sizeDeltaUsd, existingPosition, + triggerPrice, + acceptablePriceImpactBps, userReferralInfo, - ]); + uiFeeFactor, + }); + + const recommendedAcceptablePriceImpactBps = + isLimitIncreaseOrder && increaseAmounts?.acceptablePrice + ? increaseAmounts?.acceptablePriceDeltaBps.abs() + : decreaseAmounts?.recommendedAcceptablePriceDeltaBps.abs(); + + const priceImpactFeeBps = + market && + getFeeItem( + getAcceptablePriceInfo({ + indexPrice: markPrice!, + isIncrease: isIncreaseOrderType(p.order.orderType), + isLong: p.order.isLong, + marketInfo: market, + sizeDeltaUsd: sizeDeltaUsd!, + }).priceImpactDeltaUsd, + sizeDeltaUsd + )?.bps; function getError() { if (isSubmitting) { @@ -361,7 +386,11 @@ export function OrderEditor(p: Props) { return t`Enter a price`; } - if (sizeDeltaUsd?.eq(positionOrder.sizeDeltaUsd) && triggerPrice?.eq(positionOrder.triggerPrice!)) { + if ( + sizeDeltaUsd?.eq(positionOrder.sizeDeltaUsd) && + triggerPrice?.eq(positionOrder.triggerPrice!) && + acceptablePrice.eq(positionOrder.acceptablePrice) + ) { return t`Enter new amount or price`; } @@ -382,7 +411,11 @@ export function OrderEditor(p: Props) { return t`Loading...`; } - if (sizeDeltaUsd?.eq(p.order.sizeDeltaUsd || 0) && triggerPrice?.eq(positionOrder.triggerPrice || 0)) { + if ( + sizeDeltaUsd?.eq(p.order.sizeDeltaUsd || 0) && + triggerPrice?.eq(positionOrder.triggerPrice || 0) && + acceptablePrice.eq(positionOrder.acceptablePrice) + ) { return t`Enter a new size or price`; } @@ -416,7 +449,7 @@ export function OrderEditor(p: Props) { } if (isLimitIncreaseOrder) { - if (nextPositionValues?.nextLeverage?.gt(MAX_ALLOWED_LEVERAGE)) { + if (nextPositionValuesForIncrease?.nextLeverage?.gt(MAX_ALLOWED_LEVERAGE)) { return t`Max leverage: ${(MAX_ALLOWED_LEVERAGE / BASIS_POINTS_DIVISOR).toFixed(1)}x`; } } @@ -454,7 +487,7 @@ export function OrderEditor(p: Props) { triggerPrice: triggerPrice || positionOrder.triggerPrice, acceptablePrice: acceptablePrice || positionOrder.acceptablePrice, minOutputAmount: minOutputAmount || p.order.minOutputAmount, - executionFee: executionFee?.feeTokenAmount, + executionFee: additionalExecutionFee?.feeTokenAmount, indexToken: indexToken, setPendingTxns: p.setPendingTxns, }) @@ -495,7 +528,6 @@ export function OrderEditor(p: Props) { isVisible={true} setIsVisible={p.onClose} label={Edit {p.order.title}} - allowContentTouchMove > {!isSwapOrderType(p.order.orderType) && ( <> @@ -514,7 +546,7 @@ export function OrderEditor(p: Props) { onClickTopRightLabel={() => setTriggerPriceInputValue(formatAmount(markPrice, USD_DECIMALS, indexPriceDecimals || 2)) } - inputValue={triggerPirceInputValue} + inputValue={triggerPriceInputValue} onInputValueChange={(e) => setTriggerPriceInputValue(e.target.value)} > USD @@ -542,79 +574,102 @@ export function OrderEditor(p: Props) { )} -
    - {isLimitIncreaseOrder && ( - <> + + + {isLimitIncreaseOrder && ( } /> + )} + + + {!isSwapOrderType(p.order.orderType) && ( + <> + {p.order.orderType !== OrderType.StopLossDecrease && ( + <> + + +
    + + )} -
    - - )} - {!isSwapOrderType(p.order.orderType) && ( - <> - - - {existingPosition && ( - )} - - )} - {isSwapOrderType(p.order.orderType) && ( - <> + {existingPosition && ( + + )} + + )} + + + {additionalExecutionFee && ( - {formatDeltaUsd(p.order.swapPathStats?.totalSwapPriceImpactDeltaUsd)} - + ( + <> + {t`Execution Fee`}:
    } + value={formatTokenAmountWithUsd( + additionalExecutionFee.feeTokenAmount.mul(-1), + additionalExecutionFee.feeUsd?.mul(-1), + additionalExecutionFee.feeToken.symbol, + additionalExecutionFee.feeToken.decimals, + { + displayDecimals: 5, + } + )} + showDollar={false} + /> +
    +
    + As network fees have increased, an additional execution fee is needed. +
    + + )} + /> } /> + )} - - - - - )} - - {executionFee?.feeTokenAmount.gt(0) && ( - - {formatTokenAmount( - executionFee?.feeTokenAmount, - executionFee?.feeToken.decimals, - executionFee?.feeToken.symbol, - { displayDecimals: 5 } - )} - - )} -
    + {isSwapOrderType(p.order.orderType) && ( + <> + + + )} +
    +
    + {!p.hideActions && p.onSelectOrder && (
    - {renderMintableAmount({ - mintableInfo, - market, - token, - longToken, - shortToken, - })} + @@ -345,13 +345,13 @@ export function GmList({ />
    - {renderMintableAmount({ - mintableInfo, - market, - token, - longToken, - shortToken, - })} +
    @@ -409,7 +409,37 @@ export function GmList({ ); } -function renderMintableAmount({ mintableInfo, market, token, longToken, shortToken }) { +function MintableAmount({ mintableInfo, market, token, longToken, shortToken }) { + const longTokenMaxValue = useMemo( + () => [ + formatTokenAmount(mintableInfo?.longDepositCapacityAmount, longToken.decimals, longToken.symbol, { + useCommas: true, + }), + `(${formatTokenAmount(market.longPoolAmount, longToken.decimals, "", { + useCommas: true, + displayDecimals: 0, + })} / ${formatTokenAmount(getMaxPoolAmountForDeposit(market, true), longToken.decimals, longToken.symbol, { + useCommas: true, + displayDecimals: 0, + })})`, + ], + [longToken.decimals, longToken.symbol, market, mintableInfo?.longDepositCapacityAmount] + ); + const shortTokenMaxValue = useMemo( + () => [ + formatTokenAmount(mintableInfo?.shortDepositCapacityAmount, shortToken.decimals, shortToken.symbol, { + useCommas: true, + }), + `(${formatTokenAmount(market.shortPoolAmount, shortToken.decimals, "", { + useCommas: true, + displayDecimals: 0, + })} / ${formatTokenAmount(getMaxPoolAmountForDeposit(market, false), shortToken.decimals, shortToken.symbol, { + useCommas: true, + displayDecimals: 0, + })})`, + ], + [market, mintableInfo?.shortDepositCapacityAmount, shortToken.decimals, shortToken.symbol] + ); return (


    - - + + )} /> diff --git a/src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.scss b/src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.scss index 9062eb5914..461d9eab99 100644 --- a/src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.scss +++ b/src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.scss @@ -7,6 +7,7 @@ .GmConfirmationBox-main { display: flex; flex-direction: column; + margin-top: 0; } .GmConfirmationBox-approve-tokens { @@ -24,3 +25,7 @@ margin-top: 0; } } + +.GmConfirmationBox-high-fee { + margin-bottom: 0.465rem; +} diff --git a/src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.tsx b/src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.tsx index fb17fcae86..ba379cf82c 100644 --- a/src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.tsx +++ b/src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.tsx @@ -1,5 +1,4 @@ import { Trans, plural, t } from "@lingui/macro"; -import cx from "classnames"; import { ApproveTokenButton } from "components/ApproveTokenButton/ApproveTokenButton"; import Modal from "components/Modal/Modal"; import { getContract } from "config/contracts"; @@ -7,13 +6,13 @@ import { ExecutionFee } from "domain/synthetics/fees"; import { useMarkets } from "domain/synthetics/markets"; import { createDepositTxn } from "domain/synthetics/markets/createDepositTxn"; import { createWithdrawalTxn } from "domain/synthetics/markets/createWithdrawalTxn"; -import { getNeedTokenApprove, getTokenData, useTokensData } from "domain/synthetics/tokens"; +import { getNeedTokenApprove, getTokenData, useTokensDataRequest } from "domain/synthetics/tokens"; import { TokenData } from "domain/synthetics/tokens/types"; import { useTokensAllowanceData } from "domain/synthetics/tokens/useTokenAllowanceData"; import { GmSwapFees } from "domain/synthetics/trade"; import { BigNumber } from "ethers"; import { useChainId } from "lib/chains"; -import { formatTokenAmountWithUsd } from "lib/numbers"; +import { formatTokenAmount, formatUsd } from "lib/numbers"; import { getByKey } from "lib/objects"; import { uniq } from "lodash"; import { GmFees } from "../GmFees/GmFees"; @@ -25,6 +24,8 @@ import { useState } from "react"; import "./GmConfirmationBox.scss"; import { useKey } from "react-use"; import useWallet from "lib/wallets/useWallet"; +import { useHighExecutionFeeConsent } from "domain/synthetics/trade/useHighExecutionFeeConsent"; +import { FaArrowRight } from "react-icons/fa"; type Props = { isVisible: boolean; @@ -41,9 +42,6 @@ type Props = { error?: string; isDeposit: boolean; executionFee?: ExecutionFee; - isHighPriceImpact: boolean; - isHighPriceImpactAccepted: boolean; - setIsHighPriceImpactAccepted: (value: boolean) => void; onSubmitted: () => void; onClose: () => void; setPendingTxns: (txns: any) => void; @@ -73,7 +71,7 @@ export function GmConfirmationBox({ const { signer, account } = useWallet(); const { chainId } = useChainId(); const { marketsData } = useMarkets(chainId); - const { tokensData } = useTokensData(chainId); + const { tokensData } = useTokensDataRequest(chainId); const { setPendingDeposit, setPendingWithdrawal } = useSyntheticsEvents(); const [isSubmitting, setIsSubmitting] = useState(false); @@ -81,6 +79,9 @@ export function GmConfirmationBox({ const market = getByKey(marketsData, marketToken?.address); const routerAddress = getContract(chainId, "SyntheticsRouter"); + const { element: highExecutionFeeAcknowledgement, isHighFeeConsentError } = useHighExecutionFeeConsent( + executionFee?.feeUsd + ); const payTokenAddresses = (function getPayTokenAddresses() { if (!marketToken) { @@ -148,21 +149,6 @@ export function GmConfirmationBox({ const longSymbol = market?.isSameCollaterals ? `${longToken?.symbol} Long` : longToken?.symbol; const shortSymbol = market?.isSameCollaterals ? `${shortToken?.symbol} Short` : shortToken?.symbol; - const longTokenText = longTokenAmount?.gt(0) - ? formatTokenAmountWithUsd(longTokenAmount, longTokenUsd, longSymbol, longToken?.decimals) - : undefined; - - const shortTokenText = shortTokenAmount?.gt(0) - ? formatTokenAmountWithUsd(shortTokenAmount, shortTokenUsd, shortSymbol, shortToken?.decimals) - : undefined; - - const marketTokenText = formatTokenAmountWithUsd( - marketTokenAmount, - marketTokenUsd, - marketToken?.symbol, - marketToken?.decimals - ); - const operationText = isDeposit ? t`Buy` : t`Sell`; const isAllowanceLoaded = Boolean(tokensAllowanceData); @@ -203,6 +189,13 @@ export function GmConfirmationBox({ }; } + if (isHighFeeConsentError) { + return { + text: t`High Execution Fee not yet acknowledged`, + disabled: true, + }; + } + if (isSubmitting) { return { text: isDeposit ? t`Buying GM...` : t`Selling GM...`, @@ -304,39 +297,101 @@ export function GmConfirmationBox({ }); } + const renderTokenInfo = ({ + amount, + className, + overrideSymbol, + token, + usd, + }: { + amount?: BigNumber; + usd?: BigNumber; + token?: TokenData; + className?: string; + overrideSymbol?: string; + }) => { + if (!amount || !usd || !token) return; + return ( +
    +
    + + {formatTokenAmount(amount, token?.decimals, overrideSymbol ?? token?.symbol, { + useCommas: true, + })} + +
    +
    {formatUsd(usd)}
    +
    + ); + }; + + const shouldRenderDivider = Boolean(tokensToApprove?.length > 0) || Boolean(highExecutionFeeAcknowledgement); + return (
    - + {isVisible && ( <> -
    - {isDeposit && ( - <> - {[longTokenText, shortTokenText].filter(Boolean).map((text) => ( -
    - Pay {text} -
    - ))} -
    -
    - Receive {marketTokenText} -
    - - )} - {!isDeposit && ( - <> -
    - Pay {marketTokenText} -
    -
    - {[longTokenText, shortTokenText].filter(Boolean).map((text) => ( -
    - Receive {text} -
    - ))} - - )} -
    + {isDeposit && ( +
    +
    + Pay{" "} + {renderTokenInfo({ + amount: longTokenAmount, + usd: longTokenUsd, + token: longToken, + overrideSymbol: longSymbol, + })} + {renderTokenInfo({ + amount: shortTokenAmount, + usd: shortTokenUsd, + token: shortToken, + overrideSymbol: shortSymbol, + className: "mt-xs", + })} +
    + +
    + Receive{" "} + {renderTokenInfo({ + amount: marketTokenAmount, + usd: marketTokenUsd, + token: marketToken, + })} +
    +
    + )} + {!isDeposit && ( +
    +
    + Pay{" "} + {renderTokenInfo({ + amount: marketTokenAmount, + usd: marketTokenUsd, + token: marketToken, + })} +
    + +
    + Receive{" "} + {renderTokenInfo({ + amount: longTokenAmount, + usd: longTokenUsd, + token: longToken, + overrideSymbol: longSymbol, + })} + {renderTokenInfo({ + amount: shortTokenAmount, + usd: shortTokenUsd, + token: shortToken, + overrideSymbol: shortSymbol, + className: "mt-xs", + })} +
    +
    + )} + +
    - {tokensToApprove?.length > 0 &&
    } + {shouldRenderDivider &&
    } {tokensToApprove && tokensToApprove.length > 0 && (
    @@ -366,6 +421,10 @@ export function GmConfirmationBox({
    )} + {highExecutionFeeAcknowledgement ? ( +
    {highExecutionFeeAcknowledgement}
    + ) : null} +
    - FUNDING RATE / 1h + NET FEE / 1 H UTILIZATION @@ -219,10 +194,13 @@ export function MarketsList() {
    - {formatAmount(stats.totalUtilization, 2, 2)}%
    diff --git a/src/components/Synthetics/OrderList/OrderList.tsx b/src/components/Synthetics/OrderList/OrderList.tsx index 06c36d072d..e3af99cd44 100644 --- a/src/components/Synthetics/OrderList/OrderList.tsx +++ b/src/components/Synthetics/OrderList/OrderList.tsx @@ -1,35 +1,52 @@ import { Trans, t } from "@lingui/macro"; -import Checkbox from "components/Checkbox/Checkbox"; -import { MarketsInfoData } from "domain/synthetics/markets"; -import { OrdersInfoData, isLimitOrderType, isTriggerDecreaseOrderType } from "domain/synthetics/orders"; -import { cancelOrdersTxn } from "domain/synthetics/orders/cancelOrdersTxn"; -import { PositionsInfoData } from "domain/synthetics/positions"; -import { TokensData } from "domain/synthetics/tokens"; -import { useChainId } from "lib/chains"; -import useWallet from "lib/wallets/useWallet"; -import { Dispatch, SetStateAction, useState } from "react"; -import { OrderEditor } from "../OrderEditor/OrderEditor"; -import { OrderItem } from "../OrderItem/OrderItem"; +import { Dispatch, SetStateAction, useEffect, useMemo, useRef, useState } from "react"; + import { useIsLastSubaccountAction, useSubaccount, useSubaccountCancelOrdersDetailsMessage, } from "context/SubaccountContext/SubaccountContext"; +import { + useMarketsInfoData, + useOrdersInfoData, + usePositionsInfoData, +} from "context/SyntheticsStateContext/hooks/globalsHooks"; +import { + PositionOrderInfo, + SwapOrderInfo, + isLimitOrderType, + isSwapOrderType, + isTriggerDecreaseOrderType, + sortPositionOrders, + sortSwapOrders, +} from "domain/synthetics/orders"; +import { cancelOrdersTxn } from "domain/synthetics/orders/cancelOrdersTxn"; +import { useChainId } from "lib/chains"; +import useWallet from "lib/wallets/useWallet"; + +import Checkbox from "components/Checkbox/Checkbox"; +import { OrderEditor } from "../OrderEditor/OrderEditor"; +import { OrderItem } from "../OrderItem/OrderItem"; +import { AvailableTokenOptions } from "domain/synthetics/trade"; type Props = { hideActions?: boolean; - ordersData?: OrdersInfoData; - marketsInfoData?: MarketsInfoData; - tokensData?: TokensData; - positionsData?: PositionsInfoData; setSelectedOrdersKeys?: Dispatch>; selectedOrdersKeys?: { [key: string]: boolean }; isLoading: boolean; setPendingTxns: (txns: any) => void; + selectedPositionOrderKey?: string; + setSelectedPositionOrderKey?: Dispatch>; + availableTokensOptions: AvailableTokenOptions; }; export function OrderList(p: Props) { - const { marketsInfoData, tokensData, positionsData } = p; + const { setSelectedOrdersKeys, selectedPositionOrderKey, setSelectedPositionOrderKey, availableTokensOptions } = p; + const { sortedIndexTokensWithPoolValue, sortedLongAndShortTokens } = availableTokensOptions; + const marketsInfoData = useMarketsInfoData(); + const positionsData = usePositionsInfoData(); + const ordersData = useOrdersInfoData(); + const { chainId } = useChainId(); const { signer } = useWallet(); @@ -38,28 +55,66 @@ export function OrderList(p: Props) { const subaccount = useSubaccount(null); - const orders = Object.values(p.ordersData || {}).filter( - (order) => isLimitOrderType(order.orderType) || isTriggerDecreaseOrderType(order.orderType) - ); + const orders = useMemo(() => { + const { swapOrders, positionOrders } = Object.values(ordersData || {}).reduce( + (acc, order) => { + if (isLimitOrderType(order.orderType) || isTriggerDecreaseOrderType(order.orderType)) { + if (isSwapOrderType(order.orderType)) { + acc.swapOrders.push(order); + } else { + acc.positionOrders.push(order as PositionOrderInfo); + } + } + return acc; + }, + { swapOrders: [] as SwapOrderInfo[], positionOrders: [] as PositionOrderInfo[] } + ); + + return [ + ...sortPositionOrders(positionOrders, sortedIndexTokensWithPoolValue), + ...sortSwapOrders(swapOrders, sortedLongAndShortTokens), + ]; + }, [ordersData, sortedIndexTokensWithPoolValue, sortedLongAndShortTokens]); const isAllOrdersSelected = orders.length > 0 && orders.every((o) => p.selectedOrdersKeys?.[o.key]); const editingOrder = orders.find((o) => o.key === editingOrderKey); const isLastSubaccountAction = useIsLastSubaccountAction(); const cancelOrdersDetailsMessage = useSubaccountCancelOrdersDetailsMessage(undefined, 1); + const orderRefs = useRef<{ [key: string]: HTMLTableRowElement | null }>({}); + + useEffect(() => { + if (selectedPositionOrderKey) { + const orderElement = orderRefs.current[selectedPositionOrderKey]; + if (orderElement) { + const rect = orderElement.getBoundingClientRect(); + const isInViewPort = + rect.top >= 0 && rect.left >= 0 && rect.bottom <= window.innerHeight && rect.right <= window.innerWidth; + + if (!isInViewPort) { + orderElement.scrollIntoView({ behavior: "smooth", block: "center" }); + } + } + } + + return () => { + setSelectedPositionOrderKey?.(undefined); + }; + }, [selectedPositionOrderKey, setSelectedPositionOrderKey]); + function onSelectOrder(key: string) { - p.setSelectedOrdersKeys?.((prev) => ({ ...prev, [key]: !prev[key] })); + setSelectedOrdersKeys?.((prev) => ({ ...prev, [key]: !prev[key] })); } function onSelectAllOrders() { if (isAllOrdersSelected) { - p.setSelectedOrdersKeys?.({}); + setSelectedOrdersKeys?.({}); return; } const allSelectedOrders = orders.reduce((acc, order) => ({ ...acc, [order.key]: true }), {}); - p.setSelectedOrdersKeys?.(allSelectedOrders); + setSelectedOrdersKeys?.(allSelectedOrders); } function onCancelOrder(key: string) { @@ -83,23 +138,21 @@ export function OrderList(p: Props) { )}
    {!p.isLoading && - orders.map((order) => { - return ( - onSelectOrder(order.key)} - isCanceling={canellingOrdersKeys.includes(order.key)} - onCancelOrder={() => onCancelOrder(order.key)} - onEditOrder={() => setEditingOrderKey(order.key)} - marketsInfoData={marketsInfoData} - positionsInfoData={positionsData} - hideActions={p.hideActions} - /> - ); - })} + orders.map((order) => ( + onSelectOrder(order.key)} + isCanceling={canellingOrdersKeys.includes(order.key)} + onCancelOrder={() => onCancelOrder(order.key)} + onEditOrder={() => setEditingOrderKey(order.key)} + marketsInfoData={marketsInfoData} + positionsInfoData={positionsData} + hideActions={p.hideActions} + /> + ))}
    @@ -154,6 +207,7 @@ export function OrderList(p: Props) { hideActions={p.hideActions} marketsInfoData={marketsInfoData} positionsInfoData={positionsData} + setRef={(el) => (orderRefs.current[order.key] = el)} /> ); })} @@ -162,9 +216,6 @@ export function OrderList(p: Props) { {editingOrder && ( setEditingOrderKey(undefined)} setPendingTxns={p.setPendingTxns} diff --git a/src/components/Synthetics/PositionEditor/PositionEditor.tsx b/src/components/Synthetics/PositionEditor/PositionEditor.tsx index a4cc1a54af..d9fe693d87 100644 --- a/src/components/Synthetics/PositionEditor/PositionEditor.tsx +++ b/src/components/Synthetics/PositionEditor/PositionEditor.tsx @@ -17,7 +17,6 @@ import { MAX_METAMASK_MOBILE_DECIMALS } from "config/ui"; import { useSubaccount } from "context/SubaccountContext/SubaccountContext"; import { useSyntheticsEvents } from "context/SyntheticsEvents"; import { useHasOutdatedUi } from "domain/legacy"; -import { useUserReferralInfo } from "domain/referrals/hooks"; import { estimateExecuteDecreaseOrderGasLimit, estimateExecuteIncreaseOrderGasLimit, @@ -39,7 +38,6 @@ import { formatLiquidationPrice, getLeverage, getLiquidationPrice, - usePositionsConstants, } from "domain/synthetics/positions"; import { TokensData, adaptToV1InfoTokens, convertToTokenAmount, convertToUsd } from "domain/synthetics/tokens"; import { TradeFees, getMarkPrice, getMinCollateralUsdForLeverage } from "domain/synthetics/trade"; @@ -66,6 +64,8 @@ import { TradeFeesRow } from "../TradeFeesRow/TradeFeesRow"; import "./PositionEditor.scss"; import { getMinResidualAmount } from "domain/tokens"; import { SubaccountNavigationButton } from "components/SubaccountNavigationButton/SubaccountNavigationButton"; +import { usePositionsConstants, useUserReferralInfo } from "context/SyntheticsStateContext/hooks/globalsHooks"; +import { useHighExecutionFeeConsent } from "domain/synthetics/trade/useHighExecutionFeeConsent"; export type Props = { position?: PositionInfo; @@ -82,6 +82,11 @@ enum Operation { Withdraw = "Withdraw", } +const OPERATION_LABELS = { + [Operation.Deposit]: t`Deposit`, + [Operation.Withdraw]: t`Withdraw`, +}; + export function PositionEditor(p: Props) { const { position, tokensData, showPnlInLeverage, setPendingTxns, onClose, allowedSlippage } = p; const { chainId } = useChainId(); @@ -91,9 +96,9 @@ export function PositionEditor(p: Props) { const { setPendingPosition, setPendingOrder } = useSyntheticsEvents(); const { gasPrice } = useGasPrice(chainId); const { gasLimits } = useGasLimits(chainId); - const { minCollateralUsd } = usePositionsConstants(chainId); const routerAddress = getContract(chainId, "SyntheticsRouter"); - const userReferralInfo = useUserReferralInfo(signer, chainId, account); + const { minCollateralUsd } = usePositionsConstants(); + const userReferralInfo = useUserReferralInfo(); const { data: hasOutdatedUi } = useHasOutdatedUi(); const nativeToken = getByKey(tokensData, NATIVE_TOKEN_ADDRESS); @@ -200,6 +205,10 @@ export function PositionEditor(p: Props) { }; }, [chainId, collateralDeltaUsd, gasLimits, gasPrice, isDeposit, position, tokensData]); + const { element: highExecutionFeeAcknowledgement, isHighFeeConsentError } = useHighExecutionFeeConsent( + executionFee?.feeUsd + ); + const { nextCollateralUsd, nextLeverage, nextLiqPrice, receiveUsd, receiveAmount } = useMemo(() => { if (!position || !collateralDeltaUsd?.gt(0) || !minCollateralUsd || !fees?.totalFees) { return {}; @@ -287,6 +296,10 @@ export function PositionEditor(p: Props) { return t`Pending ${collateralToken?.assetSymbol ?? collateralToken?.symbol} approval`; } + if (isHighFeeConsentError) { + return t`High Execution Fee not yet acknowledged`; + } + if (isSubmitting) { return t`Creating Order...`; } @@ -297,6 +310,7 @@ export function PositionEditor(p: Props) { collateralDeltaUsd, collateralToken, hasOutdatedUi, + isHighFeeConsentError, isDeposit, isSubmitting, minCollateralUsd, @@ -429,11 +443,6 @@ export function PositionEditor(p: Props) { [isVisible, prevIsVisible] ); - const operationLabels = { - [Operation.Deposit]: t`Deposit`, - [Operation.Withdraw]: t`Withdraw`, - }; - const showMaxOnDeposit = collateralToken?.isNative ? minResidualAmount && collateralToken?.balance?.gt(minResidualAmount) : true; @@ -442,14 +451,13 @@ export function PositionEditor(p: Props) {
    Edit {position?.isLong ? t`Long` : t`Short`} {position?.indexToken?.symbol} } - allowContentTouchMove > {position && ( <> @@ -457,7 +465,7 @@ export function PositionEditor(p: Props) { onChange={setOperation} option={operation} options={Object.values(Operation)} - optionLabels={operationLabels} + optionLabels={OPERATION_LABELS} className="PositionEditor-tabs SwapBox-option-tabs" /> {availableSwapTokens ? ( setSelectedCollateralAddress(token.address)} @@ -593,6 +601,7 @@ export function PositionEditor(p: Props) { {!isDeposit && ( - {needCollateralApproval && collateralToken && ( + {((needCollateralApproval && collateralToken) || highExecutionFeeAcknowledgement) && ( <>
    - + {needCollateralApproval && collateralToken && ( + + )} + {highExecutionFeeAcknowledgement} )} @@ -624,7 +636,7 @@ export function PositionEditor(p: Props) { onClick={onSubmit} disabled={Boolean(error) && !p.shouldDisableValidation} > - {error || operationLabels[operation]} + {error || OPERATION_LABELS[operation]}
    diff --git a/src/components/Synthetics/PositionItem/PositionItem.tsx b/src/components/Synthetics/PositionItem/PositionItem.tsx index 884694ff82..7fd938cdcb 100644 --- a/src/components/Synthetics/PositionItem/PositionItem.tsx +++ b/src/components/Synthetics/PositionItem/PositionItem.tsx @@ -3,7 +3,12 @@ import cx from "classnames"; import PositionDropdown from "components/Exchange/PositionDropdown"; import StatsTooltipRow from "components/StatsTooltip/StatsTooltipRow"; import Tooltip from "components/Tooltip/Tooltip"; -import { PositionOrderInfo, isDecreaseOrderType, isIncreaseOrderType } from "domain/synthetics/orders"; +import { + PositionOrderInfo, + isDecreaseOrderType, + isIncreaseOrderType, + sortPositionOrders, +} from "domain/synthetics/orders"; import { PositionInfo, formatEstimatedLiquidationTime, @@ -11,7 +16,6 @@ import { formatLiquidationPrice, getEstimatedLiquidationTimeInHours, getTriggerNameByOrderType, - usePositionsConstants, } from "domain/synthetics/positions"; import { formatDeltaUsd, formatTokenAmount, formatUsd } from "lib/numbers"; import { AiOutlineEdit } from "react-icons/ai"; @@ -20,52 +24,59 @@ import { ImSpinner2 } from "react-icons/im"; import Button from "components/Button/Button"; import TokenIcon from "components/TokenIcon/TokenIcon"; import { useSettings } from "context/SettingsContext/SettingsContextProvider"; +import { usePositionsConstants, useSavedShowPnlAfterFees } from "context/SyntheticsStateContext/hooks/globalsHooks"; +import { + useTradeboxCollateralAddress, + useTradeboxMarketAddress, + useTradeboxTradeType, +} from "context/SyntheticsStateContext/hooks/tradeboxHooks"; import { getBorrowingFeeRateUsd, getFundingFeeRateUsd } from "domain/synthetics/fees"; import { getMarketIndexName, getMarketPoolName } from "domain/synthetics/markets"; import { TradeMode, TradeType, getTriggerThresholdType } from "domain/synthetics/trade"; -import { useChainId } from "lib/chains"; import { CHART_PERIODS } from "lib/legacy"; +import { getPositiveOrNegativeClass } from "lib/utils"; +import { Fragment, useMemo } from "react"; import { FaAngleRight } from "react-icons/fa"; import { useMedia } from "react-use"; import "./PositionItem.scss"; -import { Fragment } from "react"; -import { getPositiveOrNegativeClass } from "lib/utils"; export type Props = { position: PositionInfo; positionOrders: PositionOrderInfo[]; hideActions?: boolean; showPnlAfterFees: boolean; - savedShowPnlAfterFees: boolean; onClosePositionClick?: () => void; onEditCollateralClick?: () => void; onShareClick: () => void; onSelectPositionClick?: (tradeMode?: TradeMode) => void; - onOrdersClick?: () => void; + onOrdersClick?: (key?: string) => void; isLarge: boolean; - currentMarketAddress?: string; - currentCollateralAddress?: string; - currentTradeType?: TradeType; openSettings: () => void; onGetPendingFeesClick: () => void; }; export function PositionItem(p: Props) { - const { showDebugValues } = useSettings(); const { positionOrders } = p; - const displayedPnl = p.savedShowPnlAfterFees ? p.position.pnlAfterFees : p.position.pnl; - const displayedPnlPercentage = p.savedShowPnlAfterFees ? p.position.pnlAfterFeesPercentage : p.position.pnlPercentage; - const { chainId } = useChainId(); + const { showDebugValues } = useSettings(); + const savedShowPnlAfterFees = useSavedShowPnlAfterFees(); + const currentTradeType = useTradeboxTradeType(); + const currentMarketAddress = useTradeboxMarketAddress(); + const currentCollateralAddress = useTradeboxCollateralAddress(); + const displayedPnl = savedShowPnlAfterFees ? p.position.pnlAfterFees : p.position.pnl; + const displayedPnlPercentage = savedShowPnlAfterFees ? p.position.pnlAfterFeesPercentage : p.position.pnlPercentage; const isMobile = useMedia("(max-width: 1100px)"); const indexPriceDecimals = p.position?.indexToken?.priceDecimals; - const { minCollateralUsd } = usePositionsConstants(chainId); - - const isCurrentTradeTypeLong = p.currentTradeType === TradeType.Long; + const { minCollateralUsd } = usePositionsConstants(); + const isCurrentTradeTypeLong = currentTradeType === TradeType.Long; const isCurrentMarket = - p.currentMarketAddress === p.position.marketAddress && - p.currentCollateralAddress === p.position.collateralTokenAddress && + currentMarketAddress === p.position.marketAddress && + currentCollateralAddress === p.position.collateralTokenAddress && isCurrentTradeTypeLong === p.position.isLong; + const sortedPositionOrders = useMemo(() => { + return sortPositionOrders(positionOrders); + }, [positionOrders]); + function renderNetValue() { return ( { + return sortedPositionOrders.map((order) => { if (order.errorLevel) { return (
    @@ -351,15 +362,18 @@ export function PositionItem(p: Props) { handle={renderOrderText(order)} position="right-bottom" handleClassName={cx("position-order-error", { - "level-warning": order.errorLevel === 'warning', - "level-error": order.errorLevel === 'error', + "level-warning": order.errorLevel === "warning", + "level-error": order.errorLevel === "error", })} renderContent={() => order.errors.map((error) => ( - + {error.msg} )) @@ -368,16 +382,20 @@ export function PositionItem(p: Props) {
    ); } - return
    {renderOrderText(order)}
    ; + return ( +
    + {renderOrderText(order)} +
    + ); }); } - const ordersErrorList = positionOrders.filter((order) => order.errorLevel === "error"); - const ordersWarningsList = positionOrders.filter((order) => order.errorLevel === "warning"); + const ordersErrorList = sortedPositionOrders.filter((order) => order.errorLevel === "error"); + const ordersWarningsList = sortedPositionOrders.filter((order) => order.errorLevel === "warning"); const hasErrors = ordersErrorList.length + ordersWarningsList.length > 0; return ( -
    +
    0, })} > - ({positionOrders.length}) + ({sortedPositionOrders.length}) } @@ -407,15 +425,20 @@ export function PositionItem(p: Props) { Active Orders - {positionOrders.map((order) => { + {sortedPositionOrders.map((order) => { const errors = order.errors; return ( -
    +
    { + p.onOrdersClick?.(order.key); + }} + >
    {renderOrderText(order)}
    - {errors.map((err, i) => (
    {err.msg}
    @@ -704,7 +727,7 @@ export function PositionItem(p: Props) { Orders
    - {!p.positionOrders?.length && "None"} + {!sortedPositionOrders?.length && "None"} {renderPositionOrders(true)}
    @@ -751,3 +774,12 @@ export function PositionItem(p: Props) { return p.isLarge ? renderLarge() : renderSmall(); } + +function getKey(order: PositionOrderInfo) { + return ( + order.initialCollateralToken.address + + order.orderType + + order.triggerPrice.toString() + + order.targetCollateralToken.address + ); +} diff --git a/src/components/Synthetics/PositionList/PositionList.tsx b/src/components/Synthetics/PositionList/PositionList.tsx index 0bee5582b2..bbad6ca18e 100644 --- a/src/components/Synthetics/PositionList/PositionList.tsx +++ b/src/components/Synthetics/PositionList/PositionList.tsx @@ -1,9 +1,9 @@ import { Trans, t } from "@lingui/macro"; import PositionShare from "components/Exchange/PositionShare"; import { PositionItem } from "components/Synthetics/PositionItem/PositionItem"; -import { OrdersInfoData, PositionOrderInfo, isOrderForPosition } from "domain/synthetics/orders"; -import { PositionsInfoData } from "domain/synthetics/positions"; -import { TradeMode, TradeType } from "domain/synthetics/trade"; +import { useOrdersInfoData, usePositionsInfoData } from "context/SyntheticsStateContext/hooks/globalsHooks"; +import { PositionOrderInfo, isOrderForPosition } from "domain/synthetics/orders"; +import { TradeMode } from "domain/synthetics/trade"; import { useChainId } from "lib/chains"; import { getByKey } from "lib/objects"; import useWallet from "lib/wallets/useWallet"; @@ -14,28 +14,34 @@ type Props = { onClosePositionClick: (key: string) => void; onEditCollateralClick: (key: string) => void; onSettlePositionFeesClick: (key: string) => void; - positionsData?: PositionsInfoData; - ordersData?: OrdersInfoData; - savedIsPnlInLeverage: boolean; isLoading: boolean; - onOrdersClick: () => void; + onOrdersClick: (key?: string) => void; showPnlAfterFees: boolean; - savedShowPnlAfterFees: boolean; - currentMarketAddress?: string; - currentCollateralAddress?: string; - currentTradeType?: TradeType; openSettings: () => void; hideActions?: boolean; }; export function PositionList(p: Props) { + const { + isLoading, + onClosePositionClick, + onEditCollateralClick, + onOrdersClick, + onSelectPositionClick, + onSettlePositionFeesClick, + openSettings, + showPnlAfterFees, + hideActions, + } = p; + const positionsInfoData = usePositionsInfoData(); + const ordersData = useOrdersInfoData(); const { chainId } = useChainId(); const { account } = useWallet(); const [isPositionShareModalOpen, setIsPositionShareModalOpen] = useState(false); const [positionToShareKey, setPositionToShareKey] = useState(); - const positionToShare = getByKey(p.positionsData, positionToShareKey); - const positions = Object.values(p.positionsData || {}); - const orders = Object.values(p.ordersData || {}); + const positionToShare = getByKey(positionsInfoData, positionToShareKey); + const positions = Object.values(positionsInfoData || {}); + const orders = Object.values(ordersData || {}); const handleSharePositionClick = (positionKey: string) => { setPositionToShareKey(positionKey); setIsPositionShareModalOpen(true); @@ -45,35 +51,31 @@ export function PositionList(p: Props) {
    {positions.length === 0 && (
    - {p.isLoading ? t`Loading...` : t`No open positions`} + {isLoading ? t`Loading...` : t`No open positions`}
    )}
    - {!p.isLoading && + {!isLoading && positions.map((position) => ( isOrderForPosition(order, position.key)) as PositionOrderInfo[]} position={position} - onEditCollateralClick={() => p.onEditCollateralClick(position.key)} - onClosePositionClick={() => p.onClosePositionClick(position.key)} - onGetPendingFeesClick={() => p.onSettlePositionFeesClick(position.key)} - onOrdersClick={p.onOrdersClick} - onSelectPositionClick={(tradeMode?: TradeMode) => p.onSelectPositionClick(position.key, tradeMode)} - showPnlAfterFees={p.showPnlAfterFees} - savedShowPnlAfterFees={p.savedShowPnlAfterFees} + onEditCollateralClick={() => onEditCollateralClick(position.key)} + onClosePositionClick={() => onClosePositionClick(position.key)} + onGetPendingFeesClick={() => onSettlePositionFeesClick(position.key)} + onOrdersClick={onOrdersClick} + onSelectPositionClick={(tradeMode?: TradeMode) => onSelectPositionClick(position.key, tradeMode)} + showPnlAfterFees={showPnlAfterFees} isLarge={false} onShareClick={() => handleSharePositionClick(position.key)} - currentMarketAddress={p.currentMarketAddress} - currentCollateralAddress={p.currentCollateralAddress} - currentTradeType={p.currentTradeType} - openSettings={p.openSettings} - hideActions={p.hideActions} + openSettings={openSettings} + hideActions={hideActions} /> ))}
    -
    +
    + diff --git a/src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.scss b/src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.scss new file mode 100644 index 0000000000..540933d242 --- /dev/null +++ b/src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.scss @@ -0,0 +1,79 @@ +.PriceImpactRebatesStatsPage-table { + flex: 1; + font-size: 12px; +} + +.PriceImpactRebatesStatsPage-row { + display: flex; +} + +.PriceImpactRebatesStatsPage-row div { + // border-right: 1px solid #e8e8e8; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + width: 200px; + padding: 10px 0 10px 0; + text-align: center; + transition: background-color 0.1s linear; + align-items: center; + display: flex; + justify-content: center; +} + +.PriceImpactRebatesStatsPage-row:hover div { + background-color: #ffffff02; +} + +.PriceImpactRebatesStatsPage-subrow { + display: flex; +} + +.PriceImpactRebatesStatsPage-subrow div { + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + width: 200px; + padding: 10px 0 10px 0; + text-align: center; + transition: background-color 0.1s linear; + background-color: #ffffff09; + align-items: center; + display: flex; + justify-content: center; +} + +.PriceImpactRebatesStatsPage-subrow:hover div { + background-color: #ffffff0a; +} + +.PriceImpactRebatesStatsPage-account { + margin-bottom: 100px; +} + +.PriceImpactRebatesStatsPage-subrow div button, +.PriceImpactRebatesStatsPage-row div button { + margin: 1px; +} + +.PriceImpactRebatesStatsPage-row .PriceImpactRebatesStatsPage-cell-expand, +.PriceImpactRebatesStatsPage-subrow .PriceImpactRebatesStatsPage-cell-expand { + width: 50px; +} +.PriceImpactRebatesStatsPage-row .PriceImpactRebatesStatsPage-cell-timekey, +.PriceImpactRebatesStatsPage-subrow .PriceImpactRebatesStatsPage-cell-timekey { + width: 100px; +} + +.PriceImpactRebatesStatsPage-row .PriceImpactRebatesStatsPage-cell-token, +.PriceImpactRebatesStatsPage-subrow .PriceImpactRebatesStatsPage-cell-token { + width: 50px; +} +.PriceImpactRebatesStatsPage-row .PriceImpactRebatesStatsPage-cell-approved, +.PriceImpactRebatesStatsPage-subrow .PriceImpactRebatesStatsPage-cell-approved { + width: 90px; +} +.PriceImpactRebatesStatsPage-row .PriceImpactRebatesStatsPage-cell-usd, +.PriceImpactRebatesStatsPage-subrow .PriceImpactRebatesStatsPage-cell-usd { + width: 250px; +} + +.PriceImpactRebatesStats-loading { + margin-left: 20px; +} diff --git a/src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx b/src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx new file mode 100644 index 0000000000..a32ed010b4 --- /dev/null +++ b/src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx @@ -0,0 +1,209 @@ +import { Trans } from "@lingui/macro"; +import Checkbox from "components/Checkbox/Checkbox"; +import SpinningLoader from "components/Common/SpinningLoader"; +import Footer from "components/Footer/Footer"; +import { ARBITRUM, AVALANCHE, AVALANCHE_FUJI } from "config/chains"; +import { MarketInfo } from "domain/synthetics/markets"; +import { BigNumber } from "ethers"; +import { useChainId } from "lib/chains"; +import { formatDateTime } from "lib/dates"; +import { expandDecimals, formatAmount, formatTokenAmountWithUsd } from "lib/numbers"; +import { shortenAddressOrEns } from "lib/wallets"; +import { memo, useCallback, useEffect, useMemo, useState } from "react"; +import { Link } from "react-router-dom"; +import { useCopyToClipboard } from "react-use"; +import "./PriceImpactRebatesStats.scss"; +import { RebateGroup, usePriceImpactRebateGroups } from "./hooks/usePriceImpactRebatesStats"; + +export const PriceImpactRebatesStatsPage = memo(() => { + const [pageIndex, setPageIndex] = useState(0); + const [reviewed, setReviewed] = useState(false); + const [hasMore, loadedPageIndex, rebateGroups] = usePriceImpactRebateGroups(pageIndex, reviewed); + const loading = pageIndex !== loadedPageIndex; + + useEffect(() => { + setPageIndex(0); + }, [reviewed]); + + return ( +
    +
    + + Incl. reviewed + +
    {loading && }
    +
    + +
    + {pageIndex > 0 && ( + + )} + {hasMore && ( + + )} +
    +
    +
    + ); +}); + +const RebateStatsTable = memo(({ rebateGroups }: { rebateGroups: RebateGroup[] }) => { + return ( +
    +
    +
    Timekey
    +
    Time
    +
    Market
    +
    Token
    +
    Factor
    +
    $
    +
    +
    + {rebateGroups.map((group) => ( + + ))} +
    + ); +}); + +const RebateGroupRow = memo(({ rebateGroup }: { rebateGroup: RebateGroup }) => { + const [, copyToClipboard] = useCopyToClipboard(); + const { chainId } = useChainId(); + const handleCopyCommandClick = useCallback( + (e) => { + e.stopPropagation(); + const networkStr = { + [ARBITRUM]: "arbitrum", + [AVALANCHE]: "avalanche", + [AVALANCHE_FUJI]: "avalancheFuji", + }[chainId]; + copyToClipboard( + `MARKET=${rebateGroup.marketInfo?.marketTokenAddress} TOKEN=${rebateGroup.tokenData?.address} TIME_KEY=${ + rebateGroup.timeKey + } FACTOR=${rebateGroup.factor.toString()} npx hardhat --network ${networkStr} run scripts/updateClaimableCollateralFactor.ts` + ); + }, + [ + chainId, + copyToClipboard, + rebateGroup.factor, + rebateGroup.marketInfo?.marketTokenAddress, + rebateGroup.timeKey, + rebateGroup.tokenData?.address, + ] + ); + const handleCopyAccountsClick = useCallback( + (e) => { + e.stopPropagation(); + + copyToClipboard(rebateGroup.userRebates.map((rebateItem) => rebateItem.account).join(",")); + }, + [copyToClipboard, rebateGroup.userRebates] + ); + const [accountsShown, setAccountsShown] = useState(false); + const handleExpandClick = useCallback(() => setAccountsShown((shown) => !shown), []); + const total = useMemo(() => { + return rebateGroup.userRebates.reduce((sum, rebateItem) => sum.add(rebateItem.value), BigNumber.from(0)); + }, [rebateGroup.userRebates]); + const usd = useMemo(() => { + return rebateGroup.userRebates.reduce((sum, rebateItem) => { + const price = rebateItem.tokenData?.prices.maxPrice; + const decimals = rebateItem.tokenData?.decimals; + return price && decimals ? sum.add(rebateItem.value.mul(price).div(expandDecimals(1, decimals))) : sum; + }, BigNumber.from(0)); + }, [rebateGroup.userRebates]); + + return ( + <> +
    +
    {rebateGroup.timeKey}
    +
    {formatTime(rebateGroup.timeKey)}
    +
    {formatMarket(rebateGroup.marketInfo)}
    +
    {rebateGroup.tokenData?.symbol}
    +
    + {rebateGroup.factor.gt(0) ? `${formatAmount(rebateGroup.factor, 28, 2)}%` : "-"}{" "} +
    +
    + {formatTokenAmountWithUsd(total, usd, rebateGroup.tokenData?.symbol, rebateGroup.tokenData?.decimals)} +
    +
    + + +
    +
    + {accountsShown ? : null} + + ); +}); + +const RebateAccountsRow = memo(({ rebateGroup }: { rebateGroup: RebateGroup }) => { + return ( +
    +
    +
    +
    +
    Address
    +
    +
    Factor
    +
    USD
    +
    +
    + {rebateGroup.userRebates.map((rebateItem) => { + const price = rebateItem.tokenData?.prices.maxPrice; + const decimals = rebateItem.tokenData?.decimals; + const usd = price && decimals ? rebateItem.value.mul(price).div(expandDecimals(1, decimals)) : undefined; + return ( +
    +
    +
    +
    + {shortenAddressOrEns(rebateItem.account, 15)} +
    +
    +
    + {rebateItem.factor.gt(0) ? `${formatAmount(rebateItem.factor, 28, 2)}%` : "-"}{" "} +
    +
    + {formatTokenAmountWithUsd( + rebateItem.value, + usd, + rebateItem.tokenData?.symbol, + rebateItem.tokenData?.decimals + )} +
    +
    +
    + ); + })} +
    + ); +}); + +function formatTime(timeKey: string) { + return formatDateTime(Number(timeKey) * 60 * 60); +} + +function formatMarket(marketInfo: MarketInfo | undefined) { + if (!marketInfo) return ""; + + return marketInfo.name; +} diff --git a/src/pages/PriceImpactRebatesStats/hooks/usePriceImpactRebatesStats.ts b/src/pages/PriceImpactRebatesStats/hooks/usePriceImpactRebatesStats.ts new file mode 100644 index 0000000000..fee782c153 --- /dev/null +++ b/src/pages/PriceImpactRebatesStats/hooks/usePriceImpactRebatesStats.ts @@ -0,0 +1,128 @@ +import { gql } from "@apollo/client"; +import { MarketInfo, useMarketsInfoRequest } from "domain/synthetics/markets"; +import { TokenData } from "domain/synthetics/tokens"; +import { BigNumber } from "ethers"; +import { getAddress } from "ethers/lib/utils.js"; +import { useChainId } from "lib/chains"; +import { getByKey } from "lib/objects"; +import { getSyntheticsGraphClient } from "lib/subgraph"; +import { useEffect, useState } from "react"; +import { useLatest } from "react-use"; + +type RawRebateGroup = { + id: string; + timeKey: string; + marketAddress: string; + tokenAddress: string; + factor: string; + claimables: { + account: string; + value: BigNumber; + factor: BigNumber; + id: string; + }[]; +}; + +export type RebateGroup = { + id: string; + timeKey: string; + marketInfo: MarketInfo | undefined; + tokenData: TokenData | undefined; + factor: BigNumber; + userRebates: UserRebate[]; +}; + +export type UserRebate = { + account: string; + value: BigNumber; + factor: BigNumber; + tokenData: TokenData | undefined; + marketInfo: MarketInfo | undefined; + timeKey: string; + id: string; +}; + +const pageSize = 1000; + +export const usePriceImpactRebateGroups = ( + pageIndex: number, + inclReviewed: boolean +): [hasMore: boolean, loadedPageIndex: number, data: RebateGroup[]] => { + const { chainId } = useChainId(); + const { marketsInfoData, tokensData } = useMarketsInfoRequest(chainId); + const marketsInfoDataLatest = useLatest(marketsInfoData); + const tokensDataLatest = useLatest(tokensData); + const [marketsReady, setMarketsReady] = useState(false); + const [loadedPageIndex, setLoadedPageIndex] = useState(-1); + const [data, setData] = useState([]); + const [hasMore, setHasMore] = useState(false); + + useEffect(() => { + if (!marketsInfoData || !tokensData) return; + + setMarketsReady(true); + }, [marketsInfoData, tokensData]); + useEffect(() => { + setLoadedPageIndex(-1); + }, [inclReviewed]); + + const client = getSyntheticsGraphClient(chainId); + + useEffect(() => { + if (!marketsReady) return; + + async function load() { + if (!client) throw new Error(`Unsupported chain ${chainId}`); + const query = gql(`{ + claimableCollateralGroups( + skip: ${pageIndex * pageSize} + first: ${pageSize} + orderBy: timeKey + orderDirection: desc + where: { ${inclReviewed ? "" : "factor: 0"} } + ) { + id + timeKey + marketAddress + tokenAddress + factor + claimables { + id + account + value + factor + } + } + }`); + + const { data } = await client.query({ query, fetchPolicy: "no-cache" }); + + const rebateGroups = data.claimableCollateralGroups.map( + (group: RawRebateGroup): RebateGroup => ({ + factor: BigNumber.from(group.factor), + id: group.id, + marketInfo: getByKey(marketsInfoDataLatest.current, getAddress(group.marketAddress)), + tokenData: getByKey(tokensDataLatest.current, getAddress(group.tokenAddress)), + timeKey: group.timeKey, + userRebates: group.claimables.map((userRebate) => ({ + account: userRebate.account, + value: BigNumber.from(userRebate.value), + factor: BigNumber.from(userRebate.factor), + tokenData: getByKey(tokensDataLatest.current, getAddress(group.tokenAddress)), + marketInfo: getByKey(marketsInfoDataLatest.current, getAddress(group.marketAddress)), + timeKey: group.timeKey, + id: userRebate.id, + })), + }) + ); + + setData(rebateGroups); + setLoadedPageIndex(pageIndex); + setHasMore(rebateGroups.length === pageSize); + } + + load(); + }, [chainId, client, marketsInfoDataLatest, marketsReady, pageIndex, inclReviewed, tokensDataLatest]); + + return [hasMore, loadedPageIndex, data]; +}; diff --git a/src/pages/Referrals/Referrals.tsx b/src/pages/Referrals/Referrals.tsx index e59a310965..f1d905751d 100644 --- a/src/pages/Referrals/Referrals.tsx +++ b/src/pages/Referrals/Referrals.tsx @@ -32,6 +32,7 @@ import PageTitle from "components/PageTitle/PageTitle"; const TRADERS = "Traders"; const AFFILIATES = "Affiliates"; const TAB_OPTIONS = [TRADERS, AFFILIATES]; +const TAB_OPTION_LABELS = { [TRADERS]: t`Traders`, [AFFILIATES]: t`Affiliates` }; function Referrals({ setPendingTxns, @@ -119,7 +120,6 @@ function Referrals({ /> ); } - const TAB_OPTION_LABELS = { [TRADERS]: t`Traders`, [AFFILIATES]: t`Affiliates` }; return ( diff --git a/src/pages/Stake/StakeV2.css b/src/pages/Stake/StakeV2.css index eef6374124..960da399f7 100644 --- a/src/pages/Stake/StakeV2.css +++ b/src/pages/Stake/StakeV2.css @@ -72,6 +72,10 @@ gap: 1rem; } +.App-card-buttons.glp-buttons { + padding-top: 0.8rem; +} + .App-card-footer { position: absolute; bottom: 0; diff --git a/src/pages/Stake/StakeV2.js b/src/pages/Stake/StakeV2.js index 341ed214a9..ddf8996430 100644 --- a/src/pages/Stake/StakeV2.js +++ b/src/pages/Stake/StakeV2.js @@ -16,6 +16,9 @@ import Vester from "abis/Vester.json"; import { ARBITRUM, getConstant } from "config/chains"; import { useGmxPrice, useTotalGmxStaked, useTotalGmxSupply } from "domain/legacy"; +import { useRecommendStakeGmxAmount } from "domain/stake/useRecommendStakeGmxAmount"; +import { useAccumulatedBnGMXAmount } from "domain/rewards/useAccumulatedBnGMXAmount"; +import { useMaxBoostBasicPoints } from "domain/rewards/useMaxBoostBasisPoints"; import { ethers } from "ethers"; import { GLP_DECIMALS, @@ -43,10 +46,11 @@ import ChainsStatsTooltipRow from "components/StatsTooltip/ChainsStatsTooltipRow import StatsTooltipRow from "components/StatsTooltip/StatsTooltipRow"; import { GmList } from "components/Synthetics/GmList/GmList"; import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; +import { AlertInfo } from "components/AlertInfo/AlertInfo"; import { getIcons } from "config/icons"; import { getServerUrl } from "config/backend"; import { getIsSyntheticsSupported } from "config/features"; -import { getTotalGmInfo, useMarketTokensData, useMarketsInfo } from "domain/synthetics/markets"; +import { getTotalGmInfo, useMarketTokensData, useMarketsInfoRequest } from "domain/synthetics/markets"; import { useMarketTokensAPR } from "domain/synthetics/markets/useMarketTokensAPR"; import { approveTokens } from "domain/tokens"; import { useChainId } from "lib/chains"; @@ -231,6 +235,8 @@ function UnstakeModal(props) { reservedAmount, bonusGmxInFeeGmx, setPendingTxns, + processedData, + nativeTokenSymbol, } = props; const [isUnstaking, setIsUnstaking] = useState(false); const icons = getIcons(chainId); @@ -249,10 +255,12 @@ function UnstakeModal(props) { burnAmount = multiplierPointsAmount.mul(amount).div(bonusGmxInFeeGmx); } - const shouldShowReductionAmount = true; - let rewardReductionBasisPoints; - if (burnAmount && bonusGmxInFeeGmx) { - rewardReductionBasisPoints = burnAmount.mul(BASIS_POINTS_DIVISOR).div(bonusGmxInFeeGmx); + let unstakeBonusLostPercentage; + if (amount?.gt(0) && multiplierPointsAmount?.gt(0)) { + unstakeBonusLostPercentage = amount + ?.add(burnAmount) + .mul(BASIS_POINTS_DIVISOR) + ?.div(multiplierPointsAmount?.add(processedData.esGmxInStakedGmx)?.add(processedData.gmxInStakedGmx)); } const getError = () => { @@ -326,23 +334,24 @@ function UnstakeModal(props) { {reservedAmount && reservedAmount.gt(0) && ( -
    + You have {formatAmount(reservedAmount, 18, 2, true)} tokens reserved for vesting. -
    + )} - {burnAmount && burnAmount.gt(0) && rewardReductionBasisPoints && rewardReductionBasisPoints.gt(0) && ( -
    + {burnAmount?.gt(0) && unstakeBonusLostPercentage?.gt(0) && !amount.gt(maxAmount) && ( + Unstaking will burn  {formatAmount(burnAmount, 18, 4, true)} Multiplier Points .  - {shouldShowReductionAmount && ( - Boost Percentage: -{formatAmount(rewardReductionBasisPoints, 2, 2)}%. - )} + + You will earn {formatAmount(unstakeBonusLostPercentage, 2, 2)}% less {nativeTokenSymbol} rewards with + this action. + -
    + )}
    @@ -1990,7 +2107,7 @@ export default function StakeV2({ setPendingTxns }) {
    ( @@ -1998,6 +2115,27 @@ export default function StakeV2({ setPendingTxns }) { />
    + {active && ( +
    +
    + Your APR +
    +
    + ( + + )} + /> +
    +
    + )}
    {renderMultiplierPointsLabel()}
    {renderMultiplierPointsValue()}
    diff --git a/src/pages/Stats/Stats.tsx b/src/pages/Stats/Stats.tsx index b021424e11..b45144ec6d 100644 --- a/src/pages/Stats/Stats.tsx +++ b/src/pages/Stats/Stats.tsx @@ -25,9 +25,12 @@ function shareBar(share?: BigNumberish, total?: BigNumberish) { let progress = bigNumberify(share)!.mul(100).div(total).toNumber(); progress = Math.min(progress, 100); + // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop + const style = { width: `${progress}%` }; + return (
    -
    +
    ); } @@ -229,7 +232,7 @@ export default function Stats() { } return ( -
    +
    @@ -122,10 +124,6 @@ export function PositionList(p: Props) { onSelectPositionClick={(tradeMode?: TradeMode) => p.onSelectPositionClick(position.key, tradeMode)} showPnlAfterFees={p.showPnlAfterFees} isLarge={true} - savedShowPnlAfterFees={p.savedShowPnlAfterFees} - currentMarketAddress={p.currentMarketAddress} - currentCollateralAddress={p.currentCollateralAddress} - currentTradeType={p.currentTradeType} openSettings={p.openSettings} hideActions={p.hideActions} onShareClick={() => handleSharePositionClick(position.key)} diff --git a/src/components/Synthetics/PositionSeller/PositionSeller.tsx b/src/components/Synthetics/PositionSeller/PositionSeller.tsx index 84c3ebeb52..5ba81c3bfc 100644 --- a/src/components/Synthetics/PositionSeller/PositionSeller.tsx +++ b/src/components/Synthetics/PositionSeller/PositionSeller.tsx @@ -1,26 +1,32 @@ import { Trans, t } from "@lingui/macro"; import { useConnectModal } from "@rainbow-me/rainbowkit"; import cx from "classnames"; +import { BigNumber } from "ethers"; +import React, { useEffect, useMemo, useState } from "react"; +import { useLatest } from "react-use"; + import Button from "components/Button/Button"; import BuyInputSection from "components/BuyInputSection/BuyInputSection"; import ExchangeInfoRow from "components/Exchange/ExchangeInfoRow"; import Modal from "components/Modal/Modal"; -import PercentageInput from "components/PercentageInput/PercentageInput"; import { SubaccountNavigationButton } from "components/SubaccountNavigationButton/SubaccountNavigationButton"; import Tab from "components/Tab/Tab"; import ToggleSwitch from "components/ToggleSwitch/ToggleSwitch"; import TokenSelector from "components/TokenSelector/TokenSelector"; import Tooltip from "components/Tooltip/Tooltip"; -import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; import { ValueTransition } from "components/ValueTransition/ValueTransition"; -import { DEFAULT_SLIPPAGE_AMOUNT, EXCESSIVE_SLIPPAGE_AMOUNT } from "config/factors"; import { getKeepLeverageKey } from "config/localStorage"; import { convertTokenAddress } from "config/tokens"; -import { useSettings } from "context/SettingsContext/SettingsContextProvider"; import { useSubaccount } from "context/SubaccountContext/SubaccountContext"; import { useSyntheticsEvents } from "context/SyntheticsEvents"; +import { usePositionsConstants, useUserReferralInfo } from "context/SyntheticsStateContext/hooks/globalsHooks"; +import { + useSavedAcceptablePriceImpactBuffer, + useSavedAllowedSlippage, +} from "context/SyntheticsStateContext/hooks/settingsHooks"; +import { useSwapRoutes } from "context/SyntheticsStateContext/hooks/tradeHooks"; +import { useTradeboxTradeFlags } from "context/SyntheticsStateContext/hooks/tradeboxHooks"; import { useHasOutdatedUi } from "domain/legacy"; -import { useUserReferralInfo } from "domain/referrals/hooks"; import { estimateExecuteDecreaseOrderGasLimit, getExecutionFee, @@ -28,7 +34,6 @@ import { useGasPrice, } from "domain/synthetics/fees"; import useUiFeeFactor from "domain/synthetics/fees/utils/useUiFeeFactor"; -import { MarketsInfoData } from "domain/synthetics/markets"; import { DecreasePositionSwapType, OrderType, createDecreaseOrderTxn } from "domain/synthetics/orders"; import { PositionInfo, @@ -36,7 +41,6 @@ import { formatLeverage, formatLiquidationPrice, getTriggerNameByOrderType, - usePositionsConstants, } from "domain/synthetics/positions"; import { TokensData } from "domain/synthetics/tokens"; import { @@ -47,19 +51,16 @@ import { getNextPositionValuesForDecreaseTrade, getSwapAmountsByFromValue, getTradeFees, - useSwapRoutes, } from "domain/synthetics/trade"; import { useDebugExecutionPrice } from "domain/synthetics/trade/useExecutionPrice"; +import { useHighExecutionFeeConsent } from "domain/synthetics/trade/useHighExecutionFeeConsent"; import { usePriceImpactWarningState } from "domain/synthetics/trade/usePriceImpactWarningState"; -import { TradeFlags } from "domain/synthetics/trade/useTradeFlags"; import { getCommonError, getDecreaseError } from "domain/synthetics/trade/utils/validation"; import { getIsEquivalentTokens } from "domain/tokens"; -import { BigNumber } from "ethers"; import { useChainId } from "lib/chains"; import { USD_DECIMALS } from "lib/legacy"; import { useLocalStorageSerializeKey } from "lib/localStorage"; import { - bigNumberify, formatAmount, formatAmountFree, formatDeltaUsd, @@ -68,20 +69,19 @@ import { formatUsd, parseValue, } from "lib/numbers"; -import { getByKey } from "lib/objects"; +import { EMPTY_ARRAY, getByKey } from "lib/objects"; import { museNeverExist } from "lib/types"; import { usePrevious } from "lib/usePrevious"; import useWallet from "lib/wallets/useWallet"; -import { useEffect, useMemo, useState } from "react"; -import { useLatest } from "react-use"; import { AcceptablePriceImpactInputRow } from "../AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow"; import { HighPriceImpactWarning } from "../HighPriceImpactWarning/HighPriceImpactWarning"; import { TradeFeesRow } from "../TradeFeesRow/TradeFeesRow"; +import { AllowedSlippageRow } from "./rows/AllowedSlippageRow"; + import "./PositionSeller.scss"; export type Props = { position?: PositionInfo; - marketsInfoData?: MarketsInfoData; tokensData?: TokensData; showPnlInLeverage: boolean; availableTokensOptions?: AvailableTokenOptions; @@ -90,7 +90,6 @@ export type Props = { isHigherSlippageAllowed: boolean; setIsHigherSlippageAllowed: (isAllowed: boolean) => void; shouldDisableValidation: boolean; - tradeFlags: TradeFlags; }; enum OrderOption { @@ -98,38 +97,30 @@ enum OrderOption { Trigger = "Trigger", } +const ORDER_OPTION_LABELS = { + [OrderOption.Market]: t`Market`, + [OrderOption.Trigger]: t`TP/SL`, +}; + export function PositionSeller(p: Props) { - const { - position, - marketsInfoData, - tokensData, - showPnlInLeverage, - onClose, - setPendingTxns, - availableTokensOptions, - tradeFlags, - } = p; + const { position, tokensData, showPnlInLeverage, onClose, setPendingTxns, availableTokensOptions } = p; const { chainId } = useChainId(); - const { savedAllowedSlippage } = useSettings(); + const savedAllowedSlippage = useSavedAllowedSlippage(); const { signer, account } = useWallet(); const { openConnectModal } = useConnectModal(); const { gasPrice } = useGasPrice(chainId); const { gasLimits } = useGasLimits(chainId); - const { minCollateralUsd, minPositionSizeUsd } = usePositionsConstants(chainId); - const userReferralInfo = useUserReferralInfo(signer, chainId, account); + const { minCollateralUsd, minPositionSizeUsd } = usePositionsConstants(); + const userReferralInfo = useUserReferralInfo(); const { data: hasOutdatedUi } = useHasOutdatedUi(); const uiFeeFactor = useUiFeeFactor(chainId); - const { savedAcceptablePriceImpactBuffer } = useSettings(); + const savedAcceptablePriceImpactBuffer = useSavedAcceptablePriceImpactBuffer(); + const tradeFlags = useTradeboxTradeFlags(); const isVisible = Boolean(position); const prevIsVisible = usePrevious(isVisible); - const ORDER_OPTION_LABELS = { - [OrderOption.Market]: t`Market`, - [OrderOption.Trigger]: t`TP/SL`, - }; - const [orderOption, setOrderOption] = useState(OrderOption.Market); const [triggerPriceInputValue, setTriggerPriceInputValue] = useState(""); const triggerPrice = parseValue(triggerPriceInputValue, USD_DECIMALS); @@ -140,7 +131,7 @@ export function PositionSeller(p: Props) { const [keepLeverage, setKeepLeverage] = useLocalStorageSerializeKey(getKeepLeverageKey(chainId), true); const [defaultTriggerAcceptablePriceImpactBps, setDefaultTriggerAcceptablePriceImpactBps] = useState(); - const [selectedTriggerAcceptablePriceImpactBps, setSelectedAcceptablePriceImapctBps] = useState(); + const [selectedTriggerAcceptablePriceImpactBps, setSelectedTriggerAcceptablePriceImpactBps] = useState(); const [isSubmitting, setIsSubmitting] = useState(false); @@ -160,11 +151,7 @@ export function PositionSeller(p: Props) { ? getMarkPrice({ prices: position.indexToken.prices, isLong: position.isLong, isIncrease: false }) : undefined; - const { findSwapPath, maxSwapLiquidity } = useSwapRoutes({ - marketsInfoData, - fromTokenAddress: position?.collateralTokenAddress, - toTokenAddress: receiveTokenAddress, - }); + const { findSwapPath, maxSwapLiquidity } = useSwapRoutes(position?.collateralTokenAddress, receiveTokenAddress); const decreaseAmounts = useMemo(() => { if (!position || !minCollateralUsd || !minPositionSizeUsd) { @@ -289,6 +276,7 @@ export function PositionSeller(p: Props) { positionFeeUsd: decreaseAmounts.positionFeeUsd, swapPriceImpactDeltaUsd: swapAmounts?.swapPathStats?.totalSwapPriceImpactDeltaUsd || BigNumber.from(0), positionPriceImpactDeltaUsd: decreaseAmounts.positionPriceImpactDeltaUsd, + priceImpactDiffUsd: decreaseAmounts.priceImpactDiffUsd, borrowingFeeUsd: decreaseAmounts.borrowingFeeUsd, fundingFeeUsd: decreaseAmounts.fundingFeeUsd, feeDiscountUsd: decreaseAmounts.feeDiscountUsd, @@ -310,11 +298,15 @@ export function PositionSeller(p: Props) { uiFeeFactor, ]); + const { element: highExecutionFeeAcknowledgement, isHighFeeConsentError } = useHighExecutionFeeConsent( + executionFee?.feeUsd + ); + const priceImpactWarningState = usePriceImpactWarningState({ positionPriceImpact: fees?.positionPriceImpact, swapPriceImpact: fees?.swapPriceImpact, - tradeFlags, place: "positionSeller", + tradeFlags, }); const isNotEnoughReceiveTokenLiquidity = shouldSwap ? maxSwapLiquidity?.lt(receiveUsd || 0) : false; @@ -362,6 +354,10 @@ export function PositionSeller(p: Props) { return commonError[0] || decreaseError[0]; } + if (isHighFeeConsentError) { + return [t`High Execution Fee not yet acknowledged`]; + } + if (isSubmitting) { return t`Creating Order...`; } @@ -371,6 +367,7 @@ export function PositionSeller(p: Props) { closeSizeUsd, decreaseAmounts?.sizeDeltaUsd, hasOutdatedUi, + isHighFeeConsentError, isNotEnoughReceiveTokenLiquidity, isSubmitting, isTrigger, @@ -474,6 +471,7 @@ export function PositionSeller(p: Props) { !defaultTriggerAcceptablePriceImpactBps.eq(decreaseAmounts.recommendedAcceptablePriceDeltaBps.abs()) ) { setDefaultTriggerAcceptablePriceImpactBps(decreaseAmounts.recommendedAcceptablePriceDeltaBps.abs()); + setSelectedTriggerAcceptablePriceImpactBps(decreaseAmounts.recommendedAcceptablePriceDeltaBps.abs()); } } }, [decreaseAmounts, defaultTriggerAcceptablePriceImpactBps, isTrigger]); @@ -485,7 +483,6 @@ export function PositionSeller(p: Props) { ); - const allowedSlippageRow = ( -
    - { - return ( -
    - - You can edit the default Allowed Slippage in the settings menu on the top right of the page. -
    -
    - Note that a low allowed slippage, e.g. less than{" "} - {formatPercentage(bigNumberify(DEFAULT_SLIPPAGE_AMOUNT), { signed: false })}, may result in failed - orders if prices are volatile. -
    -
    - ); - }} - /> - } - > - -
    -
    - ); - const markPriceRow = ( ); + const isStopLoss = decreaseAmounts?.triggerOrderType === OrderType.StopLossDecrease; + const acceptablePriceImpactInputRow = (() => { if (!decreaseAmounts) { return; @@ -558,26 +523,27 @@ export function PositionSeller(p: Props) { return ( ); })(); - const acceptablePriceRow = ( - - ); + let acceptablePriceValue: React.ReactNode = "-"; + if (isStopLoss) { + acceptablePriceValue = t`NA`; + } else if (decreaseAmounts?.sizeDeltaUsd.gt(0)) { + acceptablePriceValue = formatAcceptablePrice(acceptablePrice, { + displayDecimals: indexPriceDecimals, + }); + } else { + acceptablePriceValue = "-"; + } + + const acceptablePriceRow = ; const liqPriceRow = position && ( } /> @@ -650,6 +616,7 @@ export function PositionSeller(p: Props) { const receiveTokenRow = isTrigger ? ( setReceiveTokenAddress(token.address)} - tokens={availableTokensOptions?.swapTokens || []} + tokens={availableTokensOptions?.swapTokens || EMPTY_ARRAY} showTokenImgInDropdown={true} selectedTokenLabel={ @@ -699,7 +665,28 @@ export function PositionSeller(p: Props) { /> ); - const isStopLoss = decreaseAmounts?.triggerOrderType === OrderType.StopLossDecrease; + let leverageValue: React.ReactNode = "-"; + + if (decreaseAmounts?.isFullClose) { + leverageValue = t`NA`; + } else if (position) { + if (decreaseAmounts?.sizeDeltaUsd.eq(position.sizeInUsd)) { + leverageValue = "-"; + } else { + leverageValue = ( + + ); + } + } + + const keepLeverageChecked = decreaseAmounts?.isFullClose ? false : keepLeverage ?? false; + let keepLeverageAtValue: string | undefined = "..."; + if (position?.leverage && !decreaseAmounts?.isFullClose) { + keepLeverageAtValue = formatLeverage(position.leverage); + } return (
    @@ -712,7 +699,6 @@ export function PositionSeller(p: Props) { Close {p.position?.isLong ? t`Long` : t`Short`} {p.position?.indexToken?.symbol} } - allowContentTouchMove > + +
    - + - Keep leverage at {position?.leverage ? formatLeverage(position.leverage) : "..."} + Keep leverage at {keepLeverageAtValue}
    +
    + {isTrigger ? ( <> + {acceptablePriceImpactInputRow} +
    {triggerPriceRow} - {!isStopLoss && acceptablePriceImpactInputRow} - {!isStopLoss && acceptablePriceRow} + {acceptablePriceRow} {liqPriceRow} {sizeRow} ) : ( <> - {allowedSlippageRow} - {markPriceRow} + {entryPriceRow} {acceptablePriceRow} + {markPriceRow} {liqPriceRow} {sizeRow} )} + {pnlRow} +
    - {!keepLeverage && ( - - ) - } - /> - )} - {pnlRow} {receiveTokenRow}
    - {priceImpactWarningState.shouldShowWarning && ( + {(priceImpactWarningState.shouldShowWarning || highExecutionFeeAcknowledgement) && ( <>
    - +
    + {priceImpactWarningState.shouldShowWarning && ( + + )} + + {highExecutionFeeAcknowledgement} +
    )} diff --git a/src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx b/src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx new file mode 100644 index 0000000000..bd7576597e --- /dev/null +++ b/src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx @@ -0,0 +1,50 @@ +import { Trans, t } from "@lingui/macro"; + +import { DEFAULT_SLIPPAGE_AMOUNT, EXCESSIVE_SLIPPAGE_AMOUNT } from "config/factors"; +import { bigNumberify, formatPercentage } from "lib/numbers"; + +import ExchangeInfoRow from "components/Exchange/ExchangeInfoRow"; +import PercentageInput from "components/PercentageInput/PercentageInput"; +import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; + +export function AllowedSlippageRow({ + allowedSlippage, + setAllowedSlippage, +}: { + setAllowedSlippage: (value: number) => void; + allowedSlippage: number; +}) { + return ( + { + return ( +
    + + You can edit the default Allowed Slippage in the settings menu on the top right of the page. +
    +
    + Note that a low allowed slippage, e.g. less than - + {formatPercentage(bigNumberify(DEFAULT_SLIPPAGE_AMOUNT), { signed: false })}, may result in failed + orders if prices are volatile. +
    +
    + ); + }} + /> + } + > + +
    + ); +} diff --git a/src/components/Synthetics/SettleAccruedFundingFeeModal/SettleAccruedFundingFeeModal.scss b/src/components/Synthetics/SettleAccruedFundingFeeModal/SettleAccruedFundingFeeModal.scss index 1993a44bb0..b8ca86fd38 100644 --- a/src/components/Synthetics/SettleAccruedFundingFeeModal/SettleAccruedFundingFeeModal.scss +++ b/src/components/Synthetics/SettleAccruedFundingFeeModal/SettleAccruedFundingFeeModal.scss @@ -1,56 +1,56 @@ .ClaimSettleModal-divider { - margin-top: 1.5rem; + margin-top: 1.5rem; } .ClaimSettleModal-alert { - color: rgba(255, 255, 255, 0.70); - padding-bottom: 1rem; + color: rgba(255, 255, 255, 0.7); + padding-bottom: 1rem; } .ClaimSettleModal-modal-content { - margin-top: 1.8rem; + margin-top: 1.8rem; } .ClaimSettleModal-row-text { - color: white; + color: white; } .ClaimSettleModal-info-row { - display: flex; - font-size: var(--font-sm); - margin-bottom: 1.5rem; - align-items: baseline; - + display: flex; + font-size: var(--font-sm); + margin-bottom: 1.5rem; + align-items: baseline; } .ClaimSettleModal-info-label-usd { - margin-left: auto; + margin-left: auto; } .ClaimSettleModal-header { - margin-bottom: 1.5rem; - display: flex; - color: rgba(255, 255, 255, 0.70); + margin-bottom: 1.5rem; + display: flex; + color: rgba(255, 255, 255, 0.7); + font-size: var(--font-sm); } .ClaimSettleModal-header-left { - margin-left: 2.3rem; + margin-left: 2.3rem; } .ClaimSettleModal-header-right { - margin-left: auto; + margin-left: auto; } .ClaimSettleModal-checkbox { - margin-right: 0.5rem; + margin-right: 0.5rem; } .ClaimSettleModal-tooltip { - .Tooltip-popup { - min-width: 0; - white-space: nowrap; - } + .Tooltip-popup { + min-width: 0; + white-space: nowrap; + } } .ClaimSettleModal-checkbox-label { - margin-left: 0.4rem; -} \ No newline at end of file + margin-left: 0.4rem; +} diff --git a/src/components/Synthetics/SettleAccruedFundingFeeModal/SettleAccruedFundingFeeModal.tsx b/src/components/Synthetics/SettleAccruedFundingFeeModal/SettleAccruedFundingFeeModal.tsx index ab945ff2a9..fe3a6182e7 100644 --- a/src/components/Synthetics/SettleAccruedFundingFeeModal/SettleAccruedFundingFeeModal.tsx +++ b/src/components/Synthetics/SettleAccruedFundingFeeModal/SettleAccruedFundingFeeModal.tsx @@ -3,13 +3,11 @@ import Modal from "components/Modal/Modal"; import { formatDeltaUsd, formatUsd } from "lib/numbers"; import Button from "components/Button/Button"; import { getTotalAccruedFundingUsd } from "domain/synthetics/markets"; -import { PositionsInfoData } from "domain/synthetics/positions"; import { useCallback, useEffect, useMemo, useState } from "react"; import { SettleAccruedFundingFeeRow } from "./SettleAccruedFundingFeeRow"; import Tooltip from "components/Tooltip/Tooltip"; import { useSyntheticsEvents } from "context/SyntheticsEvents"; -import { useUserReferralInfo } from "domain/referrals"; import { estimateExecuteDecreaseOrderGasLimit, getExecutionFee, @@ -17,41 +15,43 @@ import { useGasPrice, } from "domain/synthetics/fees"; import { createDecreaseOrderTxn, DecreasePositionSwapType, OrderType } from "domain/synthetics/orders"; -import { TokensData } from "domain/synthetics/tokens"; import { BigNumber } from "ethers"; import { useChainId } from "lib/chains"; import useWallet from "lib/wallets/useWallet"; import "./SettleAccruedFundingFeeModal.scss"; import { useSubaccount } from "context/SubaccountContext/SubaccountContext"; import { SubaccountNavigationButton } from "components/SubaccountNavigationButton/SubaccountNavigationButton"; +import { + usePositionsInfoData, + useTokensData, + useUserReferralInfo, +} from "context/SyntheticsStateContext/hooks/globalsHooks"; type Props = { allowedSlippage: number; isVisible: boolean; onClose: () => void; positionKeys: string[]; - positionsInfoData: PositionsInfoData | undefined; setPositionKeys: (keys: string[]) => void; - tokensData?: TokensData; setPendingTxns: (txns: any) => void; }; export function SettleAccruedFundingFeeModal({ allowedSlippage, - tokensData, isVisible, onClose, positionKeys, setPositionKeys, - positionsInfoData, setPendingTxns, }: Props) { + const tokensData = useTokensData(); const { account, signer } = useWallet(); const { chainId } = useChainId(); - const userReferralInfo = useUserReferralInfo(signer, chainId, account); + const userReferralInfo = useUserReferralInfo(); const [isSubmitting, setIsSubmitting] = useState(false); const { gasLimits } = useGasLimits(chainId); const { gasPrice } = useGasPrice(chainId); + const positionsInfoData = usePositionsInfoData(); const positiveFeePositions = useMemo( () => Object.values(positionsInfoData || {}).filter((position) => position.pendingClaimableFundingFeesUsd.gt(0)), diff --git a/src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx b/src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx index 26715736f1..fd990fc014 100644 --- a/src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx +++ b/src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx @@ -5,11 +5,13 @@ import { getWrappedToken } from "config/tokens"; import { PendingOrderData, getPendingOrderKey, useSyntheticsEvents } from "context/SyntheticsEvents"; import { MarketsInfoData } from "domain/synthetics/markets"; import { + isDecreaseOrderType, isIncreaseOrderType, isLimitOrderType, isLimitSwapOrderType, isMarketOrderType, isSwapOrderType, + isTriggerDecreaseOrderType, } from "domain/synthetics/orders"; import { TokensData } from "domain/synthetics/tokens"; import { getSwapPathOutputAddresses } from "domain/synthetics/trade"; @@ -19,15 +21,32 @@ import { getByKey } from "lib/objects"; import { useEffect, useMemo, useState } from "react"; import "./StatusNotification.scss"; import { useToastAutoClose } from "./useToastAutoClose"; +import { getTriggerNameByOrderType } from "domain/synthetics/positions"; +import ExternalLink from "components/ExternalLink/ExternalLink"; +import { cancelOrdersTxn } from "domain/synthetics/orders/cancelOrdersTxn"; +import useWallet from "lib/wallets/useWallet"; +import { + useIsLastSubaccountAction, + useSubaccount, + useSubaccountCancelOrdersDetailsMessage, +} from "context/SubaccountContext/SubaccountContext"; +import { getExplorerUrl } from "config/chains"; type Props = { toastTimestamp: number; pendingOrderData: PendingOrderData; marketsInfoData?: MarketsInfoData; tokensData?: TokensData; + hideTxLink?: "creation" | "execution" | "none"; }; -export function OrderStatusNotification({ pendingOrderData, marketsInfoData, tokensData, toastTimestamp }: Props) { +export function OrderStatusNotification({ + pendingOrderData, + marketsInfoData, + tokensData, + toastTimestamp, + hideTxLink = "none", +}: Props) { const { chainId } = useChainId(); const wrappedNativeToken = getWrappedToken(chainId); const { orderStatuses, setOrderStatusViewed } = useSyntheticsEvents(); @@ -37,10 +56,6 @@ export function OrderStatusNotification({ pendingOrderData, marketsInfoData, tok const pendingOrderKey = useMemo(() => getPendingOrderKey(pendingOrderData), [pendingOrderData]); const orderStatus = getByKey(orderStatuses, orderStatusKey); - const isCompleted = isMarketOrderType(pendingOrderData.orderType) - ? Boolean(orderStatus?.executedTxnHash) - : Boolean(orderStatus?.createdTxnHash); - const hasError = Boolean(orderStatus?.cancelledTxnHash); const orderData = useMemo(() => { @@ -114,7 +129,11 @@ export function OrderStatusNotification({ pendingOrderData, marketsInfoData, tok if (isMarketOrderType(orderType)) { orderTypeText = isIncreaseOrderType(orderType) ? t`Increasing` : t`Decreasing`; } else { - orderTypeText = isLimitOrderType(orderType) ? t`Limit order for` : t`Trigger order for`; + if (isLimitOrderType(orderType)) { + orderTypeText = t`Limit order for`; + } else if (isDecreaseOrderType(orderType)) { + orderTypeText = t`${getTriggerNameByOrderType(orderType, true)} order for`; + } } const sign = isIncreaseOrderType(orderType) ? "+" : "-"; @@ -135,8 +154,14 @@ export function OrderStatusNotification({ pendingOrderData, marketsInfoData, tok text = t`Order request sent`; } - return ; - }, [orderStatus?.createdTxnHash]); + return ( + + ); + }, [orderStatus?.createdTxnHash, hideTxLink]); const executionStatus = useMemo(() => { if (!orderData || !isMarketOrderType(orderData?.orderType)) { @@ -163,8 +188,8 @@ export function OrderStatusNotification({ pendingOrderData, marketsInfoData, tok txnHash = orderStatus?.cancelledTxnHash; } - return ; - }, [orderData, orderStatus?.cancelledTxnHash, orderStatus?.createdTxnHash, orderStatus?.executedTxnHash]); + return ; + }, [orderData, orderStatus?.cancelledTxnHash, orderStatus?.createdTxnHash, orderStatus?.executedTxnHash, hideTxLink]); useEffect( function getOrderStatusKey() { @@ -184,10 +209,8 @@ export function OrderStatusNotification({ pendingOrderData, marketsInfoData, tok [orderStatus, orderStatusKey, orderStatuses, pendingOrderKey, setOrderStatusViewed, toastTimestamp] ); - useToastAutoClose(isCompleted, toastTimestamp); - return ( -
    +
    {title}
    @@ -196,8 +219,168 @@ export function OrderStatusNotification({ pendingOrderData, marketsInfoData, tok {executionStatus}
    +
    + ); +} + +export function OrdersStatusNotificiation({ + pendingOrderData, + marketsInfoData, + tokensData, + toastTimestamp, + setPendingTxns, +}: { + pendingOrderData: PendingOrderData | PendingOrderData[]; + marketsInfoData?: MarketsInfoData; + tokensData?: TokensData; + toastTimestamp: number; + setPendingTxns: (txns: string[]) => void; +}) { + const [isCancelOrderProcessing, setIsCancelOrderProcessing] = useState(false); + const { chainId } = useChainId(); + const { signer } = useWallet(); + const { orderStatuses: allOrderStatuses, setOrderStatusViewed } = useSyntheticsEvents(); + const pendingOrders = useMemo( + () => (Array.isArray(pendingOrderData) ? pendingOrderData : [pendingOrderData]), + [pendingOrderData] + ); + + const [matchedOrderStatusKeys, setMatchedOrderStatusKeys] = useState([]); + + const matchedOrderStatuses = useMemo( + () => matchedOrderStatusKeys.map((key) => allOrderStatuses[key]), + [allOrderStatuses, matchedOrderStatusKeys] + ); + + const orderByKey = useMemo(() => { + const map = new Map(); + pendingOrders.forEach((order) => { + const key = getPendingOrderKey(order); + map.set(key, order); + }); + return map; + }, [pendingOrders]); -
    + useEffect(() => { + Object.values(allOrderStatuses).forEach((orderStatus) => { + const key = getPendingOrderKey(orderStatus.data); + + if (orderStatus.isViewed || !orderByKey.has(key)) return; + + setMatchedOrderStatusKeys((prev) => [...prev, orderStatus.key]); + setOrderStatusViewed(orderStatus.key); + }); + }, [allOrderStatuses, orderByKey, setOrderStatusViewed]); + + const isCompleted = useMemo(() => { + return pendingOrders.every((pendingOrder) => { + const orderStatus = matchedOrderStatuses.find( + (status) => getPendingOrderKey(status.data) === getPendingOrderKey(pendingOrder) + ); + return isMarketOrderType(pendingOrder.orderType) + ? Boolean(orderStatus?.executedTxnHash) + : Boolean(orderStatus?.createdTxnHash); + }); + }, [matchedOrderStatuses, pendingOrders]); + + const isMarketOrLimitOrderFailed = useMemo(() => { + return pendingOrders.some((pendingOrder) => { + if (isMarketOrderType(pendingOrder.orderType) || isLimitOrderType(pendingOrder.orderType)) { + const orderStatusKey = getPendingOrderKey(pendingOrder); + const orderStatus = matchedOrderStatuses.find((status) => getPendingOrderKey(status.data) === orderStatusKey); + return orderStatus?.cancelledTxnHash !== undefined; + } + return false; + }); + }, [matchedOrderStatuses, pendingOrders]); + + const triggerOrderKeys = useMemo(() => { + return pendingOrders.reduce((result, order) => { + if (isTriggerDecreaseOrderType(order.orderType)) { + const key = getPendingOrderKey(order); + const orderStatus = matchedOrderStatuses.find((status) => getPendingOrderKey(status.data) === key); + if (orderStatus?.createdTxnHash && orderStatus?.key) { + result.push(orderStatus.key); + } + } + return result; + }, [] as string[]); + }, [matchedOrderStatuses, pendingOrders]); + + const subaccount = useSubaccount(null, triggerOrderKeys.length); + const cancelOrdersDetailsMessage = useSubaccountCancelOrdersDetailsMessage(undefined, triggerOrderKeys.length); + const isLastSubaccountAction = useIsLastSubaccountAction(); + + function onCancelOrdersClick() { + if (!signer || !triggerOrderKeys.length || !setPendingTxns) return; + + setIsCancelOrderProcessing(true); + cancelOrdersTxn(chainId, signer, subaccount, { + orderKeys: triggerOrderKeys, + setPendingTxns, + isLastSubaccountAction, + detailsMsg: cancelOrdersDetailsMessage, + }).finally(() => setIsCancelOrderProcessing(false)); + } + + const createdTxnHashList = useMemo(() => { + const uniqueHashSet = pendingOrders.reduce((acc, order) => { + const orderStatus = matchedOrderStatuses.find( + (status) => getPendingOrderKey(status.data) === getPendingOrderKey(order) + ); + if (orderStatus?.createdTxnHash) { + acc.add(orderStatus.createdTxnHash); + } + return acc; + }, new Set()); + + const uniqueHashList = Array.from(uniqueHashSet); + + if (uniqueHashList.length > 0) { + return uniqueHashList; + } + }, [matchedOrderStatuses, pendingOrders]); + + useToastAutoClose(isCompleted, toastTimestamp); + + return ( +
    +
    + {pendingOrders.map((order, index) => { + return ( + 1 ? "creation" : "none"} + /> + ); + })} +
    + {pendingOrders.length > 1 && ( +
    +
    + {isMarketOrLimitOrderFailed && triggerOrderKeys.length > 0 && ( + + )} +
    +
    + {createdTxnHashList?.map((txnHash) => ( + + View + + ))} +
    +
    + )}
    ); } diff --git a/src/components/Synthetics/StatusNotification/StatusNotification.scss b/src/components/Synthetics/StatusNotification/StatusNotification.scss index 0127755743..28abe70024 100644 --- a/src/components/Synthetics/StatusNotification/StatusNotification.scss +++ b/src/components/Synthetics/StatusNotification/StatusNotification.scss @@ -1,20 +1,21 @@ -.StatusNotification { - position: relative; -} +.StatusNotification-wrapper { + .StatusNotification-actions { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0 0.8rem 0.8rem 0.8rem; + + .StatusNotification-cancel-all { + background: transparent; + border: none; + padding: 0; + color: var(--text-gray); + text-decoration: underline; -.StatusNotification-background { - position: absolute; - top: -10%; - left: -10%; - right: auto; - width: 150%; - height: 150%; - bottom: 0; - background-color: rgba(174, 43, 63, 0); - transition: background-color 0.3s ease-in-out; - - &.error { - background-color: rgba(174, 43, 63, 1); + &:hover { + color: white; + } + } } } @@ -29,12 +30,32 @@ .StatusNotification-items { margin-top: 1rem; +} + +.Toastify__toast.OrdersStatusNotificiation { + padding: 0; + position: relative; - .TransactionStatus-status { - margin-right: -1.8rem !important; + .Toastify__close-button { + position: absolute; + top: 8px; + right: 8px; } - .TransactionStatus-spin { - margin-right: -0.3rem !important; + .Toastify__toast-body { + padding: 0; + .StatusNotification-wrapper { + .StatusNotification-list { + .StatusNotification { + padding: 0.8rem 1rem; + &.error { + background-color: rgba(174, 43, 63, 1); + } + &:not(:last-child) { + border-bottom: 1.5px #0f463d solid; + } + } + } + } } } diff --git a/src/components/Synthetics/SubaccountModal/SubaccountModal.tsx b/src/components/Synthetics/SubaccountModal/SubaccountModal.tsx index 0fffe5f212..a41d17ae7d 100644 --- a/src/components/Synthetics/SubaccountModal/SubaccountModal.tsx +++ b/src/components/Synthetics/SubaccountModal/SubaccountModal.tsx @@ -27,7 +27,12 @@ import { getCurrentMaxActionsCount } from "domain/synthetics/subaccount/getCurre import { initSubaccount } from "domain/synthetics/subaccount/initSubaccount"; import { removeSubaccount } from "domain/synthetics/subaccount/removeSubaccount"; import { withdrawFromSubaccount } from "domain/synthetics/subaccount/withdrawFromSubaccount"; -import { getNeedTokenApprove, useTokenBalances, useTokensAllowanceData, useTokensData } from "domain/synthetics/tokens"; +import { + getNeedTokenApprove, + useTokenBalances, + useTokensAllowanceData, + useTokensDataRequest, +} from "domain/synthetics/tokens"; import { BigNumber } from "ethers"; import copyIcon from "img/ic_copy_20.svg"; import externalLinkIcon from "img/ic_new_link_20.svg"; @@ -65,7 +70,7 @@ const MainView = memo(({ setPendingTxns }: { setPendingTxns: (txns: any) => void const { signer, account } = useWallet(); const [withdrawalLoading, setWithdrawalLoading] = useState(false); const [isSubaccountUpdating, setIsSubaccountUpdating] = useState(false); - const { tokensData } = useTokensData(chainId); + const { tokensData } = useTokensDataRequest(chainId); const subaccountAddress = useSubaccountAddress(); const mainBalances = useTokenBalances(chainId, account); const subBalances = useTokenBalances(chainId, subaccountAddress ?? undefined); diff --git a/src/components/Synthetics/SubaccountModal/SubaccountStatus.tsx b/src/components/Synthetics/SubaccountModal/SubaccountStatus.tsx index 97bd250ced..31cac6f23a 100644 --- a/src/components/Synthetics/SubaccountModal/SubaccountStatus.tsx +++ b/src/components/Synthetics/SubaccountModal/SubaccountStatus.tsx @@ -1,5 +1,4 @@ import { Trans } from "@lingui/macro"; -import cx from "classnames"; import ExternalLink from "components/ExternalLink/ExternalLink"; import { getNativeToken, getWrappedToken } from "config/tokens"; import { @@ -11,10 +10,9 @@ import { useSubaccountInsufficientFunds, } from "context/SubaccountContext/SubaccountContext"; import { SUBACCOUNT_DOCS_URL } from "domain/synthetics/subaccount/constants"; -import infoIcon from "img/ic_info.svg"; -import warnIcon from "img/ic_warn.svg"; import { useChainId } from "lib/chains"; import { ReactNode, memo } from "react"; +import { AlertInfo } from "components/AlertInfo/AlertInfo"; import "./SubaccountStatus.scss"; function SubaccountStatusImpl({ hasBorder }: { hasBorder: boolean }) { @@ -39,23 +37,23 @@ function SubaccountStatusImpl({ hasBorder }: { hasBorder: boolean }) { ) { if (shouldShowAllowedActionsError) { content.push( - + The maximum number of authorized Actions has been reached. Re-authorize a higher value using the "Max allowed actions" field. - + ); } if (shouldShowSubaccountInsufficientFundsError) { content.push( - + There are insufficient funds in your Subaccount for One-Click Trading. Use the "Top-up" field to increase the Subaccount Balance. - + ); } @@ -63,22 +61,22 @@ function SubaccountStatusImpl({ hasBorder }: { hasBorder: boolean }) { const wrappedToken = getWrappedToken(chainId); const nativeToken = getNativeToken(chainId); content.push( - + Not enough {wrappedToken.symbol} on your Main Account. Use the "Convert {nativeToken.symbol} to{" "} {wrappedToken.symbol}" field to increase the Main Account {wrappedToken.symbol} balance. - + ); } } else if (!isSubaccountActive) { return ( - + Generate and activate a Subaccount for{" "} One-Click Trading to reduce signing popups. - + ); } else { return null; @@ -88,22 +86,3 @@ function SubaccountStatusImpl({ hasBorder }: { hasBorder: boolean }) { } export const SubaccountStatus = memo(SubaccountStatusImpl) as typeof SubaccountStatusImpl; - -const Info = ({ - standalone = false, - children, - warning, -}: { - children: ReactNode; - standalone?: boolean; - warning?: boolean; -}) => { - return ( -
    -
    - Warning -
    -
    {children}
    -
    - ); -}; diff --git a/src/components/Synthetics/SwapCard/SwapCard.tsx b/src/components/Synthetics/SwapCard/SwapCard.tsx index 8865632a46..187f2239b3 100644 --- a/src/components/Synthetics/SwapCard/SwapCard.tsx +++ b/src/components/Synthetics/SwapCard/SwapCard.tsx @@ -38,6 +38,17 @@ export function SwapCard(p: Props) { return `${formatAmount(markRatio.ratio, USD_DECIMALS, 4)} ${smallest.symbol} / ${largest.symbol}`; }, [fromToken, toToken]); + const maxOutValue = useMemo( + () => [ + formatTokenAmount(maxLiquidityAmount, toToken?.decimals, toToken?.symbol, { + useCommas: true, + displayDecimals: 0, + }), + `(${formatUsd(maxLiquidityUsd, { displayDecimals: 0 })})`, + ], + [maxLiquidityAmount, maxLiquidityUsd, toToken?.decimals, toToken?.symbol] + ); + return (
    @@ -75,13 +86,7 @@ export function SwapCard(p: Props) {
    diff --git a/src/components/Synthetics/TVChart/TVChart.tsx b/src/components/Synthetics/TVChart/TVChart.tsx index 46e7bb1a17..5ec73651b7 100644 --- a/src/components/Synthetics/TVChart/TVChart.tsx +++ b/src/components/Synthetics/TVChart/TVChart.tsx @@ -18,26 +18,24 @@ import { formatAmount, formatUsd, numberWithCommas } from "lib/numbers"; import { useEffect, useMemo, useState } from "react"; import "./TVChart.scss"; import ChartTokenSelector from "../ChartTokenSelector/ChartTokenSelector"; -import { TradeFlags } from "domain/synthetics/trade/useTradeFlags"; import { AvailableTokenOptions, TradeType } from "domain/synthetics/trade"; import { MarketsInfoData, getMarketIndexName, getMarketPoolName } from "domain/synthetics/markets"; import { getByKey } from "lib/objects"; import { helperToast } from "lib/helperToast"; +import { BigNumber } from "ethers"; +import { useTradeboxSetToTokenAddress, useTradeboxTradeType } from "context/SyntheticsStateContext/hooks/tradeboxHooks"; export type Props = { tradePageVersion: number; setTradePageVersion: (version: number) => void; savedShouldShowPositionLines: boolean; - onSelectChartTokenAddress: (tokenAddress: string, marketTokenAddress?: string, tradeType?: TradeType) => void; ordersInfo?: OrdersInfoData; positionsInfo?: PositionsInfoData; tokensData?: TokensData; chartTokenAddress?: string; availableTokens?: Token[]; - tradeFlags?: TradeFlags; avaialbleTokenOptions: AvailableTokenOptions; marketsInfoData?: MarketsInfoData; - currentTradeType?: TradeType; }; const DEFAULT_PERIOD = "5m"; @@ -48,14 +46,11 @@ export function TVChart({ tokensData, savedShouldShowPositionLines, chartTokenAddress, - onSelectChartTokenAddress, availableTokens, - tradeFlags, tradePageVersion, setTradePageVersion, avaialbleTokenOptions, marketsInfoData, - currentTradeType, }: Props) { const { chainId } = useChainId(); const oracleKeeperFetcher = useOracleKeeperFetcher(chainId); @@ -75,6 +70,8 @@ export function TVChart({ const selectedTokenOption = chartTokenAddress ? getToken(chainId, chartTokenAddress) : undefined; const dayPriceDelta = use24hPriceDelta(chainId, chartToken?.symbol); + const currentTradeType = useTradeboxTradeType(); + const setToTokenAddress = useTradeboxSetToTokenAddress(); const chartLines = useMemo(() => { if (!chartTokenAddress) { @@ -140,7 +137,7 @@ export function TVChart({ }, [chainId, chartTokenAddress, ordersInfo, positionsInfo, tokensData]); function onSelectTokenOption(address: string, marketTokenAddress?: string, tradeType?: TradeType) { - onSelectChartTokenAddress(address, marketTokenAddress, tradeType); + setToTokenAddress(address, marketTokenAddress, tradeType); if (marketTokenAddress) { const marketInfo = getByKey(marketsInfoData, marketTokenAddress); @@ -164,7 +161,7 @@ export function TVChart({ } function onSelectChartToken(token: Token) { - onSelectChartTokenAddress(token.address); + setToTokenAddress(token.address); } useEffect(() => { @@ -180,6 +177,21 @@ export function TVChart({ [period, setPeriod] ); + const chartTokenProp = useMemo( + () => + chartToken + ? { + symbol: chartToken.symbol, + ...chartToken.prices, + } + : { + symbol: "", + minPrice: BigNumber.from(0), + maxPrice: BigNumber.from(0), + }, + [chartToken] + ); + return (
    @@ -188,9 +200,7 @@ export function TVChart({ onSelectMarketAddress(marketInfo.marketTokenAddress)} /> diff --git a/src/components/Synthetics/TradeBox/TradeBox.tsx b/src/components/Synthetics/TradeBox/TradeBox.tsx index 71993850e4..3f34777277 100644 --- a/src/components/Synthetics/TradeBox/TradeBox.tsx +++ b/src/components/Synthetics/TradeBox/TradeBox.tsx @@ -1,9 +1,14 @@ import { Trans, t } from "@lingui/macro"; import { useConnectModal } from "@rainbow-me/rainbowkit"; +import { BigNumber } from "ethers"; +import { ReactNode, useCallback, useEffect, useMemo } from "react"; +import { IoMdSwap } from "react-icons/io"; +import { useLatest, usePrevious } from "react-use"; + import Button from "components/Button/Button"; import BuyInputSection from "components/BuyInputSection/BuyInputSection"; -import Checkbox from "components/Checkbox/Checkbox"; import ExchangeInfoRow from "components/Exchange/ExchangeInfoRow"; +import ExternalLink from "components/ExternalLink/ExternalLink"; import { LeverageSlider } from "components/LeverageSlider/LeverageSlider"; import { MarketSelector } from "components/MarketSelector/MarketSelector"; import { ConfirmationBox } from "components/Synthetics/ConfirmationBox/ConfirmationBox"; @@ -11,13 +16,26 @@ import Tab from "components/Tab/Tab"; import ToggleSwitch from "components/ToggleSwitch/ToggleSwitch"; import TokenWithIcon from "components/TokenIcon/TokenWithIcon"; import TokenSelector from "components/TokenSelector/TokenSelector"; +import Tooltip from "components/Tooltip/Tooltip"; import { ValueTransition } from "components/ValueTransition/ValueTransition"; -import { BASIS_POINTS_DIVISOR } from "config/factors"; -import { getKeepLeverageKey, getLeverageEnabledKey, getLeverageKey } from "config/localStorage"; -import { MAX_METAMASK_MOBILE_DECIMALS } from "config/ui"; +import { NATIVE_TOKEN_ADDRESS } from "config/tokens"; +import { MAX_METAMASK_MOBILE_DECIMALS, V2_LEVERAGE_SLIDER_MARKS } from "config/ui"; import { useSettings } from "context/SettingsContext/SettingsContextProvider"; +import { useMarketsInfoData, useTokensData, useUiFeeFactor } from "context/SyntheticsStateContext/hooks/globalsHooks"; +import { useSwapRoutes, useTradeRatios } from "context/SyntheticsStateContext/hooks/tradeHooks"; +import { + useTradeboxDecreasePositionAmounts, + useTradeboxExistingOrder, + useTradeboxIncreasePositionAmounts, + useTradeboxLeverage, + useTradeboxNextPositionValuesForDecrease, + useTradeboxNextPositionValuesForIncrease, + useTradeboxSelectedPosition, + useTradeboxState, + useTradeboxSwapAmounts, + useTradeboxTradeFlags, +} from "context/SyntheticsStateContext/hooks/tradeboxHooks"; import { useHasOutdatedUi } from "domain/legacy"; -import { useUserReferralInfo } from "domain/referrals/hooks"; import { estimateExecuteDecreaseOrderGasLimit, estimateExecuteIncreaseOrderGasLimit, @@ -26,43 +44,26 @@ import { useGasLimits, useGasPrice, } from "domain/synthetics/fees"; +import { getAvailableUsdLiquidityForPosition, getMarketIndexName } from "domain/synthetics/markets"; +import { DecreasePositionSwapType } from "domain/synthetics/orders"; import { - MarketInfo, - MarketsInfoData, - getAvailableUsdLiquidityForPosition, - getMarketIndexName, -} from "domain/synthetics/markets"; -import { DecreasePositionSwapType, OrderInfo, OrderType, OrdersInfoData } from "domain/synthetics/orders"; -import { - PositionInfo, - PositionsInfoData, formatLeverage, formatLiquidationPrice, getTriggerNameByOrderType, - usePositionsConstants, + usePositionsConstantsRequest, } from "domain/synthetics/positions"; -import { TokenData, TokensData, TokensRatio, convertToUsd, getTokensRatioByPrice } from "domain/synthetics/tokens"; +import { convertToUsd } from "domain/synthetics/tokens"; import { AvailableTokenOptions, - SwapAmounts, TradeFeesType, TradeMode, TradeType, - TriggerThresholdType, - getDecreasePositionAmounts, getExecutionPriceForDecrease, - getIncreasePositionAmounts, getMarkPrice, - getNextPositionValuesForDecreaseTrade, - getNextPositionValuesForIncreaseTrade, - getSwapAmountsByFromValue, - getSwapAmountsByToValue, getTradeFees, - useSwapRoutes, } from "domain/synthetics/trade"; import { useAvailableMarketsOptions } from "domain/synthetics/trade/useAvailableMarketsOptions"; import { usePriceImpactWarningState } from "domain/synthetics/trade/usePriceImpactWarningState"; -import { TradeFlags } from "domain/synthetics/trade/useTradeFlags"; import { ValidationResult, getCommonError, @@ -70,13 +71,12 @@ import { getIncreaseError, getSwapError, } from "domain/synthetics/trade/utils/validation"; -import { BigNumber } from "ethers"; +import { getMinResidualAmount } from "domain/tokens"; import longImg from "img/long.svg"; import shortImg from "img/short.svg"; import swapImg from "img/swap.svg"; import { useChainId } from "lib/chains"; import { USD_DECIMALS } from "lib/legacy"; -import { useLocalStorageSerializeKey } from "lib/localStorage"; import { formatAmount, formatAmountFree, @@ -88,61 +88,26 @@ import { limitDecimals, parseValue, } from "lib/numbers"; -import { useSafeState } from "lib/useSafeState"; +import { EMPTY_ARRAY, getByKey } from "lib/objects"; +import { museNeverExist } from "lib/types"; import useIsMetamaskMobile from "lib/wallets/useIsMetamaskMobile"; import useWallet from "lib/wallets/useWallet"; -import { ReactNode, useCallback, useEffect, useMemo, useState } from "react"; -import { IoMdSwap } from "react-icons/io"; -import { useLatest, usePrevious } from "react-use"; + +import { HighPriceImpactWarning } from "../HighPriceImpactWarning/HighPriceImpactWarning"; import { MarketCard } from "../MarketCard/MarketCard"; import { SwapCard } from "../SwapCard/SwapCard"; import { TradeFeesRow } from "../TradeFeesRow/TradeFeesRow"; import { CollateralSelectorRow } from "./CollateralSelectorRow"; import { MarketPoolSelectorRow } from "./MarketPoolSelectorRow"; import "./TradeBox.scss"; -import useUiFeeFactor from "domain/synthetics/fees/utils/useUiFeeFactor"; -import { HighPriceImpactWarning } from "../HighPriceImpactWarning/HighPriceImpactWarning"; -import ExternalLink from "components/ExternalLink/ExternalLink"; -import Tooltip from "components/Tooltip/Tooltip"; -import { museNeverExist } from "lib/types"; -import { getByKey } from "lib/objects"; -import { NATIVE_TOKEN_ADDRESS } from "config/tokens"; -import { getMinResidualAmount } from "domain/tokens"; export type Props = { - tradeType: TradeType; - tradeMode: TradeMode; - availableTradeModes: TradeMode[]; - tradeFlags: TradeFlags; - isWrapOrUnwrap: boolean; - fromTokenAddress?: string; - fromToken?: TokenData; - toTokenAddress?: string; - toToken?: TokenData; - marketAddress?: string; - marketInfo?: MarketInfo; - collateralAddress?: string; - collateralToken?: TokenData; avaialbleTokenOptions: AvailableTokenOptions; - existingPosition?: PositionInfo; - existingOrder?: OrderInfo; - positionsInfo?: PositionsInfoData; - ordersInfo?: OrdersInfoData; allowedSlippage: number; - savedIsPnlInLeverage: boolean; isHigherSlippageAllowed: boolean; shouldDisableValidation?: boolean; - marketsInfoData?: MarketsInfoData; - tokensData?: TokensData; setIsHigherSlippageAllowed: (value: boolean) => void; - onSelectFromTokenAddress: (fromTokenAddress?: string) => void; - onSelectToTokenAddress: (toTokenAddress?: string) => void; - onSelectTradeType: (tradeType: TradeType) => void; - onSelectTradeMode: (tradeMode: TradeMode) => void; setPendingTxns: (txns: any) => void; - onSelectMarketAddress: (marketAddress?: string) => void; - onSelectCollateralAddress: (collateralAddress?: string) => void; - switchTokenAddresses: () => void; }; const tradeTypeIcons = { @@ -151,43 +116,21 @@ const tradeTypeIcons = { [TradeType.Swap]: swapImg, }; +const tradeModeLabels = { + [TradeMode.Market]: t`Market`, + [TradeMode.Limit]: t`Limit`, + [TradeMode.Trigger]: t`TP/SL`, +}; + +const tradeTypeLabels = { + [TradeType.Long]: t`Long`, + [TradeType.Short]: t`Short`, + [TradeType.Swap]: t`Swap`, +}; + export function TradeBox(p: Props) { - const { - tradeMode, - tradeType, - tradeFlags, - availableTradeModes, - isWrapOrUnwrap, - tokensData, - fromTokenAddress, - fromToken, - toTokenAddress, - toToken, - marketAddress, - marketInfo, - collateralAddress, - collateralToken, - avaialbleTokenOptions, - savedIsPnlInLeverage, - positionsInfo, - existingPosition, - existingOrder, - ordersInfo, - shouldDisableValidation, - allowedSlippage, - isHigherSlippageAllowed, - marketsInfoData, - setIsHigherSlippageAllowed, - onSelectMarketAddress, - onSelectCollateralAddress, - onSelectFromTokenAddress, - onSelectToTokenAddress, - onSelectTradeMode, - onSelectTradeType, - setPendingTxns, - switchTokenAddresses, - } = p; - const { isLong, isSwap, isIncrease, isPosition, isLimit, isTrigger, isMarket } = tradeFlags; + const { avaialbleTokenOptions, shouldDisableValidation, allowedSlippage, setPendingTxns } = p; + const { openConnectModal } = useConnectModal(); const { swapTokens, @@ -197,50 +140,75 @@ export function TradeBox(p: Props) { sortedLongAndShortTokens, sortedAllMarkets, } = avaialbleTokenOptions; + const tokensData = useTokensData(); + const marketsInfoData = useMarketsInfoData(); - const tradeTypeLabels = useMemo(() => { - return { - [TradeType.Long]: t`Long`, - [TradeType.Short]: t`Short`, - [TradeType.Swap]: t`Swap`, - }; - }, []); - - const tradeModeLabels = { - [TradeMode.Market]: t`Market`, - [TradeMode.Limit]: t`Limit`, - [TradeMode.Trigger]: t`TP/SL`, - }; + const tradeFlags = useTradeboxTradeFlags(); + const { isLong, isSwap, isIncrease, isPosition, isLimit, isTrigger, isMarket } = tradeFlags; const { chainId } = useChainId(); - const { signer, account } = useWallet(); + const { account } = useWallet(); const isMetamaskMobile = useIsMetamaskMobile(); const { gasPrice } = useGasPrice(chainId); const { gasLimits } = useGasLimits(chainId); - const userReferralInfo = useUserReferralInfo(signer, chainId, account); - const { showDebugValues, savedAcceptablePriceImpactBuffer } = useSettings(); + const { showDebugValues } = useSettings(); const { data: hasOutdatedUi } = useHasOutdatedUi(); - const { minCollateralUsd, minPositionSizeUsd } = usePositionsConstants(chainId); - const uiFeeFactor = useUiFeeFactor(chainId); - const [stage, setStage] = useState<"trade" | "confirmation" | "processing">("trade"); - const [focusedInput, setFocusedInput] = useState<"from" | "to">(); - - const [fixedTriggerThresholdType, setFixedTriggerThresholdType] = useState(); - const [fixedTriggerOrderType, setFixedTriggerOrderType] = useState< - OrderType.LimitDecrease | OrderType.StopLossDecrease - >(); - - const [defaultTriggerAcceptablePriceImpactBps, setDefaultTriggerAcceptablePriceImapctBps] = useState(); - const [selectedTriggerAcceptablePriceImpactBps, setSelectedAcceptablePriceImapctBps] = useState(); - - const [fromTokenInputValue, setFromTokenInputValueRaw] = useSafeState(""); - const [toTokenInputValue, setToTokenInputValueRaw] = useSafeState(""); + const { minCollateralUsd } = usePositionsConstantsRequest(chainId); const nativeToken = getByKey(tokensData, NATIVE_TOKEN_ADDRESS); const minResidualAmount = getMinResidualAmount(nativeToken?.decimals, nativeToken?.prices.maxPrice); + const { + fromTokenInputValue, + setFromTokenInputValue: setFromTokenInputValueRaw, + toTokenInputValue, + setToTokenInputValue: setToTokenInputValueRaw, + setMarketAddress: onSelectMarketAddress, + setCollateralAddress: onSelectCollateralAddress, + setFromTokenAddress: onSelectFromTokenAddress, + setToTokenAddress: onSelectToTokenAddress, + setTradeType: onSelectTradeType, + setTradeMode: onSelectTradeMode, + stage, + setStage, + focusedInput, + setFocusedInput, + fixedTriggerThresholdType, + setFixedTriggerThresholdType, + fixedTriggerOrderType, + setFixedTriggerOrderType, + setDefaultTriggerAcceptablePriceImpactBps, + selectedTriggerAcceptablePriceImpactBps, + setSelectedAcceptablePriceImpactBps, + closeSizeInputValue, + setCloseSizeInputValue, + triggerPriceInputValue, + setTriggerPriceInputValue, + triggerRatioInputValue, + setTriggerRatioInputValue, + leverageOption, + setLeverageOption, + isLeverageEnabled, + setIsLeverageEnabled, + keepLeverage, + setKeepLeverage, + isWrapOrUnwrap, + switchTokenAddresses, + tradeMode, + tradeType, + collateralAddress, + collateralToken, + fromTokenAddress, + marketAddress, + marketInfo, + toTokenAddress, + avaialbleTradeModes: availalbleTradeModes, + } = useTradeboxState(); + const fromToken = getByKey(tokensData, fromTokenAddress); + const toToken = getByKey(tokensData, toTokenAddress); const fromTokenAmount = fromToken ? parseValue(fromTokenInputValue || "0", fromToken.decimals)! : BigNumber.from(0); + const toTokenAmount = toToken ? parseValue(toTokenInputValue || "0", toToken.decimals)! : BigNumber.from(0); const fromTokenPrice = fromToken?.prices.minPrice; const fromUsd = convertToUsd(fromTokenAmount, fromToken?.decimals, fromTokenPrice); const isNotMatchAvailableBalance = @@ -248,8 +216,6 @@ export function TradeBox(p: Props) { !fromToken.balance.eq(fromTokenAmount) && (fromToken?.isNative ? minResidualAmount && fromToken.balance.gt(minResidualAmount) : true); - const toTokenAmount = toToken ? parseValue(toTokenInputValue || "0", toToken.decimals)! : BigNumber.from(0); - const markPrice = useMemo(() => { if (!toToken) { return undefined; @@ -262,257 +228,24 @@ export function TradeBox(p: Props) { return getMarkPrice({ prices: toToken.prices, isIncrease, isLong }); }, [isIncrease, isLong, isSwap, toToken]); - const [closeSizeInputValue, setCloseSizeInputValue] = useState(""); const closeSizeUsd = parseValue(closeSizeInputValue || "0", USD_DECIMALS)!; - - const [triggerPriceInputValue, setTriggerPriceInputValue] = useState(""); const triggerPrice = parseValue(triggerPriceInputValue, USD_DECIMALS); - const [triggerRatioInputValue, setTriggerRatioInputValue] = useState(""); - const { markRatio, triggerRatio } = useMemo(() => { - if (!isSwap || !fromToken || !toToken || !fromTokenPrice || !markPrice) { - return {}; - } - - const markRatio = getTokensRatioByPrice({ - fromToken, - toToken, - fromPrice: fromTokenPrice, - toPrice: markPrice, - }); - - const triggerRatioValue = parseValue(triggerRatioInputValue, USD_DECIMALS); + const uiFeeFactor = useUiFeeFactor(); - if (!triggerRatioValue) { - return { markRatio }; - } - - const triggerRatio: TokensRatio = { - ratio: triggerRatioValue?.gt(0) ? triggerRatioValue : markRatio.ratio, - largestToken: markRatio.largestToken, - smallestToken: markRatio.smallestToken, - }; - - return { - markRatio, - triggerRatio, - }; - }, [fromToken, fromTokenPrice, isSwap, markPrice, toToken, triggerRatioInputValue]); - - const [leverageOption, setLeverageOption] = useLocalStorageSerializeKey(getLeverageKey(chainId), 2); - const leverage = BigNumber.from(parseInt(String(Number(leverageOption!) * BASIS_POINTS_DIVISOR))); - - const [isLeverageEnabled, setIsLeverageEnabled] = useLocalStorageSerializeKey(getLeverageEnabledKey(chainId), true); - const [keepLeverage, setKeepLeverage] = useLocalStorageSerializeKey(getKeepLeverageKey(chainId), true); - - const swapRoute = useSwapRoutes({ - marketsInfoData, - fromTokenAddress, - toTokenAddress: isPosition ? collateralAddress : toTokenAddress, - }); - - const swapAmounts = useMemo(() => { - if (!isSwap || !fromToken || !toToken || !fromTokenPrice) { - return undefined; - } - - if (isWrapOrUnwrap) { - const tokenAmount = focusedInput === "from" ? fromTokenAmount : toTokenAmount; - const usdAmount = convertToUsd(tokenAmount, fromToken.decimals, fromTokenPrice)!; - const price = fromTokenPrice; - - const swapAmounts: SwapAmounts = { - amountIn: tokenAmount, - usdIn: usdAmount!, - amountOut: tokenAmount, - usdOut: usdAmount!, - swapPathStats: undefined, - priceIn: price, - priceOut: price, - minOutputAmount: tokenAmount, - }; - - return swapAmounts; - } else if (focusedInput === "from") { - return getSwapAmountsByFromValue({ - tokenIn: fromToken, - tokenOut: toToken, - amountIn: fromTokenAmount, - triggerRatio: triggerRatio || markRatio, - isLimit, - findSwapPath: swapRoute.findSwapPath, - uiFeeFactor, - }); - } else { - return getSwapAmountsByToValue({ - tokenIn: fromToken, - tokenOut: toToken, - amountOut: toTokenAmount, - triggerRatio: triggerRatio || markRatio, - isLimit, - findSwapPath: swapRoute.findSwapPath, - uiFeeFactor, - }); - } - }, [ - focusedInput, - fromToken, - fromTokenAmount, - fromTokenPrice, - isLimit, - isSwap, - isWrapOrUnwrap, - markRatio, - swapRoute.findSwapPath, - toToken, - toTokenAmount, - triggerRatio, - uiFeeFactor, - ]); - - const increaseAmounts = useMemo(() => { - if (!isIncrease || !toToken || !fromToken || !collateralToken || !marketInfo) { - return undefined; - } - - return getIncreasePositionAmounts({ - marketInfo, - indexToken: toToken, - initialCollateralToken: fromToken, - collateralToken, - isLong, - initialCollateralAmount: fromTokenAmount, - indexTokenAmount: toTokenAmount, - leverage, - triggerPrice: isLimit ? triggerPrice : undefined, - position: existingPosition, - fixedAcceptablePriceImpactBps: selectedTriggerAcceptablePriceImpactBps, - acceptablePriceImpactBuffer: savedAcceptablePriceImpactBuffer, - findSwapPath: swapRoute.findSwapPath, - userReferralInfo, - uiFeeFactor, - strategy: isLeverageEnabled - ? focusedInput === "from" - ? "leverageByCollateral" - : "leverageBySize" - : "independent", - }); - }, [ - collateralToken, - existingPosition, - selectedTriggerAcceptablePriceImpactBps, - focusedInput, - fromToken, - fromTokenAmount, - isIncrease, - isLeverageEnabled, - isLimit, - isLong, - leverage, - marketInfo, - savedAcceptablePriceImpactBuffer, - swapRoute.findSwapPath, - toToken, - toTokenAmount, - triggerPrice, - userReferralInfo, - uiFeeFactor, - ]); - - const decreaseAmounts = useMemo(() => { - if (!isTrigger || !closeSizeUsd || !marketInfo || !collateralToken || !minCollateralUsd || !minPositionSizeUsd) { - return undefined; - } - - return getDecreasePositionAmounts({ - marketInfo, - collateralToken, - isLong, - position: existingPosition, - closeSizeUsd: closeSizeUsd, - keepLeverage: keepLeverage!, - triggerPrice, - fixedAcceptablePriceImpactBps: selectedTriggerAcceptablePriceImpactBps, - acceptablePriceImpactBuffer: savedAcceptablePriceImpactBuffer, - userReferralInfo, - minCollateralUsd, - minPositionSizeUsd, - uiFeeFactor, - }); - }, [ - isTrigger, - closeSizeUsd, - marketInfo, - collateralToken, - minCollateralUsd, - minPositionSizeUsd, - isLong, - existingPosition, - keepLeverage, - triggerPrice, - selectedTriggerAcceptablePriceImpactBps, - savedAcceptablePriceImpactBuffer, - userReferralInfo, - uiFeeFactor, - ]); + const swapRoute = useSwapRoutes(fromTokenAddress, isPosition ? collateralAddress : toTokenAddress); + const swapAmounts = useTradeboxSwapAmounts(); + const increaseAmounts = useTradeboxIncreasePositionAmounts(); + const decreaseAmounts = useTradeboxDecreasePositionAmounts(); + const nextPositionValuesForIncrease = useTradeboxNextPositionValuesForIncrease(); + const nextPositionValuesForDecrease = useTradeboxNextPositionValuesForDecrease(); + const selectedPosition = useTradeboxSelectedPosition(); + const existingOrder = useTradeboxExistingOrder(); + const leverage = useTradeboxLeverage(); const nextPositionValues = useMemo(() => { - if (!isPosition || !minCollateralUsd || !marketInfo || !collateralToken) { - return undefined; - } - - if (isIncrease && increaseAmounts?.acceptablePrice && fromTokenAmount.gt(0)) { - return getNextPositionValuesForIncreaseTrade({ - marketInfo, - collateralToken, - existingPosition, - isLong, - collateralDeltaUsd: increaseAmounts.collateralDeltaUsd, - collateralDeltaAmount: increaseAmounts.collateralDeltaAmount, - sizeDeltaUsd: increaseAmounts.sizeDeltaUsd, - sizeDeltaInTokens: increaseAmounts.sizeDeltaInTokens, - indexPrice: increaseAmounts.indexPrice, - showPnlInLeverage: savedIsPnlInLeverage, - minCollateralUsd, - userReferralInfo, - }); - } - - if (isTrigger && decreaseAmounts?.acceptablePrice && closeSizeUsd.gt(0)) { - return getNextPositionValuesForDecreaseTrade({ - existingPosition, - marketInfo, - collateralToken, - sizeDeltaUsd: decreaseAmounts.sizeDeltaUsd, - sizeDeltaInTokens: decreaseAmounts.sizeDeltaInTokens, - estimatedPnl: decreaseAmounts.estimatedPnl, - realizedPnl: decreaseAmounts.realizedPnl, - collateralDeltaUsd: decreaseAmounts.collateralDeltaUsd, - collateralDeltaAmount: decreaseAmounts.collateralDeltaAmount, - payedRemainingCollateralUsd: decreaseAmounts.payedRemainingCollateralUsd, - payedRemainingCollateralAmount: decreaseAmounts.payedRemainingCollateralAmount, - showPnlInLeverage: savedIsPnlInLeverage, - isLong, - minCollateralUsd, - userReferralInfo, - }); - } - }, [ - closeSizeUsd, - collateralToken, - decreaseAmounts, - existingPosition, - fromTokenAmount, - increaseAmounts, - isIncrease, - isLong, - isPosition, - isTrigger, - marketInfo, - minCollateralUsd, - savedIsPnlInLeverage, - userReferralInfo, - ]); + return tradeFlags.isIncrease ? nextPositionValuesForIncrease : nextPositionValuesForDecrease; + }, [nextPositionValuesForDecrease, nextPositionValuesForIncrease, tradeFlags.isIncrease]); const { fees, feesType, executionFee } = useMemo(() => { if (!gasLimits || !gasPrice || !tokensData) { @@ -533,6 +266,7 @@ export function TradeBox(p: Props) { positionFeeUsd: BigNumber.from(0), swapPriceImpactDeltaUsd: swapAmounts.swapPathStats.totalSwapPriceImpactDeltaUsd, positionPriceImpactDeltaUsd: BigNumber.from(0), + priceImpactDiffUsd: BigNumber.from(0), borrowingFeeUsd: BigNumber.from(0), fundingFeeUsd: BigNumber.from(0), feeDiscountUsd: BigNumber.from(0), @@ -558,8 +292,9 @@ export function TradeBox(p: Props) { positionFeeUsd: increaseAmounts.positionFeeUsd, swapPriceImpactDeltaUsd: increaseAmounts.swapPathStats?.totalSwapPriceImpactDeltaUsd || BigNumber.from(0), positionPriceImpactDeltaUsd: increaseAmounts.positionPriceImpactDeltaUsd, - borrowingFeeUsd: existingPosition?.pendingBorrowingFeesUsd || BigNumber.from(0), - fundingFeeUsd: existingPosition?.pendingFundingFeesUsd || BigNumber.from(0), + priceImpactDiffUsd: BigNumber.from(0), + borrowingFeeUsd: selectedPosition?.pendingBorrowingFeesUsd || BigNumber.from(0), + fundingFeeUsd: selectedPosition?.pendingFundingFeesUsd || BigNumber.from(0), feeDiscountUsd: increaseAmounts.feeDiscountUsd, swapProfitFeeUsd: BigNumber.from(0), uiFeeFactor, @@ -578,12 +313,13 @@ export function TradeBox(p: Props) { return { fees: getTradeFees({ isIncrease: false, - initialCollateralUsd: existingPosition?.collateralUsd || BigNumber.from(0), + initialCollateralUsd: selectedPosition?.collateralUsd || BigNumber.from(0), sizeDeltaUsd: decreaseAmounts.sizeDeltaUsd, swapSteps: [], positionFeeUsd: decreaseAmounts.positionFeeUsd, swapPriceImpactDeltaUsd: BigNumber.from(0), positionPriceImpactDeltaUsd: decreaseAmounts.positionPriceImpactDeltaUsd, + priceImpactDiffUsd: decreaseAmounts.priceImpactDiffUsd, borrowingFeeUsd: decreaseAmounts.borrowingFeeUsd, fundingFeeUsd: decreaseAmounts.fundingFeeUsd, feeDiscountUsd: decreaseAmounts.feeDiscountUsd, @@ -597,25 +333,27 @@ export function TradeBox(p: Props) { return {}; }, [ - chainId, - decreaseAmounts, - existingPosition, gasLimits, gasPrice, - increaseAmounts, - isIncrease, + tokensData, isSwap, - isTrigger, swapAmounts, - tokensData, + isIncrease, + increaseAmounts, + isTrigger, + decreaseAmounts, uiFeeFactor, + chainId, + selectedPosition?.pendingBorrowingFeesUsd, + selectedPosition?.pendingFundingFeesUsd, + selectedPosition?.collateralUsd, ]); const priceImpactWarningState = usePriceImpactWarningState({ positionPriceImpact: fees?.positionPriceImpact, swapPriceImpact: fees?.swapPriceImpact, - tradeFlags, place: "tradeBox", + tradeFlags, }); const setIsHighPositionImpactAcceptedRef = useLatest(priceImpactWarningState.setIsHighPositionImpactAccepted); @@ -643,16 +381,13 @@ export function TradeBox(p: Props) { ); const marketsOptions = useAvailableMarketsOptions({ - marketsInfoData, isIncrease, disable: !isPosition, indexToken: toToken, isLong, increaseSizeUsd: increaseAmounts?.sizeDeltaUsd, - positionsInfo, - ordersInfo, hasExistingOrder: Boolean(existingOrder), - hasExistingPosition: Boolean(existingPosition), + hasExistingPosition: Boolean(selectedPosition), }); const { availableMarkets } = marketsOptions; @@ -669,6 +404,15 @@ export function TradeBox(p: Props) { }, [marketInfo]); const swapOutLiquidity = swapRoute.maxSwapLiquidity; + const triggerRatioValue = useMemo(() => parseValue(triggerRatioInputValue, USD_DECIMALS), [triggerRatioInputValue]); + + const { markRatio, triggerRatio } = useTradeRatios({ + fromTokenAddress, + toTokenAddress, + tradeMode, + tradeType, + triggerRatioValue, + }); const { longLiquidity, shortLiquidity, isOutPositionLiquidity } = useMemo(() => { if (!marketInfo || !isIncrease) { @@ -724,7 +468,7 @@ export function TradeBox(p: Props) { targetCollateralToken: collateralToken, collateralUsd: increaseAmounts?.collateralDeltaUsd, sizeDeltaUsd: increaseAmounts?.sizeDeltaUsd, - existingPosition, + existingPosition: selectedPosition, fees, swapPathStats: increaseAmounts?.swapPathStats, collateralLiquidity: swapOutLiquidity, @@ -736,7 +480,7 @@ export function TradeBox(p: Props) { triggerPrice, priceImpactWarning: priceImpactWarningState, isLimit, - nextPositionValues, + nextPositionValues: nextPositionValuesForIncrease, }); } else if (isTrigger) { tradeError = getDecreaseError({ @@ -745,10 +489,10 @@ export function TradeBox(p: Props) { sizeDeltaUsd: decreaseAmounts?.sizeDeltaUsd, triggerPrice, markPrice, - existingPosition, + existingPosition: selectedPosition, isContractAccount: false, - receiveToken: existingPosition?.collateralToken, - nextPositionValues, + receiveToken: selectedPosition?.collateralToken, + nextPositionValues: nextPositionValuesForDecrease, isLong, isTrigger: true, minCollateralUsd, @@ -799,6 +543,7 @@ export function TradeBox(p: Props) { swapAmounts?.swapPathStats, toTokenAmount, swapOutLiquidity, + priceImpactWarningState, isLimit, isWrapOrUnwrap, triggerRatio, @@ -810,17 +555,17 @@ export function TradeBox(p: Props) { increaseAmounts?.sizeDeltaUsd, increaseAmounts?.swapPathStats, collateralToken, - existingPosition, + selectedPosition, minCollateralUsd, longLiquidity, shortLiquidity, isLong, markPrice, triggerPrice, - priceImpactWarningState, - nextPositionValues, + nextPositionValuesForIncrease, closeSizeUsd, decreaseAmounts?.sizeDeltaUsd, + nextPositionValuesForDecrease, stage, fixedTriggerThresholdType, ]); @@ -859,7 +604,6 @@ export function TradeBox(p: Props) { isSwap, toToken?.symbol, tradeType, - tradeTypeLabels, ]); function onSubmit() { @@ -876,13 +620,13 @@ export function TradeBox(p: Props) { ) { setFixedTriggerOrderType(decreaseAmounts.triggerOrderType); setFixedTriggerThresholdType(decreaseAmounts.triggerThresholdType); - setSelectedAcceptablePriceImapctBps(decreaseAmounts.recommendedAcceptablePriceDeltaBps.abs()); - setDefaultTriggerAcceptablePriceImapctBps(decreaseAmounts.recommendedAcceptablePriceDeltaBps.abs()); + setSelectedAcceptablePriceImpactBps(decreaseAmounts.recommendedAcceptablePriceDeltaBps.abs()); + setDefaultTriggerAcceptablePriceImpactBps(decreaseAmounts.recommendedAcceptablePriceDeltaBps.abs()); } if (isLimit && increaseAmounts?.acceptablePrice) { - setSelectedAcceptablePriceImapctBps(increaseAmounts.acceptablePriceDeltaBps.abs()); - setDefaultTriggerAcceptablePriceImapctBps(increaseAmounts.acceptablePriceDeltaBps.abs()); + setSelectedAcceptablePriceImpactBps(increaseAmounts.acceptablePriceDeltaBps.abs()); + setDefaultTriggerAcceptablePriceImpactBps(increaseAmounts.acceptablePriceDeltaBps.abs()); } setStage("confirmation"); @@ -942,6 +686,7 @@ export function TradeBox(p: Props) { isIncrease, isSwap, prevIsISwap, + setFocusedInput, setFromTokenInputValue, setToTokenInputValue, swapAmounts, @@ -982,7 +727,6 @@ export function TradeBox(p: Props) { marketsOptions.marketWithPosition, marketsOptions.maxLiquidityMarket, marketsOptions.minPriceImpactMarket, - onSelectCollateralAddress, onSelectMarketAddress, ] ); @@ -1005,7 +749,7 @@ export function TradeBox(p: Props) { function resetTriggerPrice() { setTriggerPriceInputValue(""); }, - [toTokenAddress, tradeMode] + [setTriggerPriceInputValue, toTokenAddress, tradeMode] ); function onSwitchTokens() { @@ -1016,12 +760,18 @@ export function TradeBox(p: Props) { } const onConfirmationClose = useCallback(() => { - setSelectedAcceptablePriceImapctBps(undefined); - setDefaultTriggerAcceptablePriceImapctBps(undefined); + setSelectedAcceptablePriceImpactBps(undefined); + setDefaultTriggerAcceptablePriceImpactBps(undefined); setFixedTriggerOrderType(undefined); setFixedTriggerThresholdType(undefined); setStage("trade"); - }, []); + }, [ + setDefaultTriggerAcceptablePriceImpactBps, + setFixedTriggerOrderType, + setFixedTriggerThresholdType, + setSelectedAcceptablePriceImpactBps, + setStage, + ]); const onConfirmed = useCallback(() => { if (isMarket) { @@ -1029,7 +779,7 @@ export function TradeBox(p: Props) { return; } setStage("trade"); - }, [isMarket]); + }, [isMarket, setStage]); if (showDebugValues) { const swapPathStats = swapAmounts?.swapPathStats || increaseAmounts?.swapPathStats; @@ -1180,16 +930,16 @@ export function TradeBox(p: Props) { return ( setCloseSizeInputValue(e.target.value)} - onClickTopRightLabel={() => setCloseSizeInputValue(formatAmount(existingPosition?.sizeInUsd, USD_DECIMALS, 2))} - showMaxButton={existingPosition?.sizeInUsd.gt(0) && !closeSizeUsd?.eq(existingPosition.sizeInUsd)} - onClickMax={() => setCloseSizeInputValue(formatAmount(existingPosition?.sizeInUsd, USD_DECIMALS, 2))} - showPercentSelector={existingPosition?.sizeInUsd.gt(0)} + onClickTopRightLabel={() => setCloseSizeInputValue(formatAmount(selectedPosition?.sizeInUsd, USD_DECIMALS, 2))} + showMaxButton={selectedPosition?.sizeInUsd.gt(0) && !closeSizeUsd?.eq(selectedPosition.sizeInUsd)} + onClickMax={() => setCloseSizeInputValue(formatAmount(selectedPosition?.sizeInUsd, USD_DECIMALS, 2))} + showPercentSelector={selectedPosition?.sizeInUsd.gt(0)} onPercentChange={(percent) => - setCloseSizeInputValue(formatAmount(existingPosition?.sizeInUsd.mul(percent).div(100), USD_DECIMALS, 2)) + setCloseSizeInputValue(formatAmount(selectedPosition?.sizeInUsd.mul(percent).div(100), USD_DECIMALS, 2)) } > USD @@ -1259,7 +1009,12 @@ export function TradeBox(p: Props) { {isLeverageEnabled && ( - + )} )} @@ -1272,7 +1027,7 @@ export function TradeBox(p: Props) { label={t`Market`} className="SwapBox-info-dropdown" selectedIndexName={toToken ? getMarketIndexName({ indexToken: toToken, isSpotOnly: false }) : undefined} - markets={sortedAllMarkets || []} + markets={sortedAllMarkets ?? EMPTY_ARRAY} isSideMenu onSelectMarket={(indexName, marketInfo) => onSelectToTokenAddress(marketInfo.indexToken.address)} /> @@ -1285,7 +1040,7 @@ export function TradeBox(p: Props) { indexToken={toToken} marketsOptions={marketsOptions} hasExistingOrder={Boolean(existingOrder)} - hasExistingPosition={Boolean(existingPosition)} + hasExistingPosition={Boolean(selectedPosition)} isOutPositionLiquidity={isOutPositionLiquidity} currentPriceImpactBps={increaseAmounts?.acceptablePriceDeltaBps} onSelectMarketAddress={onSelectMarketAddress} @@ -1297,47 +1052,83 @@ export function TradeBox(p: Props) { availableCollaterals={availableCollaterals} marketsOptions={marketsOptions} hasExistingOrder={Boolean(existingOrder)} - hasExistingPosition={Boolean(existingPosition)} + hasExistingPosition={Boolean(selectedPosition)} onSelectCollateralAddress={onSelectCollateralAddress} isMarket={isMarket} /> - - {isTrigger && existingPosition?.leverage && ( - - - Keep leverage at {formatLeverage(existingPosition.leverage)} - - - )} ); } + function renderLeverageInfo() { + if (isIncrease) { + return ( + <> + + ) : ( + formatLeverage(isLeverageEnabled ? leverage : increaseAmounts?.estimatedLeverage) || "-" + ) + } + /> +
    + + ); + } else if (isTrigger && selectedPosition) { + let leverageValue: ReactNode = "-"; + + if (decreaseAmounts?.isFullClose) { + leverageValue = t`NA`; + } else if (selectedPosition.sizeInUsd.eq(decreaseAmounts?.sizeDeltaUsd || 0)) { + leverageValue = "-"; + } else { + leverageValue = ( + + ); + } + + const keepLeverageChecked = decreaseAmounts?.isFullClose ? false : keepLeverage ?? false; + + return ( + <> + + {selectedPosition?.leverage && ( + + + Keep leverage at {formatLeverage(selectedPosition.leverage)} + + + )} +
    + + ); + } + } + function renderIncreaseOrderInfo() { return ( <> - - ) : ( - formatLeverage(isLeverageEnabled ? leverage : increaseAmounts?.estimatedLeverage) || "-" - ) - } - /> - - {existingPosition && ( + {selectedPosition && ( )} + + ); + } - {existingPosition?.sizeInUsd.gt(0) && ( + function renderExistingPositionInfo() { + return ( + <> + {selectedPosition?.sizeInUsd.gt(0) && ( } /> )} - - {existingPosition && ( - - } - /> - )} - - {existingPosition && ( - - ) - } - /> - )} - - {existingPosition && ( + {!isIncrease && ( )} + + } + /> ); } @@ -1552,7 +1328,7 @@ export function TradeBox(p: Props) { /> )} - {isIncrease && renderIncreaseOrderInfo()} - {isTrigger && renderTriggerOrderInfo()} + {renderLeverageInfo()} -
    + {(isIncrease || isTrigger) && ( + <> + {isIncrease && renderIncreaseOrderInfo()} + {isTrigger && renderTriggerOrderInfo()} +
    + + )} - {feesType && } + {((selectedPosition && !isSwap) || feesType) && ( + <> + {selectedPosition && !isSwap && renderExistingPositionInfo()} + {feesType && } +
    + + )} - {isTrigger && existingPosition && decreaseAmounts?.receiveUsd && ( - + {isTrigger && selectedPosition && decreaseAmounts?.receiveUsd && ( + <> + +
    + )} {priceImpactWarningState.shouldShowWarning && ( <> -
    +
    )}
    @@ -1623,43 +1413,25 @@ export function TradeBox(p: Props) { ); diff --git a/src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx b/src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx index d1ae99e54b..4e9137ee9d 100644 --- a/src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +++ b/src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx @@ -21,7 +21,8 @@ import { import { ReactNode, useMemo } from "react"; import "./TradeFeesRow.scss"; import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; -import { useSettings } from "context/SettingsContext/SettingsContextProvider"; +import { useExecutionFeeBufferBps } from "context/SyntheticsStateContext/hooks/settingsHooks"; +import { getPositiveOrNegativeClass } from "lib/utils"; type Props = { totalFees?: FeeItem; @@ -31,6 +32,7 @@ type Props = { swapPriceImpact?: FeeItem; positionFee?: FeeItem; positionPriceImpact?: FeeItem; + priceImpactDiff?: FeeItem; executionFee?: ExecutionFee; borrowFee?: FeeItem; fundingFee?: FeeItem; @@ -51,24 +53,53 @@ type FeeRow = { }; export function TradeFeesRow(p: Props) { - const settings = useSettings(); + const executionFeeBufferBps = useExecutionFeeBufferBps(); const { chainId } = useChainId(); const tradingIncentives = useTradingIncentives(); const shouldShowRebate = p.shouldShowRebate ?? true; const rebateIsApplicable = shouldShowRebate && p.positionFee?.deltaUsd.lt(0) && p.feesType !== "swap"; + const [fullPositionPriceImpact, hasRebates] = mergePositionPriceImpactWithPriceImpactDiff( + p.feesType, + p.positionPriceImpact, + p.priceImpactDiff + ); + const rebatesMessage = hasRebates ? ( + + Price Impact Rebates for closing trades are claimable under the Claims tab.{" "} + + Read more + + . + + ) : undefined; + const feeRows: FeeRow[] = useMemo(() => { - const positionPriceImpactRow = p.positionPriceImpact?.deltaUsd.abs().gt(0) + const positionPriceImpactRow = fullPositionPriceImpact?.deltaUsd.abs().gt(0) ? { id: "positionPriceImpact", label: ( <>
    {t`Position Price Impact`}:
    -
    ({formatPercentage(p.positionPriceImpact.bps.abs())} of position size)
    +
    ({formatPercentage(fullPositionPriceImpact.bps.abs())} of position size)
    + + ), + value: formatDeltaUsd(fullPositionPriceImpact.deltaUsd), + className: getPositiveOrNegativeClass(fullPositionPriceImpact.deltaUsd, "text-green"), + } + : undefined; + + const priceImpactDiffUsd = p.priceImpactDiff?.deltaUsd.abs().gt(0) + ? { + id: "priceImpactDiff", + label: ( + <> +
    {t`Price Impact Rebates`}:
    +
    ({formatPercentage(p.priceImpactDiff.bps.abs())} of position size)
    ), - value: formatDeltaUsd(p.positionPriceImpact.deltaUsd), - className: p.positionPriceImpact.deltaUsd.gte(0) ? "text-green" : "text-red", + value: formatDeltaUsd(p.priceImpactDiff.deltaUsd), + className: getPositiveOrNegativeClass(p.priceImpactDiff.deltaUsd, "text-green"), } : undefined; @@ -82,7 +113,7 @@ export function TradeFeesRow(p: Props) { ), value: formatDeltaUsd(p.swapPriceImpact.deltaUsd), - className: p.swapPriceImpact.deltaUsd.gte(0) ? "text-green" : "text-red", + className: getPositiveOrNegativeClass(p.swapPriceImpact.deltaUsd, "text-green"), } : undefined; @@ -101,7 +132,7 @@ export function TradeFeesRow(p: Props) { ), value: formatDeltaUsd(swap.deltaUsd), - className: swap.deltaUsd.gte(0) ? "text-green" : "text-red", + className: getPositiveOrNegativeClass(swap.deltaUsd, "text-green"), })) || []; const swapProfitFeeRow = p.swapProfitFee?.deltaUsd.abs().gt(0) @@ -114,7 +145,7 @@ export function TradeFeesRow(p: Props) { ), value: formatDeltaUsd(p.swapProfitFee.deltaUsd), - className: p.swapProfitFee.deltaUsd.gte(0) ? "text-green" : "text-red", + className: getPositiveOrNegativeClass(p.swapProfitFee.deltaUsd, "text-green"), } : undefined; @@ -129,7 +160,7 @@ export function TradeFeesRow(p: Props) { ), value: formatDeltaUsd(p.positionFee.deltaUsd), - className: p.positionFee.deltaUsd.gte(0) ? "text-green" : "text-red", + className: getPositiveOrNegativeClass(p.positionFee.deltaUsd, "text-green"), } : undefined; @@ -186,7 +217,7 @@ export function TradeFeesRow(p: Props) { ), value: formatDeltaUsd(p.borrowFee.deltaUsd), - className: p.borrowFee.deltaUsd.gte(0) ? "text-green" : "text-red", + className: getPositiveOrNegativeClass(p.borrowFee.deltaUsd, "text-green"), } : undefined; @@ -200,7 +231,7 @@ export function TradeFeesRow(p: Props) { ), value: formatDeltaUsd(p.fundingFee.deltaUsd), - className: p.fundingFee.deltaUsd.gte(0) ? "text-green" : "text-red", + className: getPositiveOrNegativeClass(p.fundingFee.deltaUsd, "text-green"), } : undefined; @@ -281,6 +312,7 @@ export function TradeFeesRow(p: Props) { if (p.feesType === "decrease") { return [ positionPriceImpactRow, + priceImpactDiffUsd, swapPriceImpactRow, borrowFeeRow, fundingFeeRow, @@ -301,7 +333,8 @@ export function TradeFeesRow(p: Props) { return []; }, [ - p.positionPriceImpact, + fullPositionPriceImpact, + p.priceImpactDiff, p.swapPriceImpact, p.swapFees, p.swapProfitFee, @@ -359,11 +392,11 @@ export function TradeFeesRow(p: Props) { }, [rebateIsApplicable, tradingIncentives]); const maxExecutionFeeText = useMemo(() => { - if (settings.executionFeeBufferBps !== undefined) { - const bps = settings.executionFeeBufferBps; + if (executionFeeBufferBps !== undefined) { + const bps = executionFeeBufferBps; return roundToTwoDecimals((bps / BASIS_POINTS_DIVISOR) * 100); } - }, [settings.executionFeeBufferBps]); + }, [executionFeeBufferBps]); return ( ))} + {hasRebates && ( + <> +
    + {rebatesMessage} + + )} {incentivesBottomText &&
    } {incentivesBottomText}
    @@ -423,3 +462,21 @@ export function TradeFeesRow(p: Props) { /> ); } + +function mergePositionPriceImpactWithPriceImpactDiff( + feesType: TradeFeesType, + positionPriceImpact: FeeItem | undefined, + priceImpactDiff: FeeItem | undefined +): [fullPositionPriceImpact: FeeItem | undefined, hasRebates: boolean] { + if (feesType !== "decrease" || !positionPriceImpact || !priceImpactDiff || priceImpactDiff.deltaUsd.lte(0)) { + return [positionPriceImpact, false]; + } + + return [ + { + bps: positionPriceImpact.bps.add(priceImpactDiff.bps.mul(-1)), + deltaUsd: positionPriceImpact.deltaUsd.add(priceImpactDiff.deltaUsd.mul(-1)), + }, + true, + ]; +} diff --git a/src/components/Synthetics/TradeHistory/TradeHistory.tsx b/src/components/Synthetics/TradeHistory/TradeHistory.tsx index 8b9ce9cf17..d23dd4c81d 100644 --- a/src/components/Synthetics/TradeHistory/TradeHistory.tsx +++ b/src/components/Synthetics/TradeHistory/TradeHistory.tsx @@ -3,9 +3,7 @@ import { useTradeHistory } from "domain/synthetics/tradeHistory"; import { useChainId } from "lib/chains"; import { TradeHistoryRow } from "../TradeHistoryRow/TradeHistoryRow"; import { useEffect } from "react"; -import { usePositionsConstants } from "domain/synthetics/positions/usePositionsConstants"; -import { MarketsInfoData } from "domain/synthetics/markets"; -import { TokensData } from "domain/synthetics/tokens"; +import { usePositionsConstantsRequest } from "domain/synthetics/positions/usePositionsConstants"; import usePagination from "components/Referrals/usePagination"; import Pagination from "components/Pagination/Pagination"; import { TRADE_HISTORY_PER_PAGE } from "config/ui"; @@ -15,17 +13,15 @@ const ENTITIES_PER_PAGE = 25; type Props = { shouldShowPaginationButtons: boolean; - marketsInfoData?: MarketsInfoData; - tokensData?: TokensData; account: string | null | undefined; forAllAccounts?: boolean; }; export function TradeHistory(p: Props) { - const { shouldShowPaginationButtons, marketsInfoData, tokensData, forAllAccounts, account } = p; + const { shouldShowPaginationButtons, forAllAccounts, account } = p; const { chainId } = useChainId(); - const { minCollateralUsd } = usePositionsConstants(chainId); + const { minCollateralUsd } = usePositionsConstantsRequest(chainId); const { tradeActions, isLoading: isHistoryLoading, @@ -34,8 +30,6 @@ export function TradeHistory(p: Props) { } = useTradeHistory(chainId, { account, forAllAccounts, - marketsInfoData, - tokensData, pageSize: PAGE_SIZE, }); diff --git a/src/components/Synthetics/TradeHistoryRow/TradeHistoryRow.tsx b/src/components/Synthetics/TradeHistoryRow/TradeHistoryRow.tsx index 8c6bd414ed..00a234d60c 100644 --- a/src/components/Synthetics/TradeHistoryRow/TradeHistoryRow.tsx +++ b/src/components/Synthetics/TradeHistoryRow/TradeHistoryRow.tsx @@ -69,7 +69,7 @@ function getPositionOrderMessage(tradeAction: PositionTradeAction, minCollateral ) : null} {message.tooltipRows?.map((props) => ( - + ))} {message.tooltipFooter ? ( diff --git a/src/components/Synthetics/TradeHistoryRow/utils.spec.ts b/src/components/Synthetics/TradeHistoryRow/utils.spec.ts index d4ddcd8ad1..6afa91a538 100644 --- a/src/components/Synthetics/TradeHistoryRow/utils.spec.ts +++ b/src/components/Synthetics/TradeHistoryRow/utils.spec.ts @@ -190,10 +190,10 @@ describe("TradeHistoryRow helpers", () => { expect(formatSwapMessage(executeSwap)).toEqual("Execute Market Swap: 1,080.6325 USDC for 1.1196 ETH"); // LIMIT SWAPS expect(formatSwapMessage(executeOrderSwap)).toEqual( - "Execute Limit Swap: 0.3000 WETH for 0.3698 BTC, Price: 1.2329 WETH / BTC" + "Execute Limit Swap: 0.3000 WETH for 0.3698 BTC, Price: 0.8110 WETH / BTC" ); expect(formatSwapMessage(failedSwap)).toEqual( - "Limit Swap Execution Failed: 0.3000 WETH for 0.1326 BTC, Price: 0.4422 WETH / BTC" + "Limit Swap Execution Failed: 0.3000 WETH for 0.1326 BTC, Price: 2.2613 WETH / BTC" ); }); }); diff --git a/src/components/Synthetics/TradeHistoryRow/utils.ts b/src/components/Synthetics/TradeHistoryRow/utils.ts index a5b2f8792e..66fc2402e2 100644 --- a/src/components/Synthetics/TradeHistoryRow/utils.ts +++ b/src/components/Synthetics/TradeHistoryRow/utils.ts @@ -259,7 +259,7 @@ export const formatSwapMessage = (tradeAction: SwapTradeAction): string => { ? [fromTokenInfo, toTokenInfo] : [toTokenInfo, fromTokenInfo]; - const ratioText = tokensRatio.ratio.gt(0) ? getExchangeRateDisplay(tokensRatio?.ratio, largest, smallest) : "0"; + const ratioText = tokensRatio.ratio.gt(0) ? getExchangeRateDisplay(tokensRatio?.ratio, smallest, largest) : "0"; return tradeAction.eventName === TradeActionType.OrderFrozen ? t`${orderTypeName} Swap Execution Failed: ${fromText} for ${toText}, Price: ${ratioText}` diff --git a/src/components/TVChartContainer/TVChartContainer.tsx b/src/components/TVChartContainer/TVChartContainer.tsx index b16a9ad919..851e34897b 100644 --- a/src/components/TVChartContainer/TVChartContainer.tsx +++ b/src/components/TVChartContainer/TVChartContainer.tsx @@ -9,7 +9,7 @@ import { getObjectKeyFromValue } from "domain/tradingview/utils"; import { BigNumber } from "ethers"; import { USD_DECIMALS } from "lib/legacy"; import { formatAmount } from "lib/numbers"; -import { useCallback, useEffect, useRef, useState } from "react"; +import { CSSProperties, useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useLocalStorage, useMedia } from "react-use"; import { ChartData, IChartingLibraryWidget, IPositionLineAdapter } from "../../charting_library"; import { SaveLoadAdapter } from "./SaveLoadAdapter"; @@ -195,14 +195,15 @@ export default function TVChartContainer({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [chainId, dataProvider]); + const style = useMemo( + () => ({ visibility: !chartDataLoading ? "visible" : "hidden" }), + [chartDataLoading] + ); + return (
    {chartDataLoading && } -
    +
    ); } diff --git a/src/components/ToggleSwitch/ToggleSwitch.scss b/src/components/ToggleSwitch/ToggleSwitch.scss index 89ef65c1a1..a363a271cd 100644 --- a/src/components/ToggleSwitch/ToggleSwitch.scss +++ b/src/components/ToggleSwitch/ToggleSwitch.scss @@ -28,6 +28,11 @@ &.checked .handle { left: 14px; } + + &.disabled { + cursor: not-allowed; + opacity: 0.5; + } } .Switch-toggle-wrapper { diff --git a/src/components/ToggleSwitch/ToggleSwitch.tsx b/src/components/ToggleSwitch/ToggleSwitch.tsx index 1c2418738c..69aea9e2b8 100644 --- a/src/components/ToggleSwitch/ToggleSwitch.tsx +++ b/src/components/ToggleSwitch/ToggleSwitch.tsx @@ -1,20 +1,31 @@ -import "./ToggleSwitch.scss"; -import { ReactNode } from "react"; import cx from "classnames"; +import type { ReactNode } from "react"; + +import "./ToggleSwitch.scss"; type Props = { isChecked: boolean; setIsChecked: (value: boolean) => void; className?: string; children?: ReactNode; + disabled?: boolean; }; -export default function ToggleSwitch({ isChecked, setIsChecked, className, children }: Props) { +export default function ToggleSwitch({ isChecked, setIsChecked, className, disabled, children }: Props) { const classNames = cx("Switch-toggle-wrapper", className); + + const handleToggle = () => { + if (disabled) { + return; + } + + setIsChecked(!isChecked); + }; + return (
    {children} -
    setIsChecked(!isChecked)}> +
    diff --git a/src/components/TokenCard/TokenCard.js b/src/components/TokenCard/TokenCard.tsx similarity index 86% rename from src/components/TokenCard/TokenCard.js rename to src/components/TokenCard/TokenCard.tsx index a3d08dc3b1..f6c8b3876a 100644 --- a/src/components/TokenCard/TokenCard.js +++ b/src/components/TokenCard/TokenCard.tsx @@ -17,12 +17,13 @@ import BannerButton from "components/Banner/BannerButton"; import { useMarketTokensAPR } from "domain/synthetics/markets/useMarketTokensAPR"; import { mergeWith } from "lodash"; import { formatPercentage } from "lib/numbers"; +import type { MarketTokensAPRData } from "domain/synthetics/markets/types"; const glpIcon = getIcon("common", "glp"); const gmxIcon = getIcon("common", "gmx"); const gmIcon = getIcon("common", "gm"); -function calculateMaxApr(apr, incentiveApr) { +function calculateMaxApr(apr: MarketTokensAPRData, incentiveApr: MarketTokensAPRData) { const totalApr = mergeWith({}, apr, incentiveApr, (aprValue, incentiveAprValue) => aprValue?.add(incentiveAprValue)); const aprValues = Object.values(totalApr || {}); @@ -31,7 +32,12 @@ function calculateMaxApr(apr, incentiveApr) { return maxApr; } -export default function TokenCard({ showRedirectModal, redirectPopupTimestamp }) { +type Props = { + showRedirectModal?: (to: string) => void; + redirectPopupTimestamp?: number; +}; + +export default function TokenCard({ showRedirectModal, redirectPopupTimestamp }: Props) { const isHome = isHomeSite(); const { chainId } = useChainId(); const { active } = useWallet(); @@ -73,7 +79,7 @@ export default function TokenCard({ showRedirectModal, redirectPopupTimestamp }) ); const BuyLink = ({ className, to, children, network }) => { - if (isHome && showRedirectModal) { + if (isHome && showRedirectModal && redirectPopupTimestamp !== undefined) { return (
    - Arbitrum APR: ,{" "} - Avalanche APR: + Arbitrum APR:{" "} + ,{" "} + Avalanche APR:{" "} +
    - Buy on Arbitrum + View on Arbitrum - Buy on Avalanche + View on Avalanche
    @@ -155,11 +163,11 @@ export default function TokenCard({ showRedirectModal, redirectPopupTimestamp })
    - Buy on Arbitrum + View on Arbitrum - Buy on Avalanche + View on Avalanche
    - Buy on Arbitrum + View on Arbitrum - Buy on Avalanche + View on Avalanche
    ); } + +function APRRange({ chainId, minLabel, maxLabel }) { + return ( + <> + - + + ); +} diff --git a/src/components/TokenSelector/TokenSelector.tsx b/src/components/TokenSelector/TokenSelector.tsx index 64d1057f88..6f75f06a7a 100644 --- a/src/components/TokenSelector/TokenSelector.tsx +++ b/src/components/TokenSelector/TokenSelector.tsx @@ -37,7 +37,6 @@ type Props = { showSymbolImage?: boolean; showNewCaret?: boolean; getTokenState?: (info: TokenInfo) => TokenState | undefined; - disableBodyScrollLock?: boolean; onSelectToken: (token: Token) => void; extendedSortSequence?: string[] | undefined; }; diff --git a/src/components/Tooltip/Tooltip.scss b/src/components/Tooltip/Tooltip.scss index af00fe03b7..1b3511ea1d 100644 --- a/src/components/Tooltip/Tooltip.scss +++ b/src/components/Tooltip/Tooltip.scss @@ -98,6 +98,16 @@ background: #252740; } } +.Tooltip-popup.right-center { + left: 3rem; + top: -50%; + &::after { + display: block; + left: -4px; + top: 50%; + background: #252740; + } +} .Tooltip-popup.left-top { left: 0; diff --git a/src/components/Tooltip/Tooltip.tsx b/src/components/Tooltip/Tooltip.tsx index b69735f56f..98353210a5 100644 --- a/src/components/Tooltip/Tooltip.tsx +++ b/src/components/Tooltip/Tooltip.tsx @@ -2,9 +2,7 @@ import cx from "classnames"; import { useCallback, useState, useRef, MouseEvent, ReactNode } from "react"; import { IS_TOUCH } from "config/env"; import "./Tooltip.scss"; - -const OPEN_DELAY = 0; -const CLOSE_DELAY = 100; +import { TOOLTIP_CLOSE_DELAY, TOOLTIP_OPEN_DELAY } from "config/ui"; export type TooltipPosition = | "left-bottom" @@ -12,6 +10,7 @@ export type TooltipPosition = | "left-top" | "right-top" | "right" + | "right-center" | "center-bottom" | "center-top"; @@ -24,6 +23,8 @@ type Props = { disableHandleStyle?: boolean; handleClassName?: string; isHandlerDisabled?: boolean; + openDelay?: number; + closeDelay?: number; }; export default function Tooltip(props: Props) { @@ -44,9 +45,9 @@ export default function Tooltip(props: Props) { intervalOpenRef.current = setTimeout(() => { setVisible(true); intervalOpenRef.current = null; - }, OPEN_DELAY); + }, props.openDelay ?? TOOLTIP_OPEN_DELAY); } - }, [setVisible, intervalCloseRef, intervalOpenRef, trigger]); + }, [setVisible, trigger, props.openDelay]); const onMouseClick = useCallback(() => { if (trigger !== "click" && !IS_TOUCH) return; @@ -60,18 +61,18 @@ export default function Tooltip(props: Props) { } setVisible(true); - }, [setVisible, intervalCloseRef, trigger]); + }, [setVisible, trigger]); const onMouseLeave = useCallback(() => { intervalCloseRef.current = setTimeout(() => { setVisible(false); intervalCloseRef.current = null; - }, CLOSE_DELAY); + }, props.closeDelay ?? TOOLTIP_CLOSE_DELAY); if (intervalOpenRef.current) { clearInterval(intervalOpenRef.current); intervalOpenRef.current = null; } - }, [setVisible, intervalCloseRef]); + }, [setVisible, props.closeDelay]); const onHandleClick = useCallback((event: MouseEvent) => { event.preventDefault(); diff --git a/src/components/Tooltip/TooltipWithPortal.tsx b/src/components/Tooltip/TooltipWithPortal.tsx index b2c1a991c2..2509ddd6cd 100644 --- a/src/components/Tooltip/TooltipWithPortal.tsx +++ b/src/components/Tooltip/TooltipWithPortal.tsx @@ -1,16 +1,17 @@ -import React, { MouseEvent, useCallback, useRef, useState } from "react"; +import React, { CSSProperties, MouseEvent, PropsWithChildren, useCallback, useMemo, useRef, useState } from "react"; import cx from "classnames"; import "./Tooltip.scss"; import { IS_TOUCH } from "config/env"; import Portal from "../Common/Portal"; import { TooltipPosition } from "./Tooltip"; +import { TOOLTIP_CLOSE_DELAY, TOOLTIP_OPEN_DELAY } from "config/ui"; -const OPEN_DELAY = 0; -const CLOSE_DELAY = 100; - -type Props = { - handle: React.ReactNode; +type Props = PropsWithChildren<{ + /** + * Takes precedence over `children` + */ + handle?: React.ReactNode; renderContent: () => React.ReactNode; position?: TooltipPosition; trigger?: string; @@ -21,9 +22,11 @@ type Props = { isHandlerDisabled?: boolean; fitHandleWidth?: boolean; closeOnDoubleClick?: boolean; - isInsideModal?: boolean; + openDelay?: number; + closeDelay?: number; shouldStopPropagation?: boolean; -}; + disabled?: boolean; +}>; type Coords = { height?: number; @@ -70,10 +73,10 @@ export default function TooltipWithPortal(props: Props) { intervalOpenRef.current = setTimeout(() => { setVisible(true); intervalOpenRef.current = null; - }, OPEN_DELAY); + }, props.openDelay ?? TOOLTIP_OPEN_DELAY); } updateTooltipCoords(); - }, [setVisible, intervalCloseRef, intervalOpenRef, trigger, updateTooltipCoords]); + }, [setVisible, trigger, updateTooltipCoords, props.openDelay]); const onMouseClick = useCallback( (event: MouseEvent) => { @@ -104,19 +107,21 @@ export default function TooltipWithPortal(props: Props) { intervalCloseRef.current = setTimeout(() => { setVisible(false); intervalCloseRef.current = null; - }, CLOSE_DELAY); + }, props.closeDelay ?? TOOLTIP_CLOSE_DELAY); if (intervalOpenRef.current) { clearInterval(intervalOpenRef.current); intervalOpenRef.current = null; } updateTooltipCoords(); - }, [setVisible, intervalCloseRef, updateTooltipCoords]); + }, [setVisible, updateTooltipCoords, props.closeDelay]); const onHandleClick = useCallback((event: MouseEvent) => { event.preventDefault(); }, []); const className = cx("Tooltip", props.className); + const portalStyle = useMemo(() => ({ ...coords, position: "absolute" }), [coords]); + const popupStyle = useMemo(() => ({ width: tooltipWidth }), [tooltipWidth]); return ( @@ -126,12 +131,16 @@ export default function TooltipWithPortal(props: Props) { ref={handlerRef} > {/* For onMouseLeave to work on disabled button https://github.com/react-component/tooltip/issues/18#issuecomment-411476678 */} - {props.isHandlerDisabled ?
    {props.handle}
    : <>{props.handle}} + {props.isHandlerDisabled ? ( +
    {props.handle || props.children}
    + ) : ( + <>{props.handle || props.children} + )}
    - {visible && coords.left && ( + {visible && coords.left && !props.disabled && ( -
    -
    +
    +
    {props.renderContent()}
    diff --git a/src/components/ValueTransition/ValueTransition.scss b/src/components/ValueTransition/ValueTransition.scss new file mode 100644 index 0000000000..a472b1b4d8 --- /dev/null +++ b/src/components/ValueTransition/ValueTransition.scss @@ -0,0 +1,4 @@ +.ValueTransition { + display: inline-block; + vertical-align: top; +} diff --git a/src/components/ValueTransition/ValueTransition.tsx b/src/components/ValueTransition/ValueTransition.tsx index 4da7bf9fbd..d11942015e 100644 --- a/src/components/ValueTransition/ValueTransition.tsx +++ b/src/components/ValueTransition/ValueTransition.tsx @@ -1,3 +1,4 @@ +import "./ValueTransition.scss"; import { ReactNode } from "react"; import { BsArrowRight } from "react-icons/bs"; @@ -11,12 +12,12 @@ export function ValueTransition(p: Props) { if (!p.from) return <>{p.to}; return ( - <> +
    {p.from}
    {p.to} - +
    ); } diff --git a/src/config/chains.ts b/src/config/chains.ts index 437159c8d2..69f4d1ece3 100644 --- a/src/config/chains.ts +++ b/src/config/chains.ts @@ -53,9 +53,15 @@ export const MAX_GAS_PRICE_MAP = { }; export const HIGH_EXECUTION_FEES_MAP = { - [ARBITRUM]: 3, // 3 USD - [AVALANCHE]: 3, // 3 USD - [AVALANCHE_FUJI]: 3, // 3 USD + [ARBITRUM]: 5, // 5 USD + [AVALANCHE]: 5, // 5 USD + [AVALANCHE_FUJI]: 5, // 5 USD +}; + +export const EXCESSIVE_EXECUTION_FEES_MAP = { + [ARBITRUM]: 10, // 10 USD + [AVALANCHE]: 10, // 10 USD + [AVALANCHE_FUJI]: 10, // 10 USD }; export const EXECUTION_FEE_MULTIPLIER_MAP = { @@ -350,7 +356,11 @@ export function getExplorerUrl(chainId) { } export function getHighExecutionFee(chainId) { - return HIGH_EXECUTION_FEES_MAP[chainId] || 3; + return HIGH_EXECUTION_FEES_MAP[chainId] ?? 5; +} + +export function getExcessiveExecutionFee(chainId) { + return EXCESSIVE_EXECUTION_FEES_MAP[chainId] ?? 10; } export function getExecutionFeeMultiplier(chainId) { diff --git a/src/config/events.ts b/src/config/events.ts index 2887323466..ec7a340842 100644 --- a/src/config/events.ts +++ b/src/config/events.ts @@ -63,7 +63,7 @@ export const appEventsData: EventData[] = [ "Adaptive Funding Rates are enabled for the ARB/USD market on Arbitrum and AVAX/USD market on Avalanche. This is a trial to improve the open interest balance and reduce price impact for markets.", buttons: [ { - text: "More Info.", + text: "Read more.", link: "https://docs.gmx.io/docs/trading/v2/#adaptive-funding", newTab: true, }, @@ -78,7 +78,7 @@ export const appEventsData: EventData[] = [ "Adaptive Funding Rates will be enabled for the ARB/USD market on Arbitrum and AVAX/USD market on Avalanche this week. This is a trial to improve the open interest balance and reduce price impact for markets.", buttons: [ { - text: "More Info.", + text: "Read more.", link: "https://docs.gmx.io/docs/trading/v2/#adaptive-funding", newTab: true, }, @@ -92,7 +92,7 @@ export const appEventsData: EventData[] = [ bodyText: "Arbitrum STIP incentives are live for Arbitrum GM pools and GLP to GM migrations.", buttons: [ { - text: "More Info.", + text: "Read more.", link: "https://gmxio.notion.site/GMX-S-T-I-P-Incentives-Distribution-1a5ab9ca432b4f1798ff8810ce51fec3", newTab: true, }, @@ -102,17 +102,16 @@ export const appEventsData: EventData[] = [ id: "all-incentives-launch", title: "Incentives are live", isActive: true, - validTill: "31 Oct 2024, 12:00", + validTill: "30 Mar 2024, 00:00", bodyText: [ `Arbitrum STIP incentives are live for:`, "", - "• Arbitrum GM Pools.", - "• Arbitrum GLP to GM migration.", - "• Arbitrum Trading.", + "• Arbitrum GM Pools Liquidity.", + "• Arbitrum GMX V2 Trading.", ], buttons: [ { - text: "More Info.", + text: "Read more.", link: "https://gmxio.notion.site/GMX-S-T-I-P-Incentives-Distribution-1a5ab9ca432b4f1798ff8810ce51fec3", newTab: true, }, @@ -127,7 +126,7 @@ export const appEventsData: EventData[] = [ "Adaptive Funding Rates are enabled for all markets. This is to improve the open interest balance and reduce price impact for markets.", buttons: [ { - text: "More Info.", + text: "Read more.", link: "https://docs.gmx.io/docs/trading/v2/#adaptive-funding", newTab: true, }, @@ -147,4 +146,18 @@ export const appEventsData: EventData[] = [ validTill: "16 Dec 2023, 12:00", bodyText: ["They are currently working to resolve the issue."], }, + { + id: "bnb-market", + title: "BNB market added on Arbitrum!", + isActive: true, + validTill: "15 Feb 2024, 12:00", + bodyText: ["Trade BNB or provide liquidity using BNB or USDC in the GM Pool."], + buttons: [ + { + text: "Read more.", + link: "https://twitter.com/GMX_IO/status/1750157046748446982", + newTab: true, + }, + ], + }, ]; diff --git a/src/config/factors.ts b/src/config/factors.ts index be5710f187..beaba45f1c 100644 --- a/src/config/factors.ts +++ b/src/config/factors.ts @@ -5,6 +5,7 @@ export const BASIS_POINTS_DIVISOR = 10000; export const MAX_LEVERAGE = 100 * BASIS_POINTS_DIVISOR; export const MAX_ALLOWED_LEVERAGE = 50 * BASIS_POINTS_DIVISOR; export const HIGH_SPREAD_THRESHOLD = expandDecimals(1, 30).div(100); // 1% +export const COLLATERAL_SPREAD_SHOW_AFTER_INITIAL_ZERO_THRESHOLD = 5; // 0.05% export const DEFAULT_SLIPPAGE_AMOUNT = 30; // 0.3% export const DEFAULT_HIGHER_SLIPPAGE_AMOUNT = 100; // 1% diff --git a/src/config/links.ts b/src/config/links.ts index f494eb9b7c..3599d433ca 100644 --- a/src/config/links.ts +++ b/src/config/links.ts @@ -33,3 +33,10 @@ export function getLeaderboardLink(chainId) { } return "https://www.gmx.house"; } + +export const DOCS_LINKS = { + multiplierPoints: "https://docs.gmx.io/docs/tokenomics/rewards/#multiplier-points", + fundingFees: "https://docs.gmx.io/docs/trading/v2/#funding-fees", + adaptiveFunding: "https://docs.gmx.io/docs/trading/v2/#adaptive-funding", + borrowingFees: "https://docs.gmx.io/docs/trading/v2/#borrowing-fees", +}; diff --git a/src/config/subgraph.ts b/src/config/subgraph.ts index 2f7acbdf51..bdded7bf0a 100644 --- a/src/config/subgraph.ts +++ b/src/config/subgraph.ts @@ -7,8 +7,7 @@ const SUBGRAPH_URLS = { stats: "https://subgraph.satsuma-prod.com/3b2ced13c8d9/gmx/gmx-arbitrum-stats/api", referrals: "https://subgraph.satsuma-prod.com/3b2ced13c8d9/gmx/gmx-arbitrum-referrals/api", nissohVault: "https://api.thegraph.com/subgraphs/name/nissoh/gmx-vault", - syntheticsStats: - "https://subgraph.satsuma-prod.com/3b2ced13c8d9/gmx/synthetics-arbitrum-stats/version/add-timestamp-231212190517-5cb777b/api", + syntheticsStats: "https://subgraph.satsuma-prod.com/3b2ced13c8d9/gmx/synthetics-arbitrum-stats/api", }, [ARBITRUM_GOERLI]: { @@ -21,8 +20,7 @@ const SUBGRAPH_URLS = { [AVALANCHE]: { stats: "https://subgraph.satsuma-prod.com/3b2ced13c8d9/gmx/gmx-avalanche-stats/api", referrals: "https://subgraph.satsuma-prod.com/3b2ced13c8d9/gmx/gmx-avalanche-referrals/api", - syntheticsStats: - "https://subgraph.satsuma-prod.com/3b2ced13c8d9/gmx/synthetics-avalanche-stats/version/add-timestamp-231212190539-5cb777b/api", + syntheticsStats: "https://subgraph.satsuma-prod.com/3b2ced13c8d9/gmx/synthetics-avalanche-stats/api", }, [AVALANCHE_FUJI]: { diff --git a/src/config/ui.ts b/src/config/ui.ts index 0c0f31dbb7..b66fab0e6b 100644 --- a/src/config/ui.ts +++ b/src/config/ui.ts @@ -10,3 +10,8 @@ export const INPUT_LABEL_SEPARATOR = ":"; export const TRADE_HISTORY_PER_PAGE = 25; export const UI_FEE_RECEIVER_ACCOUNT = process.env.REACT_APP_UI_FEE_RECEIVER || null; + +export const V2_LEVERAGE_SLIDER_MARKS = [0.1, 1, 2, 5, 10, 15, 20, 25, 30, 40, 50]; + +export const TOOLTIP_OPEN_DELAY = 100; // ms +export const TOOLTIP_CLOSE_DELAY = 100; // ms diff --git a/src/context/SettingsContext/SettingsContextProvider.tsx b/src/context/SettingsContext/SettingsContextProvider.tsx index faf3ddbbd6..f85fca23d1 100644 --- a/src/context/SettingsContext/SettingsContextProvider.tsx +++ b/src/context/SettingsContext/SettingsContextProvider.tsx @@ -1,9 +1,16 @@ +import noop from "lodash/noop"; +import { Dispatch, ReactNode, SetStateAction, createContext, useContext, useEffect, useMemo } from "react"; + import { EXECUTION_FEE_CONFIG_V2, SUPPORTED_CHAIN_IDS } from "config/chains"; import { isDevelopment } from "config/env"; import { DEFAULT_ACCEPABLE_PRICE_IMPACT_BUFFER, DEFAULT_SLIPPAGE_AMOUNT } from "config/factors"; import { + DISABLE_ORDER_VALIDATION_KEY, + IS_PNL_IN_LEVERAGE_KEY, ORACLE_KEEPER_INSTANCES_CONFIG_KEY, + SHOULD_SHOW_POSITION_LINES_KEY, SHOW_DEBUG_VALUES_KEY, + SHOW_PNL_AFTER_FEES_KEY, getAllowedSlippageKey, getExecutionFeeBufferBpsKey, getSyntheticsAcceptablePriceImpactBufferKey, @@ -11,7 +18,6 @@ import { import { getOracleKeeperRandomIndex } from "config/oracleKeeper"; import { useChainId } from "lib/chains"; import { useLocalStorageSerializeKey } from "lib/localStorage"; -import { Dispatch, ReactNode, SetStateAction, createContext, useContext, useEffect, useMemo } from "react"; export type SettingsContextType = { showDebugValues: boolean; @@ -25,6 +31,14 @@ export type SettingsContextType = { shouldUseExecutionFeeBuffer: boolean; oracleKeeperInstancesConfig: { [chainId: number]: number }; setOracleKeeperInstancesConfig: Dispatch>; + showPnlAfterFees: boolean; + setShowPnlAfterFees: (val: boolean) => void; + isPnlInLeverage: boolean; + setIsPnlInLeverage: (val: boolean) => void; + shouldDisableValidationForTesting: boolean; + setShouldDisableValidationForTesting: (val: boolean) => void; + shouldShowPositionLines: boolean; + setShouldShowPositionLines: (val: boolean) => void; }; export const SettingsContext = createContext({}); @@ -60,6 +74,35 @@ export function SettingsContextProvider({ children }: { children: ReactNode }) { }, {} as { [chainId: number]: number }) ); + const [savedShowPnlAfterFees, setSavedShowPnlAfterFees] = useLocalStorageSerializeKey( + [chainId, SHOW_PNL_AFTER_FEES_KEY], + true + ); + + const [savedIsPnlInLeverage, setSavedIsPnlInLeverage] = useLocalStorageSerializeKey( + [chainId, IS_PNL_IN_LEVERAGE_KEY], + false + ); + + let savedShouldDisableValidationForTesting: boolean | undefined; + let setSavedShouldDisableValidationForTesting: (val: boolean) => void; + if (isDevelopment()) { + // Safety: isDevelopment never changes + // eslint-disable-next-line react-hooks/rules-of-hooks + [savedShouldDisableValidationForTesting, setSavedShouldDisableValidationForTesting] = useLocalStorageSerializeKey( + [chainId, DISABLE_ORDER_VALIDATION_KEY], + false + ); + } else { + savedShouldDisableValidationForTesting = false; + setSavedShouldDisableValidationForTesting = noop; + } + + const [savedShouldShowPositionLines, setSavedShouldShowPositionLines] = useLocalStorageSerializeKey( + [chainId, SHOULD_SHOW_POSITION_LINES_KEY], + false + ); + useEffect(() => { if (shouldUseExecutionFeeBuffer && executionFeeBufferBps === undefined) { setExecutionFeeBufferBps(EXECUTION_FEE_CONFIG_V2[chainId].defaultBufferBps); @@ -79,6 +122,14 @@ export function SettingsContextProvider({ children }: { children: ReactNode }) { setOracleKeeperInstancesConfig, savedAcceptablePriceImpactBuffer: savedAcceptablePriceImpactBuffer!, setSavedAcceptablePriceImpactBuffer, + showPnlAfterFees: savedShowPnlAfterFees!, + setShowPnlAfterFees: setSavedShowPnlAfterFees, + isPnlInLeverage: savedIsPnlInLeverage!, + setIsPnlInLeverage: setSavedIsPnlInLeverage, + shouldDisableValidationForTesting: savedShouldDisableValidationForTesting!, + setShouldDisableValidationForTesting: setSavedShouldDisableValidationForTesting, + shouldShowPositionLines: savedShouldShowPositionLines!, + setShouldShowPositionLines: setSavedShouldShowPositionLines, }; }, [ showDebugValues, @@ -92,6 +143,14 @@ export function SettingsContextProvider({ children }: { children: ReactNode }) { setOracleKeeperInstancesConfig, savedAcceptablePriceImpactBuffer, setSavedAcceptablePriceImpactBuffer, + savedShowPnlAfterFees, + setSavedShowPnlAfterFees, + savedIsPnlInLeverage, + setSavedIsPnlInLeverage, + savedShouldDisableValidationForTesting, + setSavedShouldDisableValidationForTesting, + savedShouldShowPositionLines, + setSavedShouldShowPositionLines, ]); return {children}; diff --git a/src/context/SubaccountContext/SubaccountContext.tsx b/src/context/SubaccountContext/SubaccountContext.tsx index 359829fbf9..affb98a230 100644 --- a/src/context/SubaccountContext/SubaccountContext.tsx +++ b/src/context/SubaccountContext/SubaccountContext.tsx @@ -21,7 +21,7 @@ import { } from "domain/synthetics/fees"; import { STRING_FOR_SIGNING } from "domain/synthetics/subaccount/constants"; import { SubaccountSerializedConfig } from "domain/synthetics/subaccount/types"; -import { useTokenBalances, useTokensData } from "domain/synthetics/tokens"; +import { useTokenBalances, useTokensDataRequest } from "domain/synthetics/tokens"; import { BigNumber, ethers } from "ethers"; import { useChainId } from "lib/chains"; import { useLocalStorageSerializeKey } from "lib/localStorage"; @@ -98,7 +98,7 @@ export function SubaccountContextProvider({ children }: PropsWithChildren) { const { gasPrice } = useGasPrice(chainId); const { gasLimits } = useGasLimits(chainId); - const { tokensData } = useTokensData(chainId); + const { tokensData } = useTokensDataRequest(chainId); // fee that is used as a approx basis to calculate // costs of subaccount actions diff --git a/src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx b/src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx index d4bcb97bc3..a13f9f5413 100644 --- a/src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx +++ b/src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx @@ -1,13 +1,13 @@ import { t } from "@lingui/macro"; import EventEmitter from "abis/EventEmitter.json"; import { GmStatusNotification } from "components/Synthetics/StatusNotification/GmStatusNotification"; -import { OrderStatusNotification } from "components/Synthetics/StatusNotification/OrderStatusNotification"; +import { OrdersStatusNotificiation } from "components/Synthetics/StatusNotification/OrderStatusNotification"; import { getContract } from "config/contracts"; import { isDevelopment } from "config/env"; import { getToken, getWrappedToken } from "config/tokens"; import { WS_LOST_FOCUS_TIMEOUT } from "config/ui"; import { useWebsocketProvider } from "context/WebsocketContext/WebsocketContextProvider"; -import { useMarketsInfo } from "domain/synthetics/markets"; +import { useMarketsInfoRequest } from "domain/synthetics/markets"; import { isDecreaseOrderType, isIncreaseOrderType, @@ -15,7 +15,7 @@ import { isMarketOrderType, } from "domain/synthetics/orders"; import { getPositionKey } from "domain/synthetics/positions"; -import { useTokensData } from "domain/synthetics/tokens"; +import { useTokensDataRequest } from "domain/synthetics/tokens"; import { getSwapPathOutputAddresses } from "domain/synthetics/trade"; import { BigNumber, ethers } from "ethers"; import { useChainId } from "lib/chains"; @@ -69,7 +69,13 @@ export function useSyntheticsEvents(): SyntheticsEventsContextType { return useContext(SyntheticsEventsContext) as SyntheticsEventsContextType; } -export function SyntheticsEventsProvider({ children }: { children: ReactNode }) { +export function SyntheticsEventsProvider({ + children, + setPendingTxns, +}: { + children: ReactNode; + setPendingTxns: (txns: string[]) => void; +}) { const { chainId } = useChainId(); const { account: currentAccount } = useWallet(); const { wsProvider } = useWebsocketProvider(); @@ -80,8 +86,8 @@ export function SyntheticsEventsProvider({ children }: { children: ReactNode }) debugId: "V2 Events", }); - const { tokensData } = useTokensData(chainId); - const { marketsInfoData } = useMarketsInfo(chainId); + const { tokensData } = useTokensDataRequest(chainId); + const { marketsInfoData } = useMarketsInfoRequest(chainId); const [orderStatuses, setOrderStatuses] = useState({}); const [depositStatuses, setDepositStatuses] = useState({}); @@ -550,19 +556,21 @@ export function SyntheticsEventsProvider({ children }: { children: ReactNode }) pendingPositionsUpdates, positionIncreaseEvents, positionDecreaseEvents, - setPendingOrder: (data: PendingOrderData) => { + setPendingOrder: (data: PendingOrderData | PendingOrderData[]) => { const toastId = Date.now(); helperToast.success( - , { autoClose: false, toastId, + className: "OrdersStatusNotificiation", } ); }, @@ -638,6 +646,7 @@ export function SyntheticsEventsProvider({ children }: { children: ReactNode }) positionIncreaseEvents, tokensData, withdrawalStatuses, + setPendingTxns, ]); return {children}; diff --git a/src/context/SyntheticsEvents/types.ts b/src/context/SyntheticsEvents/types.ts index e000777d62..50aebcd98b 100644 --- a/src/context/SyntheticsEvents/types.ts +++ b/src/context/SyntheticsEvents/types.ts @@ -18,7 +18,7 @@ export type SyntheticsEventsContextType = { setWithdrawalStatusViewed: (key: string) => void; }; -export type SetPendingOrder = (data: PendingOrderData) => void; +export type SetPendingOrder = (data: PendingOrderData | PendingOrderData[]) => void; export type SetPendingPosition = (update: PendingPositionUpdate) => void; export type SetPendingDeposit = (data: PendingDepositData) => void; export type SetPendingWithdrawal = (data: PendingWithdrawalData) => void; diff --git a/src/context/SyntheticsStateContext/SyntheticsStateContextProvider.tsx b/src/context/SyntheticsStateContext/SyntheticsStateContextProvider.tsx new file mode 100644 index 0000000000..132ffee43a --- /dev/null +++ b/src/context/SyntheticsStateContext/SyntheticsStateContextProvider.tsx @@ -0,0 +1,140 @@ +import { SettingsContextType, useSettings } from "context/SettingsContext/SettingsContextProvider"; +import { UserReferralInfo, useUserReferralInfoRequest } from "domain/referrals"; +import useUiFeeFactor from "domain/synthetics/fees/utils/useUiFeeFactor"; +import { MarketsInfoResult, MarketsResult, useMarkets, useMarketsInfoRequest } from "domain/synthetics/markets"; +import { AggregatedOrdersDataResult, useOrdersInfoRequest } from "domain/synthetics/orders/useOrdersInfo"; +import { + PositionsConstantsResult, + PositionsInfoResult, + usePositionsConstantsRequest, + usePositionsInfoRequest, +} from "domain/synthetics/positions"; +import { TradeState, useTradeState } from "domain/synthetics/trade/useTradeState"; +import { BigNumber, ethers } from "ethers"; +import { useChainId } from "lib/chains"; +import useWallet from "lib/wallets/useWallet"; +import { ReactNode, useMemo } from "react"; +import { useParams } from "react-router-dom"; +import { Context, createContext, useContext, useContextSelector } from "use-context-selector"; + +export type SyntheticsTradeState = { + pageType: "actions" | "trade" | "pools"; + globals: { + chainId: number; + markets: MarketsResult; + marketsInfo: MarketsInfoResult; + positionsInfo: PositionsInfoResult; + account: string | undefined; + ordersInfo: AggregatedOrdersDataResult; + positionsConstants: PositionsConstantsResult; + uiFeeFactor: BigNumber; + userReferralInfo: UserReferralInfo | undefined; + savedIsPnlInLeverage: boolean; + savedShowPnlAfterFees: boolean; + }; + settings: SettingsContextType; + tradebox: TradeState; +}; + +const StateCtx = createContext(null); + +export function SyntheticsStateContextProvider({ + children, + savedIsPnlInLeverage, + savedShowPnlAfterFees, + skipLocalReferralCode, + pageType, +}: { + children: ReactNode; + savedIsPnlInLeverage: boolean; + savedShowPnlAfterFees: boolean; + skipLocalReferralCode: boolean; + pageType: "actions" | "trade" | "pools"; +}) { + const { chainId } = useChainId(); + const { account: walletAccount, signer } = useWallet(); + const { account: paramsAccount } = useParams<{ account?: string }>(); + + let checkSummedAccount: string | undefined; + + if (paramsAccount && ethers.utils.isAddress(paramsAccount)) { + checkSummedAccount = ethers.utils.getAddress(paramsAccount); + } + + const account = pageType === "actions" ? checkSummedAccount : walletAccount; + const markets = useMarkets(chainId); + const marketsInfo = useMarketsInfoRequest(chainId); + const positionsConstants = usePositionsConstantsRequest(chainId); + const uiFeeFactor = useUiFeeFactor(chainId); + const userReferralInfo = useUserReferralInfoRequest(signer, chainId, account, skipLocalReferralCode); + + const positionsInfo = usePositionsInfoRequest(chainId, { + account, + showPnlInLeverage: savedIsPnlInLeverage, + marketsInfoData: marketsInfo.marketsInfoData, + pricesUpdatedAt: marketsInfo.pricesUpdatedAt, + skipLocalReferralCode, + tokensData: marketsInfo.tokensData, + }); + const ordersInfo = useOrdersInfoRequest(chainId, { + account, + marketsInfoData: marketsInfo.marketsInfoData, + positionsInfoData: positionsInfo.positionsInfoData, + tokensData: marketsInfo.tokensData, + }); + const settings = useSettings(); + + const tradeState = useTradeState(chainId, { + marketsInfoData: marketsInfo.marketsInfoData, + tokensData: marketsInfo.tokensData, + }); + + const state = useMemo(() => { + const s: SyntheticsTradeState = { + pageType, + globals: { + chainId, + account, + markets, + marketsInfo, + ordersInfo, + positionsConstants, + positionsInfo, + uiFeeFactor, + userReferralInfo, + + savedIsPnlInLeverage, + savedShowPnlAfterFees, + }, + settings, + tradebox: tradeState, + }; + + return s; + }, [ + pageType, + chainId, + account, + markets, + marketsInfo, + ordersInfo, + positionsConstants, + positionsInfo, + uiFeeFactor, + userReferralInfo, + savedIsPnlInLeverage, + savedShowPnlAfterFees, + settings, + tradeState, + ]); + + return {children}; +} + +export function useSyntheticsStateSelector(selector: (s: SyntheticsTradeState) => Selected) { + const value = useContext(StateCtx); + if (!value) { + throw new Error("Used useSyntheticsStateSelector outside of SyntheticsStateContextProvider"); + } + return useContextSelector(StateCtx as Context, selector) as Selected; +} diff --git a/src/context/SyntheticsStateContext/hooks/globalsHooks.ts b/src/context/SyntheticsStateContext/hooks/globalsHooks.ts new file mode 100644 index 0000000000..a9a9722cde --- /dev/null +++ b/src/context/SyntheticsStateContext/hooks/globalsHooks.ts @@ -0,0 +1,30 @@ +import { + selectMarketsInfoData, + selectTokensData, + selectOrdersInfoData, + selectIsOrdersLoading, + selectPricesUpdatedAt, + selectUserReferralInfo, + selectSavedIsPnlInLeverage, + selectSavedShowPnlAfterFees, + selectPositionsInfoData, + selectIsPositionsLoading, + selectUiFeeFactor, + selectPositionConstants, + selectAccount, +} from "../selectors/globalSelectors"; +import { useSelector } from "../utils"; + +export const useMarketsInfoData = () => useSelector(selectMarketsInfoData); +export const useTokensData = () => useSelector(selectTokensData); +export const useOrdersInfoData = () => useSelector(selectOrdersInfoData); +export const useIsOrdersLoading = () => useSelector(selectIsOrdersLoading); +export const usePricesUpdatedAt = () => useSelector(selectPricesUpdatedAt); +export const useUserReferralInfo = () => useSelector(selectUserReferralInfo); +export const useSavedIsPnlInLeverage = () => useSelector(selectSavedIsPnlInLeverage); +export const useSavedShowPnlAfterFees = () => useSelector(selectSavedShowPnlAfterFees); +export const usePositionsInfoData = () => useSelector(selectPositionsInfoData); +export const useIsPositionsLoading = () => useSelector(selectIsPositionsLoading); +export const useUiFeeFactor = () => useSelector(selectUiFeeFactor); +export const usePositionsConstants = () => useSelector(selectPositionConstants); +export const useAccount = () => useSelector(selectAccount); diff --git a/src/context/SyntheticsStateContext/hooks/settingsHooks.ts b/src/context/SyntheticsStateContext/hooks/settingsHooks.ts new file mode 100644 index 0000000000..1d6d486c24 --- /dev/null +++ b/src/context/SyntheticsStateContext/hooks/settingsHooks.ts @@ -0,0 +1,26 @@ +import { useSyntheticsStateSelector as useSelector } from "../SyntheticsStateContextProvider"; +import { + selectExecutionFeeBufferBps, + selectOracleKeeperInstancesConfig, + selectSavedAcceptablePriceImpactBuffer, + selectSavedAllowedSlippage, + selectSetExecutionFeeBufferBps, + selectSetOracleKeeperInstancesConfig, + selectSetSavedAcceptablePriceImpactBuffer, + selectSetSavedAllowedSlippage, + selectSetShowDebugValues, + selectShouldUseExecutionFeeBuffer, + selectShowDebugValues, +} from "../selectors/settingsSelectors"; + +export const useShowDebugValues = () => useSelector(selectShowDebugValues); +export const useSetShowDebugValues = () => useSelector(selectSetShowDebugValues); +export const useSavedAllowedSlippage = () => useSelector(selectSavedAllowedSlippage); +export const useSetSavedAllowedSlippage = () => useSelector(selectSetSavedAllowedSlippage); +export const useExecutionFeeBufferBps = () => useSelector(selectExecutionFeeBufferBps); +export const useSetExecutionFeeBufferBps = () => useSelector(selectSetExecutionFeeBufferBps); +export const useSavedAcceptablePriceImpactBuffer = () => useSelector(selectSavedAcceptablePriceImpactBuffer); +export const useSetSavedAcceptablePriceImpactBuffer = () => useSelector(selectSetSavedAcceptablePriceImpactBuffer); +export const useShouldUseExecutionFeeBuffer = () => useSelector(selectShouldUseExecutionFeeBuffer); +export const useOracleKeeperInstancesConfig = () => useSelector(selectOracleKeeperInstancesConfig); +export const useSetOracleKeeperInstancesConfig = () => useSelector(selectSetOracleKeeperInstancesConfig); diff --git a/src/context/SyntheticsStateContext/hooks/tradeHooks.ts b/src/context/SyntheticsStateContext/hooks/tradeHooks.ts new file mode 100644 index 0000000000..9584f334ad --- /dev/null +++ b/src/context/SyntheticsStateContext/hooks/tradeHooks.ts @@ -0,0 +1,119 @@ +import { TradeMode, TradeType } from "domain/synthetics/trade"; +import { BigNumber } from "ethers"; +import { useMemo } from "react"; +import { + TokenTypeForSwapRoute, + createTradeFlags, + makeSelectNextPositionValuesForIncrease, + makeSelectSwapRoutes, + makeSelectTradeRatios, +} from "../selectors/tradeSelectors"; +import { useSelector } from "../utils"; + +export const useNextPositionValuesForIncrease = ({ + collateralTokenAddress, + fixedAcceptablePriceImpactBps, + initialCollateralTokenAddress, + initialCollateralAmount, + leverage, + marketAddress, + positionKey, + strategy, + indexTokenAddress, + indexTokenAmount, + tradeMode, + tradeType, + triggerPrice, + tokenTypeForSwapRoute, +}: { + initialCollateralTokenAddress: string | undefined; + indexTokenAddress: string | undefined; + positionKey: string | undefined; + tradeMode: TradeMode; + tradeType: TradeType; + collateralTokenAddress: string | undefined; + marketAddress: string | undefined; + initialCollateralAmount: BigNumber; + indexTokenAmount: BigNumber | undefined; + leverage: BigNumber | undefined; + triggerPrice: BigNumber | undefined; + fixedAcceptablePriceImpactBps: BigNumber | undefined; + strategy: "leverageByCollateral" | "leverageBySize" | "independent"; + tokenTypeForSwapRoute: TokenTypeForSwapRoute; +}) => { + const selector = useMemo( + () => + makeSelectNextPositionValuesForIncrease({ + collateralTokenAddress, + fixedAcceptablePriceImpactBps, + initialCollateralTokenAddress, + initialCollateralAmount, + leverage, + marketAddress, + positionKey, + increaseStrategy: strategy, + indexTokenAddress, + indexTokenAmount, + tradeMode, + tradeType, + triggerPrice, + tokenTypeForSwapRoute, + }), + [ + collateralTokenAddress, + fixedAcceptablePriceImpactBps, + indexTokenAddress, + indexTokenAmount, + initialCollateralAmount, + initialCollateralTokenAddress, + leverage, + marketAddress, + positionKey, + strategy, + tokenTypeForSwapRoute, + tradeMode, + tradeType, + triggerPrice, + ] + ); + return useSelector(selector); +}; + +export const useSwapRoutes = (fromTokenAddress: string | undefined, toTokenAddress: string | undefined) => { + const selector = useMemo( + () => makeSelectSwapRoutes(fromTokenAddress, toTokenAddress), + [fromTokenAddress, toTokenAddress] + ); + return useSelector(selector); +}; + +export const useTradeRatios = ({ + fromTokenAddress, + toTokenAddress, + tradeType, + tradeMode, + triggerRatioValue, +}: { + fromTokenAddress: string | undefined; + toTokenAddress: string | undefined; + tradeType: TradeType; + tradeMode: TradeMode; + triggerRatioValue: BigNumber | undefined; +}) => { + const selector = useMemo( + () => + makeSelectTradeRatios({ + fromTokenAddress, + toTokenAddress, + tradeType, + tradeMode, + triggerRatioValue, + }), + [fromTokenAddress, toTokenAddress, tradeType, tradeMode, triggerRatioValue] + ); + return useSelector(selector); +}; + +export const useTradeFlags = ({ tradeType, tradeMode }: { tradeType: TradeType; tradeMode: TradeMode }) => { + return useMemo(() => createTradeFlags(tradeType, tradeMode), [tradeType, tradeMode]); +}; diff --git a/src/context/SyntheticsStateContext/hooks/tradeboxHooks.ts b/src/context/SyntheticsStateContext/hooks/tradeboxHooks.ts new file mode 100644 index 0000000000..362ea5cdb3 --- /dev/null +++ b/src/context/SyntheticsStateContext/hooks/tradeboxHooks.ts @@ -0,0 +1,41 @@ +import { + selectTradeboxTradeFlags, + selectTradeboxState, + selectTradeboxSelectedPosition, + selectTradeboxExistingOrder, + selectTradeboxLeverage, + selectTradeboxFromTokenAddress, + selectTradeboxToTokenAddress, + selectTradeboxMarketAddress, + selectTradeboxCollateralTokenAddress, + selectTradeboxAvailableTokensOptions, + selectTradeboxSetActivePosition, + selectTradeboxTradeType, + selectTradeboxSetToTokenAddress, + selectTradeboxIncreasePositionAmounts, + selectTradeboxDecreasePositionAmounts, + selectTradeboxSwapAmounts, + selectTradeboxNextPositionValuesForIncrease, + selectTradeboxNextPositionValuesForDecrease, +} from "../selectors/tradeboxSelectors"; +import { useSelector } from "../utils"; + +export const useTradeboxTradeFlags = () => useSelector(selectTradeboxTradeFlags); +export const useTradeboxState = () => useSelector(selectTradeboxState); +export const useTradeboxSelectedPosition = () => useSelector(selectTradeboxSelectedPosition); +export const useTradeboxExistingOrder = () => useSelector(selectTradeboxExistingOrder); +export const useTradeboxLeverage = () => useSelector(selectTradeboxLeverage); +export const useTradeboxFromTokenAddress = () => useSelector(selectTradeboxFromTokenAddress); +export const useTradeboxToTokenAddress = () => useSelector(selectTradeboxToTokenAddress); +export const useTradeboxMarketAddress = () => useSelector(selectTradeboxMarketAddress); +export const useTradeboxCollateralAddress = () => useSelector(selectTradeboxCollateralTokenAddress); +export const useTradeboxAvailableTokensOptions = () => useSelector(selectTradeboxAvailableTokensOptions); +export const useTradeboxSetActivePosition = () => useSelector(selectTradeboxSetActivePosition); +export const useTradeboxTradeType = () => useSelector(selectTradeboxTradeType); +export const useTradeboxSetToTokenAddress = () => useSelector(selectTradeboxSetToTokenAddress); + +export const useTradeboxSwapAmounts = () => useSelector(selectTradeboxSwapAmounts); +export const useTradeboxNextPositionValuesForIncrease = () => useSelector(selectTradeboxNextPositionValuesForIncrease); +export const useTradeboxNextPositionValuesForDecrease = () => useSelector(selectTradeboxNextPositionValuesForDecrease); +export const useTradeboxIncreasePositionAmounts = () => useSelector(selectTradeboxIncreasePositionAmounts); +export const useTradeboxDecreasePositionAmounts = () => useSelector(selectTradeboxDecreasePositionAmounts); diff --git a/src/context/SyntheticsStateContext/selectors/globalSelectors.ts b/src/context/SyntheticsStateContext/selectors/globalSelectors.ts new file mode 100644 index 0000000000..be7a50610f --- /dev/null +++ b/src/context/SyntheticsStateContext/selectors/globalSelectors.ts @@ -0,0 +1,27 @@ +import { SyntheticsTradeState } from "../SyntheticsStateContextProvider"; +import { createSelector } from "../utils"; + +export const selectAccount = (s: SyntheticsTradeState) => s.globals.account; +export const selectOrdersInfoData = (s: SyntheticsTradeState) => s.globals.ordersInfo.ordersInfoData; +export const selectIsOrdersLoading = (s: SyntheticsTradeState) => s.globals.ordersInfo.isLoading; +export const selectPositionsInfoData = (s: SyntheticsTradeState) => s.globals.positionsInfo.positionsInfoData; +export const selectIsPositionsLoading = (s: SyntheticsTradeState) => s.globals.positionsInfo.isLoading; +export const selectMarketsInfoData = (s: SyntheticsTradeState) => s.globals.marketsInfo.marketsInfoData; +export const selectTokensData = (s: SyntheticsTradeState) => s.globals.marketsInfo.tokensData; +export const selectPricesUpdatedAt = (s: SyntheticsTradeState) => s.globals.marketsInfo.pricesUpdatedAt; +export const selectUiFeeFactor = (s: SyntheticsTradeState) => s.globals.uiFeeFactor; +export const selectUserReferralInfo = (s: SyntheticsTradeState) => s.globals.userReferralInfo; +export const selectChainId = (s: SyntheticsTradeState) => s.globals.chainId; +export const selectSavedIsPnlInLeverage = (s: SyntheticsTradeState) => s.globals.savedIsPnlInLeverage; +export const selectSavedShowPnlAfterFees = (s: SyntheticsTradeState) => s.globals.savedShowPnlAfterFees; + +export const selectMinCollateralUsd = (s: SyntheticsTradeState) => s.globals.positionsConstants.minCollateralUsd; +export const selectMinPositionSizeUsd = (s: SyntheticsTradeState) => s.globals.positionsConstants.minPositionSizeUsd; + +export const selectPositionConstants = createSelector( + [selectMinCollateralUsd, selectMinPositionSizeUsd], + (minCollateralUsd, minPositionSizeUsd) => ({ + minCollateralUsd, + minPositionSizeUsd, + }) +); diff --git a/src/context/SyntheticsStateContext/selectors/settingsSelectors.ts b/src/context/SyntheticsStateContext/selectors/settingsSelectors.ts new file mode 100644 index 0000000000..9636148960 --- /dev/null +++ b/src/context/SyntheticsStateContext/selectors/settingsSelectors.ts @@ -0,0 +1,16 @@ +import { SyntheticsTradeState } from "../SyntheticsStateContextProvider"; + +export const selectShowDebugValues = (s: SyntheticsTradeState) => s.settings.showDebugValues; +export const selectSetShowDebugValues = (s: SyntheticsTradeState) => s.settings.setShowDebugValues; +export const selectSavedAllowedSlippage = (s: SyntheticsTradeState) => s.settings.savedAllowedSlippage; +export const selectExecutionFeeBufferBps = (s: SyntheticsTradeState) => s.settings.executionFeeBufferBps; +export const selectSetExecutionFeeBufferBps = (s: SyntheticsTradeState) => s.settings.setExecutionFeeBufferBps; +export const selectSetSavedAllowedSlippage = (s: SyntheticsTradeState) => s.settings.setSavedAllowedSlippage; +export const selectSavedAcceptablePriceImpactBuffer = (s: SyntheticsTradeState) => + s.settings.savedAcceptablePriceImpactBuffer; +export const selectSetSavedAcceptablePriceImpactBuffer = (s: SyntheticsTradeState) => + s.settings.setSavedAcceptablePriceImpactBuffer; +export const selectShouldUseExecutionFeeBuffer = (s: SyntheticsTradeState) => s.settings.shouldUseExecutionFeeBuffer; +export const selectOracleKeeperInstancesConfig = (s: SyntheticsTradeState) => s.settings.oracleKeeperInstancesConfig; +export const selectSetOracleKeeperInstancesConfig = (s: SyntheticsTradeState) => + s.settings.setOracleKeeperInstancesConfig; diff --git a/src/context/SyntheticsStateContext/selectors/tradeSelectors.ts b/src/context/SyntheticsStateContext/selectors/tradeSelectors.ts new file mode 100644 index 0000000000..b6f5a35e17 --- /dev/null +++ b/src/context/SyntheticsStateContext/selectors/tradeSelectors.ts @@ -0,0 +1,582 @@ +import { NATIVE_TOKEN_ADDRESS, convertTokenAddress, getWrappedToken } from "config/tokens"; +import { + TradeFlags, + TradeMode, + TradeType, + createSwapEstimator, + findAllPaths, + getBestSwapPath, + getDecreasePositionAmounts, + getIncreasePositionAmounts, + getMarkPrice, + getMarketsGraph, + getMaxSwapPathLiquidity, + getNextPositionValuesForDecreaseTrade, + getNextPositionValuesForIncreaseTrade, + getSwapPathStats, +} from "domain/synthetics/trade"; +import { BigNumber } from "ethers"; +import { getByKey } from "lib/objects"; +import { + selectChainId, + selectMarketsInfoData, + selectPositionConstants, + selectPositionsInfoData, + selectSavedIsPnlInLeverage, + selectTokensData, + selectUiFeeFactor, + selectUserReferralInfo, +} from "./globalSelectors"; +import { selectSavedAcceptablePriceImpactBuffer } from "./settingsSelectors"; +import { TokensRatio, getTokensRatioByPrice } from "domain/synthetics/tokens"; +import { createSelector } from "../utils"; + +export type TokenTypeForSwapRoute = "collateralToken" | "indexToken"; + +// dont swap addresses here +export const makeSelectSwapRoutes = (fromTokenAddress: string | undefined, toTokenAddress: string | undefined) => + createSelector([selectChainId, selectMarketsInfoData], (chainId, marketsInfoData) => { + const wrappedToken = getWrappedToken(chainId); + + const isWrap = fromTokenAddress === NATIVE_TOKEN_ADDRESS && toTokenAddress === wrappedToken.address; + const isUnwrap = fromTokenAddress === wrappedToken.address && toTokenAddress === NATIVE_TOKEN_ADDRESS; + const isSameToken = fromTokenAddress === toTokenAddress; + + const wrappedFromAddress = fromTokenAddress ? convertTokenAddress(chainId, fromTokenAddress, "wrapped") : undefined; + const wrappedToAddress = toTokenAddress ? convertTokenAddress(chainId, toTokenAddress, "wrapped") : undefined; + + const { graph, estimator } = (() => { + if (!marketsInfoData) { + return { + graph: undefined, + estimator: undefined, + }; + } + + return { + graph: getMarketsGraph(Object.values(marketsInfoData)), + estimator: createSwapEstimator(marketsInfoData), + }; + })(); + + const allRoutes = (() => { + if (!marketsInfoData || !graph || !wrappedFromAddress || !wrappedToAddress || isWrap || isUnwrap || isSameToken) { + return undefined; + } + + const paths = findAllPaths(marketsInfoData, graph, wrappedFromAddress, wrappedToAddress) + ?.sort((a, b) => { + return b.liquidity.sub(a.liquidity).gt(0) ? 1 : -1; + }) + .slice(0, 5); + + return paths; + })(); + + const { maxLiquidity, maxLiquidityPath } = (() => { + let maxLiquidity = BigNumber.from(0); + let maxLiquidityPath: string[] | undefined = undefined; + + if (!allRoutes || !marketsInfoData || !wrappedFromAddress) { + return { maxLiquidity, maxLiquidityPath }; + } + + for (const route of allRoutes) { + const liquidity = getMaxSwapPathLiquidity({ + marketsInfoData, + swapPath: route.path, + initialCollateralAddress: wrappedFromAddress, + }); + + if (liquidity.gt(maxLiquidity)) { + maxLiquidity = liquidity; + maxLiquidityPath = route.path; + } + } + + return { maxLiquidity, maxLiquidityPath }; + })(); + + const findSwapPath = (usdIn: BigNumber, opts: { byLiquidity?: boolean }) => { + if (!allRoutes?.length || !estimator || !marketsInfoData || !fromTokenAddress) { + return undefined; + } + + let swapPath: string[] | undefined = undefined; + + if (opts.byLiquidity) { + swapPath = allRoutes[0].path; + } else { + swapPath = getBestSwapPath(allRoutes, usdIn, estimator); + } + + if (!swapPath) { + return undefined; + } + + const swapPathStats = getSwapPathStats({ + marketsInfoData, + swapPath, + initialCollateralAddress: fromTokenAddress, + wrappedNativeTokenAddress: wrappedToken.address, + shouldUnwrapNativeToken: toTokenAddress === NATIVE_TOKEN_ADDRESS, + shouldApplyPriceImpact: true, + usdIn, + }); + + if (!swapPathStats) { + return undefined; + } + + return swapPathStats; + }; + + return { + maxSwapLiquidity: maxLiquidity, + maxLiquiditySwapPath: maxLiquidityPath, + findSwapPath, + }; + }); + +export const makeSelectIncreasePositionAmounts = ({ + collateralTokenAddress, + fixedAcceptablePriceImpactBps, + initialCollateralTokenAddress, + initialCollateralAmount, + leverage, + marketAddress, + positionKey, + strategy, + indexTokenAddress, + indexTokenAmount, + tradeMode, + tradeType, + triggerPrice, + tokenTypeForSwapRoute, +}: { + initialCollateralTokenAddress: string | undefined; + indexTokenAddress: string | undefined; + positionKey: string | undefined; + tradeMode: TradeMode; + tradeType: TradeType; + collateralTokenAddress: string | undefined; + marketAddress: string | undefined; + initialCollateralAmount: BigNumber; + indexTokenAmount: BigNumber | undefined; + leverage: BigNumber | undefined; + triggerPrice: BigNumber | undefined; + fixedAcceptablePriceImpactBps: BigNumber | undefined; + strategy: "leverageByCollateral" | "leverageBySize" | "independent"; + tokenTypeForSwapRoute: TokenTypeForSwapRoute; +}) => + createSelector( + [ + selectTokensData, + selectMarketsInfoData, + selectPositionsInfoData, + selectSavedAcceptablePriceImpactBuffer, + makeSelectSwapRoutes( + initialCollateralTokenAddress, + tokenTypeForSwapRoute === "indexToken" ? indexTokenAddress : collateralTokenAddress + ), + selectUserReferralInfo, + selectUiFeeFactor, + ], + ( + tokensData, + marketsInfoData, + positionsInfoData, + acceptablePriceImpactBuffer, + { findSwapPath }, + userReferralInfo, + uiFeeFactor + ) => { + const position = positionKey ? getByKey(positionsInfoData, positionKey) : undefined; + const tradeFlags = createTradeFlags(tradeType, tradeMode); + const indexToken = indexTokenAddress ? getByKey(tokensData, indexTokenAddress) : undefined; + const initialCollateralToken = initialCollateralTokenAddress + ? getByKey(tokensData, initialCollateralTokenAddress) + : undefined; + const collateralToken = collateralTokenAddress ? getByKey(tokensData, collateralTokenAddress) : undefined; + const marketInfo = marketAddress ? getByKey(marketsInfoData, marketAddress) : undefined; + + if ( + !indexTokenAmount || + !tradeFlags.isIncrease || + !indexToken || + !initialCollateralToken || + !collateralToken || + !marketInfo + ) { + return undefined; + } + + return getIncreasePositionAmounts({ + marketInfo, + indexToken, + initialCollateralToken, + collateralToken, + isLong: tradeFlags.isLong, + initialCollateralAmount, + indexTokenAmount, + leverage, + triggerPrice: tradeFlags.isLimit ? triggerPrice : undefined, + position, + fixedAcceptablePriceImpactBps, + acceptablePriceImpactBuffer, + findSwapPath, + userReferralInfo, + uiFeeFactor, + strategy, + }); + } + ); + +export const createTradeFlags = (tradeType: TradeType, tradeMode: TradeMode): TradeFlags => { + const isLong = tradeType === TradeType.Long; + const isShort = tradeType === TradeType.Short; + const isSwap = tradeType === TradeType.Swap; + const isPosition = isLong || isShort; + const isMarket = tradeMode === TradeMode.Market; + const isLimit = tradeMode === TradeMode.Limit; + const isTrigger = tradeMode === TradeMode.Trigger; + const isIncrease = isPosition && (isMarket || isLimit); + + const tradeFlags: TradeFlags = { + isLong, + isShort, + isSwap, + isPosition, + isIncrease, + isMarket, + isLimit, + isTrigger, + }; + + return tradeFlags; +}; + +export const makeSelectDecreasePositionAmounts = ({ + collateralTokenAddress, + marketAddress, + positionKey, + tradeMode, + tradeType, + triggerPrice, + closeSizeUsd, + keepLeverage, + fixedAcceptablePriceImpactBps, +}: { + positionKey: string | undefined; + tradeMode: TradeMode; + tradeType: TradeType; + collateralTokenAddress: string | undefined; + marketAddress: string | undefined; + triggerPrice: BigNumber | undefined; + closeSizeUsd: BigNumber | undefined; + fixedAcceptablePriceImpactBps: BigNumber | undefined; + keepLeverage: boolean | undefined; +}) => + createSelector( + [ + selectPositionsInfoData, + selectTokensData, + selectMarketsInfoData, + selectPositionConstants, + selectSavedAcceptablePriceImpactBuffer, + selectUserReferralInfo, + selectUiFeeFactor, + ], + ( + positionsInfoData, + tokensData, + marketsInfoData, + { minCollateralUsd, minPositionSizeUsd }, + savedAcceptablePriceImpactBuffer, + userReferralInfo, + uiFeeFactor + ) => { + const position = positionKey ? getByKey(positionsInfoData, positionKey) : undefined; + const tradeFlags = createTradeFlags(tradeType, tradeMode); + const collateralToken = collateralTokenAddress ? getByKey(tokensData, collateralTokenAddress) : undefined; + const marketInfo = marketAddress ? getByKey(marketsInfoData, marketAddress) : undefined; + + if ( + !tradeFlags.isTrigger || + !closeSizeUsd || + !marketInfo || + !collateralToken || + !minCollateralUsd || + !minPositionSizeUsd + ) { + return undefined; + } + + return getDecreasePositionAmounts({ + marketInfo, + collateralToken, + isLong: tradeFlags.isLong, + position, + closeSizeUsd, + keepLeverage: keepLeverage!, + triggerPrice, + fixedAcceptablePriceImpactBps, + acceptablePriceImpactBuffer: savedAcceptablePriceImpactBuffer, + userReferralInfo, + minCollateralUsd, + minPositionSizeUsd, + uiFeeFactor, + }); + } + ); + +export const selectMarkPrice = ({ + toTokenAddress, + tradeMode, + tradeType, +}: { + toTokenAddress: string | undefined; + tradeType: TradeType; + tradeMode: TradeMode; +}) => + createSelector([selectTokensData], (tokensData) => { + const tradeFlags = createTradeFlags(tradeType, tradeMode); + const toToken = toTokenAddress ? getByKey(tokensData, toTokenAddress) : undefined; + + if (!toToken) { + return undefined; + } + + if (tradeFlags.isSwap) { + return toToken.prices.minPrice; + } + + return getMarkPrice({ prices: toToken.prices, isIncrease: tradeFlags.isIncrease, isLong: tradeFlags.isLong }); + }); + +export const makeSelectTradeRatios = ({ + fromTokenAddress, + toTokenAddress, + tradeType, + tradeMode, + triggerRatioValue, +}: { + fromTokenAddress: string | undefined; + toTokenAddress: string | undefined; + tradeType: TradeType; + tradeMode: TradeMode; + triggerRatioValue: BigNumber | undefined; +}) => + createSelector( + [ + selectTokensData, + selectMarkPrice({ + toTokenAddress, + tradeMode, + tradeType, + }), + ], + (tokensData, markPrice) => { + const tradeFlags = createTradeFlags(tradeType, tradeMode); + const toToken = toTokenAddress ? getByKey(tokensData, toTokenAddress) : undefined; + const fromToken = fromTokenAddress ? getByKey(tokensData, fromTokenAddress) : undefined; + const fromTokenPrice = fromToken?.prices.minPrice; + if (!tradeFlags.isSwap || !fromToken || !toToken || !fromTokenPrice || !markPrice) { + return {}; + } + const markRatio = getTokensRatioByPrice({ + fromToken, + toToken, + fromPrice: fromTokenPrice, + toPrice: markPrice, + }); + if (!triggerRatioValue) { + return { markRatio }; + } + const triggerRatio: TokensRatio = { + ratio: triggerRatioValue?.gt(0) ? triggerRatioValue : markRatio.ratio, + largestToken: markRatio.largestToken, + smallestToken: markRatio.smallestToken, + }; + return { + markRatio, + triggerRatio, + }; + } + ); + +export const makeSelectNextPositionValuesForIncrease = ({ + collateralTokenAddress, + fixedAcceptablePriceImpactBps, + initialCollateralTokenAddress, + initialCollateralAmount, + leverage, + marketAddress, + positionKey, + increaseStrategy, + indexTokenAddress, + indexTokenAmount, + tradeMode, + tradeType, + triggerPrice, + tokenTypeForSwapRoute, +}: { + initialCollateralTokenAddress: string | undefined; + indexTokenAddress: string | undefined; + positionKey: string | undefined; + tradeMode: TradeMode; + tradeType: TradeType; + collateralTokenAddress: string | undefined; + marketAddress: string | undefined; + initialCollateralAmount: BigNumber; + indexTokenAmount: BigNumber | undefined; + leverage: BigNumber | undefined; + triggerPrice: BigNumber | undefined; + fixedAcceptablePriceImpactBps: BigNumber | undefined; + increaseStrategy: "leverageByCollateral" | "leverageBySize" | "independent"; + tokenTypeForSwapRoute: TokenTypeForSwapRoute; +}) => + createSelector( + [ + selectPositionConstants, + selectMarketsInfoData, + selectTokensData, + makeSelectIncreasePositionAmounts({ + collateralTokenAddress, + fixedAcceptablePriceImpactBps, + initialCollateralTokenAddress, + initialCollateralAmount, + leverage, + marketAddress, + positionKey, + strategy: increaseStrategy, + indexTokenAddress, + indexTokenAmount, + tradeMode, + tradeType, + triggerPrice, + tokenTypeForSwapRoute, + }), + selectPositionsInfoData, + selectSavedIsPnlInLeverage, + selectUserReferralInfo, + ], + ( + { minCollateralUsd }, + marketsInfoData, + tokensData, + increaseAmounts, + positionsInfoData, + savedIsPnlInLeverage, + userReferralInfo + ) => { + const tradeFlags = createTradeFlags(tradeType, tradeMode); + const marketInfo = getByKey(marketsInfoData, marketAddress); + const collateralToken = collateralTokenAddress ? getByKey(tokensData, collateralTokenAddress) : undefined; + const position = positionKey ? getByKey(positionsInfoData, positionKey) : undefined; + + if (!tradeFlags.isPosition || !minCollateralUsd || !marketInfo || !collateralToken) { + return undefined; + } + + if (tradeFlags.isIncrease && increaseAmounts?.acceptablePrice && initialCollateralAmount.gt(0)) { + return getNextPositionValuesForIncreaseTrade({ + marketInfo, + collateralToken, + existingPosition: position, + isLong: tradeFlags.isLong, + collateralDeltaUsd: increaseAmounts.collateralDeltaUsd, + collateralDeltaAmount: increaseAmounts.collateralDeltaAmount, + sizeDeltaUsd: increaseAmounts.sizeDeltaUsd, + sizeDeltaInTokens: increaseAmounts.sizeDeltaInTokens, + indexPrice: increaseAmounts.indexPrice, + showPnlInLeverage: savedIsPnlInLeverage, + minCollateralUsd, + userReferralInfo, + }); + } + } + ); + +export const makeSelectNextPositionValuesForDecrease = ({ + closeSizeUsd, + collateralTokenAddress, + fixedAcceptablePriceImpactBps, + keepLeverage, + marketAddress, + positionKey, + tradeMode, + tradeType, + triggerPrice, +}: { + closeSizeUsd: BigNumber | undefined; + collateralTokenAddress: string | undefined; + fixedAcceptablePriceImpactBps: BigNumber | undefined; + keepLeverage: boolean | undefined; + marketAddress: string | undefined; + positionKey: string | undefined; + tradeMode: TradeMode; + tradeType: TradeType; + triggerPrice: BigNumber | undefined; +}) => + createSelector( + [ + selectPositionConstants, + selectMarketsInfoData, + selectTokensData, + makeSelectDecreasePositionAmounts({ + closeSizeUsd, + collateralTokenAddress, + fixedAcceptablePriceImpactBps, + keepLeverage, + marketAddress, + positionKey, + tradeMode, + tradeType, + triggerPrice, + }), + selectPositionsInfoData, + selectSavedIsPnlInLeverage, + selectUserReferralInfo, + ], + ( + { minCollateralUsd }, + marketsInfoData, + tokensData, + decreaseAmounts, + positionsInfoData, + savedIsPnlInLeverage, + userReferralInfo + ) => { + const tradeFlags = createTradeFlags(tradeType, tradeMode); + const marketInfo = getByKey(marketsInfoData, marketAddress); + const collateralToken = collateralTokenAddress ? getByKey(tokensData, collateralTokenAddress) : undefined; + const position = positionKey ? getByKey(positionsInfoData, positionKey) : undefined; + + if (!tradeFlags.isPosition || !minCollateralUsd || !marketInfo || !collateralToken) { + return undefined; + } + + if (!closeSizeUsd) throw new Error("makeSelectNextPositionValuesForDecrease: closeSizeUsd is undefined"); + + if (tradeFlags.isTrigger && decreaseAmounts?.acceptablePrice && closeSizeUsd.gt(0)) { + return getNextPositionValuesForDecreaseTrade({ + existingPosition: position, + marketInfo, + collateralToken, + sizeDeltaUsd: decreaseAmounts.sizeDeltaUsd, + sizeDeltaInTokens: decreaseAmounts.sizeDeltaInTokens, + estimatedPnl: decreaseAmounts.estimatedPnl, + realizedPnl: decreaseAmounts.realizedPnl, + collateralDeltaUsd: decreaseAmounts.collateralDeltaUsd, + collateralDeltaAmount: decreaseAmounts.collateralDeltaAmount, + payedRemainingCollateralUsd: decreaseAmounts.payedRemainingCollateralUsd, + payedRemainingCollateralAmount: decreaseAmounts.payedRemainingCollateralAmount, + showPnlInLeverage: savedIsPnlInLeverage, + isLong: tradeFlags.isLong, + minCollateralUsd, + userReferralInfo, + }); + } + } + ); diff --git a/src/context/SyntheticsStateContext/selectors/tradeboxSelectors.ts b/src/context/SyntheticsStateContext/selectors/tradeboxSelectors.ts new file mode 100644 index 0000000000..18e30799e1 --- /dev/null +++ b/src/context/SyntheticsStateContext/selectors/tradeboxSelectors.ts @@ -0,0 +1,346 @@ +import { SyntheticsTradeState } from "../SyntheticsStateContextProvider"; +import { + selectAccount, + selectOrdersInfoData, + selectPositionsInfoData, + selectTokensData, + selectUiFeeFactor, +} from "./globalSelectors"; +import { getByKey } from "lib/objects"; +import { parseValue } from "lib/numbers"; +import { BigNumber } from "ethers"; +import { + createTradeFlags, + makeSelectDecreasePositionAmounts, + makeSelectIncreasePositionAmounts, + makeSelectNextPositionValuesForDecrease, + makeSelectNextPositionValuesForIncrease, + makeSelectSwapRoutes, + makeSelectTradeRatios, +} from "./tradeSelectors"; +import { USD_DECIMALS, getPositionKey } from "lib/legacy"; +import { BASIS_POINTS_DIVISOR } from "config/factors"; +import { createEnhancedSelector, createSelector } from "../utils"; +import { isSwapOrderType } from "domain/synthetics/orders"; +import { SwapAmounts, TradeType, getSwapAmountsByFromValue, getSwapAmountsByToValue } from "domain/synthetics/trade"; +import { convertToUsd } from "domain/synthetics/tokens"; + +const selectOnlyOnTradeboxPage = (s: SyntheticsTradeState, selection: T) => + s.pageType === "trade" ? selection : undefined; +export const selectTradeboxState = (s: SyntheticsTradeState) => s.tradebox; +export const selectTradeboxTradeType = (s: SyntheticsTradeState) => s.tradebox.tradeType; +export const selectTradeboxTradeMode = (s: SyntheticsTradeState) => s.tradebox.tradeMode; +export const selectTradeboxIsWrapOrUnwrap = (s: SyntheticsTradeState) => s.tradebox.isWrapOrUnwrap; +export const selectTradeboxFromTokenAddress = (s: SyntheticsTradeState) => s.tradebox.fromTokenAddress; +export const selectTradeboxToTokenAddress = (s: SyntheticsTradeState) => s.tradebox.toTokenAddress; +export const selectTradeboxMarketAddress = (s: SyntheticsTradeState) => + selectOnlyOnTradeboxPage(s, s.tradebox.marketAddress); +export const selectTradeboxMarketInfo = (s: SyntheticsTradeState) => s.tradebox.marketInfo; +export const selectTradeboxCollateralTokenAddress = (s: SyntheticsTradeState) => + selectOnlyOnTradeboxPage(s, s.tradebox.collateralAddress); +export const selectTradeboxCollateralToken = (s: SyntheticsTradeState) => s.tradebox.collateralToken; +export const selectTradeboxAvailableTradeModes = (s: SyntheticsTradeState) => s.tradebox.avaialbleTradeModes; +export const selectTradeboxAvailableTokensOptions = (s: SyntheticsTradeState) => s.tradebox.availableTokensOptions; +export const selectTradeboxFromTokenInputValue = (s: SyntheticsTradeState) => s.tradebox.fromTokenInputValue; +export const selectTradeboxToTokenInputValue = (s: SyntheticsTradeState) => s.tradebox.toTokenInputValue; +export const selectTradeboxStage = (s: SyntheticsTradeState) => s.tradebox.stage; +export const selectTradeboxFocusedInput = (s: SyntheticsTradeState) => s.tradebox.focusedInput; +export const selectTradeboxFixedTriggerThresholdType = (s: SyntheticsTradeState) => + s.tradebox.fixedTriggerThresholdType; +export const selectTradeboxFixedTriggerOrderType = (s: SyntheticsTradeState) => s.tradebox.fixedTriggerOrderType; +export const selectTradeboxDefaultTriggerAcceptablePriceImpactBps = (s: SyntheticsTradeState) => + s.tradebox.defaultTriggerAcceptablePriceImpactBps; +export const selectTradeboxSelectedTriggerAcceptablePriceImpactBps = (s: SyntheticsTradeState) => + s.tradebox.selectedTriggerAcceptablePriceImpactBps; +export const selectTradeboxCloseSizeInputValue = (s: SyntheticsTradeState) => s.tradebox.closeSizeInputValue; +export const selectTradeboxTriggerPriceInputValue = (s: SyntheticsTradeState) => s.tradebox.triggerPriceInputValue; +export const selectTradeboxTriggerRatioInputValue = (s: SyntheticsTradeState) => s.tradebox.triggerRatioInputValue; +export const selectTradeboxLeverageOption = (s: SyntheticsTradeState) => s.tradebox.leverageOption; +export const selectTradeboxIsLeverageEnabled = (s: SyntheticsTradeState) => s.tradebox.isLeverageEnabled; +export const selectTradeboxKeepLeverage = (s: SyntheticsTradeState) => s.tradebox.keepLeverage; +export const selectTradeboxSetActivePosition = (s: SyntheticsTradeState) => s.tradebox.setActivePosition; +export const selectTradeboxSetToTokenAddress = (s: SyntheticsTradeState) => s.tradebox.setToTokenAddress; + +export const selectTradeboxIncreasePositionAmounts = createEnhancedSelector((q) => { + const tokensData = q(selectTokensData); + const tradeMode = q(selectTradeboxTradeMode); + const tradeType = q(selectTradeboxTradeType); + const fromTokenAddress = q(selectTradeboxFromTokenAddress); + const fromTokenInputValue = q(selectTradeboxFromTokenInputValue); + const toTokenAddress = q(selectTradeboxToTokenAddress); + const toTokenInputValue = q(selectTradeboxToTokenInputValue); + const marketAddress = q(selectTradeboxMarketAddress); + const leverageOption = q(selectTradeboxLeverageOption); + const isLeverageEnabled = q(selectTradeboxIsLeverageEnabled); + const focusedInput = q(selectTradeboxFocusedInput); + const collateralTokenAddress = q(selectTradeboxCollateralTokenAddress); + const selectedTriggerAcceptablePriceImpactBps = q(selectTradeboxSelectedTriggerAcceptablePriceImpactBps); + const triggerPriceInputValue = q(selectTradeboxTriggerPriceInputValue); + + const tradeFlags = createTradeFlags(tradeType, tradeMode); + const fromToken = fromTokenAddress ? getByKey(tokensData, fromTokenAddress) : undefined; + const fromTokenAmount = fromToken ? parseValue(fromTokenInputValue || "0", fromToken.decimals)! : BigNumber.from(0); + const toToken = toTokenAddress ? getByKey(tokensData, toTokenAddress) : undefined; + const toTokenAmount = toToken ? parseValue(toTokenInputValue || "0", toToken.decimals)! : BigNumber.from(0); + const leverage = BigNumber.from(parseInt(String(Number(leverageOption!) * BASIS_POINTS_DIVISOR))); + const triggerPrice = parseValue(triggerPriceInputValue, USD_DECIMALS); + const positionKey = q(selectTradeboxSelectedPositionKey); + + const selector = makeSelectIncreasePositionAmounts({ + collateralTokenAddress, + fixedAcceptablePriceImpactBps: selectedTriggerAcceptablePriceImpactBps, + indexTokenAddress: toTokenAddress, + indexTokenAmount: toTokenAmount, + initialCollateralAmount: fromTokenAmount, + initialCollateralTokenAddress: fromTokenAddress, + leverage, + marketAddress, + positionKey, + strategy: isLeverageEnabled ? (focusedInput === "from" ? "leverageByCollateral" : "leverageBySize") : "independent", + tradeMode, + tradeType, + triggerPrice, + tokenTypeForSwapRoute: tradeFlags.isPosition ? "collateralToken" : "indexToken", + }); + + return q(selector); +}); + +export const selectTradeboxDecreasePositionAmounts = createEnhancedSelector((q) => { + const tradeMode = q(selectTradeboxTradeMode); + const tradeType = q(selectTradeboxTradeType); + const collateralTokenAddress = q(selectTradeboxCollateralTokenAddress); + const marketAddress = q(selectTradeboxMarketAddress); + const triggerPriceInputValue = q(selectTradeboxTriggerPriceInputValue); + const closeSizeInputValue = q(selectTradeboxCloseSizeInputValue); + const keepLeverage = q(selectTradeboxKeepLeverage); + const selectedTriggerAcceptablePriceImpactBps = q(selectTradeboxSelectedTriggerAcceptablePriceImpactBps); + const positionKey = q(selectTradeboxSelectedPositionKey); + + const closeSizeUsd = parseValue(closeSizeInputValue || "0", USD_DECIMALS)!; + const triggerPrice = parseValue(triggerPriceInputValue, USD_DECIMALS); + + if (typeof keepLeverage === "undefined") + throw new Error("selectTradeboxDecreasePositionAmounts: keepLeverage is undefined"); + + const selector = makeSelectDecreasePositionAmounts({ + collateralTokenAddress: collateralTokenAddress, + fixedAcceptablePriceImpactBps: selectedTriggerAcceptablePriceImpactBps, + marketAddress, + positionKey, + tradeMode, + tradeType, + triggerPrice, + closeSizeUsd, + keepLeverage, + }); + + return q(selector); +}); + +export const selectTradeboxSwapAmounts = createEnhancedSelector((q) => { + const tokensData = q(selectTokensData); + const tradeMode = q(selectTradeboxTradeMode); + const fromTokenAddress = q(selectTradeboxFromTokenAddress); + const fromTokenInputValue = q(selectTradeboxFromTokenInputValue); + const toTokenAddress = q(selectTradeboxToTokenAddress); + const toTokenInputValue = q(selectTradeboxToTokenInputValue); + const amountBy = q(selectTradeboxFocusedInput); + const uiFeeFactor = q(selectUiFeeFactor); + const collateralTokenAddress = q(selectTradeboxCollateralTokenAddress); + + const fromToken = fromTokenAddress ? getByKey(tokensData, fromTokenAddress) : undefined; + const fromTokenAmount = fromToken ? parseValue(fromTokenInputValue || "0", fromToken.decimals)! : BigNumber.from(0); + const toToken = toTokenAddress ? getByKey(tokensData, toTokenAddress) : undefined; + const toTokenAmount = toToken ? parseValue(toTokenInputValue || "0", toToken.decimals)! : BigNumber.from(0); + const tradeFlags = createTradeFlags(TradeType.Swap, tradeMode); + const isWrapOrUnwrap = q(selectTradeboxIsWrapOrUnwrap); + + const fromTokenPrice = fromToken?.prices.minPrice; + + if (!fromToken || !toToken || !fromTokenPrice) { + return undefined; + } + + const { findSwapPath } = q( + makeSelectSwapRoutes(fromTokenAddress, tradeFlags.isPosition ? collateralTokenAddress : toTokenAddress) + ); + const triggerRatioInputValue = q(selectTradeboxTriggerRatioInputValue); + const triggerRatioValue = parseValue(triggerRatioInputValue, USD_DECIMALS); + + const { markRatio, triggerRatio } = q( + makeSelectTradeRatios({ + fromTokenAddress, + toTokenAddress, + tradeMode, + tradeType: TradeType.Swap, + triggerRatioValue, + }) + ); + + if (isWrapOrUnwrap) { + const tokenAmount = amountBy === "from" ? fromTokenAmount : toTokenAmount; + const usdAmount = convertToUsd(tokenAmount, fromToken.decimals, fromTokenPrice)!; + const price = fromTokenPrice; + + const swapAmounts: SwapAmounts = { + amountIn: tokenAmount, + usdIn: usdAmount!, + amountOut: tokenAmount, + usdOut: usdAmount!, + swapPathStats: undefined, + priceIn: price, + priceOut: price, + minOutputAmount: tokenAmount, + }; + + return swapAmounts; + } else if (amountBy === "from") { + return getSwapAmountsByFromValue({ + tokenIn: fromToken, + tokenOut: toToken, + amountIn: fromTokenAmount, + triggerRatio: triggerRatio || markRatio, + isLimit: tradeFlags.isLimit, + findSwapPath: findSwapPath, + uiFeeFactor, + }); + } else { + return getSwapAmountsByToValue({ + tokenIn: fromToken, + tokenOut: toToken, + amountOut: toTokenAmount, + triggerRatio: triggerRatio || markRatio, + isLimit: tradeFlags.isLimit, + findSwapPath: findSwapPath, + uiFeeFactor, + }); + } +}); + +export const selectTradeboxTradeFlags = createSelector( + [selectTradeboxTradeType, selectTradeboxTradeMode], + (tradeType, tradeMode) => { + const tradeFlags = createTradeFlags(tradeType, tradeMode); + return tradeFlags; + } +); + +export const selectTradeboxLeverage = createSelector([selectTradeboxLeverageOption], (leverageOption) => + BigNumber.from(parseInt(String(Number(leverageOption!) * BASIS_POINTS_DIVISOR))) +); + +export const selectTradeboxNextPositionValuesForIncrease = createEnhancedSelector((q) => { + const tokensData = q(selectTokensData); + const tradeMode = q(selectTradeboxTradeMode); + const tradeType = q(selectTradeboxTradeType); + const fromTokenAddress = q(selectTradeboxFromTokenAddress); + const fromTokenInputValue = q(selectTradeboxFromTokenInputValue); + const toTokenAddress = q(selectTradeboxToTokenAddress); + const toTokenInputValue = q(selectTradeboxToTokenInputValue); + const marketAddress = q(selectTradeboxMarketAddress); + const leverageOption = q(selectTradeboxLeverageOption); + const isLeverageEnabled = q(selectTradeboxIsLeverageEnabled); + const focusedInput = q(selectTradeboxFocusedInput); + const collateralTokenAddress = q(selectTradeboxCollateralTokenAddress); + const selectedTriggerAcceptablePriceImpactBps = q(selectTradeboxSelectedTriggerAcceptablePriceImpactBps); + const triggerPriceInputValue = q(selectTradeboxTriggerPriceInputValue); + const positionKey = q(selectTradeboxSelectedPositionKey); + + const tradeFlags = createTradeFlags(tradeType, tradeMode); + const fromToken = fromTokenAddress ? getByKey(tokensData, fromTokenAddress) : undefined; + const fromTokenAmount = fromToken ? parseValue(fromTokenInputValue || "0", fromToken.decimals)! : BigNumber.from(0); + const toToken = toTokenAddress ? getByKey(tokensData, toTokenAddress) : undefined; + const toTokenAmount = toToken ? parseValue(toTokenInputValue || "0", toToken.decimals)! : BigNumber.from(0); + const leverage = BigNumber.from(parseInt(String(Number(leverageOption!) * BASIS_POINTS_DIVISOR))); + const triggerPrice = parseValue(triggerPriceInputValue, USD_DECIMALS); + const selector = makeSelectNextPositionValuesForIncrease({ + collateralTokenAddress, + fixedAcceptablePriceImpactBps: selectedTriggerAcceptablePriceImpactBps, + indexTokenAddress: toTokenAddress, + indexTokenAmount: toTokenAmount, + initialCollateralAmount: fromTokenAmount, + initialCollateralTokenAddress: fromTokenAddress, + leverage, + marketAddress, + positionKey, + increaseStrategy: isLeverageEnabled + ? focusedInput === "from" + ? "leverageByCollateral" + : "leverageBySize" + : "independent", + tradeMode, + tradeType, + triggerPrice, + tokenTypeForSwapRoute: tradeFlags.isPosition ? "collateralToken" : "indexToken", + }); + + return q(selector); +}); + +export const selectTradeboxNextPositionValuesForDecrease = createEnhancedSelector((q) => { + const tradeMode = q(selectTradeboxTradeMode); + const tradeType = q(selectTradeboxTradeType); + const collateralTokenAddress = q(selectTradeboxCollateralTokenAddress); + const marketAddress = q(selectTradeboxMarketAddress); + const triggerPriceInputValue = q(selectTradeboxTriggerPriceInputValue); + const closeSizeInputValue = q(selectTradeboxCloseSizeInputValue); + const keepLeverage = q(selectTradeboxKeepLeverage); + const selectedTriggerAcceptablePriceImpactBps = q(selectTradeboxSelectedTriggerAcceptablePriceImpactBps); + const positionKey = q(selectTradeboxSelectedPositionKey); + + const closeSizeUsd = parseValue(closeSizeInputValue || "0", USD_DECIMALS)!; + const triggerPrice = parseValue(triggerPriceInputValue, USD_DECIMALS); + + const selector = makeSelectNextPositionValuesForDecrease({ + collateralTokenAddress: collateralTokenAddress, + fixedAcceptablePriceImpactBps: selectedTriggerAcceptablePriceImpactBps, + marketAddress, + positionKey, + tradeMode, + tradeType, + triggerPrice, + closeSizeUsd, + keepLeverage, + }); + + return q(selector); +}); + +export const selectTradeboxSelectedPositionKey = createSelector( + [selectAccount, selectTradeboxCollateralTokenAddress, selectTradeboxMarketAddress, selectTradeboxTradeFlags], + (account, collateralAddress, marketAddress, tradeFlags) => { + if (!account || !collateralAddress || !marketAddress) { + return undefined; + } + + return getPositionKey(account, marketAddress, collateralAddress, tradeFlags.isLong); + } +); + +export const selectTradeboxSelectedPosition = createSelector( + [selectTradeboxSelectedPositionKey, selectPositionsInfoData], + (selectedPositionKey, positionsInfoData) => getByKey(positionsInfoData, selectedPositionKey) +); + +export const selectTradeboxExistingOrder = createSelector( + [selectTradeboxSelectedPositionKey, selectOrdersInfoData], + (selectedPositionKey, ordersInfoData) => { + if (!selectedPositionKey) { + return undefined; + } + + return Object.values(ordersInfoData || {}) + .filter((order) => !isSwapOrderType(order.orderType)) + .find((order) => { + if (isSwapOrderType(order.orderType)) { + return false; + } + + return ( + getPositionKey(order.account, order.marketAddress, order.targetCollateralToken.address, order.isLong) === + selectedPositionKey + ); + }); + } +); diff --git a/src/context/SyntheticsStateContext/utils.ts b/src/context/SyntheticsStateContext/utils.ts new file mode 100644 index 0000000000..6eb915819b --- /dev/null +++ b/src/context/SyntheticsStateContext/utils.ts @@ -0,0 +1,9 @@ +import { createSelector as createSelectorCommon } from "lib/selectors"; +import { createSelectionContext } from "@taskworld.com/rereselect"; +import { SyntheticsTradeState } from "./SyntheticsStateContextProvider"; +export { useSyntheticsStateSelector as useSelector } from "./SyntheticsStateContextProvider"; + +export const createSelector = createSelectorCommon.withTypes(); +const context = createSelectionContext(); + +export const createEnhancedSelector = context.makeSelector; diff --git a/src/domain/referrals/hooks/index.ts b/src/domain/referrals/hooks/index.ts index 3de24bc701..f3dfaedbba 100644 --- a/src/domain/referrals/hooks/index.ts +++ b/src/domain/referrals/hooks/index.ts @@ -55,7 +55,7 @@ async function getCodeOwnersData(network, account, codes = []) { }); } -export function useUserReferralInfo( +export function useUserReferralInfoRequest( signer: Signer | undefined, chainId: number, account?: string | null, diff --git a/src/domain/rewards/useAccumulatedBnGMXAmount.ts b/src/domain/rewards/useAccumulatedBnGMXAmount.ts new file mode 100644 index 0000000000..3c0c0997bc --- /dev/null +++ b/src/domain/rewards/useAccumulatedBnGMXAmount.ts @@ -0,0 +1,9 @@ +import { useClaimableBnGMXAmount } from "domain/rewards/useClaimableBnGMXAmount"; +import { useUnstakedBnGMXAmount } from "domain/rewards/useUnstakedBnGMXAmount"; + +export function useAccumulatedBnGMXAmount() { + const claimableBnGMXAmount = useClaimableBnGMXAmount(); + const unstakedBnGMXAmount = useUnstakedBnGMXAmount(); + + return unstakedBnGMXAmount && claimableBnGMXAmount?.add(unstakedBnGMXAmount); +} diff --git a/src/domain/rewards/useClaimableBnGMXAmount.ts b/src/domain/rewards/useClaimableBnGMXAmount.ts new file mode 100644 index 0000000000..b368429e32 --- /dev/null +++ b/src/domain/rewards/useClaimableBnGMXAmount.ts @@ -0,0 +1,22 @@ +import useSWR from "swr"; + +import { useChainId } from "lib/chains"; +import { contractFetcher } from "lib/contracts"; +import useWallet from "lib/wallets/useWallet"; +import RewardTracker from "abis/RewardTracker.json"; +import { getContract } from "config/contracts"; + +export function useClaimableBnGMXAmount() { + const { signer, active, account } = useWallet(); + const { chainId } = useChainId(); + const feeGmxTrackerAddress = getContract(chainId, "BonusGmxTracker"); + + const { data: claimableBnGMXAmount } = useSWR( + [`claimableBnGMXAmount:${active}`, chainId, feeGmxTrackerAddress, "claimable", account], + { + fetcher: contractFetcher(signer, RewardTracker), + } + ); + + return claimableBnGMXAmount; +} diff --git a/src/domain/rewards/useMaxBoostBasisPoints.ts b/src/domain/rewards/useMaxBoostBasisPoints.ts new file mode 100644 index 0000000000..d2443216c0 --- /dev/null +++ b/src/domain/rewards/useMaxBoostBasisPoints.ts @@ -0,0 +1,19 @@ +import useSWR from "swr"; + +import { useChainId } from "lib/chains"; +import { contractFetcher } from "lib/contracts"; +import useWallet from "lib/wallets/useWallet"; +import RewardRouter from "abis/RewardRouter.json"; +import { getContract } from "config/contracts"; + +export function useMaxBoostBasicPoints() { + const { signer, active } = useWallet(); + const { chainId } = useChainId(); + const rewardRouterAddress = getContract(chainId, "RewardRouter"); + + const { data: maxBoostPoints } = useSWR([active, chainId, rewardRouterAddress, "maxBoostBasisPoints"], { + fetcher: contractFetcher(signer, RewardRouter), + }); + + return maxBoostPoints; +} diff --git a/src/domain/rewards/useUnstakedBnGMXAmount.ts b/src/domain/rewards/useUnstakedBnGMXAmount.ts new file mode 100644 index 0000000000..f666a4fea4 --- /dev/null +++ b/src/domain/rewards/useUnstakedBnGMXAmount.ts @@ -0,0 +1,22 @@ +import useSWR from "swr"; + +import { useChainId } from "lib/chains"; +import { contractFetcher } from "lib/contracts"; +import useWallet from "lib/wallets/useWallet"; +import { getContract } from "config/contracts"; +import Token from "abis/Token.json"; + +export function useUnstakedBnGMXAmount() { + const { signer, active, account } = useWallet(); + const { chainId } = useChainId(); + const bnGmxAddress = getContract(chainId, "BN_GMX"); + + const { data: unstakedBnGmx } = useSWR( + [`unstakedBnGMXAmount:${active}`, chainId, bnGmxAddress, "balanceOf", account], + { + fetcher: contractFetcher(signer, Token), + } + ); + + return unstakedBnGmx; +} diff --git a/src/domain/stake/useRecommendStakeGmxAmount.ts b/src/domain/stake/useRecommendStakeGmxAmount.ts new file mode 100644 index 0000000000..cab34fce46 --- /dev/null +++ b/src/domain/stake/useRecommendStakeGmxAmount.ts @@ -0,0 +1,46 @@ +import { BigNumber } from "ethers"; +import { BN_ZERO } from "lib/numbers"; +import { BASIS_POINTS_DIVISOR } from "config/factors"; + +import { useMaxBoostBasicPoints } from "domain/rewards/useMaxBoostBasisPoints"; + +export function useRecommendStakeGmxAmount( + p: { + accumulatedGMX?: BigNumber; + accumulatedBnGMX?: BigNumber; + accumulatedEsGMX?: BigNumber; + stakedGMX?: BigNumber; + stakedBnGMX?: BigNumber; + stakedEsGMX?: BigNumber; + }, + conditions: { + shouldStakeGmx?: boolean; + shouldStakeEsGmx?: boolean; + } +) { + const maxBoostBasicPoints = useMaxBoostBasicPoints(); + + const accumulatedGMX = p.accumulatedGMX ?? BN_ZERO; + const accumulatedBnGMX = p.accumulatedBnGMX ?? BN_ZERO; + const accumulatedEsGMX = p.accumulatedEsGMX ?? BN_ZERO; + const stakedGMX = p.stakedGMX ?? BN_ZERO; + const stakedBnGMX = p.stakedBnGMX ?? BN_ZERO; + const stakedEsGMX = p.stakedEsGMX ?? BN_ZERO; + + const nextTotalBnGMX = stakedBnGMX.add(accumulatedBnGMX); + let nextTotalGmx = stakedGMX.add(stakedEsGMX); + + if (conditions.shouldStakeGmx) { + nextTotalGmx = nextTotalGmx.add(accumulatedGMX); + } + + if (conditions.shouldStakeEsGmx) { + nextTotalGmx = nextTotalGmx.add(accumulatedEsGMX); + } + + if (nextTotalGmx.gt(0) && nextTotalBnGMX.mul(BASIS_POINTS_DIVISOR).div(nextTotalGmx).gt(maxBoostBasicPoints)) { + return nextTotalBnGMX.mul(BASIS_POINTS_DIVISOR).div(maxBoostBasicPoints).sub(nextTotalGmx); + } + + return BN_ZERO; +} diff --git a/src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts b/src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts new file mode 100644 index 0000000000..405ddaa811 --- /dev/null +++ b/src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts @@ -0,0 +1,35 @@ +import { t } from "@lingui/macro"; +import ExchangeRouter from "abis/ExchangeRouter.json"; +import { getContract } from "config/contracts"; +import { Signer, ethers } from "ethers"; +import { callContract } from "lib/contracts"; +import { RebateInfoItem } from "../fees/useRebatesInfo"; + +export type ClaimPriceImpactRebateParams = { + account: string; + claimablePositionPriceImpactFees: RebateInfoItem[]; +}; + +export async function createClaimCollateralTxn( + chainId: number, + signer: Signer, + { account, claimablePositionPriceImpactFees }: ClaimPriceImpactRebateParams +) { + const exchangeRouter = new ethers.Contract(getContract(chainId, "ExchangeRouter"), ExchangeRouter.abi, signer); + + const args: [markets: string[], tokens: string[], timeKeys: number[], account: string] = [[], [], [], account]; + + claimablePositionPriceImpactFees.forEach((p) => { + args[0].push(p.marketAddress); + args[1].push(p.tokenAddress); + args[2].push(Number(p.timeKey)); + }); + + const txn = await callContract(chainId, exchangeRouter, "claimCollateral", args, { + sentMsg: t`Claiming Price Impact Rebate...`, + successMsg: t`Price Impact Rebate Claimed`, + failMsg: t`Failed to Claim Price Impact Rebate`, + }); + + return txn; +} diff --git a/src/domain/synthetics/claimHistory/useClaimHistory.ts b/src/domain/synthetics/claimHistory/useClaimHistory.ts index 1a0659dc36..26b8a7c23b 100644 --- a/src/domain/synthetics/claimHistory/useClaimHistory.ts +++ b/src/domain/synthetics/claimHistory/useClaimHistory.ts @@ -1,17 +1,17 @@ import { gql } from "@apollo/client"; +import { getToken } from "config/tokens"; +import { useMarketsInfoData, useTokensData } from "context/SyntheticsStateContext/hooks/globalsHooks"; import { MarketsInfoData } from "domain/synthetics/markets"; -import { TokensData } from "domain/synthetics/tokens"; import { BigNumber } from "ethers"; +import { getAddress } from "ethers/lib/utils.js"; import { bigNumberify } from "lib/numbers"; import { getByKey } from "lib/objects"; import { getSyntheticsGraphClient } from "lib/subgraph"; +import useWallet from "lib/wallets/useWallet"; import { useMemo } from "react"; import useSWR from "swr"; import { useFixedAddreseses } from "../common/useFixedAddresses"; import { ClaimAction, ClaimCollateralAction, ClaimFundingFeeAction, ClaimMarketItem, ClaimType } from "./types"; -import useWallet from "lib/wallets/useWallet"; -import { getAddress } from "ethers/lib/utils.js"; -import { getToken } from "config/tokens"; export type ClaimCollateralHistoryResult = { claimActions?: ClaimAction[]; @@ -34,9 +34,11 @@ type RawClaimAction = { export function useClaimCollateralHistory( chainId: number, - p: { marketsInfoData?: MarketsInfoData; tokensData?: TokensData; pageIndex: number; pageSize: number } + p: { pageIndex: number; pageSize: number } ): ClaimCollateralHistoryResult { - const { pageIndex, pageSize, marketsInfoData, tokensData } = p; + const { pageIndex, pageSize } = p; + const marketsInfoData = useMarketsInfoData(); + const tokensData = useTokensData(); const { account } = useWallet(); const fixedAddresses = useFixedAddreseses(marketsInfoData, tokensData); @@ -73,7 +75,7 @@ export function useClaimCollateralHistory( const { data } = await client!.query({ query, fetchPolicy: "no-cache" }); - return data?.claimActions as RawClaimAction[]; + return data.claimActions as RawClaimAction[]; }, }); diff --git a/src/domain/synthetics/common/useBigNumberInput.ts b/src/domain/synthetics/common/useBigNumberInput.ts index 447815fc21..bb3093e472 100644 --- a/src/domain/synthetics/common/useBigNumberInput.ts +++ b/src/domain/synthetics/common/useBigNumberInput.ts @@ -41,32 +41,32 @@ function stringToNumber(value: string, decimals: number) { } export function useBigNumberInput(initialValue: BigNumber | null, decimals: number, displayDecimals: number) { - const [value, setRawValue] = useState(initialValue); - const [displayValue, setRawDisplayValue] = useState(() => numberToString(initialValue, decimals, displayDecimals)); + const [value, setValue] = useState(initialValue); + const [displayValue, setDisplayValue] = useState(() => numberToString(initialValue, decimals, displayDecimals)); - const setValue = useCallback( + const setValueWrapped = useCallback( (newValue: BigNumber | null) => { - setRawValue(newValue); - setRawDisplayValue(numberToString(newValue, decimals, displayDecimals)); + setValue(newValue); + setDisplayValue(numberToString(newValue, decimals, displayDecimals)); }, [decimals, displayDecimals] ); - const setDisplayValue = useCallback( + const setDisplayValueWrapped = useCallback( (newValue: string) => { const number = stringToNumber(newValue, decimals); - setRawDisplayValue(newValue); - setRawValue(number); + setDisplayValue(newValue); + setValue(number); }, [decimals] ); return { value, - setValue, + setValue: setValueWrapped, displayValue, - setDisplayValue, + setDisplayValue: setDisplayValueWrapped, isEmpty: !displayValue.trim(), }; } diff --git a/src/domain/synthetics/fees/useRebatesInfo.ts b/src/domain/synthetics/fees/useRebatesInfo.ts new file mode 100644 index 0000000000..f393354956 --- /dev/null +++ b/src/domain/synthetics/fees/useRebatesInfo.ts @@ -0,0 +1,110 @@ +import { gql } from "@apollo/client"; +import { BigNumber } from "ethers"; +import { getAddress } from "ethers/lib/utils.js"; +import { expandDecimals } from "lib/numbers"; +import { getSyntheticsGraphClient } from "lib/subgraph"; +import useWallet from "lib/wallets/useWallet"; +import { useMemo } from "react"; +import useSWR from "swr"; + +type RawClaimableCollateral = { + marketAddress: string; + tokenAddress: string; + timeKey: string; + value: string; + factor: string; + factorByTime: string; + id: string; +}; + +export type RebateInfoItem = { + factor: BigNumber; + value: BigNumber; + marketAddress: string; + timeKey: string; + tokenAddress: string; + valueByFactor: BigNumber; + id: string; +}; + +export type RebatesInfoResult = { + accruedPositionPriceImpactFees: RebateInfoItem[]; + claimablePositionPriceImpactFees: RebateInfoItem[]; +}; + +export function useRebatesInfo(chainId: number): RebatesInfoResult { + const { account } = useWallet(); + const client = getSyntheticsGraphClient(chainId); + + const key = chainId && client && account ? [chainId, "useRebatesInfo", account] : null; + + const { data } = useSWR(key, { + fetcher: async () => { + const query = gql(`{ + claimableCollaterals( + where: { account: "${account!.toLowerCase()}", claimed: false } + ) { + id + marketAddress + tokenAddress + timeKey + value + factor + factorByTime + } + }`); + + const { data } = await client!.query({ query, fetchPolicy: "no-cache" }); + + return data.claimableCollaterals as RawClaimableCollateral[]; + }, + }); + + const { accruedPositionPriceImpactFees, claimablePositionPriceImpactFees } = useMemo(() => { + const res: { + accruedPositionPriceImpactFees: RebateInfoItem[]; + claimablePositionPriceImpactFees: RebateInfoItem[]; + } = { accruedPositionPriceImpactFees: [], claimablePositionPriceImpactFees: [] }; + + data?.forEach((rawRebateInfo) => { + let factor = BigNumber.from(rawRebateInfo.factor); + const factorByTime = BigNumber.from(rawRebateInfo.factorByTime); + + if (factorByTime.gt(factor)) { + factor = factorByTime; + } + + const value = BigNumber.from(rawRebateInfo.value); + const valueByFactor = value.mul(factor).div(expandDecimals(1, 30)); + + const rebateInfo: RebateInfoItem = { + factor, + value, + valueByFactor, + timeKey: rawRebateInfo.timeKey, + marketAddress: getAddress(rawRebateInfo.marketAddress), + tokenAddress: getAddress(rawRebateInfo.tokenAddress), + id: rawRebateInfo.id, + }; + + if (factor.gt(0) && valueByFactor.eq(0)) { + // this is claimable entity but factor is too small + // skipping to avoid CollateralAlreadyClaimed error + return; + } + + if (rebateInfo.factor.eq(0)) { + res.accruedPositionPriceImpactFees.push(rebateInfo); + } else { + res.claimablePositionPriceImpactFees.push(rebateInfo); + } + }); + + return res; + }, [data]); + + return { + accruedPositionPriceImpactFees, + claimablePositionPriceImpactFees, + }; +} diff --git a/src/domain/synthetics/fees/utils/executionFee.ts b/src/domain/synthetics/fees/utils/executionFee.ts index 0bc100b6dc..89856d34c2 100644 --- a/src/domain/synthetics/fees/utils/executionFee.ts +++ b/src/domain/synthetics/fees/utils/executionFee.ts @@ -1,5 +1,5 @@ import { t } from "@lingui/macro"; -import { getChainName, getHighExecutionFee } from "config/chains"; +import { getChainName, getHighExecutionFee, getExcessiveExecutionFee } from "config/chains"; import { NATIVE_TOKEN_ADDRESS } from "config/tokens"; import { TokensData, convertToUsd, getTokenData } from "domain/synthetics/tokens"; import { BigNumber } from "ethers"; @@ -27,12 +27,16 @@ export function getExecutionFee( const feeUsd = convertToUsd(feeTokenAmount, nativeToken.decimals, nativeToken.prices.minPrice)!; const isFeeHigh = feeUsd.gt(expandDecimals(getHighExecutionFee(chainId), USD_DECIMALS)); + const isFeeVeryHigh = feeUsd.gt(expandDecimals(getExcessiveExecutionFee(chainId), USD_DECIMALS)); - const warning = isFeeHigh - ? t`The network Fees are very high currently, which may be due to a temporary increase in transactions on the ${getChainName( - chainId - )} network.` - : undefined; + const highWarning = t`The network Fees are high currently, which may be due to a temporary increase in transactions on the ${getChainName( + chainId + )} network.`; + const veryHighWarning = t`The network Fees are very high currently, which may be due to a temporary increase in transactions on the ${getChainName( + chainId + )} network.`; + + const warning = isFeeVeryHigh ? veryHighWarning : isFeeHigh ? highWarning : undefined; return { feeUsd, diff --git a/src/domain/synthetics/fees/utils/useUiFeeFactor.ts b/src/domain/synthetics/fees/utils/useUiFeeFactor.ts index 51db279fcb..4472389d26 100644 --- a/src/domain/synthetics/fees/utils/useUiFeeFactor.ts +++ b/src/domain/synthetics/fees/utils/useUiFeeFactor.ts @@ -5,7 +5,8 @@ import { uiFeeFactorKey } from "config/dataStore"; import { BigNumber } from "ethers"; import { UI_FEE_RECEIVER_ACCOUNT } from "config/ui"; -export default function useUiFeeFactor(chainId: number, account = UI_FEE_RECEIVER_ACCOUNT) { +export default function useUiFeeFactor(chainId: number) { + const account = UI_FEE_RECEIVER_ACCOUNT; const { data: uiFeeFactorForAccount } = useMulticall(chainId, "uiFeeFactorForAccount", { key: account ? [account] : null, refreshInterval: 60000, diff --git a/src/domain/synthetics/markets/claimCollateralTxn.ts b/src/domain/synthetics/markets/claimFundingFeesTxn.ts similarity index 91% rename from src/domain/synthetics/markets/claimCollateralTxn.ts rename to src/domain/synthetics/markets/claimFundingFeesTxn.ts index 47c6fe6e52..218f7dfaf8 100644 --- a/src/domain/synthetics/markets/claimCollateralTxn.ts +++ b/src/domain/synthetics/markets/claimFundingFeesTxn.ts @@ -13,7 +13,7 @@ type Params = { setPendingTxns: (txns: any) => void; }; -export function claimCollateralTxn(chainId: number, signer: Signer, p: Params) { +export function claimFundingFeesTxn(chainId: number, signer: Signer, p: Params) { const { setPendingTxns, fundingFees, account } = p; const contract = new ethers.Contract(getContract(chainId, "ExchangeRouter"), ExchangeRouter.abi, signer); diff --git a/src/domain/synthetics/markets/index.ts b/src/domain/synthetics/markets/index.ts index a898c7dfb1..2ab256535b 100644 --- a/src/domain/synthetics/markets/index.ts +++ b/src/domain/synthetics/markets/index.ts @@ -4,4 +4,4 @@ export * from "./createDepositTxn"; export * from "./createWithdrawalTxn"; export * from "./useMarketTokensData"; export * from "./useMarkets"; -export * from "./useMarketsInfo"; +export * from "./useMarketsInfoRequest"; diff --git a/src/domain/synthetics/markets/useMarketTokensAPR.ts b/src/domain/synthetics/markets/useMarketTokensAPR.ts index 48e566ae2b..592459bab9 100644 --- a/src/domain/synthetics/markets/useMarketTokensAPR.ts +++ b/src/domain/synthetics/markets/useMarketTokensAPR.ts @@ -7,8 +7,8 @@ import { expandDecimals } from "lib/numbers"; import { getSyntheticsGraphClient } from "lib/subgraph"; import { useMemo } from "react"; import useSWR from "swr"; -import { useMarketsInfo } from "."; -import { useTokensData } from "../tokens"; +import { useMarketsInfoRequest } from "."; +import { useTokensDataRequest } from "../tokens"; import { MarketTokensAPRData } from "./types"; import { useMarketTokensData } from "./useMarketTokensData"; import { getByKey } from "lib/objects"; @@ -31,7 +31,7 @@ type SwrResult = { }; function useMarketAddresses(chainId: number) { - const { marketsInfoData } = useMarketsInfo(chainId); + const { marketsInfoData } = useMarketsInfoRequest(chainId); return useMemo( () => Object.keys(marketsInfoData || {}).filter((address) => !marketsInfoData![address].isDisabled), [marketsInfoData] @@ -40,9 +40,9 @@ function useMarketAddresses(chainId: number) { function useIncentivesBonusApr(chainId: number): MarketTokensAPRData { const rawIncentivesStats = useIncentiveStats(chainId); - const { tokensData } = useTokensData(chainId); + const { tokensData } = useTokensDataRequest(chainId); const marketAddresses = useMarketAddresses(chainId); - const { marketsInfoData } = useMarketsInfo(chainId); + const { marketsInfoData } = useMarketsInfoRequest(chainId); return useMemo(() => { let arbTokenAddress: null | string = null; diff --git a/src/domain/synthetics/markets/useMarketTokensData.ts b/src/domain/synthetics/markets/useMarketTokensData.ts index f2147fb15d..c97d5be39b 100644 --- a/src/domain/synthetics/markets/useMarketTokensData.ts +++ b/src/domain/synthetics/markets/useMarketTokensData.ts @@ -4,7 +4,7 @@ import { getExplorerUrl } from "config/chains"; import { getContract } from "config/contracts"; import { MAX_PNL_FACTOR_FOR_DEPOSITS_KEY, MAX_PNL_FACTOR_FOR_WITHDRAWALS_KEY } from "config/dataStore"; import { getTokenBySymbol } from "config/tokens"; -import { TokensData, useTokensData } from "domain/synthetics/tokens"; +import { TokensData, useTokensDataRequest } from "domain/synthetics/tokens"; import { BigNumber } from "ethers"; import { USD_DECIMALS } from "lib/legacy"; import { useMulticall } from "lib/multicall"; @@ -21,7 +21,7 @@ type MarketTokensDataResult = { export function useMarketTokensData(chainId: number, p: { isDeposit: boolean }): MarketTokensDataResult { const { isDeposit } = p; const { account } = useWallet(); - const { tokensData, pricesUpdatedAt } = useTokensData(chainId); + const { tokensData, pricesUpdatedAt } = useTokensDataRequest(chainId); const { marketsData, marketsAddresses } = useMarkets(chainId); const isDataLoaded = tokensData && marketsAddresses?.length; diff --git a/src/domain/synthetics/markets/useMarkets.ts b/src/domain/synthetics/markets/useMarkets.ts index c1a65fa2ed..3fb3d94711 100644 --- a/src/domain/synthetics/markets/useMarkets.ts +++ b/src/domain/synthetics/markets/useMarkets.ts @@ -7,7 +7,7 @@ import { useMulticall } from "lib/multicall"; import { MarketsData } from "./types"; import { getMarketFullName } from "./utils"; -type MarketsResult = { +export type MarketsResult = { marketsData?: MarketsData; marketsAddresses?: string[]; }; @@ -16,7 +16,7 @@ const MARKETS_COUNT = 100; export function useMarkets(chainId: number): MarketsResult { const { data } = useMulticall(chainId, "useMarketsData", { - key: [], + key: [chainId], refreshInterval: 60000, diff --git a/src/domain/synthetics/markets/useMarketsInfo.ts b/src/domain/synthetics/markets/useMarketsInfoRequest.ts similarity index 99% rename from src/domain/synthetics/markets/useMarketsInfo.ts rename to src/domain/synthetics/markets/useMarketsInfoRequest.ts index 0c251f1b01..59819d5b05 100644 --- a/src/domain/synthetics/markets/useMarketsInfo.ts +++ b/src/domain/synthetics/markets/useMarketsInfoRequest.ts @@ -46,7 +46,7 @@ import { convertTokenAddress } from "config/tokens"; import { BigNumber } from "ethers"; import { useMulticall } from "lib/multicall"; import { getByKey } from "lib/objects"; -import { TokensData, useTokensData } from "../tokens"; +import { TokensData, useTokensDataRequest } from "../tokens"; import { MarketsInfoData } from "./types"; import { useMarkets } from "./useMarkets"; import { getContractMarketPrices } from "./utils"; @@ -58,10 +58,10 @@ export type MarketsInfoResult = { pricesUpdatedAt?: number; }; -export function useMarketsInfo(chainId: number): MarketsInfoResult { +export function useMarketsInfoRequest(chainId: number): MarketsInfoResult { const { account } = useWallet(); const { marketsData, marketsAddresses } = useMarkets(chainId); - const { tokensData, pricesUpdatedAt } = useTokensData(chainId); + const { tokensData, pricesUpdatedAt } = useTokensDataRequest(chainId); const dataStoreAddress = getContract(chainId, "DataStore"); const isDepencenciesLoading = !marketsAddresses || !tokensData; diff --git a/src/domain/synthetics/markets/useUserEarnings.ts b/src/domain/synthetics/markets/useUserEarnings.ts index ee24259946..0b50f3de72 100644 --- a/src/domain/synthetics/markets/useUserEarnings.ts +++ b/src/domain/synthetics/markets/useUserEarnings.ts @@ -9,7 +9,7 @@ import { UserEarningsData } from "./types"; import { useDaysConsideredInMarketsApr } from "./useDaysConsideredInMarketsApr"; import { useMarketTokensAPR } from "./useMarketTokensAPR"; import { useMarketTokensData } from "./useMarketTokensData"; -import { useMarketsInfo } from "./useMarketsInfo"; +import { useMarketsInfoRequest } from "./useMarketsInfoRequest"; type RawBalanceChange = { cumulativeIncome: string; @@ -28,7 +28,7 @@ type RawCollectedMarketFeesInfo = { }; export const useUserEarnings = (chainId: number) => { - const { marketsInfoData } = useMarketsInfo(chainId); + const { marketsInfoData } = useMarketsInfoRequest(chainId); const { marketTokensData } = useMarketTokensData(chainId, { isDeposit: true }); const client = getSyntheticsGraphClient(chainId); diff --git a/src/domain/synthetics/orders/createDecreaseOrderTxn.ts b/src/domain/synthetics/orders/createDecreaseOrderTxn.ts index c35e8f6523..b9e2519b14 100644 --- a/src/domain/synthetics/orders/createDecreaseOrderTxn.ts +++ b/src/domain/synthetics/orders/createDecreaseOrderTxn.ts @@ -11,10 +11,10 @@ import { applySlippageToMinOut, applySlippageToPrice } from "../trade"; import { PriceOverrides, simulateExecuteOrderTxn } from "./simulateExecuteOrderTxn"; import { DecreasePositionSwapType, OrderType } from "./types"; import { isMarketOrderType } from "./utils"; -import { UI_FEE_RECEIVER_ACCOUNT } from "config/ui"; import { t } from "@lingui/macro"; import { Subaccount } from "context/SubaccountContext/SubaccountContext"; import { getSubaccountRouterContract } from "../subaccount/getSubaccountContract"; +import { UI_FEE_RECEIVER_ACCOUNT } from "config/ui"; const { AddressZero } = ethers.constants; @@ -62,7 +62,7 @@ export async function createDecreaseOrderTxn( const orderVaultAddress = getContract(chainId, "OrderVault"); const totalWntAmount = ps.reduce((acc, p) => acc.add(p.executionFee), BigNumber.from(0)); const account = ps[0].account; - const encodedPayload = createEncodedPayload({ + const encodedPayload = createDecreaseEncodedPayload({ router, orderVaultAddress, ps, @@ -70,7 +70,7 @@ export async function createDecreaseOrderTxn( mainAccountAddress: account, chainId, }); - const simulationEncodedPayload = createEncodedPayload({ + const simulationEncodedPayload = createDecreaseEncodedPayload({ router: exchangeRouter, orderVaultAddress, ps, @@ -133,7 +133,7 @@ export async function createDecreaseOrderTxn( return txn; } -function getPendingOrderFromParams(chainId: number, p: DecreaseOrderParams) { +export function getPendingOrderFromParams(chainId: number, p: DecreaseOrderParams) { const isNativeReceive = p.receiveTokenAddress === NATIVE_TOKEN_ADDRESS; const shouldApplySlippage = isMarketOrderType(p.orderType); @@ -173,7 +173,7 @@ function getPendingPositionFromParams( }; } -function createEncodedPayload({ +export function createDecreaseEncodedPayload({ router, orderVaultAddress, ps, diff --git a/src/domain/synthetics/orders/createIncreaseOrderTxn.ts b/src/domain/synthetics/orders/createIncreaseOrderTxn.ts index ba15a09dd9..0cd07a65ba 100644 --- a/src/domain/synthetics/orders/createIncreaseOrderTxn.ts +++ b/src/domain/synthetics/orders/createIncreaseOrderTxn.ts @@ -14,6 +14,7 @@ import { UI_FEE_RECEIVER_ACCOUNT } from "config/ui"; import { t } from "@lingui/macro"; import { getSubaccountRouterContract } from "../subaccount/getSubaccountContract"; import { Subaccount } from "context/SubaccountContext/SubaccountContext"; +import { DecreaseOrderParams, createDecreaseEncodedPayload, getPendingOrderFromParams } from "./createDecreaseOrderTxn"; const { AddressZero } = ethers.constants; @@ -46,7 +47,8 @@ export async function createIncreaseOrderTxn( chainId: number, signer: Signer, subaccount: Subaccount, - p: IncreaseOrderParams + p: IncreaseOrderParams, + decreaseOrderParams?: DecreaseOrderParams[] ) { const isNativePayment = p.initialCollateralAddress === NATIVE_TOKEN_ADDRESS; subaccount = isNativePayment ? null : subaccount; @@ -55,17 +57,19 @@ export async function createIncreaseOrderTxn( const router = subaccount ? getSubaccountRouterContract(chainId, subaccount.signer) : exchangeRouter; const orderVaultAddress = getContract(chainId, "OrderVault"); const wntCollateralAmount = isNativePayment ? p.initialCollateralAmount : BigNumber.from(0); - const totalWntAmount = wntCollateralAmount.add(p.executionFee); const initialCollateralTokenAddress = convertTokenAddress(chainId, p.initialCollateralAddress, "wrapped"); const shouldApplySlippage = isMarketOrderType(p.orderType); const acceptablePrice = shouldApplySlippage ? applySlippageToPrice(p.allowedSlippage, p.acceptablePrice, true, p.isLong) : p.acceptablePrice; + const wntAmountToIncrease = wntCollateralAmount.add(p.executionFee); + const totalWntAmount = (decreaseOrderParams || []).reduce((acc, p) => acc.add(p.executionFee), wntAmountToIncrease); + const encodedPayload = await createEncodedPayload({ router, orderVaultAddress, - totalWntAmount, + totalWntAmount: wntAmountToIncrease, p, acceptablePrice, subaccount, @@ -76,7 +80,7 @@ export async function createIncreaseOrderTxn( const simulationEncodedPayload = await createEncodedPayload({ router: exchangeRouter, orderVaultAddress, - totalWntAmount, + totalWntAmount: wntAmountToIncrease, p, acceptablePrice, subaccount: null, @@ -84,6 +88,16 @@ export async function createIncreaseOrderTxn( initialCollateralTokenAddress, signer, }); + + const decreaseEncodedPayload = createDecreaseEncodedPayload({ + router, + orderVaultAddress, + ps: decreaseOrderParams || [], + subaccount, + mainAccountAddress: p.account, + chainId, + }); + const secondaryPriceOverrides: PriceOverrides = {}; const primaryPriceOverrides: PriceOverrides = {}; @@ -106,9 +120,10 @@ export async function createIncreaseOrderTxn( }); } + const finalPayload = [...encodedPayload, ...decreaseEncodedPayload]; const txnCreatedAt = Date.now(); const txnCreatedAtBlock = await signer.provider?.getBlockNumber(); - const txn = await callContract(chainId, router, "multicall", [encodedPayload], { + const txn = await callContract(chainId, router, "multicall", [finalPayload], { value: totalWntAmount, hideSentMsg: true, hideSuccessMsg: true, @@ -128,7 +143,7 @@ export async function createIncreaseOrderTxn( }); } - p.setPendingOrder({ + const increaseOrder = { account: p.account, marketAddress: p.marketAddress, initialCollateralTokenAddress, @@ -139,7 +154,10 @@ export async function createIncreaseOrderTxn( isLong: p.isLong, orderType: p.orderType, shouldUnwrapNativeToken: isNativePayment, - }); + }; + const orders = decreaseOrderParams?.map((p) => getPendingOrderFromParams(chainId, p)) || []; + + p.setPendingOrder([increaseOrder, ...orders]); }); return txn; diff --git a/src/domain/synthetics/orders/index.ts b/src/domain/synthetics/orders/index.ts index ab4818d577..d905f3e106 100644 --- a/src/domain/synthetics/orders/index.ts +++ b/src/domain/synthetics/orders/index.ts @@ -3,3 +3,4 @@ export * from "./types"; export * from "./createDecreaseOrderTxn"; export * from "./createIncreaseOrderTxn"; export * from "./createSwapOrderTxn"; +export * from "./updateOrderTxn"; diff --git a/src/domain/synthetics/orders/updateOrderTxn.ts b/src/domain/synthetics/orders/updateOrderTxn.ts index a4eb639c07..b1637ddfdc 100644 --- a/src/domain/synthetics/orders/updateOrderTxn.ts +++ b/src/domain/synthetics/orders/updateOrderTxn.ts @@ -1,12 +1,13 @@ import { t } from "@lingui/macro"; +import { BigNumber, Signer, ethers } from "ethers"; + import ExchangeRouter from "abis/ExchangeRouter.json"; import { getContract } from "config/contracts"; -import { BigNumber, Signer, ethers } from "ethers"; -import { callContract } from "lib/contracts"; -import { convertToContractPrice } from "../tokens"; -import { Token } from "domain/tokens"; import { Subaccount } from "context/SubaccountContext/SubaccountContext"; -import { getSubaccountRouterContract } from "../subaccount/getSubaccountContract"; +import { getSubaccountRouterContract } from "domain/synthetics/subaccount/getSubaccountContract"; +import { convertToContractPrice } from "domain/synthetics/tokens"; +import { Token } from "domain/tokens"; +import { callContract } from "lib/contracts"; export type UpdateOrderParams = { orderKey: string; @@ -20,7 +21,12 @@ export type UpdateOrderParams = { setPendingTxns: (txns: any) => void; }; -export function updateOrderTxn(chainId: number, signer: Signer, subaccount: Subaccount, p: UpdateOrderParams) { +export function updateOrderTxn( + chainId: number, + signer: Signer, + subaccount: Subaccount, + p: UpdateOrderParams +): Promise { const { orderKey, sizeDeltaUsd, @@ -39,7 +45,7 @@ export function updateOrderTxn(chainId: number, signer: Signer, subaccount: Suba const orderVaultAddress = getContract(chainId, "OrderVault"); const multicall: { method: string; params: any[] }[] = []; - if (p.executionFee?.gt(0)) { + if (executionFee?.gt(0)) { multicall.push({ method: "sendWnt", params: [orderVaultAddress, executionFee] }); } multicall.push({ @@ -58,7 +64,7 @@ export function updateOrderTxn(chainId: number, signer: Signer, subaccount: Suba .map((call) => router.interface.encodeFunctionData(call!.method, call!.params)); return callContract(chainId, router, "multicall", [encodedPayload], { - value: p.executionFee?.gt(0) ? p.executionFee : undefined, + value: executionFee?.gt(0) ? executionFee : undefined, sentMsg: t`Updating order`, successMsg: t`Update order executed`, failMsg: t`Failed to update order`, diff --git a/src/domain/synthetics/orders/useOrderEntries.ts b/src/domain/synthetics/orders/useOrderEntries.ts new file mode 100644 index 0000000000..dd6fe8d225 --- /dev/null +++ b/src/domain/synthetics/orders/useOrderEntries.ts @@ -0,0 +1,89 @@ +import { NUMBER_WITH_TWO_DECIMALS } from "components/PercentageInput/PercentageInput"; +import { removeTrailingZeros } from "lib/numbers"; +import { uniqueId } from "lodash"; +import { useCallback, useMemo, useState } from "react"; + +const MAX_PERCENTAGE = 100; + +export type OrderEntry = { + id: string; + price: string; + percentage: string; + error?: null | { + price?: string; + percentage?: string; + }; +}; + +export type OrderEntriesInfo = { + entries: OrderEntry[]; + addEntry: () => void; + canAddEntry: boolean; + updateEntry: (id: string, updatedEntry: Partial) => void; + deleteEntry: (id: string) => void; + reset: () => void; +}; + +function getDefaultEntry(id: string, override?: Partial) { + return { id: uniqueId(id), price: "", percentage: "100", error: null, ...override }; +} + +export default function useOrderEntries( + id: string, + errorHandler: (entry: Partial) => Partial +): OrderEntriesInfo { + const [entries, setEntries] = useState([getDefaultEntry(id)]); + + const totalPercentage = useMemo(() => { + return entries.reduce((total, entry) => total + Number(entry.percentage), 0); + }, [entries]); + + const addEntry = useCallback(() => { + if (totalPercentage <= MAX_PERCENTAGE) { + const leftPercentage = MAX_PERCENTAGE - totalPercentage; + setEntries((prevEntries) => [...prevEntries, getDefaultEntry(id, { percentage: String(leftPercentage) })]); + } + }, [totalPercentage, id]); + + const updateEntry = useCallback( + (id: string, updatedEntry: Partial) => { + setEntries((prevEntries) => { + const totalExcludingCurrent = prevEntries.reduce( + (total, entry) => total + (entry.id !== id ? Number(entry.percentage) : 0), + 0 + ); + + if (totalExcludingCurrent + Number(updatedEntry.percentage) > MAX_PERCENTAGE) { + const remainingPercentage = String(removeTrailingZeros((MAX_PERCENTAGE - totalExcludingCurrent).toFixed(2))); + + if (NUMBER_WITH_TWO_DECIMALS.test(remainingPercentage)) { + updatedEntry.percentage = remainingPercentage; + } + } + + return prevEntries.map((entry) => + entry.id === id ? { ...entry, ...updatedEntry, ...errorHandler(updatedEntry) } : entry + ); + }); + }, + [errorHandler] + ); + + const reset = useCallback(() => setEntries([getDefaultEntry(id)]), [id]); + + const deleteEntry = useCallback( + (id: string) => { + setEntries((prevEntries) => { + if (prevEntries.length > 1) { + return prevEntries.filter((entry) => entry.id !== id); + } else { + reset(); + return prevEntries; + } + }); + }, + [reset] + ); + + return { entries, addEntry, updateEntry, deleteEntry, reset, canAddEntry: totalPercentage <= MAX_PERCENTAGE }; +} diff --git a/src/domain/synthetics/orders/useOrdersInfo.ts b/src/domain/synthetics/orders/useOrdersInfo.ts index c55e80ab32..f8a6354160 100644 --- a/src/domain/synthetics/orders/useOrdersInfo.ts +++ b/src/domain/synthetics/orders/useOrdersInfo.ts @@ -8,12 +8,12 @@ import { OrdersInfoData } from "./types"; import { useOrders } from "./useOrders"; import { getOrderInfo, isVisibleOrder } from "./utils"; -type AggregatedOrdersDataResult = { +export type AggregatedOrdersDataResult = { ordersInfoData?: OrdersInfoData; isLoading: boolean; }; -export function useOrdersInfo( +export function useOrdersInfoRequest( chainId: number, p: { marketsInfoData?: MarketsInfoData; diff --git a/src/domain/synthetics/orders/useSLTPEntries.ts b/src/domain/synthetics/orders/useSLTPEntries.ts new file mode 100644 index 0000000000..4bc7d9ebdb --- /dev/null +++ b/src/domain/synthetics/orders/useSLTPEntries.ts @@ -0,0 +1,329 @@ +import { useCallback, useMemo } from "react"; +import { + DecreasePositionAmounts, + IncreasePositionAmounts, + NextPositionValues, + TradeFlags, + getDecreasePositionAmounts, +} from "domain/synthetics/trade"; +import { parseValue } from "lib/numbers"; +import { USD_DECIMALS, getPositionKey } from "lib/legacy"; +import { MarketInfo } from "../markets"; +import { PositionInfo, getPendingMockPosition } from "../positions"; +import { TokenData } from "../tokens"; +import { BASIS_POINTS_DIVISOR } from "config/factors"; +import useWallet from "lib/wallets/useWallet"; +import { t } from "@lingui/macro"; +import { BigNumber } from "ethers"; +import useOrderEntries, { OrderEntriesInfo, OrderEntry } from "./useOrderEntries"; +import { + usePositionsConstants, + useUiFeeFactor, + useUserReferralInfo, +} from "context/SyntheticsStateContext/hooks/globalsHooks"; + +type SLTPEntry = OrderEntry & { + amounts?: DecreasePositionAmounts; +}; + +export type SLTPInfo = Omit & { + entries: SLTPEntry[]; + totalPnL: BigNumber; + totalPnLPercentage: BigNumber; +}; + +type Props = { + tradeFlags: TradeFlags; + marketInfo?: MarketInfo; + collateralToken?: TokenData; + increaseAmounts?: IncreasePositionAmounts; + nextPositionValues?: NextPositionValues; + triggerPrice?: BigNumber; +}; + +export default function useSLTPEntries({ + marketInfo, + tradeFlags, + collateralToken, + increaseAmounts, + nextPositionValues, + triggerPrice, +}: Props) { + const { isLong, isLimit } = tradeFlags; + const { account } = useWallet(); + const userReferralInfo = useUserReferralInfo(); + const { minCollateralUsd, minPositionSizeUsd } = usePositionsConstants(); + const uiFeeFactor = useUiFeeFactor(); + + const { handleSLErrors, handleTPErrors } = createErrorHandlers({ + liqPrice: nextPositionValues?.nextLiqPrice, + entryPrice: isLimit ? triggerPrice : nextPositionValues?.nextEntryPrice, + isLong, + isLimit, + }); + + const stopLossEntriesInfo = useOrderEntries("sl_", handleSLErrors); + const takeProfitEntriesInfo = useOrderEntries("tp_", handleTPErrors); + + const positionKey = useMemo(() => { + if (!account || !marketInfo || !collateralToken) { + return undefined; + } + + return getPositionKey(account, marketInfo.marketTokenAddress, collateralToken.address, isLong); + }, [account, collateralToken, isLong, marketInfo]); + + const currentPosition = useMemo(() => { + if (!positionKey || !collateralToken || !marketInfo) return; + + return getPendingMockPosition({ + isIncrease: true, + positionKey, + sizeDeltaUsd: increaseAmounts?.sizeDeltaUsd || BigNumber.from(0), + sizeDeltaInTokens: increaseAmounts?.sizeDeltaInTokens || BigNumber.from(0), + collateralDeltaAmount: increaseAmounts?.collateralDeltaAmount || BigNumber.from(0), + updatedAt: Date.now(), + updatedAtBlock: BigNumber.from(0), + }); + }, [positionKey, collateralToken, increaseAmounts, marketInfo]); + + const currentPositionInfo: PositionInfo | undefined = useMemo(() => { + if (!marketInfo || !collateralToken || !increaseAmounts || !currentPosition || !nextPositionValues) return; + + return { + ...currentPosition, + marketInfo, + indexToken: marketInfo.indexToken, + collateralToken, + pnlToken: isLong ? marketInfo.longToken : marketInfo.shortToken, + markPrice: nextPositionValues.nextEntryPrice!, + entryPrice: nextPositionValues.nextEntryPrice, + triggerPrice: isLimit ? triggerPrice : undefined, + liquidationPrice: nextPositionValues.nextLiqPrice, + collateralUsd: increaseAmounts?.initialCollateralUsd, + remainingCollateralUsd: increaseAmounts?.collateralDeltaUsd, + remainingCollateralAmount: increaseAmounts?.collateralDeltaAmount, + netValue: increaseAmounts?.collateralDeltaUsd, + hasLowCollateral: false, + leverage: nextPositionValues.nextLeverage, + leverageWithPnl: nextPositionValues.nextLeverage, + pnl: BigNumber.from(0), + pnlPercentage: BigNumber.from(0), + pnlAfterFees: BigNumber.from(0), + pnlAfterFeesPercentage: BigNumber.from(0), + closingFeeUsd: BigNumber.from(0), + uiFeeUsd: BigNumber.from(0), + pendingFundingFeesUsd: BigNumber.from(0), + pendingClaimableFundingFeesUsd: BigNumber.from(0), + }; + }, [ + collateralToken, + increaseAmounts, + isLong, + marketInfo, + nextPositionValues, + currentPosition, + isLimit, + triggerPrice, + ]); + + const getDecreaseAmountsFromEntry = useCallback( + (entry: OrderEntry) => { + if (!Number(entry.price) || !entry.percentage || entry.error) { + return; + } + + if ( + !increaseAmounts || + !marketInfo || + !collateralToken || + !currentPositionInfo || + !minPositionSizeUsd || + !minCollateralUsd + ) { + return; + } + + const percentage = Math.floor(Number.parseFloat(entry.percentage) * 100); + const sizeUsd = increaseAmounts.sizeDeltaUsd.mul(percentage).div(BASIS_POINTS_DIVISOR); + const price = parseValue(entry.price, USD_DECIMALS); + + return getDecreasePositionAmounts({ + marketInfo, + collateralToken, + isLong, + position: currentPositionInfo, + closeSizeUsd: sizeUsd, + keepLeverage: true, + triggerPrice: price, + userReferralInfo, + minCollateralUsd, + minPositionSizeUsd, + uiFeeFactor, + isLimit, + limitPrice: triggerPrice, + }); + }, + [ + collateralToken, + currentPositionInfo, + increaseAmounts, + isLong, + isLimit, + marketInfo, + triggerPrice, + minCollateralUsd, + minPositionSizeUsd, + uiFeeFactor, + userReferralInfo, + ] + ); + + const stopLoss = useMemo(() => { + const entries = stopLossEntriesInfo.entries.map((entry) => { + return { + ...entry, + amounts: getDecreaseAmountsFromEntry(entry), + }; + }); + + const totalPnL = entries.reduce((acc, entry) => acc.add(entry.amounts?.realizedPnl || 0), BigNumber.from(0)); + const totalPnLPercentage = entries.reduce( + (acc, entry) => acc.add(entry.amounts?.realizedPnlPercentage || 0), + BigNumber.from(0) + ); + + return { + ...stopLossEntriesInfo, + entries, + totalPnL, + totalPnLPercentage, + }; + }, [getDecreaseAmountsFromEntry, stopLossEntriesInfo]); + + const takeProfit = useMemo(() => { + const entries = takeProfitEntriesInfo.entries.map((entry) => { + return { + ...entry, + amounts: getDecreaseAmountsFromEntry(entry), + }; + }); + + const totalPnL = entries.reduce((acc, entry) => acc.add(entry.amounts?.realizedPnl || 0), BigNumber.from(0)); + const totalPnLPercentage = entries.reduce( + (acc, entry) => acc.add(entry.amounts?.realizedPnlPercentage || 0), + BigNumber.from(0) + ); + + return { + ...takeProfitEntriesInfo, + entries, + totalPnL, + totalPnLPercentage, + }; + }, [getDecreaseAmountsFromEntry, takeProfitEntriesInfo]); + + return { + stopLoss, + takeProfit, + }; +} + +function createErrorHandlers({ + liqPrice, + entryPrice, + isLong, + isLimit, +}: { + liqPrice?: BigNumber; + entryPrice?: BigNumber; + isLong?: boolean; + isLimit?: boolean; +}) { + function getErrorHandler(entry: Partial, isStopLoss: boolean): Partial { + if (!liqPrice || !entryPrice || !entry.price || parseFloat(entry.price) === 0) { + return { ...entry, error: null }; + } + + const inputPrice = parseValue(entry.price, USD_DECIMALS); + + const isPriceAboveMark = inputPrice?.gte(entryPrice); + const isPriceBelowMark = inputPrice?.lte(entryPrice); + const priceLiqError = isLong ? t`Price below Liq. Price.` : t`Price above Liq. Price.`; + const priceAboveMsg = isLimit ? t`Price above Limit Price.` : t`Price above Mark Price.`; + const priceBelowMsg = isLimit ? t`Price below Limit Price.` : t`Price below Mark Price.`; + + if (isStopLoss) { + if (inputPrice?.lte(liqPrice) && isLong) { + return { + ...entry, + error: { + price: priceLiqError, + }, + }; + } + if (inputPrice?.gte(liqPrice) && !isLong) { + return { + ...entry, + error: { + price: priceLiqError, + }, + }; + } + + if (isPriceAboveMark && isLong) { + return { + ...entry, + error: { + price: priceAboveMsg, + }, + }; + } + + if (isPriceBelowMark && !isLong) { + return { + ...entry, + error: { + price: priceBelowMsg, + }, + }; + } + } + + if (!isStopLoss) { + if (isPriceBelowMark && isLong) { + return { + ...entry, + error: { + price: priceBelowMsg, + }, + }; + } + + if (isPriceAboveMark && !isLong) { + return { + ...entry, + error: { + price: priceAboveMsg, + }, + }; + } + } + + if (inputPrice?.gt(0) && (!entry.percentage || parseFloat(entry.percentage) === 0)) { + return { + ...entry, + error: { + percentage: t`A Size percentage is required.`, + }, + }; + } + + return { ...entry, error: null }; + } + + const handleSLErrors = (entry: Partial) => getErrorHandler(entry, true); + const handleTPErrors = (entry: Partial) => getErrorHandler(entry, false); + + return { handleSLErrors, handleTPErrors }; +} diff --git a/src/domain/synthetics/orders/utils.ts b/src/domain/synthetics/orders/utils.ts index d1e4c36022..861f674d58 100644 --- a/src/domain/synthetics/orders/utils.ts +++ b/src/domain/synthetics/orders/utils.ts @@ -31,7 +31,10 @@ export function isOrderForPosition(order: OrderInfo, positionKey: string): order // For limit orders, we need to check the target collateral token if (isLimitOrderType(order.orderType)) { - isMatch = isMatch && order.targetCollateralToken.address === collateralAddress; + const targetCollateralTokenAddress = order.targetCollateralToken.isNative + ? order.targetCollateralToken.wrappedAddress + : order.targetCollateralToken.address; + isMatch = isMatch && targetCollateralTokenAddress === collateralAddress; } else if (isTriggerDecreaseOrderType(order.orderType)) { isMatch = isMatch && order.initialCollateralTokenAddress === collateralAddress; } @@ -131,7 +134,6 @@ export function getOrderInfo(p: { if (isSwapOrderType(order.orderType)) { const initialCollateralToken = getByKey(tokensData, order.initialCollateralTokenAddress); - const { outTokenAddress } = getSwapPathOutputAddresses({ marketsInfoData, swapPath: order.swapPath, @@ -211,6 +213,7 @@ export function getOrderInfo(p: { } else { const marketInfo = getByKey(marketsInfoData, order.marketAddress); const indexToken = marketInfo?.indexToken; + const initialCollateralToken = getByKey(tokensData, order.initialCollateralTokenAddress); const { outTokenAddress } = getSwapPathOutputAddresses({ marketsInfoData, @@ -219,6 +222,7 @@ export function getOrderInfo(p: { wrappedNativeTokenAddress: wrappedNativeToken.address, shouldUnwrapNativeToken: order.shouldUnwrapNativeToken, }); + const targetCollateralToken = getByKey(tokensData, outTokenAddress); if (!marketInfo || !indexToken || !initialCollateralToken || !targetCollateralToken) { @@ -346,16 +350,14 @@ export function getOrderErrors(p: { }); if (currentAcceptablePriceDeltaBps.lt(0) && currentAcceptablePriceDeltaBps.lt(orderAcceptablePriceDeltaBps)) { - const priceText = positionOrder.orderType === OrderType.LimitIncrease ? t`Limit Price` : t`Trigger Price`; - const suggestionType = positionOrder.orderType === OrderType.LimitIncrease ? t`Limit` : t`Take-Profit`; + const priceText = positionOrder.orderType === OrderType.LimitIncrease ? t`limit price` : t`trigger price`; + const formattedCurrentAcceptablePriceImpact = formatPercentage(currentAcceptablePriceDeltaBps, { signed: true }); + const formattedOrderAcceptablePriceImpact = formatPercentage(orderAcceptablePriceDeltaBps, { + signed: true, + }); errors.push({ - msg: t`The Order may not execute at the desired ${priceText} as the current Price Impact ${formatPercentage( - currentAcceptablePriceDeltaBps, - { signed: true } - )} is higher than its Acceptable Price Impact ${formatPercentage(orderAcceptablePriceDeltaBps, { - signed: true, - })}. Consider canceling and creating a new ${suggestionType} Order.`, + msg: t`The order may not execute at the desired ${priceText} as its acceptable price impact is set to ${formattedOrderAcceptablePriceImpact}, which is lower than the current market price impact of ${formattedCurrentAcceptablePriceImpact}. It can be edited using the "Edit" button.`, level: "warning", }); } @@ -394,16 +396,17 @@ export function getOrderErrors(p: { } if (!position) { + const collateralSymbol = order.targetCollateralToken.symbol; const sameMarketPosition = Object.values(positionsInfoData || {}).find( (pos) => pos.marketAddress === order.marketAddress && pos.isLong === order.isLong ); - const longText = sameMarketPosition?.isLong ? t`Long` : t`Short`; + const symbol = sameMarketPosition?.collateralToken.symbol; + const longText = sameMarketPosition?.isLong ? t`long` : t`short`; if (sameMarketPosition) { errors.push({ - msg: t`You have an existing ${longText} position with ${sameMarketPosition?.collateralToken.symbol} as Collateral. This Order will not - be valid for that Position.`, + msg: t`This order using ${collateralSymbol} as collateral will not be valid for the existing ${longText} position using ${symbol} as collateral.`, level: "warning", }); } @@ -418,7 +421,7 @@ export function getOrderErrors(p: { if (isInvalidTriggerPrice) { errors.push({ - msg: t`Order Trigger Price is beyond position's Liquidation Price.`, + msg: t`The order will not be executed as its trigger price is beyond the position's liquidation price.`, level: "error", }); } @@ -464,3 +467,48 @@ export function getOrderErrors(p: { level, }; } + +function getTokenIndex(token: Token, referenceArray: string[]): number { + return referenceArray.indexOf( + token.wrappedAddress && referenceArray.includes(token.wrappedAddress) ? token.wrappedAddress : token.address + ); +} + +export function sortPositionOrders(orders: PositionOrderInfo[], tokenSortOrder?: string[]): PositionOrderInfo[] { + return orders.sort((a, b) => { + if (tokenSortOrder) { + const indexA = getTokenIndex(a.marketInfo.indexToken, tokenSortOrder); + const indexB = getTokenIndex(b.marketInfo.indexToken, tokenSortOrder); + if (indexA !== indexB) return indexA - indexB; + } else { + const nameComparison = a.marketInfo.name.localeCompare(b.marketInfo.name); + if (nameComparison) return nameComparison; + } + + // Compare by trigger price + const triggerPriceComparison = a.triggerPrice.sub(b.triggerPrice); + if (!triggerPriceComparison.isZero()) return triggerPriceComparison.isNegative() ? -1 : 1; + + // Compare by order type + const orderTypeComparison = a.orderType - b.orderType; + if (orderTypeComparison) return orderTypeComparison; + + // Finally, sort by size delta USD + return b.sizeDeltaUsd.sub(a.sizeDeltaUsd).isNegative() ? -1 : 1; + }); +} + +export function sortSwapOrders(orders: SwapOrderInfo[], tokenSortOrder?: string[]): SwapOrderInfo[] { + return orders.sort((a, b) => { + if (tokenSortOrder) { + const indexA = getTokenIndex(a.targetCollateralToken, tokenSortOrder); + const indexB = getTokenIndex(b.targetCollateralToken, tokenSortOrder); + if (indexA !== indexB) return indexA - indexB; + } else { + const collateralComparison = a.targetCollateralToken.symbol.localeCompare(b.targetCollateralToken.symbol); + if (collateralComparison) return collateralComparison; + } + + return a.minOutputAmount.sub(b.minOutputAmount).isNegative() ? -1 : 1; + }); +} diff --git a/src/domain/synthetics/positions/usePositions.ts b/src/domain/synthetics/positions/usePositions.ts index b682404bd8..b29c47706b 100644 --- a/src/domain/synthetics/positions/usePositions.ts +++ b/src/domain/synthetics/positions/usePositions.ts @@ -285,7 +285,7 @@ function applyEventChanges(position: Position, event: PositionIncreaseEvent | Po return nextPosition; } -function getPendingMockPosition(pendingUpdate: PendingPositionUpdate): Position { +export function getPendingMockPosition(pendingUpdate: PendingPositionUpdate): Position { const { account, marketAddress, collateralAddress, isLong } = parsePositionKey(pendingUpdate.positionKey); return { diff --git a/src/domain/synthetics/positions/usePositionsConstants.ts b/src/domain/synthetics/positions/usePositionsConstants.ts index 6764901ddd..d9d5ab4c21 100644 --- a/src/domain/synthetics/positions/usePositionsConstants.ts +++ b/src/domain/synthetics/positions/usePositionsConstants.ts @@ -9,7 +9,7 @@ export type PositionsConstantsResult = { minPositionSizeUsd?: BigNumber; }; -export function usePositionsConstants(chainId: number): PositionsConstantsResult { +export function usePositionsConstantsRequest(chainId: number): PositionsConstantsResult { const { data } = useMulticall(chainId, "usePositionsConstants", { key: [], diff --git a/src/domain/synthetics/positions/usePositionsInfo.ts b/src/domain/synthetics/positions/usePositionsInfo.ts index 315f9a7f78..e26f57f0b9 100644 --- a/src/domain/synthetics/positions/usePositionsInfo.ts +++ b/src/domain/synthetics/positions/usePositionsInfo.ts @@ -1,4 +1,4 @@ -import { useUserReferralInfo } from "domain/referrals"; +import { useUserReferralInfoRequest } from "domain/referrals"; import { BigNumber } from "ethers"; import { MAX_ALLOWED_LEVERAGE } from "config/factors"; import { getBasisPoints } from "lib/numbers"; @@ -9,7 +9,7 @@ import { MarketsInfoData } from "../markets"; import { TokensData, convertToTokenAmount, convertToUsd } from "../tokens"; import { getMarkPrice } from "../trade"; import { PositionsInfoData } from "./types"; -import { usePositionsConstants } from "./usePositionsConstants"; +import { usePositionsConstantsRequest } from "./usePositionsConstants"; import { getEntryPrice, getLeverage, @@ -22,12 +22,12 @@ import { usePositions } from "./usePositions"; import useWallet from "lib/wallets/useWallet"; import useUiFeeFactor from "../fees/utils/useUiFeeFactor"; -type PositionsInfoResult = { +export type PositionsInfoResult = { positionsInfoData?: PositionsInfoData; isLoading: boolean; }; -export function usePositionsInfo( +export function usePositionsInfoRequest( chainId: number, p: { account: string | null | undefined; @@ -42,9 +42,9 @@ export function usePositionsInfo( const { signer } = useWallet(); const { positionsData } = usePositions(chainId, p); - const { minCollateralUsd } = usePositionsConstants(chainId); + const { minCollateralUsd } = usePositionsConstantsRequest(chainId); const uiFeeFactor = useUiFeeFactor(chainId); - const userReferralInfo = useUserReferralInfo(signer, chainId, account, skipLocalReferralCode); + const userReferralInfo = useUserReferralInfoRequest(signer, chainId, account, skipLocalReferralCode); return useMemo(() => { if (!marketsInfoData || !tokensData || !positionsData || !minCollateralUsd) { diff --git a/src/domain/synthetics/stats/useV2Stats.ts b/src/domain/synthetics/stats/useV2Stats.ts index b0f84259bf..fa683c84d9 100644 --- a/src/domain/synthetics/stats/useV2Stats.ts +++ b/src/domain/synthetics/stats/useV2Stats.ts @@ -3,7 +3,7 @@ import { BigNumber } from "ethers"; import useVolumeInfo from "../stats/useVolumeInfo"; import useFeesInfo from "../stats/useFeesInfo"; import useUsers from "../stats/useUsers"; -import { useMarketsInfo } from "../markets"; +import { useMarketsInfoRequest } from "../markets"; type DashboardOverview = { totalGMLiquidity: BigNumber; @@ -20,7 +20,7 @@ type DashboardOverview = { export default function useV2Stats(chainId: number): DashboardOverview { const volumeInfo = useVolumeInfo(chainId); const feesInfo = useFeesInfo(chainId); - const { marketsInfoData } = useMarketsInfo(chainId); + const { marketsInfoData } = useMarketsInfoRequest(chainId); const usersInfo = useUsers(chainId); const stats = useMemo(() => { diff --git a/src/domain/synthetics/tokens/index.ts b/src/domain/synthetics/tokens/index.ts index 006395556f..b9b21fe44b 100644 --- a/src/domain/synthetics/tokens/index.ts +++ b/src/domain/synthetics/tokens/index.ts @@ -2,7 +2,7 @@ export * from "./types"; export * from "./useTokenAllowanceData"; export * from "./useTokenBalances"; export * from "./useTokenRecentPricesData"; -export * from "./useTokensData"; +export * from "./useTokensDataRequest"; export * from "./use24PriceDelta"; export * from "./useOracleKeeperFetcher"; export * from "./utils"; diff --git a/src/domain/synthetics/tokens/useTokensData.ts b/src/domain/synthetics/tokens/useTokensDataRequest.ts similarity index 94% rename from src/domain/synthetics/tokens/useTokensData.ts rename to src/domain/synthetics/tokens/useTokensDataRequest.ts index 453d00c420..a510c094ce 100644 --- a/src/domain/synthetics/tokens/useTokensData.ts +++ b/src/domain/synthetics/tokens/useTokensDataRequest.ts @@ -9,7 +9,7 @@ type TokensDataResult = { pricesUpdatedAt?: number; }; -export function useTokensData(chainId: number): TokensDataResult { +export function useTokensDataRequest(chainId: number): TokensDataResult { const tokenConfigs = getTokensMap(chainId); const { balancesData } = useTokenBalances(chainId); const { pricesData, updatedAt: pricesUpdatedAt } = useTokenRecentPrices(chainId); diff --git a/src/domain/synthetics/trade/index.ts b/src/domain/synthetics/trade/index.ts index 5b6fb3d349..c27c7dce12 100644 --- a/src/domain/synthetics/trade/index.ts +++ b/src/domain/synthetics/trade/index.ts @@ -1,4 +1,3 @@ export * from "./utils"; export * from "./useAvailableTokenOptions"; -export * from "./useSwapRoute"; export * from "./types"; diff --git a/src/domain/synthetics/trade/types.ts b/src/domain/synthetics/trade/types.ts index c5396f928b..8f835e85c8 100644 --- a/src/domain/synthetics/trade/types.ts +++ b/src/domain/synthetics/trade/types.ts @@ -20,6 +20,17 @@ export enum TriggerThresholdType { Below = "<", } +export type TradeFlags = { + isLong: boolean; + isShort: boolean; + isSwap: boolean; + isPosition: boolean; + isIncrease: boolean; + isTrigger: boolean; + isMarket: boolean; + isLimit: boolean; +}; + export type SwapAmounts = { amountIn: BigNumber; usdIn: BigNumber; @@ -82,6 +93,7 @@ export type DecreasePositionAmounts = { estimatedPnl: BigNumber; estimatedPnlPercentage: BigNumber; realizedPnl: BigNumber; + realizedPnlPercentage: BigNumber; positionFeeUsd: BigNumber; uiFeeUsd: BigNumber; @@ -208,6 +220,7 @@ export type TradeFees = { positionFee?: FeeItem; swapPriceImpact?: FeeItem; positionPriceImpact?: FeeItem; + priceImpactDiff?: FeeItem; positionFeeFactor?: BigNumber; borrowFee?: FeeItem; fundingFee?: FeeItem; diff --git a/src/domain/synthetics/trade/useAvailableMarketsOptions.ts b/src/domain/synthetics/trade/useAvailableMarketsOptions.ts index 03878e49d3..facc8f9c24 100644 --- a/src/domain/synthetics/trade/useAvailableMarketsOptions.ts +++ b/src/domain/synthetics/trade/useAvailableMarketsOptions.ts @@ -1,19 +1,22 @@ +import { + useMarketsInfoData, + useOrdersInfoData, + usePositionsInfoData, +} from "context/SyntheticsStateContext/hooks/globalsHooks"; import { MarketInfo, - MarketsInfoData, getAvailableUsdLiquidityForPosition, getMinPriceImpactMarket, getMostLiquidMarketForPosition, isMarketIndexToken, } from "domain/synthetics/markets"; -import { PositionsInfoData } from "domain/synthetics/positions"; import { TokenData } from "domain/synthetics/tokens"; import { BigNumber } from "ethers"; import { USD_DECIMALS } from "lib/legacy"; import { expandDecimals } from "lib/numbers"; import { getByKey } from "lib/objects"; import { useMemo } from "react"; -import { OrdersInfoData, PositionOrderInfo, isIncreaseOrderType } from "../orders"; +import { PositionOrderInfo, isIncreaseOrderType } from "../orders"; import { getAcceptablePriceByPriceImpact, getMarkPrice } from "./utils"; export type AvailableMarketsOptions = { @@ -30,29 +33,18 @@ export type AvailableMarketsOptions = { }; export function useAvailableMarketsOptions(p: { - marketsInfoData?: MarketsInfoData; isIncrease: boolean; disable?: boolean; indexToken: TokenData | undefined; isLong: boolean; increaseSizeUsd: BigNumber | undefined; - positionsInfo: PositionsInfoData | undefined; - ordersInfo: OrdersInfoData | undefined; hasExistingPosition: boolean; hasExistingOrder: boolean; }): AvailableMarketsOptions { - const { - marketsInfoData, - disable, - positionsInfo, - ordersInfo, - hasExistingPosition, - hasExistingOrder, - isIncrease, - indexToken, - increaseSizeUsd, - isLong, - } = p; + const { disable, hasExistingPosition, hasExistingOrder, isIncrease, indexToken, increaseSizeUsd, isLong } = p; + const marketsInfoData = useMarketsInfoData(); + const positionsInfo = usePositionsInfoData(); + const ordersInfo = useOrdersInfoData(); return useMemo(() => { if (disable || !indexToken || isLong === undefined) { diff --git a/src/domain/synthetics/trade/useHighExecutionFeeConsent.tsx b/src/domain/synthetics/trade/useHighExecutionFeeConsent.tsx new file mode 100644 index 0000000000..0c923f18ee --- /dev/null +++ b/src/domain/synthetics/trade/useHighExecutionFeeConsent.tsx @@ -0,0 +1,31 @@ +import { Trans } from "@lingui/macro"; +import Checkbox from "components/Checkbox/Checkbox"; +import { getExcessiveExecutionFee } from "config/chains"; +import { BigNumber } from "ethers"; +import { useChainId } from "lib/chains"; +import { USD_DECIMALS } from "lib/legacy"; +import { expandDecimals } from "lib/numbers"; +import { useMemo, useState } from "react"; + +export function useHighExecutionFeeConsent(executionFeeUsd: BigNumber | undefined) { + const [isHighExecutionFeeAccepted, setIsHighExecutionFeeAccepted] = useState(false); + const { chainId } = useChainId(); + const veryHighExecutionFeeUsd = useMemo( + () => expandDecimals(getExcessiveExecutionFee(chainId), USD_DECIMALS), + [chainId] + ); + const shouldAccept = executionFeeUsd?.gte(veryHighExecutionFeeUsd); + + return { + isHighFeeConsentError: shouldAccept && !isHighExecutionFeeAccepted, + element: shouldAccept ? ( +
    + + + Acknowledge very high network Fees + + +
    + ) : null, + }; +} diff --git a/src/domain/synthetics/trade/usePriceImpactWarningState.ts b/src/domain/synthetics/trade/usePriceImpactWarningState.ts index 4038021174..5939470f76 100644 --- a/src/domain/synthetics/trade/usePriceImpactWarningState.ts +++ b/src/domain/synthetics/trade/usePriceImpactWarningState.ts @@ -1,23 +1,23 @@ import { HIGH_POSITION_IMPACT_BPS, HIGH_SWAP_IMPACT_BPS } from "config/factors"; +import { museNeverExist } from "lib/types"; +import { usePrevious } from "lib/usePrevious"; import { useEffect, useMemo, useState } from "react"; import shallowEqual from "shallowequal"; import { FeeItem } from "../fees"; -import { TradeFlags } from "./useTradeFlags"; -import { museNeverExist } from "lib/types"; -import { usePrevious } from "lib/usePrevious"; +import { TradeFlags } from "./types"; export type PriceImpactWarningState = ReturnType; export function usePriceImpactWarningState({ positionPriceImpact, swapPriceImpact, - tradeFlags, place, + tradeFlags, }: { positionPriceImpact?: FeeItem; swapPriceImpact?: FeeItem; - tradeFlags: TradeFlags; place: "tradeBox" | "positionSeller" | "confirmationBox"; + tradeFlags: TradeFlags; }) { const [isHighPositionImpactAccepted, setIsHighPositionImpactAccepted] = useState(false); const [isHighSwapImpactAccepted, setIsHighSwapImpactAccepted] = useState(false); diff --git a/src/domain/synthetics/trade/useSwapRoute.ts b/src/domain/synthetics/trade/useSwapRoute.ts deleted file mode 100644 index 35d790e18b..0000000000 --- a/src/domain/synthetics/trade/useSwapRoute.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { NATIVE_TOKEN_ADDRESS, convertTokenAddress, getWrappedToken } from "config/tokens"; -import { MarketsInfoData } from "domain/synthetics/markets"; -import { BigNumber } from "ethers"; -import { useChainId } from "lib/chains"; -import { useCallback, useMemo } from "react"; -import { FindSwapPath } from "./types"; -import { - createSwapEstimator, - findAllPaths, - getBestSwapPath, - getMarketsGraph, - getMaxSwapPathLiquidity, - getSwapPathStats, -} from "./utils"; - -export type SwapRoutesResult = { - maxSwapLiquidity: BigNumber; - maxLiquiditySwapPath?: string[]; - findSwapPath: FindSwapPath; -}; - -export function useSwapRoutes(p: { - marketsInfoData?: MarketsInfoData; - fromTokenAddress?: string; - toTokenAddress?: string; -}): SwapRoutesResult { - const { fromTokenAddress, toTokenAddress, marketsInfoData } = p; - const { chainId } = useChainId(); - - const wrappedToken = getWrappedToken(chainId); - - const isWrap = fromTokenAddress === NATIVE_TOKEN_ADDRESS && toTokenAddress === wrappedToken.address; - const isUnwrap = fromTokenAddress === wrappedToken.address && toTokenAddress === NATIVE_TOKEN_ADDRESS; - const isSameToken = fromTokenAddress === toTokenAddress; - - const wrappedFromAddress = fromTokenAddress ? convertTokenAddress(chainId, fromTokenAddress, "wrapped") : undefined; - const wrappedToAddress = toTokenAddress ? convertTokenAddress(chainId, toTokenAddress, "wrapped") : undefined; - - const { graph, estimator } = useMemo(() => { - if (!marketsInfoData) { - return {}; - } - - return { - graph: getMarketsGraph(Object.values(marketsInfoData)), - estimator: createSwapEstimator(marketsInfoData), - }; - }, [marketsInfoData]); - - const allRoutes = useMemo(() => { - if (!marketsInfoData || !graph || !wrappedFromAddress || !wrappedToAddress || isWrap || isUnwrap || isSameToken) { - return undefined; - } - - const paths = findAllPaths(marketsInfoData, graph, wrappedFromAddress, wrappedToAddress) - ?.sort((a, b) => { - return b.liquidity.sub(a.liquidity).gt(0) ? 1 : -1; - }) - .slice(0, 5); - - return paths; - }, [graph, isSameToken, isUnwrap, isWrap, marketsInfoData, wrappedFromAddress, wrappedToAddress]); - - const { maxLiquidity, maxLiquidityPath } = useMemo(() => { - let maxLiquidity = BigNumber.from(0); - let maxLiquidityPath: string[] | undefined = undefined; - - if (!allRoutes || !marketsInfoData || !wrappedFromAddress) { - return { maxLiquidity, maxLiquidityPath }; - } - - for (const route of allRoutes) { - const liquidity = getMaxSwapPathLiquidity({ - marketsInfoData, - swapPath: route.path, - initialCollateralAddress: wrappedFromAddress, - }); - - if (liquidity.gt(maxLiquidity)) { - maxLiquidity = liquidity; - maxLiquidityPath = route.path; - } - } - - return { maxLiquidity, maxLiquidityPath }; - }, [allRoutes, marketsInfoData, wrappedFromAddress]); - - const findSwapPath = useCallback( - (usdIn: BigNumber, opts: { byLiquidity?: boolean }) => { - if (!allRoutes?.length || !estimator || !marketsInfoData || !fromTokenAddress) { - return undefined; - } - - let swapPath: string[] | undefined = undefined; - - if (opts.byLiquidity) { - swapPath = allRoutes[0].path; - } else { - swapPath = getBestSwapPath(allRoutes, usdIn, estimator); - } - - if (!swapPath) { - return undefined; - } - - const swapPathStats = getSwapPathStats({ - marketsInfoData, - swapPath, - initialCollateralAddress: fromTokenAddress, - wrappedNativeTokenAddress: wrappedToken.address, - shouldUnwrapNativeToken: toTokenAddress === NATIVE_TOKEN_ADDRESS, - shouldApplyPriceImpact: true, - usdIn, - }); - - if (!swapPathStats) { - return undefined; - } - - return swapPathStats; - }, - [allRoutes, estimator, fromTokenAddress, marketsInfoData, toTokenAddress, wrappedToken.address] - ); - - return { - maxSwapLiquidity: maxLiquidity, - maxLiquiditySwapPath: maxLiquidityPath, - findSwapPath, - }; -} diff --git a/src/domain/synthetics/trade/useTradeFlags.ts b/src/domain/synthetics/trade/useTradeFlags.ts deleted file mode 100644 index c6b4c6168f..0000000000 --- a/src/domain/synthetics/trade/useTradeFlags.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { TradeMode, TradeType } from "./types"; -import { useMemo } from "react"; - -export type TradeFlags = { - isLong: boolean; - isShort: boolean; - isSwap: boolean; - isPosition: boolean; - isIncrease: boolean; - isTrigger: boolean; - isMarket: boolean; - isLimit: boolean; -}; - -export function useTradeFlags(tradeType: TradeType, tradeMode: TradeMode): TradeFlags { - return useMemo(() => { - const isLong = tradeType === TradeType.Long; - const isShort = tradeType === TradeType.Short; - const isSwap = tradeType === TradeType.Swap; - - const isPosition = isLong || isShort; - - const isMarket = tradeMode === TradeMode.Market; - const isLimit = tradeMode === TradeMode.Limit; - const isTrigger = tradeMode === TradeMode.Trigger; - - const isIncrease = isPosition && (isMarket || isLimit); - - return { - isLong, - isShort, - isSwap, - isPosition, - isIncrease, - isMarket, - isLimit, - isTrigger, - }; - }, [tradeMode, tradeType]); -} diff --git a/src/domain/synthetics/trade/useSelectedTradeOption.ts b/src/domain/synthetics/trade/useTradeState.ts similarity index 69% rename from src/domain/synthetics/trade/useSelectedTradeOption.ts rename to src/domain/synthetics/trade/useTradeState.ts index dc4b546f4b..b81b632293 100644 --- a/src/domain/synthetics/trade/useSelectedTradeOption.ts +++ b/src/domain/synthetics/trade/useTradeState.ts @@ -1,30 +1,40 @@ -import { getSyntheticsTradeOptionsKey } from "config/localStorage"; +import { + getKeepLeverageKey, + getLeverageEnabledKey, + getLeverageKey, + getSyntheticsTradeOptionsKey, +} from "config/localStorage"; import { getIsUnwrap, getIsWrap } from "domain/tokens"; import { useLocalStorageSerializeKey } from "lib/localStorage"; import { getByKey } from "lib/objects"; -import { useCallback, useEffect, useMemo } from "react"; +import { Dispatch, SetStateAction, useCallback, useEffect, useMemo, useState } from "react"; import { MarketInfo, MarketsInfoData } from "../markets"; import { PositionInfo, PositionsInfoData } from "../positions"; import { TokenData, TokensData } from "../tokens"; -import { TradeMode, TradeType } from "./types"; +import { TradeMode, TradeType, TriggerThresholdType } from "./types"; import { AvailableTokenOptions, useAvailableTokenOptions } from "./useAvailableTokenOptions"; -import { TradeFlags, useTradeFlags } from "./useTradeFlags"; +import { useSafeState } from "lib/useSafeState"; +import { OrderType } from "../orders/types"; +import { BigNumber } from "ethers"; +import { createTradeFlags } from "context/SyntheticsStateContext/selectors/tradeSelectors"; -export type SelectedTradeOption = { +type ReactSetState = Dispatch>; +type LocalStorageSetState = Dispatch>; +type TradeStage = "trade" | "confirmation" | "processing"; + +export type TradeState = { tradeType: TradeType; tradeMode: TradeMode; - tradeFlags: TradeFlags; isWrapOrUnwrap: boolean; fromTokenAddress?: string; - fromToken?: TokenData; toTokenAddress?: string; - toToken?: TokenData; marketAddress?: string; marketInfo?: MarketInfo; collateralAddress?: string; collateralToken?: TokenData; avaialbleTradeModes: TradeMode[]; availableTokensOptions: AvailableTokenOptions; + setActivePosition: (position?: PositionInfo, tradeMode?: TradeMode) => void; setTradeType: (tradeType: TradeType) => void; setTradeMode: (tradeMode: TradeMode) => void; @@ -33,6 +43,48 @@ export type SelectedTradeOption = { setMarketAddress: (marketAddress?: string) => void; setCollateralAddress: (tokenAddress?: string) => void; switchTokenAddresses: () => void; + + fromTokenInputValue: string; + setFromTokenInputValue: ReactSetState; + + toTokenInputValue: string; + setToTokenInputValue: ReactSetState; + + stage: TradeStage; + setStage: ReactSetState; + + focusedInput: "from" | "to" | undefined; + setFocusedInput: ReactSetState<"from" | "to" | undefined>; + + fixedTriggerThresholdType: TriggerThresholdType | undefined; + setFixedTriggerThresholdType: ReactSetState; + + fixedTriggerOrderType: OrderType.LimitDecrease | OrderType.StopLossDecrease | undefined; + setFixedTriggerOrderType: ReactSetState; + + defaultTriggerAcceptablePriceImpactBps: BigNumber | undefined; + setDefaultTriggerAcceptablePriceImpactBps: ReactSetState; + + selectedTriggerAcceptablePriceImpactBps: BigNumber | undefined; + setSelectedAcceptablePriceImpactBps: ReactSetState; + + closeSizeInputValue: string; + setCloseSizeInputValue: ReactSetState; + + triggerPriceInputValue: string; + setTriggerPriceInputValue: ReactSetState; + + triggerRatioInputValue: string; + setTriggerRatioInputValue: ReactSetState; + + leverageOption: number | undefined; + setLeverageOption: LocalStorageSetState; + + isLeverageEnabled: boolean | undefined; + setIsLeverageEnabled: LocalStorageSetState; + + keepLeverage: boolean | undefined; + setKeepLeverage: LocalStorageSetState; }; type StoredTradeOptions = { @@ -52,14 +104,14 @@ type StoredTradeOptions = { collateralAddress?: string; }; -export function useSelectedTradeOption( +export function useTradeState( chainId: number, p: { marketsInfoData?: MarketsInfoData; positionsInfoData?: PositionsInfoData; tokensData?: TokensData; } -): SelectedTradeOption { +): TradeState { const { marketsInfoData, positionsInfoData, tokensData } = p; const [storedOptions, setStoredOptions] = useLocalStorageSerializeKey( @@ -73,12 +125,30 @@ export function useSelectedTradeOption( } ); + const [fromTokenInputValue, setFromTokenInputValue] = useSafeState(""); + const [toTokenInputValue, setToTokenInputValue] = useSafeState(""); + const [stage, setStage] = useState("trade"); + const [focusedInput, setFocusedInput] = useState<"from" | "to">(); + const [fixedTriggerThresholdType, setFixedTriggerThresholdType] = useState(); + const [fixedTriggerOrderType, setFixedTriggerOrderType] = useState< + OrderType.LimitDecrease | OrderType.StopLossDecrease + >(); + const [defaultTriggerAcceptablePriceImpactBps, setDefaultTriggerAcceptablePriceImpactBps] = useState(); + const [selectedTriggerAcceptablePriceImpactBps, setSelectedTriggerAcceptablePriceImpactBps] = useState(); + const [closeSizeInputValue, setCloseSizeInputValue] = useState(""); + const [triggerPriceInputValue, setTriggerPriceInputValue] = useState(""); + const [triggerRatioInputValue, setTriggerRatioInputValue] = useState(""); + const availableTokensOptions = useAvailableTokenOptions(chainId, { marketsInfoData, tokensData }); const { swapTokens, indexTokens } = availableTokensOptions; const tradeType = storedOptions?.tradeType; const tradeMode = storedOptions?.tradeMode; + const [leverageOption, setLeverageOption] = useLocalStorageSerializeKey(getLeverageKey(chainId), 2); + const [isLeverageEnabled, setIsLeverageEnabled] = useLocalStorageSerializeKey(getLeverageEnabledKey(chainId), true); + const [keepLeverage, setKeepLeverage] = useLocalStorageSerializeKey(getKeepLeverageKey(chainId), true); + const avaialbleTradeModes = useMemo(() => { if (!tradeType) { return []; @@ -91,7 +161,7 @@ export function useSelectedTradeOption( }[tradeType]; }, [tradeType]); - const tradeFlags = useTradeFlags(tradeType!, tradeMode!); + const tradeFlags = useMemo(() => createTradeFlags(tradeType!, tradeMode!), [tradeType, tradeMode]); const { isSwap, isLong, isPosition } = tradeFlags; const fromTokenAddress = storedOptions?.tokens.fromTokenAddress; @@ -320,12 +390,9 @@ export function useSelectedTradeOption( return { tradeType: tradeType!, tradeMode: tradeMode!, - tradeFlags, isWrapOrUnwrap, fromTokenAddress, - fromToken, toTokenAddress, - toToken, marketAddress, marketInfo, collateralAddress, @@ -340,5 +407,33 @@ export function useSelectedTradeOption( setTradeType, setTradeMode, switchTokenAddresses, + fromTokenInputValue, + setFromTokenInputValue, + toTokenInputValue, + setToTokenInputValue, + stage, + setStage, + focusedInput, + setFocusedInput, + fixedTriggerThresholdType, + setFixedTriggerThresholdType, + fixedTriggerOrderType, + setFixedTriggerOrderType, + defaultTriggerAcceptablePriceImpactBps, + setDefaultTriggerAcceptablePriceImpactBps, + selectedTriggerAcceptablePriceImpactBps, + setSelectedAcceptablePriceImpactBps: setSelectedTriggerAcceptablePriceImpactBps, + closeSizeInputValue, + setCloseSizeInputValue, + triggerPriceInputValue, + setTriggerPriceInputValue, + triggerRatioInputValue, + setTriggerRatioInputValue, + leverageOption, + setLeverageOption, + isLeverageEnabled, + setIsLeverageEnabled, + keepLeverage, + setKeepLeverage, }; } diff --git a/src/domain/synthetics/trade/utils/common.ts b/src/domain/synthetics/trade/utils/common.ts index 8f316f0a2c..0061594695 100644 --- a/src/domain/synthetics/trade/utils/common.ts +++ b/src/domain/synthetics/trade/utils/common.ts @@ -33,6 +33,7 @@ export function getTradeFees(p: { positionFeeUsd: BigNumber; swapPriceImpactDeltaUsd: BigNumber; positionPriceImpactDeltaUsd: BigNumber; + priceImpactDiffUsd: BigNumber; borrowingFeeUsd: BigNumber; fundingFeeUsd: BigNumber; feeDiscountUsd: BigNumber; @@ -47,6 +48,7 @@ export function getTradeFees(p: { positionFeeUsd, swapPriceImpactDeltaUsd, positionPriceImpactDeltaUsd, + priceImpactDiffUsd, borrowingFeeUsd, fundingFeeUsd, feeDiscountUsd, @@ -117,6 +119,7 @@ export function getTradeFees(p: { swapPriceImpact, positionFee: positionFeeBeforeDiscount, positionPriceImpact, + priceImpactDiff: getFeeItem(priceImpactDiffUsd, sizeDeltaUsd), borrowFee, fundingFee, feeDiscountUsd, diff --git a/src/domain/synthetics/trade/utils/decrease.ts b/src/domain/synthetics/trade/utils/decrease.ts index 795fbcc2d0..73bbd521e1 100644 --- a/src/domain/synthetics/trade/utils/decrease.ts +++ b/src/domain/synthetics/trade/utils/decrease.ts @@ -33,6 +33,9 @@ export function getDecreasePositionAmounts(p: { minCollateralUsd: BigNumber; minPositionSizeUsd: BigNumber; uiFeeFactor: BigNumber; + isLimit?: boolean; + limitPrice?: BigNumber; + triggerOrderType?: DecreasePositionAmounts["triggerOrderType"]; }) { const { marketInfo, @@ -48,6 +51,9 @@ export function getDecreasePositionAmounts(p: { minCollateralUsd, minPositionSizeUsd, uiFeeFactor, + isLimit, + limitPrice, + triggerOrderType: orderType, } = p; const { indexToken } = marketInfo; @@ -71,6 +77,7 @@ export function getDecreasePositionAmounts(p: { estimatedPnl: BigNumber.from(0), estimatedPnlPercentage: BigNumber.from(0), realizedPnl: BigNumber.from(0), + realizedPnlPercentage: BigNumber.from(0), positionFeeUsd: BigNumber.from(0), uiFeeUsd: BigNumber.from(0), @@ -86,7 +93,7 @@ export function getDecreasePositionAmounts(p: { receiveTokenAmount: BigNumber.from(0), receiveUsd: BigNumber.from(0), - triggerOrderType: undefined, + triggerOrderType: orderType, triggerThresholdType: undefined, decreaseSwapType: DecreasePositionSwapType.NoSwap, }; @@ -108,8 +115,8 @@ export function getDecreasePositionAmounts(p: { ? triggerPrice : collateralToken.prices.minPrice; - values.triggerOrderType = getTriggerDecreaseOrderType({ - markPrice, + values.triggerOrderType ||= getTriggerDecreaseOrderType({ + markPrice: isLimit ? limitPrice || BigNumber.from(0) : markPrice, triggerPrice, isLong, }); @@ -199,6 +206,9 @@ export function getDecreasePositionAmounts(p: { }); values.realizedPnl = values.estimatedPnl.mul(values.sizeDeltaInTokens).div(position.sizeInTokens); + values.realizedPnlPercentage = !estimatedCollateralUsd.eq(0) + ? getBasisPoints(values.realizedPnl, estimatedCollateralUsd) + : BigNumber.from(0); values.estimatedPnlPercentage = !estimatedCollateralUsd.eq(0) ? getBasisPoints(values.estimatedPnl, estimatedCollateralUsd) : BigNumber.from(0); @@ -559,7 +569,6 @@ function applyAcceptablePrice(p: { values.acceptablePrice = triggerAcceptablePriceInfo.acceptablePrice; values.acceptablePriceDeltaBps = triggerAcceptablePriceInfo.acceptablePriceDeltaBps; - values.priceImpactDiffUsd = triggerAcceptablePriceInfo.priceImpactDiffUsd; } } diff --git a/src/domain/synthetics/tradeHistory/useTradeHistory.ts b/src/domain/synthetics/tradeHistory/useTradeHistory.ts index 4a6374cd93..598a419334 100644 --- a/src/domain/synthetics/tradeHistory/useTradeHistory.ts +++ b/src/domain/synthetics/tradeHistory/useTradeHistory.ts @@ -1,12 +1,12 @@ -import { useMemo } from "react"; import { gql } from "@apollo/client"; import { getWrappedToken } from "config/tokens"; -import { MarketsInfoData } from "domain/synthetics/markets"; -import { TokensData, parseContractPrice } from "domain/synthetics/tokens"; +import { useMarketsInfoData, useTokensData } from "context/SyntheticsStateContext/hooks/globalsHooks"; +import { parseContractPrice } from "domain/synthetics/tokens"; import { BigNumber, ethers } from "ethers"; import { bigNumberify } from "lib/numbers"; import { getByKey } from "lib/objects"; import { getSyntheticsGraphClient } from "lib/subgraph"; +import { useMemo } from "react"; import useInfinateSwr from "swr/infinite"; import { isSwapOrderType } from "../orders"; import { getSwapPathOutputAddresses } from "../trade/utils"; @@ -24,12 +24,12 @@ export function useTradeHistory( p: { account: string | null | undefined; forAllAccounts?: boolean; - marketsInfoData?: MarketsInfoData; - tokensData?: TokensData; pageSize: number; } ) { - const { pageSize, marketsInfoData, tokensData, account, forAllAccounts } = p; + const { pageSize, account, forAllAccounts } = p; + const marketsInfoData = useMarketsInfoData(); + const tokensData = useTokensData(); const client = getSyntheticsGraphClient(chainId); diff --git a/src/img/ic_info_circle.svg b/src/img/ic_info_circle.svg new file mode 100644 index 0000000000..f202a3f80d --- /dev/null +++ b/src/img/ic_info_circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/img/ic_warning.svg b/src/img/ic_warning.svg new file mode 100644 index 0000000000..dbb4b32636 --- /dev/null +++ b/src/img/ic_warning.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/lib/legacy.ts b/src/lib/legacy.ts index b81401da1a..b732d6b1f1 100644 --- a/src/lib/legacy.ts +++ b/src/lib/legacy.ts @@ -1089,7 +1089,8 @@ export function getProcessedData( nativeTokenPrice, stakedGmxSupply, gmxPrice, - gmxSupply + gmxSupply, + maxBoostMultiplier ) { if ( !balanceData || @@ -1101,11 +1102,11 @@ export function getProcessedData( !nativeTokenPrice || !stakedGmxSupply || !gmxPrice || - !gmxSupply + !gmxSupply || + !maxBoostMultiplier ) { return {}; } - const maxBoostMultiplier = 2; const data: any = {}; data.gmxBalance = balanceData.gmx; @@ -1138,8 +1139,6 @@ export function getProcessedData( data.stakedGmxTrackerRewards = stakingData.stakedGmxTracker.claimable; data.stakedGmxTrackerRewardsUsd = stakingData.stakedGmxTracker.claimable.mul(gmxPrice).div(expandDecimals(1, 18)); - data.bonusGmxTrackerRewards = stakingData.bonusGmxTracker.claimable; - data.feeGmxTrackerRewards = stakingData.feeGmxTracker.claimable; data.feeGmxTrackerRewardsUsd = stakingData.feeGmxTracker.claimable.mul(nativeTokenPrice).div(expandDecimals(1, 18)); diff --git a/src/lib/localStorage/index.ts b/src/lib/localStorage/index.ts index d22db6670e..8e5719aade 100644 --- a/src/lib/localStorage/index.ts +++ b/src/lib/localStorage/index.ts @@ -40,7 +40,7 @@ export type LocalStorageKey = string | number | boolean | null | undefined; export function useLocalStorageSerializeKey( key: LocalStorageKey | LocalStorageKey[], - value: T, + initialValue: T, opts?: { raw: boolean; serializer: (val: T) => string; @@ -49,5 +49,5 @@ export function useLocalStorageSerializeKey( ) { key = JSON.stringify(key); - return useLocalStorage(key, value, opts); + return useLocalStorage(key, initialValue, opts); } diff --git a/src/lib/numbers.ts b/src/lib/numbers.ts index e1ceaf6df7..909d9ba1d9 100644 --- a/src/lib/numbers.ts +++ b/src/lib/numbers.ts @@ -7,6 +7,8 @@ import { getPlusOrMinusSymbol } from "./utils"; const MAX_EXCEEDING_THRESHOLD = "1000000000"; const MIN_EXCEEDING_THRESHOLD = "0.01"; +export const BN_ZERO = BigNumber.from(0); + export function bigNumberify(n?: BigNumberish) { try { return BigNumber.from(n); @@ -335,6 +337,14 @@ export function getBasisPoints(numerator: BigNumber, denominator: BigNumber, sho return result; } +export function formatRatePercentage(rate?: BigNumber, displayDecimals?: number) { + if (!rate) { + return "-"; + } + + return `${getPlusOrMinusSymbol(rate)}${formatAmount(rate.mul(100).abs(), 30, displayDecimals ?? 4)}%`; +} + export function basisPointsToFloat(basisPoints: BigNumber) { return basisPoints.mul(PRECISION).div(BASIS_POINTS_DIVISOR); } diff --git a/src/lib/objects.ts b/src/lib/objects.ts index 4d762fd492..98650f22e2 100644 --- a/src/lib/objects.ts +++ b/src/lib/objects.ts @@ -13,3 +13,7 @@ export function getByKey(obj?: { [key: string]: T }, key?: string): T | undef return obj[key]; } + +export const EMPTY_OBJECT = {}; + +export const EMPTY_ARRAY = []; diff --git a/src/lib/selectors.ts b/src/lib/selectors.ts new file mode 100644 index 0000000000..e866e05d99 --- /dev/null +++ b/src/lib/selectors.ts @@ -0,0 +1 @@ +export { createSelector, createStructuredSelector } from "reselect"; diff --git a/src/lib/useSafeState.ts b/src/lib/useSafeState.ts index c476e4dbe8..2d7926cbb8 100644 --- a/src/lib/useSafeState.ts +++ b/src/lib/useSafeState.ts @@ -5,18 +5,18 @@ export function useSafeState( inititalValue?: S | (() => S), shouldUpdateFn: (prev: S, next: S) => boolean = (a, b) => a !== b ): [S, Dispatch>] { - const [state, _setState] = useState(inititalValue); + const [state, setState] = useState(inititalValue); - const setState = useCallback( + const setStateWrapped = useCallback( (value: S | ((prevState: S) => S)) => { if (typeof value === "function") { - _setState(value); + setState(value); } else if (shouldUpdateFn(state, value)) { - _setState(value); + setState(value); } }, [shouldUpdateFn, state] ); - return [state, setState]; + return [state, setStateWrapped]; } diff --git a/src/lib/utils.ts b/src/lib/utils.ts index b08c28e21f..96ecbb8e98 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,10 +1,10 @@ import { BigNumber } from "ethers"; -export function getPositiveOrNegativeClass(value?: BigNumber): string { +export function getPositiveOrNegativeClass(value?: BigNumber, zeroValue: "" | "text-red" | "text-green" = ""): string { if (!value) { return ""; } - return value.isZero() ? "" : value.isNegative() ? "text-red" : "text-green"; + return value.isZero() ? zeroValue : value.isNegative() ? "text-red" : "text-green"; } export function getPlusOrMinusSymbol(value?: BigNumber, opts: { showPlusForZero?: boolean } = {}): string { diff --git a/src/locales/de/messages.po b/src/locales/de/messages.po index 3c2b051fc6..b9c9537348 100644 --- a/src/locales/de/messages.po +++ b/src/locales/de/messages.po @@ -135,6 +135,10 @@ msgstr "" msgid "<0>{0} <1><2>{indexName}<3>[{poolName}] <4>market selected" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "A Size percentage is required." +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "A snapshot of the USD value of your {0} collateral is taken when the position is opened." msgstr "Bei der Eröffnung der Position wird eine Momentaufnahme des USD-Wertes deines {0} Kollaterals erstellt." @@ -243,6 +247,14 @@ msgstr "" msgid "Accrued Positive Funding Fees for Positions not yet claimable. They will become available to claim by using the \"Settle\" button, or after the Position is increased, decreased or closed." msgstr "" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +msgid "Accrued Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Accrued Price Impact Rebates. They will become Claimable after some time.<0/><1/><2>Read more." +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "Acknowledge epoch is ending in {minutes} minutes" msgstr "" @@ -257,6 +269,10 @@ msgstr "" msgid "Acknowledge high Swap Price Impact" msgstr "" +#: src/domain/synthetics/trade/useHighExecutionFeeConsent.tsx +msgid "Acknowledge very high network Fees" +msgstr "" + #: src/pages/Actions/Actions.js #: src/pages/SyntheticsActions/SyntheticsActions.tsx msgid "Actions" @@ -303,6 +319,10 @@ msgstr "Hinzufügen des Empfehlungscodes fehlgeschlagen." msgid "Adding..." msgstr "Hinzufügen..." +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +#~ msgid "Additional Execution Fee" +#~ msgstr "" + #: src/pages/Stake/StakeV2.js msgid "Additional reserve required" msgstr "Zusätzliche Reserve erforderlich" @@ -344,15 +364,15 @@ msgstr "" msgid "Allow {wrappedTokenSymbol} to be spent" msgstr "" -#: src/App/App.js #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/SettingsModal/SettingsModal.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Allowed Slippage" msgstr "Erlaubter Slippage" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Allowed Slippage below {0}% may result in failed orders." msgstr "" @@ -444,11 +464,15 @@ msgstr "Genehmigung von {stakingTokenSymbol}..." msgid "Approving..." msgstr " Genehmigung..." -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Arbitrum APR:" msgstr "Arbitrum APR:" +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "As network fees have increased, an additional execution fee is needed." +msgstr "" + #: src/components/Exchange/NoLiquidityErrorModal.tsx msgid "As there is not enough liquidity in GLP to swap {0} to {swapTokenSymbol}, you can use the option below to do so:" msgstr "Da die Liquidität in GLP nicht ausreicht, um {0} in {swapTokenSymbol} zu tauschen, kannst du die unten stehende Option verwenden, um dies zu tun:" @@ -492,8 +516,8 @@ msgstr "Verfügbarer Auszahlungsbetrag aus GLP. Mittel, die nicht durch aktuelle msgid "Available on your preferred network" msgstr "Verfügbar in deinem bevorzugten Netzwerk" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Avalanche APR:" msgstr "Avalanche APR:" @@ -518,6 +542,10 @@ msgstr "Balance" msgid "Base APR" msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Base {nativeTokenSymbol} APR" +msgstr "" + #: src/pages/BeginAccountTransfer/BeginAccountTransfer.js msgid "Begin Transfer" msgstr "Übertragung beginnen" @@ -546,7 +574,6 @@ msgstr "Steigere deine Belohnungen mit Multiplikatorpunkten. <0>Mehr Infos. #: src/components/Exchange/PositionsList.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Borrow Fee" @@ -561,6 +588,11 @@ msgstr "Leihgebühr / Tag" msgid "Borrow Fee Rate" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Borrowing fees help ensure available liquidity. <0>Read more." +msgstr "" + #: src/components/Synthetics/BridgingInfo/BridgingInfo.tsx msgid "Bridge {tokenSymbol} to {chainName} using any of the options below:" msgstr "" @@ -596,7 +628,7 @@ msgstr "" msgid "Buy GLP" msgstr "GLP Kaufen" -#: src/pages/Buy/Buy.js +#: src/pages/Buy/Buy.tsx msgid "Buy GLP or GMX" msgstr "" @@ -649,26 +681,10 @@ msgstr "" msgid "Buy GMX using any token from any network:" msgstr "" -#: src/pages/Buy/Buy.js -msgid "Buy Protocol Tokens" -msgstr "" - #: src/components/Glp/GlpSwap.js msgid "Buy failed." msgstr "Kauf fehlgeschlagen." -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Arbitrum" -msgstr "Auf Arbitrum kaufen" - -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Avalanche" -msgstr "Auf Avalanche kaufen" - #: src/pages/BuyGMX/BuyGMX.tsx msgid "Buy or Transfer AVAX to Avalanche" msgstr "" @@ -729,7 +745,6 @@ msgstr "Kann wegen eines Fehlers nicht ausgeführt werden" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts @@ -759,7 +774,7 @@ msgstr "Abbruch übermittelt." msgid "Cancelling {ordersText}" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Chart positions" @@ -781,6 +796,7 @@ msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/Claims/ClaimableCard.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV1.js @@ -807,7 +823,7 @@ msgid "Claim GMX Rewards" msgstr "Beanspruche GMX Rewards" #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx -msgid "Claim Price Impact" +msgid "Claim Price Impact Rebates" msgstr "" #: src/pages/Stake/StakeV2.js @@ -853,6 +869,10 @@ msgstr "Anspruch übermittelt! <0>Status anzeigen." msgid "Claim submitted." msgstr "Anspruch übermittelt." +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "Claim {totalUsd}" +msgstr "" + #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "Claim {wrappedTokenSymbol} Rewards" @@ -864,30 +884,37 @@ msgstr "Beanspruche {wrappedTokenSymbol} Belohnungen" msgid "Claimable" msgstr "Beanspruchbar" +#: src/components/Synthetics/Claims/ClaimableCard.tsx +msgid "Claimable Price Impact Rebates.<0/><1/><2>Read more." +msgstr "" + #: src/components/Referrals/AffiliatesStats.tsx msgid "Claimable Rebates" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Claiming Price Impact Rebate..." +msgstr "" + +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Claiming failed" msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV2.js msgid "Claiming..." msgstr "Beanspruchen..." -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Claims" msgstr "" #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx -msgid "Claims (1)" +msgid "Claims ({totalClaimables})" msgstr "" #: src/components/Exchange/PositionsList.js @@ -1044,6 +1071,7 @@ msgstr "Zusammenfassen..." #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx msgid "Confirm Claim" msgstr "" @@ -1350,7 +1378,6 @@ msgstr "Dezentralisierte<0/>Perpetual Börse" #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -1370,6 +1397,10 @@ msgstr "" msgid "Decrease the Leverage by using the slider. If the Leverage slider is disabled, you can increase the Pay amount or reduce the Order size." msgstr "" +#: src/components/Synthetics/ConfirmationBox/SLTPEntries.tsx +msgid "Decrease {0} Long by {1} at ${2}." +msgstr "" + #: src/components/Exchange/TradeHistory.js #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx msgid "Decreased" @@ -1463,7 +1494,7 @@ msgstr "Einzahlen..." msgid "Diff" msgstr "Diff" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Disable order validations" msgstr "Orderprüfungen deaktivieren" @@ -1471,7 +1502,7 @@ msgstr "Orderprüfungen deaktivieren" msgid "Disconnect" msgstr "Verbindung trennen" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Display PnL after fees" msgstr "PnL nach Gebühren anzeigen" @@ -1502,6 +1533,10 @@ msgstr "Verdienen" msgid "Earn ARB tokens by purchasing GM tokens, trading, or migrating liquidity from GLP to GM. Only for GMX V2." msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Earn an extra {0}% {nativeTokenSymbol} Boosted APR by increasing your staked <0>Multiplier Points." +msgstr "" + #: src/components/Header/AppHeaderLinks.tsx msgid "Ecosystem" msgstr "Ökosystem" @@ -1771,6 +1806,7 @@ msgid "Execute {orderTypeName} Order: {positionText} {sizeDeltaText}," msgstr "" #: src/components/Exchange/FeesTooltip.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx msgid "Execution Fee" msgstr "" @@ -1815,14 +1851,14 @@ msgstr "GEBÜHREN" msgid "FUNDING FEE" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "FUNDING RATE / 1h" -msgstr "" - #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx msgid "Failed Settlement of Funding Fees" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Failed to Claim Price Impact Rebate" +msgstr "" + #: src/domain/synthetics/orders/cancelOrdersTxn.ts msgid "Failed to cancel {ordersText}" msgstr "" @@ -1847,6 +1883,7 @@ msgstr "" #: src/components/Glp/GlpSwap.js #: src/components/Glp/GlpSwap.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Fees" msgstr "Gebühren" @@ -1963,11 +2000,10 @@ msgstr "" msgid "Fulfilling order request" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts msgid "Funding Claimed" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Funding Fee" @@ -1977,14 +2013,15 @@ msgstr "" msgid "Funding Fee Rate" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Funding Rate / 1h" -msgstr "" - #: src/components/Synthetics/Claims/ClaimableCardUI.tsx msgid "Funding fees" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Funding fees help to balance longs and shorts and are exchanged between both sides. <0>Read more." +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "GBC NFTs APR tracker and rewards" msgstr "GBC NFTs APR-Tracker und Belohnungen" @@ -2015,7 +2052,7 @@ msgstr "" msgid "GLP buy disabled, pending {0} upgrade" msgstr "GLP-Kauf deaktiviert, {0} Aktualisierung steht noch aus" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GLP is the liquidity provider token for GMX V1 markets. Accrues 70% of the V1 markets generated fees." msgstr "" @@ -2043,7 +2080,7 @@ msgstr "" msgid "GM can be sold for {0} and {1} for this market up to the specified selling caps. The remaining tokens in the pool are reserved for currently open Positions." msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GM is the liquidity provider token for GMX V2 markets. Accrues 63% of the V2 markets generated fees." msgstr "" @@ -2132,7 +2169,7 @@ msgstr "GMX ist derzeit auf Arbitrum und Avalanche verfügbar." msgid "GMX is not actively looking for new hires at the moment. However, if you think you can contribute to the project, please email <0>jobs@gmx.io." msgstr "GMX sucht im Moment nicht aktiv nach neuen Mitarbeitern. Wenn du jedoch der Meinung bist, dass du zu dem Projekt beitragen kannst, sende bitte eine E-Mail an <0>jobs@gmx.io." -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GMX is the utility and governance token. Accrues 30% and 27% of V1 and V2 markets generated fees, respectively." msgstr "" @@ -2185,6 +2222,13 @@ msgstr "" msgid "Governance" msgstr "Governance" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.tsx +#: src/components/Synthetics/PositionEditor/PositionEditor.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "High Execution Fee not yet acknowledged" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "High Slippage, Swap Anyway" msgstr "Hoher Slippage, trotzdem tauschen" @@ -2193,6 +2237,13 @@ msgstr "Hoher Slippage, trotzdem tauschen" msgid "High USDG Slippage, Long Anyway" msgstr "Hohe USDG-Abweichung, trotzdem Long" +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#~ msgid "High network Fee not yet acknowledged" +#~ msgstr "" + #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "I am aware of the trigger orders" @@ -2228,7 +2279,7 @@ msgstr "" msgid "Incentives are airdropped weekly." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Include PnL in leverage display" msgstr "PnL in die Anzeige der Hebelwirkung einbeziehen" @@ -2250,7 +2301,6 @@ msgstr "Falsches Netzwerk" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -2408,7 +2458,7 @@ msgstr "Ungültige Empfängeradresse" msgid "Invalid Transfer Addresses: Please check the url." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid execution fee buffer value" msgstr "" @@ -2426,7 +2476,7 @@ msgstr "Ungültiger Liq.-Preis" msgid "Invalid price, see warning" msgstr "Ungültiger Preis, siehe Warnung" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid slippage value" msgstr "Ungültiger Slippagewert" @@ -2455,7 +2505,6 @@ msgid "Keep Leverage is not possible" msgstr "" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "Keep leverage at {0}" msgstr "" @@ -2464,6 +2513,10 @@ msgstr "" msgid "Keep leverage at {0}x" msgstr "" +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "Keep leverage at {keepLeverageAtValue}" +msgstr "" + #: src/components/Synthetics/ChartTokenSelector/ChartTokenSelector.tsx msgid "LONG LIQ." msgstr "" @@ -2548,7 +2601,6 @@ msgstr "" #: src/components/Synthetics/PositionItem/PositionItem.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts -#: src/domain/synthetics/orders/utils.ts msgid "Limit" msgstr "Limit" @@ -2572,7 +2624,6 @@ msgstr "" #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Limit Price" msgstr "Limit Preis" @@ -2705,8 +2756,8 @@ msgstr "Lädt..." #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -2723,7 +2774,6 @@ msgstr "Lädt..." #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -2738,14 +2788,6 @@ msgstr "Long" msgid "Long Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Long Liquidity" msgstr "" @@ -2754,14 +2796,11 @@ msgstr "" msgid "Long Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Long Positions" msgstr "Long Positionen" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Long positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Long {0}" msgstr "Long {0}" @@ -2778,7 +2817,9 @@ msgstr "Sieht so aus, als hättest du keinen Empfehlungscode, den du weitergeben msgid "Loss" msgstr "Verlust" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/GmList/GmList.tsx msgid "MARKET" msgstr "" @@ -2894,16 +2935,15 @@ msgid "Max Capacity for {0} Reached" msgstr "Max. Kapazität für {0} erreicht" #: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Max Execution Fee" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee Buffer" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee buffer below {0}% may result in failed orders." msgstr "" @@ -2945,7 +2985,7 @@ msgstr "" msgid "Max close amount exceeded" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max execution fee buffer precision is 0.01%" msgstr "" @@ -2975,9 +3015,13 @@ msgstr "Max. Poolkapazität für {0} erreicht. Bitte minte GLP mit einem anderen msgid "Max pool capacity reached for {0}<0/><1/>Please mint GLP using another token" msgstr "Max. Pool-Kapazität für {0}<0/><1/> erreicht. Bitte minte GLP mit einem anderen Token" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Max slippage precision is -0.01%" +msgstr "" + #: src/App/App.js -msgid "Max slippage precision is 0.01%" -msgstr "Die max. Slippagegenauigkeit beträgt 0,01 %." +#~ msgid "Max slippage precision is 0.01%" +#~ msgstr "Die max. Slippagegenauigkeit beträgt 0,01 %." #: src/components/Synthetics/MarketStats/MarketStats.tsx #: src/components/Synthetics/MarketStats/MarketStats.tsx @@ -3025,11 +3069,11 @@ msgstr "Max. {0} Short-Kapazität" msgid "Max {0} short exceeded" msgstr "Max {0} Short überschritten" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Arbitrum APR:" msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Avalanche APR: {0}" msgstr "" @@ -3038,7 +3082,11 @@ msgid "Max. Leverage exceeded" msgstr "" #: src/components/Stake/GMXAprTooltip.tsx -msgid "Max. {nativeTokenSymbol} APR with 200% Boost for this week: {0}%." +msgid "Max. {nativeTokenSymbol} APR" +msgstr "" + +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Max. {nativeTokenSymbol} APR is calculated with the max. 200% Boost Percentage by staking <0>Multiplier Points." msgstr "" #: src/components/Migration/Migration.js @@ -3148,9 +3196,16 @@ msgid "Multiplier Points APR" msgstr "Multiplikator-Punkte APR" #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "NA" msgstr "" +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "NET FEE / 1 H" +msgstr "" + #: src/pages/NftWallet/NftWallet.js msgid "NFT Address" msgstr "NFT Adresse" @@ -3171,6 +3226,20 @@ msgstr "" msgid "Neither Collateral nor realized PnL is enough to cover pending Fees. Please close a larger position amount." msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Fee" +msgstr "" + +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Net Fee / 1h" +msgstr "" + +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Rebate" +msgstr "" + #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -3199,7 +3268,12 @@ msgstr "Netzwerke" msgid "Networks and Settings" msgstr "Netzwerke und Einstellungen" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "New Collateral" +msgstr "" + #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Next" msgstr "Weiter" @@ -3275,6 +3349,10 @@ msgstr "" msgid "Note that orders are not guaranteed to be executed.<0/><1/>This can occur in a few situations including but not exclusive to:" msgstr "Beachte, dass die Ausführung von Aufträgen nicht garantiert ist.<0/><1/>Dies kann in einigen Situationen vorkommen, einschließlich, aber nicht ausschließlich bei:" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Old Collateral" +msgstr "" + #: src/components/AddressDropdown/AddressDropdown.tsx #: src/components/Synthetics/SubaccountModal/SubaccountModal.tsx msgid "One-Click Trading" @@ -3351,10 +3429,6 @@ msgstr "Öffnen..." msgid "Order" msgstr "Order" -#: src/domain/synthetics/orders/utils.ts -msgid "Order Trigger Price is beyond position's Liquidation Price." -msgstr "" - #: src/components/Synthetics/OrderItem/OrderItem.tsx msgid "Order Type" msgstr "" @@ -3635,7 +3709,6 @@ msgstr "Positionen" msgid "Positions ({0})" msgstr "Positionen ({0})" -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Positions{0}" msgstr "" @@ -3645,6 +3718,7 @@ msgid "Positive Funding Fees for a Position become claimable after the Position msgstr "" #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Prev" msgstr "Prev" @@ -3686,6 +3760,20 @@ msgstr "Preis" msgid "Price Impact" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Price Impact Rebate Claimed" +msgstr "" + +#: src/components/Synthetics/Claims/ClaimableCardUI.tsx +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates for closing trades are claimable under the Claims tab. <0>Read more." +msgstr "" + +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts @@ -3693,6 +3781,10 @@ msgstr "" msgid "Price Impact not yet acknowledged" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3700,6 +3792,10 @@ msgstr "" msgid "Price above Liq. Price" msgstr "Preis über Liq. Preis" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3713,6 +3809,14 @@ msgstr "Preis über Liq. Preis" msgid "Price above Mark Price" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Mark Price." +msgstr "" + +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3720,6 +3824,10 @@ msgstr "" msgid "Price below Liq. Price" msgstr "Preis unter Liq. Preis" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3733,6 +3841,10 @@ msgstr "Preis unter Liq. Preis" msgid "Price below Mark Price" msgstr "Preis unter Mark Preis" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Mark Price." +msgstr "" + #: src/pages/OrdersOverview/OrdersOverview.js msgid "Price conditions are met" msgstr "Preisbedingungen sind erfüllt" @@ -3775,6 +3887,10 @@ msgstr "Reserve-Nachweis" msgid "Protocol" msgstr "" +#: src/pages/Buy/Buy.tsx +msgid "Protocol Tokens" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js #: src/pages/Ecosystem/Ecosystem.js msgid "Protocol analytics" @@ -3796,9 +3912,14 @@ msgstr "" msgid "Purchase Insurance" msgstr "Versicherung kaufen" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "REBATE" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Read more" msgstr "Mehr lesen" @@ -4025,7 +4146,7 @@ msgstr "" msgid "Same as current active code" msgstr "Gleicher Code wie der derzeitige aktive Code" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Save" msgstr "Sparen" @@ -4191,10 +4312,10 @@ msgstr "" msgid "Set TP/SL" msgstr "" -#: src/App/App.js #: src/components/Header/AppHeaderLinks.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx +#: src/components/SettingsModal/SettingsModal.tsx msgid "Settings" msgstr "Einstellungen" @@ -4256,8 +4377,8 @@ msgstr "Position teilen" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4274,7 +4395,6 @@ msgstr "Position teilen" #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -4289,14 +4409,6 @@ msgstr "Short" msgid "Short Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Short Liquidity" msgstr "" @@ -4305,14 +4417,11 @@ msgstr "" msgid "Short Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Short Positions" msgstr "Short Positionen" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Short positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Short {0}" msgstr "Short {0}" @@ -4321,10 +4430,14 @@ msgstr "Short {0}" msgid "Shorting..." msgstr "Shorten..." -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Show debug values" msgstr "" +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Show details" +msgstr "" + #: src/pages/Home/Home.js msgid "Simple Swaps" msgstr "Einfache Swaps" @@ -4350,6 +4463,7 @@ msgstr "" #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4361,14 +4475,18 @@ msgstr "Größe" #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Slippage is too high" msgstr "" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Slippage should be less than -5%" +msgstr "" + #: src/App/App.js -msgid "Slippage should be less than 5%" -msgstr "Der Slippage sollte weniger als 5% betragen" +#~ msgid "Slippage should be less than 5%" +#~ msgstr "Der Slippage sollte weniger als 5% betragen" #: src/components/Exchange/UsefulLinks.tsx msgid "Speed up page loading" @@ -4472,10 +4590,15 @@ msgstr "Statistiken" msgid "Stop Loss Decrease" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Stop-Loss" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Stop-Loss PnL" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "Structured Products" msgstr "Strukturierte Produkte" @@ -4524,7 +4647,7 @@ msgstr "" msgid "Submit" msgstr "Übermitteln" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Success claimings" msgstr "" @@ -4550,10 +4673,6 @@ msgstr "Swap" msgid "Swap Fee" msgstr "" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx -msgid "Swap Fees" -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Swap Order created!" msgstr "Swap Order erstellt!" @@ -4566,7 +4685,6 @@ msgstr "Swap Order Erstellung fehlgeschlagen." msgid "Swap Order submitted!" msgstr "Swap Order übermittelt!" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Swap Price Impact" msgstr "" @@ -4700,11 +4818,15 @@ msgstr "" msgid "TP/SL" msgstr "" -#: src/domain/synthetics/orders/utils.ts +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Take-Profit" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Take-Profit PnL" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "Take-profit and stop-loss orders can be set after opening a position. <0/><1/>There will be a \"Close\" button on each position row, clicking this will display the option to set trigger orders. <2/><3/>For screenshots and more information, please see the <4>docs." msgstr "Take-Profit- und Stop-Loss-Orders können nach der Eröffnung einer Position gesetzt werden. <0/><1/>Auf jeder Positionszeile befindet sich ein Button \"Schließen\", durch Anklicken dieser Schaltfläche wird die Option zum Setzen von Trigger-Orders angezeigt. <2/><3/>Screenshots und weitere Informationen findest du in den <4>Dokumenten." @@ -4771,10 +4893,6 @@ msgstr "" msgid "The Bonus Rebate will be airdropped as ARB tokens on a pro-rata basis. <0>Read more." msgstr "" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "The Boosted APR is from your staked Multiplier Points." -msgstr "Der erhöhte APR ergibt sich aus den von dir gestaketen Multiplikatorpunkten." - #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx msgid "The Current Price Impact is {0}. Consider adding a buffer of 0.30% to it so the order is more likely to be processed." msgstr "" @@ -4787,18 +4905,15 @@ msgstr "" msgid "The Gambit protocol is in beta, please read the <0>staking detailsbefore participating." msgstr "Das Gambit-Protokoll befindet sich in der Beta-Phase, bitte lese die <0>Details zum Staking, bevor du teilnimmst." +#: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "The Max Execution Fee is overestimated by {maxExecutionFeeText}%. Upon execution, the excess Execution Fee is sent back to your account." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "The Max Execution Fee is set to a higher value to handle potential increases in gas price during order execution. Any excess execution fee will be refunded to your account when the order is executed. Only applicable to GMX V2." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "The Order may not execute at the desired {priceText} as the current Price Impact {0} is higher than its Acceptable Price Impact {1}. Consider canceling and creating a new {suggestionType} Order." -msgstr "" - #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "The address of the esGMX (IOU) token is {esGmxIouAddress}." msgstr "Die Adresse des esGMX (IOU)-Tokens lautet {esGmxIouAddress}" @@ -4827,11 +4942,23 @@ msgstr "Der Mark-Preis hat sich geändert. Erhöhe dein zulässiges Slippage, in msgid "The maximum number of authorized Actions has been reached. Re-authorize a higher value using the \"Max allowed actions\" field." msgstr "" +#: src/domain/synthetics/fees/utils/executionFee.ts +msgid "The network Fees are high currently, which may be due to a temporary increase in transactions on the {0} network." +msgstr "" + #: src/domain/legacy.ts #: src/domain/synthetics/fees/utils/executionFee.ts msgid "The network Fees are very high currently, which may be due to a temporary increase in transactions on the {0} network." msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "The order may not execute at the desired {priceText} as its acceptable price impact is set to {formattedOrderAcceptablePriceImpact}, which is lower than the current market price impact of {formattedCurrentAcceptablePriceImpact}. It can be edited using the \"Edit\" button." +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "The order will not be executed as its trigger price is beyond the position's liquidation price." +msgstr "" + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "The order will only execute if the Min. Receive is met and there is sufficient liquidity." msgstr "" @@ -4853,9 +4980,13 @@ msgid "The pending borrow fee will be charged on this transaction." msgstr "" #: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of -{1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#~ msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +#~ msgstr "" + #: src/components/Exchange/SwapBox.js msgid "The position will be opened at {0} USD with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "Die Position wird zu {0} USD mit einer maximalen Slippage von {1}% eröffnet.<0/><1/>Die Höhe des Slippage kann unter Einstellungen konfiguriert werden, die du findest, wenn du auf deiner Adresse oben rechts auf der Seite klickst, nachdem du deine Wallet verbunden hast.<2/><3/><4>Mehr Info" @@ -4964,9 +5095,8 @@ msgstr "Dieser Code ist noch nicht auf {0} registriert, du wirst dort keine Raba msgid "This is the maximum top-up amount that will be sent from your Main account to your Subaccount after each transaction. The actual amount sent will depend on the final transaction fee." msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "This market uses an Adaptive Funding Rate. The Funding Rate will adjust over time depending on the ratio of longs and shorts. <0>Read more." +#: src/domain/synthetics/orders/utils.ts +msgid "This order using {collateralSymbol} as collateral will not be valid for the existing {longText} position using {symbol} as collateral." msgstr "" #: src/components/Exchange/TradeHistory.js @@ -5137,7 +5267,6 @@ msgstr "" #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Trades" msgstr "Trades" @@ -5240,7 +5369,6 @@ msgstr "Trigger" #: src/components/Synthetics/OrderList/OrderList.tsx #: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Trigger Price" msgstr "" @@ -5252,10 +5380,6 @@ msgstr "" msgid "Trigger order disabled, pending {0} upgrade" msgstr "" -#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx -msgid "Trigger order for" -msgstr "" - #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Triggered at: {0}" msgstr "" @@ -5359,7 +5483,7 @@ msgid "Unstake submitted! <0>View status." msgstr "Unstaken übermittelt! <0>Status anzeigen." #: src/pages/Stake/StakeV2.js -msgid "Unstaking will burn <0>{0} Multiplier Points. {1}" +msgid "Unstaking will burn <0>{0} Multiplier Points. <1>You will earn {1}% less {nativeTokenSymbol} rewards with this action." msgstr "" #: src/pages/Stake/StakeV1.js @@ -5569,6 +5693,18 @@ msgstr "Ansicht" msgid "View in Explorer" msgstr "Ansicht im Explorer" +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Arbitrum" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Avalanche" +msgstr "" + #: src/components/Synthetics/StatusNotification/SubaccountNotification.tsx msgid "View status" msgstr "" @@ -5799,9 +5935,12 @@ msgstr "Du kannst deine Claim-Historie <0>hier einsehen." msgid "You can currently vest a maximum of {0} esGMX tokens at a ratio of {1} {stakingToken} to 1 esGMX." msgstr "Du kannst derzeit maximal {0} esGMX-Token in einem Verhältnis von {1} {stakingToken} zu 1 esGMX übertragen." +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx +msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than -{0}, may result in failed orders if prices are volatile." +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than {0}, may result in failed orders if prices are volatile." msgstr "" @@ -5829,10 +5968,6 @@ msgstr "Du hast eine ausstehende Überweisung von {sender}." msgid "You have an active Limit Order to Increase {longOrShortText} {sizeInToken} {0} (${1}) at price ${2}" msgstr "Du hast eine aktive Limit-Order zur Erhöhung von {longOrShortText} {sizeInToken} {0} (${1}) zum Preis von ${2}" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have an active Limit Order to Increase {longShortText} {0} {sizeText} at price {1}." -msgstr "" - #: src/components/Exchange/PositionSeller.js msgid "You have an active order to decrease {longOrShortText} {sizeInToken} {0} (${1}) at {prefix} {2}" msgstr "" @@ -5861,25 +5996,24 @@ msgstr "" msgid "You have an existing position with {0} as collateral. This action will not apply for that position." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "" -"You have an existing {longText} position with {0} as Collateral. This Order will not\n" -"be valid for that Position." -msgstr "" - #: src/components/Exchange/ConfirmationBox.js msgid "You have multiple existing Increase {longOrShortText} {0} limit orders" msgstr "Du hast mehrere bestehende {longOrShortText} {0} Limit-Orders zur Erhöhung" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have multiple existing Increase {longShortText} {0} limit orders" -msgstr "" - #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "You have not deposited any tokens for vesting." msgstr "Du hast keine Token für das Vesting hinterlegt." +#: src/components/Stake/GMXAprTooltip.tsx +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points using the \"Compound\" button." +msgstr "" + +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points." +msgstr "" + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "You have selected {collateralTokenSymbol} as Collateral, the Liquidation Price will vary based on the price of {collateralTokenSymbol}." msgstr "" @@ -5928,14 +6062,19 @@ msgstr "Du wirst mind. {0} {1} erhalten, wenn dieser Auftrag ausgeführt wird. D msgid "You will receive at least {toAmountText} if this order is executed. This price is being updated in real time based on Swap Fees and Price Impact." msgstr "" +#: src/pages/Stake/StakeV2.js +#: src/pages/Stake/StakeV2.js +msgid "Your APR" +msgstr "" + #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "Your esGMX (IOU) balance will decrease by your claim amount after claiming, this is expected behaviour." msgstr "Dein esGMX-Guthaben (IOU) verringert sich nach der Beanspruchung um deinen beanspruchten Betrag, dies ist ein zu erwartendes Verhalten." #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "Your position's collateral after deducting fees." -msgstr "Das Kollateral deiner Position nach Abzug der Gebühren." +msgid "Your position's collateral after deducting fees:" +msgstr "Das Kollateral deiner Position nach Abzug der Gebühren:" #: src/pages/CompleteAccountTransfer/CompleteAccountTransfer.js msgid "Your transfer has been completed." @@ -5970,7 +6109,6 @@ msgid "from" msgstr "" #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "hide" msgstr "Verstecken" @@ -5978,20 +6116,32 @@ msgstr "Verstecken" msgid "in liquidity" msgstr "In Liquidität" +#: src/domain/synthetics/orders/utils.ts +msgid "limit price" +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "long" +msgstr "" + #: src/pages/Dashboard/DashboardV2.js msgid "not staked" msgstr "Nicht gestaket" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "pay" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "receive" msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "short" +msgstr "" + #: src/pages/PositionsOverview/PositionsOverview.js msgid "size" msgstr "Größe" @@ -6004,8 +6154,11 @@ msgstr "Gestaket" msgid "time to liq" msgstr "Zeit zur Liq" +#: src/domain/synthetics/orders/utils.ts +msgid "trigger price" +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "view" msgstr "Ansicht" @@ -6022,6 +6175,10 @@ msgstr "" msgid "{0, plural, one {Pending {symbolsText} approval} other {Pending {symbolsText} approvals}}" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "{0, plural, one {You have an active Limit Order to Increase} other {You have multiple active Limit Orders to Increase}}" +msgstr "" + #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "{0} <0><1>{indexName}<2>[{poolName}] <3>market selected." msgstr "" @@ -6102,6 +6259,10 @@ msgstr "" msgid "{0} is required for collateral." msgstr "{0} ist für das Kollateral erforderlich." +#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx +msgid "{0} order for" +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "{0} pool exceeded, try different token" msgstr "{0} Pool überschritten, anderen Token versuchen" @@ -6202,6 +6363,22 @@ msgstr "" msgid "{longOrShortText} {0} market selected" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee and pay a borrow fee of {borrowRate} per hour." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee or a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and do not pay a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and {borrowAction} a borrow fee of {borrowRate} per hour." +msgstr "" + #: src/components/Synthetics/MarketCard/MarketCard.tsx msgid "{longShortText} {0} Open Interest" msgstr "" @@ -6218,10 +6395,6 @@ msgstr "" msgid "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR" msgstr "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "{nativeTokenSymbol} APR" -msgstr "" - #: src/components/Stake/GMXAprTooltip.tsx msgid "{nativeTokenSymbol} Base APR" msgstr "" diff --git a/src/locales/en/messages.po b/src/locales/en/messages.po index d87aa37e47..0dec8fec71 100644 --- a/src/locales/en/messages.po +++ b/src/locales/en/messages.po @@ -135,6 +135,10 @@ msgstr "<0>{0} <1><2>{indexName}<3>[{poolName}]" msgid "<0>{0} <1><2>{indexName}<3>[{poolName}] <4>market selected" msgstr "<0>{0} <1><2>{indexName}<3>[{poolName}] <4>market selected" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "A Size percentage is required." +msgstr "A Size percentage is required." + #: src/components/Exchange/SwapBox.js msgid "A snapshot of the USD value of your {0} collateral is taken when the position is opened." msgstr "A snapshot of the USD value of your {0} collateral is taken when the position is opened." @@ -243,6 +247,14 @@ msgstr "Accrued Positive Funding Fee" msgid "Accrued Positive Funding Fees for Positions not yet claimable. They will become available to claim by using the \"Settle\" button, or after the Position is increased, decreased or closed." msgstr "Accrued Positive Funding Fees for Positions not yet claimable. They will become available to claim by using the \"Settle\" button, or after the Position is increased, decreased or closed." +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +msgid "Accrued Price Impact Rebates" +msgstr "Accrued Price Impact Rebates" + +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Accrued Price Impact Rebates. They will become Claimable after some time.<0/><1/><2>Read more." +msgstr "Accrued Price Impact Rebates. They will become Claimable after some time.<0/><1/><2>Read more." + #: src/components/Glp/GlpSwap.js msgid "Acknowledge epoch is ending in {minutes} minutes" msgstr "Acknowledge epoch is ending in {minutes} minutes" @@ -257,6 +269,10 @@ msgstr "Acknowledge high Price Impact" msgid "Acknowledge high Swap Price Impact" msgstr "Acknowledge high Swap Price Impact" +#: src/domain/synthetics/trade/useHighExecutionFeeConsent.tsx +msgid "Acknowledge very high network Fees" +msgstr "Acknowledge very high network Fees" + #: src/pages/Actions/Actions.js #: src/pages/SyntheticsActions/SyntheticsActions.tsx msgid "Actions" @@ -303,6 +319,10 @@ msgstr "Adding referral code failed." msgid "Adding..." msgstr "Adding..." +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +#~ msgid "Additional Execution Fee" +#~ msgstr "Additional Execution Fee" + #: src/pages/Stake/StakeV2.js msgid "Additional reserve required" msgstr "Additional reserve required" @@ -344,15 +364,15 @@ msgstr "Allow {0} to be spent" msgid "Allow {wrappedTokenSymbol} to be spent" msgstr "Allow {wrappedTokenSymbol} to be spent" -#: src/App/App.js #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/SettingsModal/SettingsModal.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Allowed Slippage" msgstr "Allowed Slippage" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Allowed Slippage below {0}% may result in failed orders." msgstr "Allowed Slippage below {0}% may result in failed orders." @@ -444,11 +464,15 @@ msgstr "Approving {stakingTokenSymbol}..." msgid "Approving..." msgstr "Approving..." -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Arbitrum APR:" msgstr "Arbitrum APR:" +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "As network fees have increased, an additional execution fee is needed." +msgstr "As network fees have increased, an additional execution fee is needed." + #: src/components/Exchange/NoLiquidityErrorModal.tsx msgid "As there is not enough liquidity in GLP to swap {0} to {swapTokenSymbol}, you can use the option below to do so:" msgstr "As there is not enough liquidity in GLP to swap {0} to {swapTokenSymbol}, you can use the option below to do so:" @@ -492,8 +516,8 @@ msgstr "Available amount to withdraw from GLP. Funds not utilized by current ope msgid "Available on your preferred network" msgstr "Available on your preferred network" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Avalanche APR:" msgstr "Avalanche APR:" @@ -518,6 +542,10 @@ msgstr "Balance" msgid "Base APR" msgstr "Base APR" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Base {nativeTokenSymbol} APR" +msgstr "Base {nativeTokenSymbol} APR" + #: src/pages/BeginAccountTransfer/BeginAccountTransfer.js msgid "Begin Transfer" msgstr "Begin Transfer" @@ -546,7 +574,6 @@ msgstr "Boost your rewards with Multiplier Points. <0>More info." #: src/components/Exchange/PositionsList.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Borrow Fee" @@ -561,6 +588,11 @@ msgstr "Borrow Fee / Day" msgid "Borrow Fee Rate" msgstr "Borrow Fee Rate" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Borrowing fees help ensure available liquidity. <0>Read more." +msgstr "Borrowing fees help ensure available liquidity. <0>Read more." + #: src/components/Synthetics/BridgingInfo/BridgingInfo.tsx msgid "Bridge {tokenSymbol} to {chainName} using any of the options below:" msgstr "Bridge {tokenSymbol} to {chainName} using any of the options below:" @@ -596,7 +628,7 @@ msgstr "Buy Fee" msgid "Buy GLP" msgstr "Buy GLP" -#: src/pages/Buy/Buy.js +#: src/pages/Buy/Buy.tsx msgid "Buy GLP or GMX" msgstr "Buy GLP or GMX" @@ -649,26 +681,10 @@ msgstr "Buy GMX using FIAT gateways:" msgid "Buy GMX using any token from any network:" msgstr "Buy GMX using any token from any network:" -#: src/pages/Buy/Buy.js -msgid "Buy Protocol Tokens" -msgstr "Buy Protocol Tokens" - #: src/components/Glp/GlpSwap.js msgid "Buy failed." msgstr "Buy failed." -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Arbitrum" -msgstr "Buy on Arbitrum" - -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Avalanche" -msgstr "Buy on Avalanche" - #: src/pages/BuyGMX/BuyGMX.tsx msgid "Buy or Transfer AVAX to Avalanche" msgstr "Buy or Transfer AVAX to Avalanche" @@ -729,7 +745,6 @@ msgstr "Can't execute because of an error" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts @@ -759,7 +774,7 @@ msgstr "Cancel submitted." msgid "Cancelling {ordersText}" msgstr "Cancelling {ordersText}" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Chart positions" @@ -781,6 +796,7 @@ msgstr "Choose to buy from decentralized or centralized exchanges." #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/Claims/ClaimableCard.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV1.js @@ -807,8 +823,8 @@ msgid "Claim GMX Rewards" msgstr "Claim GMX Rewards" #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx -msgid "Claim Price Impact" -msgstr "Claim Price Impact" +msgid "Claim Price Impact Rebates" +msgstr "Claim Price Impact Rebates" #: src/pages/Stake/StakeV2.js msgid "Claim Rewards" @@ -853,6 +869,10 @@ msgstr "Claim submitted! <0>View status." msgid "Claim submitted." msgstr "Claim submitted." +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "Claim {totalUsd}" +msgstr "Claim {totalUsd}" + #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "Claim {wrappedTokenSymbol} Rewards" @@ -864,31 +884,38 @@ msgstr "Claim {wrappedTokenSymbol} Rewards" msgid "Claimable" msgstr "Claimable" +#: src/components/Synthetics/Claims/ClaimableCard.tsx +msgid "Claimable Price Impact Rebates.<0/><1/><2>Read more." +msgstr "Claimable Price Impact Rebates.<0/><1/><2>Read more." + #: src/components/Referrals/AffiliatesStats.tsx msgid "Claimable Rebates" msgstr "Claimable Rebates" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Claiming Price Impact Rebate..." +msgstr "Claiming Price Impact Rebate..." + +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Claiming failed" msgstr "Claiming failed" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV2.js msgid "Claiming..." msgstr "Claiming..." -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Claims" msgstr "Claims" #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx -msgid "Claims (1)" -msgstr "Claims (1)" +msgid "Claims ({totalClaimables})" +msgstr "Claims ({totalClaimables})" #: src/components/Exchange/PositionsList.js msgid "Click on the Position to select its market, then use the trade box to increase your Position Size if needed." @@ -1044,6 +1071,7 @@ msgstr "Compounding..." #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx msgid "Confirm Claim" msgstr "Confirm Claim" @@ -1350,7 +1378,6 @@ msgstr "Decentralized<0/>Perpetual Exchange" #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -1370,6 +1397,10 @@ msgstr "Decrease size" msgid "Decrease the Leverage by using the slider. If the Leverage slider is disabled, you can increase the Pay amount or reduce the Order size." msgstr "Decrease the Leverage by using the slider. If the Leverage slider is disabled, you can increase the Pay amount or reduce the Order size." +#: src/components/Synthetics/ConfirmationBox/SLTPEntries.tsx +msgid "Decrease {0} Long by {1} at ${2}." +msgstr "Decrease {0} Long by {1} at ${2}." + #: src/components/Exchange/TradeHistory.js #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx msgid "Decreased" @@ -1463,7 +1494,7 @@ msgstr "Depositing..." msgid "Diff" msgstr "Diff" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Disable order validations" msgstr "Disable order validations" @@ -1471,7 +1502,7 @@ msgstr "Disable order validations" msgid "Disconnect" msgstr "Disconnect" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Display PnL after fees" msgstr "Display PnL after fees" @@ -1502,6 +1533,10 @@ msgstr "Earn" msgid "Earn ARB tokens by purchasing GM tokens, trading, or migrating liquidity from GLP to GM. Only for GMX V2." msgstr "Earn ARB tokens by purchasing GM tokens, trading, or migrating liquidity from GLP to GM. Only for GMX V2." +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Earn an extra {0}% {nativeTokenSymbol} Boosted APR by increasing your staked <0>Multiplier Points." +msgstr "Earn an extra {0}% {nativeTokenSymbol} Boosted APR by increasing your staked <0>Multiplier Points." + #: src/components/Header/AppHeaderLinks.tsx msgid "Ecosystem" msgstr "Ecosystem" @@ -1771,6 +1806,7 @@ msgid "Execute {orderTypeName} Order: {positionText} {sizeDeltaText}," msgstr "Execute {orderTypeName} Order: {positionText} {sizeDeltaText}," #: src/components/Exchange/FeesTooltip.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx msgid "Execution Fee" msgstr "Execution Fee" @@ -1815,14 +1851,14 @@ msgstr "FEES" msgid "FUNDING FEE" msgstr "FUNDING FEE" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "FUNDING RATE / 1h" -msgstr "FUNDING RATE / 1h" - #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx msgid "Failed Settlement of Funding Fees" msgstr "Failed Settlement of Funding Fees" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Failed to Claim Price Impact Rebate" +msgstr "Failed to Claim Price Impact Rebate" + #: src/domain/synthetics/orders/cancelOrdersTxn.ts msgid "Failed to cancel {ordersText}" msgstr "Failed to cancel {ordersText}" @@ -1847,6 +1883,7 @@ msgstr "Fee values do not include incentives." #: src/components/Glp/GlpSwap.js #: src/components/Glp/GlpSwap.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Fees" msgstr "Fees" @@ -1963,11 +2000,10 @@ msgstr "Fulfilling Sell request" msgid "Fulfilling order request" msgstr "Fulfilling order request" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts msgid "Funding Claimed" msgstr "Funding Claimed" -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Funding Fee" @@ -1977,14 +2013,15 @@ msgstr "Funding Fee" msgid "Funding Fee Rate" msgstr "Funding Fee Rate" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Funding Rate / 1h" -msgstr "Funding Rate / 1h" - #: src/components/Synthetics/Claims/ClaimableCardUI.tsx msgid "Funding fees" msgstr "Funding fees" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Funding fees help to balance longs and shorts and are exchanged between both sides. <0>Read more." +msgstr "Funding fees help to balance longs and shorts and are exchanged between both sides. <0>Read more." + #: src/pages/Ecosystem/Ecosystem.js msgid "GBC NFTs APR tracker and rewards" msgstr "GBC NFTs APR tracker and rewards" @@ -2015,7 +2052,7 @@ msgstr "GLP autocompounding vaults" msgid "GLP buy disabled, pending {0} upgrade" msgstr "GLP buy disabled, pending {0} upgrade" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GLP is the liquidity provider token for GMX V1 markets. Accrues 70% of the V1 markets generated fees." msgstr "GLP is the liquidity provider token for GMX V1 markets. Accrues 70% of the V1 markets generated fees." @@ -2043,7 +2080,7 @@ msgstr "GM Token pricing includes positions' Pending PnL, Impact Pool Amount and msgid "GM can be sold for {0} and {1} for this market up to the specified selling caps. The remaining tokens in the pool are reserved for currently open Positions." msgstr "GM can be sold for {0} and {1} for this market up to the specified selling caps. The remaining tokens in the pool are reserved for currently open Positions." -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GM is the liquidity provider token for GMX V2 markets. Accrues 63% of the V2 markets generated fees." msgstr "GM is the liquidity provider token for GMX V2 markets. Accrues 63% of the V2 markets generated fees." @@ -2132,7 +2169,7 @@ msgstr "GMX is currently live on Arbitrum and Avalanche." msgid "GMX is not actively looking for new hires at the moment. However, if you think you can contribute to the project, please email <0>jobs@gmx.io." msgstr "GMX is not actively looking for new hires at the moment. However, if you think you can contribute to the project, please email <0>jobs@gmx.io." -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GMX is the utility and governance token. Accrues 30% and 27% of V1 and V2 markets generated fees, respectively." msgstr "GMX is the utility and governance token. Accrues 30% and 27% of V1 and V2 markets generated fees, respectively." @@ -2185,6 +2222,13 @@ msgstr "Get fee discounts and earn rebates through the GMX referral program.<0/> msgid "Governance" msgstr "Governance" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.tsx +#: src/components/Synthetics/PositionEditor/PositionEditor.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "High Execution Fee not yet acknowledged" +msgstr "High Execution Fee not yet acknowledged" + #: src/components/Exchange/SwapBox.js msgid "High Slippage, Swap Anyway" msgstr "High Slippage, Swap Anyway" @@ -2193,6 +2237,13 @@ msgstr "High Slippage, Swap Anyway" msgid "High USDG Slippage, Long Anyway" msgstr "High USDG Slippage, Long Anyway" +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#~ msgid "High network Fee not yet acknowledged" +#~ msgstr "High network Fee not yet acknowledged" + #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "I am aware of the trigger orders" @@ -2228,7 +2279,7 @@ msgstr "Incentives Distribution History" msgid "Incentives are airdropped weekly." msgstr "Incentives are airdropped weekly." -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Include PnL in leverage display" msgstr "Include PnL in leverage display" @@ -2250,7 +2301,6 @@ msgstr "Incorrect network" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -2408,7 +2458,7 @@ msgstr "Invalid Receiver Address" msgid "Invalid Transfer Addresses: Please check the url." msgstr "Invalid Transfer Addresses: Please check the url." -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid execution fee buffer value" msgstr "Invalid execution fee buffer value" @@ -2426,7 +2476,7 @@ msgstr "Invalid liq. price" msgid "Invalid price, see warning" msgstr "Invalid price, see warning" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid slippage value" msgstr "Invalid slippage value" @@ -2455,7 +2505,6 @@ msgid "Keep Leverage is not possible" msgstr "Keep Leverage is not possible" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "Keep leverage at {0}" msgstr "Keep leverage at {0}" @@ -2464,6 +2513,10 @@ msgstr "Keep leverage at {0}" msgid "Keep leverage at {0}x" msgstr "Keep leverage at {0}x" +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "Keep leverage at {keepLeverageAtValue}" +msgstr "Keep leverage at {keepLeverageAtValue}" + #: src/components/Synthetics/ChartTokenSelector/ChartTokenSelector.tsx msgid "LONG LIQ." msgstr "LONG LIQ." @@ -2548,7 +2601,6 @@ msgstr "Leverage slider" #: src/components/Synthetics/PositionItem/PositionItem.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts -#: src/domain/synthetics/orders/utils.ts msgid "Limit" msgstr "Limit" @@ -2572,7 +2624,6 @@ msgstr "Limit Order Price will vary based on Fees and Price Impact to guarantee #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Limit Price" msgstr "Limit Price" @@ -2708,8 +2759,8 @@ msgstr "Loading..." #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -2726,7 +2777,6 @@ msgstr "Loading..." #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -2741,14 +2791,6 @@ msgstr "Long" msgid "Long Collateral" msgstr "Long Collateral" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Payments" -msgstr "Long Funding Payments" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Rewards" -msgstr "Long Funding Rewards" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Long Liquidity" msgstr "Long Liquidity" @@ -2757,14 +2799,11 @@ msgstr "Long Liquidity" msgid "Long Open Interest" msgstr "Long Open Interest" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Long Positions" msgstr "Long Positions" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Long positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "Long positions {0} a Funding Fee of <0>{1}{2}% per hour." - #: src/components/Exchange/SwapBox.js msgid "Long {0}" msgstr "Long {0}" @@ -2781,7 +2820,9 @@ msgstr "Looks like you don't have a referral code to share. <0/> Create one now msgid "Loss" msgstr "Loss" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/GmList/GmList.tsx msgid "MARKET" msgstr "MARKET" @@ -2897,16 +2938,15 @@ msgid "Max Capacity for {0} Reached" msgstr "Max Capacity for {0} Reached" #: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Max Execution Fee" msgstr "Max Execution Fee" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee Buffer" msgstr "Max Execution Fee Buffer" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee buffer below {0}% may result in failed orders." msgstr "Max Execution Fee buffer below {0}% may result in failed orders." @@ -2948,7 +2988,7 @@ msgstr "Max auto top-up amount" msgid "Max close amount exceeded" msgstr "Max close amount exceeded" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max execution fee buffer precision is 0.01%" msgstr "Max execution fee buffer precision is 0.01%" @@ -2978,9 +3018,13 @@ msgstr "Max pool capacity reached for {0}. Please mint GLP using another token" msgid "Max pool capacity reached for {0}<0/><1/>Please mint GLP using another token" msgstr "Max pool capacity reached for {0}<0/><1/>Please mint GLP using another token" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Max slippage precision is -0.01%" +msgstr "Max slippage precision is -0.01%" + #: src/App/App.js -msgid "Max slippage precision is 0.01%" -msgstr "Max slippage precision is 0.01%" +#~ msgid "Max slippage precision is 0.01%" +#~ msgstr "Max slippage precision is 0.01%" #: src/components/Synthetics/MarketStats/MarketStats.tsx #: src/components/Synthetics/MarketStats/MarketStats.tsx @@ -3028,11 +3072,11 @@ msgstr "Max {0} short capacity" msgid "Max {0} short exceeded" msgstr "Max {0} short exceeded" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Arbitrum APR:" msgstr "Max. Arbitrum APR:" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Avalanche APR: {0}" msgstr "Max. Avalanche APR: {0}" @@ -3041,8 +3085,12 @@ msgid "Max. Leverage exceeded" msgstr "Max. Leverage exceeded" #: src/components/Stake/GMXAprTooltip.tsx -msgid "Max. {nativeTokenSymbol} APR with 200% Boost for this week: {0}%." -msgstr "Max. {nativeTokenSymbol} APR with 200% Boost for this week: {0}%." +msgid "Max. {nativeTokenSymbol} APR" +msgstr "Max. {nativeTokenSymbol} APR" + +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Max. {nativeTokenSymbol} APR is calculated with the max. 200% Boost Percentage by staking <0>Multiplier Points." +msgstr "Max. {nativeTokenSymbol} APR is calculated with the max. 200% Boost Percentage by staking <0>Multiplier Points." #: src/components/Migration/Migration.js #: src/pages/Stake/StakeV1.js @@ -3151,9 +3199,16 @@ msgid "Multiplier Points APR" msgstr "Multiplier Points APR" #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "NA" msgstr "NA" +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "NET FEE / 1 H" +msgstr "NET FEE / 1 H" + #: src/pages/NftWallet/NftWallet.js msgid "NFT Address" msgstr "NFT Address" @@ -3174,6 +3229,20 @@ msgstr "Negative Funding Fees are settled against the collateral automatically a msgid "Neither Collateral nor realized PnL is enough to cover pending Fees. Please close a larger position amount." msgstr "Neither Collateral nor realized PnL is enough to cover pending Fees. Please close a larger position amount." +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Fee" +msgstr "Net Fee" + +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Net Fee / 1h" +msgstr "Net Fee / 1h" + +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Rebate" +msgstr "Net Rebate" + #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -3202,7 +3271,12 @@ msgstr "Networks" msgid "Networks and Settings" msgstr "Networks and Settings" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "New Collateral" +msgstr "New Collateral" + #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Next" msgstr "Next" @@ -3278,6 +3352,10 @@ msgstr "Not enough {0} on your Main Account. Use the \"Convert {1} to {2}\" fiel msgid "Note that orders are not guaranteed to be executed.<0/><1/>This can occur in a few situations including but not exclusive to:" msgstr "Note that orders are not guaranteed to be executed.<0/><1/>This can occur in a few situations including but not exclusive to:" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Old Collateral" +msgstr "Old Collateral" + #: src/components/AddressDropdown/AddressDropdown.tsx #: src/components/Synthetics/SubaccountModal/SubaccountModal.tsx msgid "One-Click Trading" @@ -3354,10 +3432,6 @@ msgstr "Opening..." msgid "Order" msgstr "Order" -#: src/domain/synthetics/orders/utils.ts -msgid "Order Trigger Price is beyond position's Liquidation Price." -msgstr "Order Trigger Price is beyond position's Liquidation Price." - #: src/components/Synthetics/OrderItem/OrderItem.tsx msgid "Order Type" msgstr "Order Type" @@ -3638,7 +3712,6 @@ msgstr "Positions" msgid "Positions ({0})" msgstr "Positions ({0})" -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Positions{0}" msgstr "Positions{0}" @@ -3648,6 +3721,7 @@ msgid "Positive Funding Fees for a Position become claimable after the Position msgstr "Positive Funding Fees for a Position become claimable after the Position is increased, decreased or closed; or settled its fees with the option under \"Accrued\"." #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Prev" msgstr "Prev" @@ -3689,6 +3763,20 @@ msgstr "Price" msgid "Price Impact" msgstr "Price Impact" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Price Impact Rebate Claimed" +msgstr "Price Impact Rebate Claimed" + +#: src/components/Synthetics/Claims/ClaimableCardUI.tsx +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates" +msgstr "Price Impact Rebates" + +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates for closing trades are claimable under the Claims tab. <0>Read more." +msgstr "Price Impact Rebates for closing trades are claimable under the Claims tab. <0>Read more." + +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts @@ -3696,6 +3784,10 @@ msgstr "Price Impact" msgid "Price Impact not yet acknowledged" msgstr "Price Impact not yet acknowledged" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Limit Price." +msgstr "Price above Limit Price." + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3703,6 +3795,10 @@ msgstr "Price Impact not yet acknowledged" msgid "Price above Liq. Price" msgstr "Price above Liq. Price" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Liq. Price." +msgstr "Price above Liq. Price." + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3716,6 +3812,14 @@ msgstr "Price above Liq. Price" msgid "Price above Mark Price" msgstr "Price above Mark Price" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Mark Price." +msgstr "Price above Mark Price." + +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Limit Price." +msgstr "Price below Limit Price." + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3723,6 +3827,10 @@ msgstr "Price above Mark Price" msgid "Price below Liq. Price" msgstr "Price below Liq. Price" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Liq. Price." +msgstr "Price below Liq. Price." + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3736,6 +3844,10 @@ msgstr "Price below Liq. Price" msgid "Price below Mark Price" msgstr "Price below Mark Price" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Mark Price." +msgstr "Price below Mark Price." + #: src/pages/OrdersOverview/OrdersOverview.js msgid "Price conditions are met" msgstr "Price conditions are met" @@ -3778,6 +3890,10 @@ msgstr "Proof of Reserves" msgid "Protocol" msgstr "Protocol" +#: src/pages/Buy/Buy.tsx +msgid "Protocol Tokens" +msgstr "Protocol Tokens" + #: src/pages/Ecosystem/Ecosystem.js #: src/pages/Ecosystem/Ecosystem.js msgid "Protocol analytics" @@ -3799,9 +3915,14 @@ msgstr "Purchase <0>GM Tokens to earn fees from swaps and leverage trading." msgid "Purchase Insurance" msgstr "Purchase Insurance" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "REBATE" +msgstr "REBATE" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Read more" msgstr "Read more" @@ -4028,7 +4149,7 @@ msgstr "SL" msgid "Same as current active code" msgstr "Same as current active code" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Save" msgstr "Save" @@ -4194,10 +4315,10 @@ msgstr "Sending settle request" msgid "Set TP/SL" msgstr "Set TP/SL" -#: src/App/App.js #: src/components/Header/AppHeaderLinks.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx +#: src/components/SettingsModal/SettingsModal.tsx msgid "Settings" msgstr "Settings" @@ -4259,8 +4380,8 @@ msgstr "Share Position" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4277,7 +4398,6 @@ msgstr "Share Position" #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -4292,14 +4412,6 @@ msgstr "Short" msgid "Short Collateral" msgstr "Short Collateral" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Payments" -msgstr "Short Funding Payments" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Rewards" -msgstr "Short Funding Rewards" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Short Liquidity" msgstr "Short Liquidity" @@ -4308,14 +4420,11 @@ msgstr "Short Liquidity" msgid "Short Open Interest" msgstr "Short Open Interest" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Short Positions" msgstr "Short Positions" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Short positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "Short positions {0} a Funding Fee of <0>{1}{2}% per hour." - #: src/components/Exchange/SwapBox.js msgid "Short {0}" msgstr "Short {0}" @@ -4324,10 +4433,14 @@ msgstr "Short {0}" msgid "Shorting..." msgstr "Shorting..." -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Show debug values" msgstr "Show debug values" +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Show details" +msgstr "Show details" + #: src/pages/Home/Home.js msgid "Simple Swaps" msgstr "Simple Swaps" @@ -4353,6 +4466,7 @@ msgstr "Single" #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4364,14 +4478,18 @@ msgstr "Size" #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Slippage is too high" msgstr "Slippage is too high" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Slippage should be less than -5%" +msgstr "Slippage should be less than -5%" + #: src/App/App.js -msgid "Slippage should be less than 5%" -msgstr "Slippage should be less than 5%" +#~ msgid "Slippage should be less than 5%" +#~ msgstr "Slippage should be less than 5%" #: src/components/Exchange/UsefulLinks.tsx msgid "Speed up page loading" @@ -4475,10 +4593,15 @@ msgstr "Stats" msgid "Stop Loss Decrease" msgstr "Stop Loss Decrease" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Stop-Loss" msgstr "Stop-Loss" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Stop-Loss PnL" +msgstr "Stop-Loss PnL" + #: src/pages/Ecosystem/Ecosystem.js msgid "Structured Products" msgstr "Structured Products" @@ -4527,7 +4650,7 @@ msgstr "Subaccount:" msgid "Submit" msgstr "Submit" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Success claimings" msgstr "Success claimings" @@ -4553,10 +4676,6 @@ msgstr "Swap" msgid "Swap Fee" msgstr "Swap Fee" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx -msgid "Swap Fees" -msgstr "Swap Fees" - #: src/components/Exchange/SwapBox.js msgid "Swap Order created!" msgstr "Swap Order created!" @@ -4569,7 +4688,6 @@ msgstr "Swap Order creation failed." msgid "Swap Order submitted!" msgstr "Swap Order submitted!" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Swap Price Impact" msgstr "Swap Price Impact" @@ -4703,11 +4821,15 @@ msgstr "TP" msgid "TP/SL" msgstr "TP/SL" -#: src/domain/synthetics/orders/utils.ts +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Take-Profit" msgstr "Take-Profit" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Take-Profit PnL" +msgstr "Take-Profit PnL" + #: src/components/Exchange/SwapBox.js msgid "Take-profit and stop-loss orders can be set after opening a position. <0/><1/>There will be a \"Close\" button on each position row, clicking this will display the option to set trigger orders. <2/><3/>For screenshots and more information, please see the <4>docs." msgstr "Take-profit and stop-loss orders can be set after opening a position. <0/><1/>There will be a \"Close\" button on each position row, clicking this will display the option to set trigger orders. <2/><3/>For screenshots and more information, please see the <4>docs." @@ -4774,10 +4896,6 @@ msgstr "The Bonus Rebate is an estimate and will be airdropped as ARB tokens whe msgid "The Bonus Rebate will be airdropped as ARB tokens on a pro-rata basis. <0>Read more." msgstr "The Bonus Rebate will be airdropped as ARB tokens on a pro-rata basis. <0>Read more." -#: src/components/Stake/GMXAprTooltip.tsx -msgid "The Boosted APR is from your staked Multiplier Points." -msgstr "The Boosted APR is from your staked Multiplier Points." - #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx msgid "The Current Price Impact is {0}. Consider adding a buffer of 0.30% to it so the order is more likely to be processed." msgstr "The Current Price Impact is {0}. Consider adding a buffer of 0.30% to it so the order is more likely to be processed." @@ -4790,18 +4908,15 @@ msgstr "The Execution Price didn't meet the Acceptable Price condition. The Orde msgid "The Gambit protocol is in beta, please read the <0>staking detailsbefore participating." msgstr "The Gambit protocol is in beta, please read the <0>staking detailsbefore participating." +#: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "The Max Execution Fee is overestimated by {maxExecutionFeeText}%. Upon execution, the excess Execution Fee is sent back to your account." msgstr "The Max Execution Fee is overestimated by {maxExecutionFeeText}%. Upon execution, the excess Execution Fee is sent back to your account." -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "The Max Execution Fee is set to a higher value to handle potential increases in gas price during order execution. Any excess execution fee will be refunded to your account when the order is executed. Only applicable to GMX V2." msgstr "The Max Execution Fee is set to a higher value to handle potential increases in gas price during order execution. Any excess execution fee will be refunded to your account when the order is executed. Only applicable to GMX V2." -#: src/domain/synthetics/orders/utils.ts -msgid "The Order may not execute at the desired {priceText} as the current Price Impact {0} is higher than its Acceptable Price Impact {1}. Consider canceling and creating a new {suggestionType} Order." -msgstr "The Order may not execute at the desired {priceText} as the current Price Impact {0} is higher than its Acceptable Price Impact {1}. Consider canceling and creating a new {suggestionType} Order." - #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "The address of the esGMX (IOU) token is {esGmxIouAddress}." msgstr "The address of the esGMX (IOU) token is {esGmxIouAddress}." @@ -4830,11 +4945,23 @@ msgstr "The mark price has changed, consider increasing your Allowed Slippage by msgid "The maximum number of authorized Actions has been reached. Re-authorize a higher value using the \"Max allowed actions\" field." msgstr "The maximum number of authorized Actions has been reached. Re-authorize a higher value using the \"Max allowed actions\" field." +#: src/domain/synthetics/fees/utils/executionFee.ts +msgid "The network Fees are high currently, which may be due to a temporary increase in transactions on the {0} network." +msgstr "The network Fees are high currently, which may be due to a temporary increase in transactions on the {0} network." + #: src/domain/legacy.ts #: src/domain/synthetics/fees/utils/executionFee.ts msgid "The network Fees are very high currently, which may be due to a temporary increase in transactions on the {0} network." msgstr "The network Fees are very high currently, which may be due to a temporary increase in transactions on the {0} network." +#: src/domain/synthetics/orders/utils.ts +msgid "The order may not execute at the desired {priceText} as its acceptable price impact is set to {formattedOrderAcceptablePriceImpact}, which is lower than the current market price impact of {formattedCurrentAcceptablePriceImpact}. It can be edited using the \"Edit\" button." +msgstr "The order may not execute at the desired {priceText} as its acceptable price impact is set to {formattedOrderAcceptablePriceImpact}, which is lower than the current market price impact of {formattedCurrentAcceptablePriceImpact}. It can be edited using the \"Edit\" button." + +#: src/domain/synthetics/orders/utils.ts +msgid "The order will not be executed as its trigger price is beyond the position's liquidation price." +msgstr "The order will not be executed as its trigger price is beyond the position's liquidation price." + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "The order will only execute if the Min. Receive is met and there is sufficient liquidity." msgstr "The order will only execute if the Min. Receive is met and there is sufficient liquidity." @@ -4856,8 +4983,12 @@ msgid "The pending borrow fee will be charged on this transaction." msgstr "The pending borrow fee will be charged on this transaction." #: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" -msgstr "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of -{1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +msgstr "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of -{1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" + +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#~ msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +#~ msgstr "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" #: src/components/Exchange/SwapBox.js msgid "The position will be opened at {0} USD with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" @@ -4967,10 +5098,9 @@ msgstr "This code is not yet registered on {0}, you will not receive rebates the msgid "This is the maximum top-up amount that will be sent from your Main account to your Subaccount after each transaction. The actual amount sent will depend on the final transaction fee." msgstr "This is the maximum top-up amount that will be sent from your Main account to your Subaccount after each transaction. The actual amount sent will depend on the final transaction fee." -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "This market uses an Adaptive Funding Rate. The Funding Rate will adjust over time depending on the ratio of longs and shorts. <0>Read more." -msgstr "This market uses an Adaptive Funding Rate. The Funding Rate will adjust over time depending on the ratio of longs and shorts. <0>Read more." +#: src/domain/synthetics/orders/utils.ts +msgid "This order using {collateralSymbol} as collateral will not be valid for the existing {longText} position using {symbol} as collateral." +msgstr "This order using {collateralSymbol} as collateral will not be valid for the existing {longText} position using {symbol} as collateral." #: src/components/Exchange/TradeHistory.js msgid "This position was liquidated as the max leverage of 100x was exceeded." @@ -5140,7 +5270,6 @@ msgstr "Traders Referred on Avalanche Fuji" #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Trades" msgstr "Trades" @@ -5243,7 +5372,6 @@ msgstr "Trigger" #: src/components/Synthetics/OrderList/OrderList.tsx #: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Trigger Price" msgstr "Trigger Price" @@ -5255,10 +5383,6 @@ msgstr "Trigger Price: {pricePrefix} {0}" msgid "Trigger order disabled, pending {0} upgrade" msgstr "Trigger order disabled, pending {0} upgrade" -#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx -msgid "Trigger order for" -msgstr "Trigger order for" - #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Triggered at: {0}" msgstr "Triggered at: {0}" @@ -5362,8 +5486,8 @@ msgid "Unstake submitted! <0>View status." msgstr "Unstake submitted! <0>View status." #: src/pages/Stake/StakeV2.js -msgid "Unstaking will burn <0>{0} Multiplier Points. {1}" -msgstr "Unstaking will burn <0>{0} Multiplier Points. {1}" +msgid "Unstaking will burn <0>{0} Multiplier Points. <1>You will earn {1}% less {nativeTokenSymbol} rewards with this action." +msgstr "Unstaking will burn <0>{0} Multiplier Points. <1>You will earn {1}% less {nativeTokenSymbol} rewards with this action." #: src/pages/Stake/StakeV1.js #: src/pages/Stake/StakeV2.js @@ -5572,6 +5696,18 @@ msgstr "View" msgid "View in Explorer" msgstr "View in Explorer" +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Arbitrum" +msgstr "View on Arbitrum" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Avalanche" +msgstr "View on Avalanche" + #: src/components/Synthetics/StatusNotification/SubaccountNotification.tsx msgid "View status" msgstr "View status" @@ -5802,9 +5938,12 @@ msgstr "You can check your claim history <0>here." msgid "You can currently vest a maximum of {0} esGMX tokens at a ratio of {1} {stakingToken} to 1 esGMX." msgstr "You can currently vest a maximum of {0} esGMX tokens at a ratio of {1} {stakingToken} to 1 esGMX." +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx +msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than -{0}, may result in failed orders if prices are volatile." +msgstr "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than -{0}, may result in failed orders if prices are volatile." + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than {0}, may result in failed orders if prices are volatile." msgstr "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than {0}, may result in failed orders if prices are volatile." @@ -5832,10 +5971,6 @@ msgstr "You have a pending transfer from {sender}." msgid "You have an active Limit Order to Increase {longOrShortText} {sizeInToken} {0} (${1}) at price ${2}" msgstr "You have an active Limit Order to Increase {longOrShortText} {sizeInToken} {0} (${1}) at price ${2}" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have an active Limit Order to Increase {longShortText} {0} {sizeText} at price {1}." -msgstr "You have an active Limit Order to Increase {longShortText} {0} {sizeText} at price {1}." - #: src/components/Exchange/PositionSeller.js msgid "You have an active order to decrease {longOrShortText} {sizeInToken} {0} (${1}) at {prefix} {2}" msgstr "You have an active order to decrease {longOrShortText} {sizeInToken} {0} (${1}) at {prefix} {2}" @@ -5864,27 +5999,24 @@ msgstr "You have an existing position with {0} as collateral. This Order will no msgid "You have an existing position with {0} as collateral. This action will not apply for that position." msgstr "You have an existing position with {0} as collateral. This action will not apply for that position." -#: src/domain/synthetics/orders/utils.ts -msgid "" -"You have an existing {longText} position with {0} as Collateral. This Order will not\n" -"be valid for that Position." -msgstr "" -"You have an existing {longText} position with {0} as Collateral. This Order will not\n" -"be valid for that Position." - #: src/components/Exchange/ConfirmationBox.js msgid "You have multiple existing Increase {longOrShortText} {0} limit orders" msgstr "You have multiple existing Increase {longOrShortText} {0} limit orders" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have multiple existing Increase {longShortText} {0} limit orders" -msgstr "You have multiple existing Increase {longShortText} {0} limit orders" - #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "You have not deposited any tokens for vesting." msgstr "You have not deposited any tokens for vesting." +#: src/components/Stake/GMXAprTooltip.tsx +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points using the \"Compound\" button." +msgstr "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points using the \"Compound\" button." + +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points." +msgstr "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points." + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "You have selected {collateralTokenSymbol} as Collateral, the Liquidation Price will vary based on the price of {collateralTokenSymbol}." msgstr "You have selected {collateralTokenSymbol} as Collateral, the Liquidation Price will vary based on the price of {collateralTokenSymbol}." @@ -5933,14 +6065,19 @@ msgstr "You will receive at least {0} {1} if this order is executed. The executi msgid "You will receive at least {toAmountText} if this order is executed. This price is being updated in real time based on Swap Fees and Price Impact." msgstr "You will receive at least {toAmountText} if this order is executed. This price is being updated in real time based on Swap Fees and Price Impact." +#: src/pages/Stake/StakeV2.js +#: src/pages/Stake/StakeV2.js +msgid "Your APR" +msgstr "Your APR" + #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "Your esGMX (IOU) balance will decrease by your claim amount after claiming, this is expected behaviour." msgstr "Your esGMX (IOU) balance will decrease by your claim amount after claiming, this is expected behaviour." #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "Your position's collateral after deducting fees." -msgstr "Your position's collateral after deducting fees." +msgid "Your position's collateral after deducting fees:" +msgstr "Your position's collateral after deducting fees:" #: src/pages/CompleteAccountTransfer/CompleteAccountTransfer.js msgid "Your transfer has been completed." @@ -5975,7 +6112,6 @@ msgid "from" msgstr "from" #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "hide" msgstr "hide" @@ -5983,20 +6119,32 @@ msgstr "hide" msgid "in liquidity" msgstr "in liquidity" +#: src/domain/synthetics/orders/utils.ts +msgid "limit price" +msgstr "limit price" + +#: src/domain/synthetics/orders/utils.ts +msgid "long" +msgstr "long" + #: src/pages/Dashboard/DashboardV2.js msgid "not staked" msgstr "not staked" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "pay" msgstr "pay" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "receive" msgstr "receive" +#: src/domain/synthetics/orders/utils.ts +msgid "short" +msgstr "short" + #: src/pages/PositionsOverview/PositionsOverview.js msgid "size" msgstr "size" @@ -6009,8 +6157,11 @@ msgstr "staked" msgid "time to liq" msgstr "time to liq" +#: src/domain/synthetics/orders/utils.ts +msgid "trigger price" +msgstr "trigger price" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "view" msgstr "view" @@ -6027,6 +6178,10 @@ msgstr "{0, plural, one {Cancel order} other {Cancel # orders}}" msgid "{0, plural, one {Pending {symbolsText} approval} other {Pending {symbolsText} approvals}}" msgstr "{0, plural, one {Pending {symbolsText} approval} other {Pending {symbolsText} approvals}}" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "{0, plural, one {You have an active Limit Order to Increase} other {You have multiple active Limit Orders to Increase}}" +msgstr "{0, plural, one {You have an active Limit Order to Increase} other {You have multiple active Limit Orders to Increase}}" + #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "{0} <0><1>{indexName}<2>[{poolName}] <3>market selected." msgstr "{0} <0><1>{indexName}<2>[{poolName}] <3>market selected." @@ -6107,6 +6262,10 @@ msgstr "{0} is below its target weight.<0/><1/>Get lower fees to <2>buy GLP msgid "{0} is required for collateral." msgstr "{0} is required for collateral." +#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx +msgid "{0} order for" +msgstr "{0} order for" + #: src/components/Glp/GlpSwap.js msgid "{0} pool exceeded, try different token" msgstr "{0} pool exceeded, try different token" @@ -6210,6 +6369,22 @@ msgstr "{increaseOrDecreaseText} {tokenText} by {sizeText}" msgid "{longOrShortText} {0} market selected" msgstr "{longOrShortText} {0} market selected" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee and pay a borrow fee of {borrowRate} per hour." +msgstr "{longOrShort} positions do not pay a funding fee and pay a borrow fee of {borrowRate} per hour." + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee or a borrow fee." +msgstr "{longOrShort} positions do not pay a funding fee or a borrow fee." + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and do not pay a borrow fee." +msgstr "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and do not pay a borrow fee." + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and {borrowAction} a borrow fee of {borrowRate} per hour." +msgstr "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and {borrowAction} a borrow fee of {borrowRate} per hour." + #: src/components/Synthetics/MarketCard/MarketCard.tsx msgid "{longShortText} {0} Open Interest" msgstr "{longShortText} {0} Open Interest" @@ -6226,10 +6401,6 @@ msgstr "{marketsCount, plural, one {# Market} other {# Markets}}" msgid "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR" msgstr "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "{nativeTokenSymbol} APR" -msgstr "{nativeTokenSymbol} APR" - #: src/components/Stake/GMXAprTooltip.tsx msgid "{nativeTokenSymbol} Base APR" msgstr "{nativeTokenSymbol} Base APR" diff --git a/src/locales/es/messages.po b/src/locales/es/messages.po index 8b97a515f0..215226ab78 100644 --- a/src/locales/es/messages.po +++ b/src/locales/es/messages.po @@ -135,6 +135,10 @@ msgstr "" msgid "<0>{0} <1><2>{indexName}<3>[{poolName}] <4>market selected" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "A Size percentage is required." +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "A snapshot of the USD value of your {0} collateral is taken when the position is opened." msgstr "Se registra el valor en USD de tu {0} garantía en el momento que la posición se abre." @@ -243,6 +247,14 @@ msgstr "" msgid "Accrued Positive Funding Fees for Positions not yet claimable. They will become available to claim by using the \"Settle\" button, or after the Position is increased, decreased or closed." msgstr "" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +msgid "Accrued Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Accrued Price Impact Rebates. They will become Claimable after some time.<0/><1/><2>Read more." +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "Acknowledge epoch is ending in {minutes} minutes" msgstr "" @@ -257,6 +269,10 @@ msgstr "" msgid "Acknowledge high Swap Price Impact" msgstr "" +#: src/domain/synthetics/trade/useHighExecutionFeeConsent.tsx +msgid "Acknowledge very high network Fees" +msgstr "" + #: src/pages/Actions/Actions.js #: src/pages/SyntheticsActions/SyntheticsActions.tsx msgid "Actions" @@ -303,6 +319,10 @@ msgstr "Fallo al añadir el código de referido." msgid "Adding..." msgstr "Añadiendo..." +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +#~ msgid "Additional Execution Fee" +#~ msgstr "" + #: src/pages/Stake/StakeV2.js msgid "Additional reserve required" msgstr "Reserva adicional requerida" @@ -344,15 +364,15 @@ msgstr "" msgid "Allow {wrappedTokenSymbol} to be spent" msgstr "" -#: src/App/App.js #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/SettingsModal/SettingsModal.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Allowed Slippage" msgstr "Deslizamiento permitido" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Allowed Slippage below {0}% may result in failed orders." msgstr "" @@ -444,11 +464,15 @@ msgstr "Aprobando {stakingTokenSymbol}..." msgid "Approving..." msgstr "Aprobando..." -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Arbitrum APR:" msgstr "Arbitrum APR:" +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "As network fees have increased, an additional execution fee is needed." +msgstr "" + #: src/components/Exchange/NoLiquidityErrorModal.tsx msgid "As there is not enough liquidity in GLP to swap {0} to {swapTokenSymbol}, you can use the option below to do so:" msgstr "Como no hay liquidez suficiente en GLP para intercambiar {0} a {swapTokenSymbol}, puedes usar la opción a continuación para hacerlo:" @@ -492,8 +516,8 @@ msgstr "Cantidad disponible para retirar de GLP. Fondos no utilizados por posici msgid "Available on your preferred network" msgstr "Disponible en su red preferida" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Avalanche APR:" msgstr "Avalanche APR:" @@ -518,6 +542,10 @@ msgstr "Balance" msgid "Base APR" msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Base {nativeTokenSymbol} APR" +msgstr "" + #: src/pages/BeginAccountTransfer/BeginAccountTransfer.js msgid "Begin Transfer" msgstr "Comenzar Transferencia" @@ -546,7 +574,6 @@ msgstr "Aumenta tus recompensas con los Puntos Multiplicadores. <0>Más informa #: src/components/Exchange/PositionsList.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Borrow Fee" @@ -561,6 +588,11 @@ msgstr "Tasa de Préstamo / Día" msgid "Borrow Fee Rate" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Borrowing fees help ensure available liquidity. <0>Read more." +msgstr "" + #: src/components/Synthetics/BridgingInfo/BridgingInfo.tsx msgid "Bridge {tokenSymbol} to {chainName} using any of the options below:" msgstr "" @@ -596,7 +628,7 @@ msgstr "" msgid "Buy GLP" msgstr "Comprar GLP" -#: src/pages/Buy/Buy.js +#: src/pages/Buy/Buy.tsx msgid "Buy GLP or GMX" msgstr "" @@ -649,26 +681,10 @@ msgstr "" msgid "Buy GMX using any token from any network:" msgstr "" -#: src/pages/Buy/Buy.js -msgid "Buy Protocol Tokens" -msgstr "" - #: src/components/Glp/GlpSwap.js msgid "Buy failed." msgstr "Compra fallida." -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Arbitrum" -msgstr "Comprar en Arbitrum" - -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Avalanche" -msgstr "Comprar en Avalanche" - #: src/pages/BuyGMX/BuyGMX.tsx msgid "Buy or Transfer AVAX to Avalanche" msgstr "" @@ -729,7 +745,6 @@ msgstr "No se puede ejecutar debido a un error" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts @@ -759,7 +774,7 @@ msgstr "Cancelación enviada." msgid "Cancelling {ordersText}" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Chart positions" @@ -781,6 +796,7 @@ msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/Claims/ClaimableCard.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV1.js @@ -807,7 +823,7 @@ msgid "Claim GMX Rewards" msgstr "Reclamar Recompensas GMX" #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx -msgid "Claim Price Impact" +msgid "Claim Price Impact Rebates" msgstr "" #: src/pages/Stake/StakeV2.js @@ -853,6 +869,10 @@ msgstr "¡Reclamación enviada! <0>Ver estado." msgid "Claim submitted." msgstr "Reclamación enviada." +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "Claim {totalUsd}" +msgstr "" + #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "Claim {wrappedTokenSymbol} Rewards" @@ -864,30 +884,37 @@ msgstr "Reclamar Recompensas {wrappedTokenSymbol}" msgid "Claimable" msgstr "Reclamable" +#: src/components/Synthetics/Claims/ClaimableCard.tsx +msgid "Claimable Price Impact Rebates.<0/><1/><2>Read more." +msgstr "" + #: src/components/Referrals/AffiliatesStats.tsx msgid "Claimable Rebates" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Claiming Price Impact Rebate..." +msgstr "" + +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Claiming failed" msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV2.js msgid "Claiming..." msgstr "Reclamando..." -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Claims" msgstr "" #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx -msgid "Claims (1)" +msgid "Claims ({totalClaimables})" msgstr "" #: src/components/Exchange/PositionsList.js @@ -1044,6 +1071,7 @@ msgstr "Componiendo..." #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx msgid "Confirm Claim" msgstr "" @@ -1350,7 +1378,6 @@ msgstr "Exchange<0/>Perpetuo Decentralizado" #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -1370,6 +1397,10 @@ msgstr "" msgid "Decrease the Leverage by using the slider. If the Leverage slider is disabled, you can increase the Pay amount or reduce the Order size." msgstr "" +#: src/components/Synthetics/ConfirmationBox/SLTPEntries.tsx +msgid "Decrease {0} Long by {1} at ${2}." +msgstr "" + #: src/components/Exchange/TradeHistory.js #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx msgid "Decreased" @@ -1463,7 +1494,7 @@ msgstr "Depositando..." msgid "Diff" msgstr "Dif" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Disable order validations" msgstr "Deshabilitar validación de órdenes" @@ -1471,7 +1502,7 @@ msgstr "Deshabilitar validación de órdenes" msgid "Disconnect" msgstr "Desconectar" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Display PnL after fees" msgstr "Mostrar GyP después de comisiones" @@ -1502,6 +1533,10 @@ msgstr "Ganar" msgid "Earn ARB tokens by purchasing GM tokens, trading, or migrating liquidity from GLP to GM. Only for GMX V2." msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Earn an extra {0}% {nativeTokenSymbol} Boosted APR by increasing your staked <0>Multiplier Points." +msgstr "" + #: src/components/Header/AppHeaderLinks.tsx msgid "Ecosystem" msgstr "Ecosistema" @@ -1771,6 +1806,7 @@ msgid "Execute {orderTypeName} Order: {positionText} {sizeDeltaText}," msgstr "" #: src/components/Exchange/FeesTooltip.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx msgid "Execution Fee" msgstr "" @@ -1815,14 +1851,14 @@ msgstr "COMISIONES" msgid "FUNDING FEE" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "FUNDING RATE / 1h" -msgstr "" - #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx msgid "Failed Settlement of Funding Fees" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Failed to Claim Price Impact Rebate" +msgstr "" + #: src/domain/synthetics/orders/cancelOrdersTxn.ts msgid "Failed to cancel {ordersText}" msgstr "" @@ -1847,6 +1883,7 @@ msgstr "" #: src/components/Glp/GlpSwap.js #: src/components/Glp/GlpSwap.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Fees" msgstr "Comisiones" @@ -1963,11 +2000,10 @@ msgstr "" msgid "Fulfilling order request" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts msgid "Funding Claimed" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Funding Fee" @@ -1977,14 +2013,15 @@ msgstr "" msgid "Funding Fee Rate" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Funding Rate / 1h" -msgstr "" - #: src/components/Synthetics/Claims/ClaimableCardUI.tsx msgid "Funding fees" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Funding fees help to balance longs and shorts and are exchanged between both sides. <0>Read more." +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "GBC NFTs APR tracker and rewards" msgstr "Rastreador de GBC NFTs APR y recompensas" @@ -2015,7 +2052,7 @@ msgstr "" msgid "GLP buy disabled, pending {0} upgrade" msgstr "Compra de GLP desactivada, actualización {0} pendiente" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GLP is the liquidity provider token for GMX V1 markets. Accrues 70% of the V1 markets generated fees." msgstr "" @@ -2043,7 +2080,7 @@ msgstr "" msgid "GM can be sold for {0} and {1} for this market up to the specified selling caps. The remaining tokens in the pool are reserved for currently open Positions." msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GM is the liquidity provider token for GMX V2 markets. Accrues 63% of the V2 markets generated fees." msgstr "" @@ -2132,7 +2169,7 @@ msgstr "GMX esta actualmente en vivo en Arbitrum y Avalanche." msgid "GMX is not actively looking for new hires at the moment. However, if you think you can contribute to the project, please email <0>jobs@gmx.io." msgstr "GMX no se encuentra contratando en este momento. Sin embargo, si crees que puedes contribuir al proyecto, manda un email por favor <0>jobs@gmx.io." -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GMX is the utility and governance token. Accrues 30% and 27% of V1 and V2 markets generated fees, respectively." msgstr "" @@ -2185,6 +2222,13 @@ msgstr "" msgid "Governance" msgstr "Gobernanza" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.tsx +#: src/components/Synthetics/PositionEditor/PositionEditor.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "High Execution Fee not yet acknowledged" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "High Slippage, Swap Anyway" msgstr "Alto Deslizamiento, Intercambiar de todos modos" @@ -2193,6 +2237,13 @@ msgstr "Alto Deslizamiento, Intercambiar de todos modos" msgid "High USDG Slippage, Long Anyway" msgstr "Alto Deslizamiento de USDG, ir Largo de todas formas" +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#~ msgid "High network Fee not yet acknowledged" +#~ msgstr "" + #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "I am aware of the trigger orders" @@ -2228,7 +2279,7 @@ msgstr "" msgid "Incentives are airdropped weekly." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Include PnL in leverage display" msgstr "Incluir GyP en la visualización de apalancamiento" @@ -2250,7 +2301,6 @@ msgstr "Red incorrecta" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -2408,7 +2458,7 @@ msgstr "Dirección del Receptor Inválida" msgid "Invalid Transfer Addresses: Please check the url." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid execution fee buffer value" msgstr "" @@ -2426,7 +2476,7 @@ msgstr "Precio de liquidación inválido" msgid "Invalid price, see warning" msgstr "Precio no válido, ver advertencia" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid slippage value" msgstr "Valor de deslizamiento no válido" @@ -2455,7 +2505,6 @@ msgid "Keep Leverage is not possible" msgstr "" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "Keep leverage at {0}" msgstr "" @@ -2464,6 +2513,10 @@ msgstr "" msgid "Keep leverage at {0}x" msgstr "" +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "Keep leverage at {keepLeverageAtValue}" +msgstr "" + #: src/components/Synthetics/ChartTokenSelector/ChartTokenSelector.tsx msgid "LONG LIQ." msgstr "" @@ -2548,7 +2601,6 @@ msgstr "" #: src/components/Synthetics/PositionItem/PositionItem.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts -#: src/domain/synthetics/orders/utils.ts msgid "Limit" msgstr "Límite" @@ -2572,7 +2624,6 @@ msgstr "" #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Limit Price" msgstr "Precio límite" @@ -2705,8 +2756,8 @@ msgstr "Cargando..." #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -2723,7 +2774,6 @@ msgstr "Cargando..." #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -2738,14 +2788,6 @@ msgstr "Largo" msgid "Long Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Long Liquidity" msgstr "" @@ -2754,14 +2796,11 @@ msgstr "" msgid "Long Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Long Positions" msgstr "Posiciones largas" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Long positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Long {0}" msgstr "Largo {0}" @@ -2778,7 +2817,9 @@ msgstr "Parece que no tienes un código de referido para compartir. <0/> ¡Crea msgid "Loss" msgstr "Pérdida" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/GmList/GmList.tsx msgid "MARKET" msgstr "" @@ -2894,16 +2935,15 @@ msgid "Max Capacity for {0} Reached" msgstr "Capacidad Máxima para {0} Alcanzada" #: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Max Execution Fee" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee Buffer" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee buffer below {0}% may result in failed orders." msgstr "" @@ -2945,7 +2985,7 @@ msgstr "" msgid "Max close amount exceeded" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max execution fee buffer precision is 0.01%" msgstr "" @@ -2975,9 +3015,13 @@ msgstr "Capacidad máxima de reserva alcanzada para {0}. Por favor, acuñe GLP u msgid "Max pool capacity reached for {0}<0/><1/>Please mint GLP using another token" msgstr "Capacidad máxima de reserva alcanzada para {0}<0/><1/>Por favor, acuñe GLP usando otro token" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Max slippage precision is -0.01%" +msgstr "" + #: src/App/App.js -msgid "Max slippage precision is 0.01%" -msgstr "La precisión máxima del deslizamiento es de 0.01%" +#~ msgid "Max slippage precision is 0.01%" +#~ msgstr "La precisión máxima del deslizamiento es de 0.01%" #: src/components/Synthetics/MarketStats/MarketStats.tsx #: src/components/Synthetics/MarketStats/MarketStats.tsx @@ -3025,11 +3069,11 @@ msgstr "Capacidad Máx. {0} cortos" msgid "Max {0} short exceeded" msgstr "Superados cortos Máx. de {0}" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Arbitrum APR:" msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Avalanche APR: {0}" msgstr "" @@ -3038,7 +3082,11 @@ msgid "Max. Leverage exceeded" msgstr "" #: src/components/Stake/GMXAprTooltip.tsx -msgid "Max. {nativeTokenSymbol} APR with 200% Boost for this week: {0}%." +msgid "Max. {nativeTokenSymbol} APR" +msgstr "" + +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Max. {nativeTokenSymbol} APR is calculated with the max. 200% Boost Percentage by staking <0>Multiplier Points." msgstr "" #: src/components/Migration/Migration.js @@ -3148,9 +3196,16 @@ msgid "Multiplier Points APR" msgstr "APR de Puntos Multiplicadores" #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "NA" msgstr "" +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "NET FEE / 1 H" +msgstr "" + #: src/pages/NftWallet/NftWallet.js msgid "NFT Address" msgstr "Dirección NFT" @@ -3171,6 +3226,20 @@ msgstr "" msgid "Neither Collateral nor realized PnL is enough to cover pending Fees. Please close a larger position amount." msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Fee" +msgstr "" + +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Net Fee / 1h" +msgstr "" + +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Rebate" +msgstr "" + #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -3199,7 +3268,12 @@ msgstr "Redes" msgid "Networks and Settings" msgstr "Redes y Ajustes" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "New Collateral" +msgstr "" + #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Next" msgstr "Siguiente" @@ -3275,6 +3349,10 @@ msgstr "" msgid "Note that orders are not guaranteed to be executed.<0/><1/>This can occur in a few situations including but not exclusive to:" msgstr "Tenga en cuenta que no se garantiza la ejecución de las órdenes.<0/><1/>Esto puede ocurrir en algunas situaciones que incluyen, pero no exclusivamente:" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Old Collateral" +msgstr "" + #: src/components/AddressDropdown/AddressDropdown.tsx #: src/components/Synthetics/SubaccountModal/SubaccountModal.tsx msgid "One-Click Trading" @@ -3351,10 +3429,6 @@ msgstr "Abriendo..." msgid "Order" msgstr "Orden" -#: src/domain/synthetics/orders/utils.ts -msgid "Order Trigger Price is beyond position's Liquidation Price." -msgstr "" - #: src/components/Synthetics/OrderItem/OrderItem.tsx msgid "Order Type" msgstr "" @@ -3635,7 +3709,6 @@ msgstr "Posiciones" msgid "Positions ({0})" msgstr "Posiciones ({0})" -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Positions{0}" msgstr "" @@ -3645,6 +3718,7 @@ msgid "Positive Funding Fees for a Position become claimable after the Position msgstr "" #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Prev" msgstr "Prev" @@ -3686,6 +3760,20 @@ msgstr "Precio" msgid "Price Impact" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Price Impact Rebate Claimed" +msgstr "" + +#: src/components/Synthetics/Claims/ClaimableCardUI.tsx +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates for closing trades are claimable under the Claims tab. <0>Read more." +msgstr "" + +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts @@ -3693,6 +3781,10 @@ msgstr "" msgid "Price Impact not yet acknowledged" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3700,6 +3792,10 @@ msgstr "" msgid "Price above Liq. Price" msgstr "Precio superior al de liquidación" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3713,6 +3809,14 @@ msgstr "Precio superior al de liquidación" msgid "Price above Mark Price" msgstr "Precio superior al Precio de Referencia" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Mark Price." +msgstr "" + +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3720,6 +3824,10 @@ msgstr "Precio superior al Precio de Referencia" msgid "Price below Liq. Price" msgstr "Precio inferior al de liquidación" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3733,6 +3841,10 @@ msgstr "Precio inferior al de liquidación" msgid "Price below Mark Price" msgstr "Precio inferior al Precio de Marca" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Mark Price." +msgstr "" + #: src/pages/OrdersOverview/OrdersOverview.js msgid "Price conditions are met" msgstr "Las condiciones de precio se cumplen" @@ -3775,6 +3887,10 @@ msgstr "Prueba de reservas" msgid "Protocol" msgstr "" +#: src/pages/Buy/Buy.tsx +msgid "Protocol Tokens" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js #: src/pages/Ecosystem/Ecosystem.js msgid "Protocol analytics" @@ -3796,9 +3912,14 @@ msgstr "" msgid "Purchase Insurance" msgstr "Comprar Seguro" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "REBATE" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Read more" msgstr "Leer más" @@ -4025,7 +4146,7 @@ msgstr "" msgid "Same as current active code" msgstr "Igual que el código activo actual" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Save" msgstr "Guardar" @@ -4191,10 +4312,10 @@ msgstr "" msgid "Set TP/SL" msgstr "" -#: src/App/App.js #: src/components/Header/AppHeaderLinks.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx +#: src/components/SettingsModal/SettingsModal.tsx msgid "Settings" msgstr "Ajustes" @@ -4256,8 +4377,8 @@ msgstr "Compartir Posición" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4274,7 +4395,6 @@ msgstr "Compartir Posición" #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -4289,14 +4409,6 @@ msgstr "Corto" msgid "Short Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Short Liquidity" msgstr "" @@ -4305,14 +4417,11 @@ msgstr "" msgid "Short Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Short Positions" msgstr "Posiciones en Corto" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Short positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Short {0}" msgstr "Corto {0}" @@ -4321,10 +4430,14 @@ msgstr "Corto {0}" msgid "Shorting..." msgstr "Entrando a corto..." -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Show debug values" msgstr "" +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Show details" +msgstr "" + #: src/pages/Home/Home.js msgid "Simple Swaps" msgstr "Intercambios Simples" @@ -4350,6 +4463,7 @@ msgstr "" #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4361,14 +4475,18 @@ msgstr "Tamaño" #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Slippage is too high" msgstr "" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Slippage should be less than -5%" +msgstr "" + #: src/App/App.js -msgid "Slippage should be less than 5%" -msgstr "El deslizamiento debe ser inferior al 5%" +#~ msgid "Slippage should be less than 5%" +#~ msgstr "El deslizamiento debe ser inferior al 5%" #: src/components/Exchange/UsefulLinks.tsx msgid "Speed up page loading" @@ -4472,10 +4590,15 @@ msgstr "Estadísticas" msgid "Stop Loss Decrease" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Stop-Loss" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Stop-Loss PnL" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "Structured Products" msgstr "Productos Estructurados" @@ -4524,7 +4647,7 @@ msgstr "" msgid "Submit" msgstr "Enviar" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Success claimings" msgstr "" @@ -4550,10 +4673,6 @@ msgstr "Intercambiar" msgid "Swap Fee" msgstr "" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx -msgid "Swap Fees" -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Swap Order created!" msgstr "¡Orden de Intercambio creada!" @@ -4566,7 +4685,6 @@ msgstr "Falló la creación de la Orden de Intercambio." msgid "Swap Order submitted!" msgstr "¡Orden de Intercambio enviada!" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Swap Price Impact" msgstr "" @@ -4700,11 +4818,15 @@ msgstr "" msgid "TP/SL" msgstr "" -#: src/domain/synthetics/orders/utils.ts +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Take-Profit" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Take-Profit PnL" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "Take-profit and stop-loss orders can be set after opening a position. <0/><1/>There will be a \"Close\" button on each position row, clicking this will display the option to set trigger orders. <2/><3/>For screenshots and more information, please see the <4>docs." msgstr "Las órdenes de take-profit y stop-loss se pueden poner después de abrir una posición. <0/><1/>Habrá un botón de \"Cerrar\" en cada fila de posiciones, hacer clic mostrará la opción para establecer las órdenes de activación. <2/><3/>Para capturas de pantalla y más información, por favor mira los <4>docs." @@ -4771,10 +4893,6 @@ msgstr "" msgid "The Bonus Rebate will be airdropped as ARB tokens on a pro-rata basis. <0>Read more." msgstr "" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "The Boosted APR is from your staked Multiplier Points." -msgstr "El APR aumentado es de sus Puntos Multiplicadores stakeados." - #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx msgid "The Current Price Impact is {0}. Consider adding a buffer of 0.30% to it so the order is more likely to be processed." msgstr "" @@ -4787,18 +4905,15 @@ msgstr "" msgid "The Gambit protocol is in beta, please read the <0>staking detailsbefore participating." msgstr "El protocolo Gambit se encuentra en beta, por favor lea los <0>detalles de stakingantes de participar." +#: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "The Max Execution Fee is overestimated by {maxExecutionFeeText}%. Upon execution, the excess Execution Fee is sent back to your account." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "The Max Execution Fee is set to a higher value to handle potential increases in gas price during order execution. Any excess execution fee will be refunded to your account when the order is executed. Only applicable to GMX V2." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "The Order may not execute at the desired {priceText} as the current Price Impact {0} is higher than its Acceptable Price Impact {1}. Consider canceling and creating a new {suggestionType} Order." -msgstr "" - #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "The address of the esGMX (IOU) token is {esGmxIouAddress}." msgstr "La dirección del token esGMX (IOU) es {esGmxIouAddress}." @@ -4827,11 +4942,23 @@ msgstr "El precio de referencia ha cambiado, considera incrementar el deslizamie msgid "The maximum number of authorized Actions has been reached. Re-authorize a higher value using the \"Max allowed actions\" field." msgstr "" +#: src/domain/synthetics/fees/utils/executionFee.ts +msgid "The network Fees are high currently, which may be due to a temporary increase in transactions on the {0} network." +msgstr "" + #: src/domain/legacy.ts #: src/domain/synthetics/fees/utils/executionFee.ts msgid "The network Fees are very high currently, which may be due to a temporary increase in transactions on the {0} network." msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "The order may not execute at the desired {priceText} as its acceptable price impact is set to {formattedOrderAcceptablePriceImpact}, which is lower than the current market price impact of {formattedCurrentAcceptablePriceImpact}. It can be edited using the \"Edit\" button." +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "The order will not be executed as its trigger price is beyond the position's liquidation price." +msgstr "" + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "The order will only execute if the Min. Receive is met and there is sufficient liquidity." msgstr "" @@ -4853,9 +4980,13 @@ msgid "The pending borrow fee will be charged on this transaction." msgstr "" #: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of -{1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#~ msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +#~ msgstr "" + #: src/components/Exchange/SwapBox.js msgid "The position will be opened at {0} USD with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "La posición se abrirá a {0} USD con un deslizamiento máximo de {1}%.<0/><1/>La cantidad de deslizamiento se puede configurar desde Ajustes, que se encuentra haciendo clic en tu dirección en la esquina superior derecha de la página después de conectar tu monedero.<2/><3/><4>Más Info" @@ -4964,9 +5095,8 @@ msgstr "Este código no está registrado en {0}, por lo que no recibirás reembo msgid "This is the maximum top-up amount that will be sent from your Main account to your Subaccount after each transaction. The actual amount sent will depend on the final transaction fee." msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "This market uses an Adaptive Funding Rate. The Funding Rate will adjust over time depending on the ratio of longs and shorts. <0>Read more." +#: src/domain/synthetics/orders/utils.ts +msgid "This order using {collateralSymbol} as collateral will not be valid for the existing {longText} position using {symbol} as collateral." msgstr "" #: src/components/Exchange/TradeHistory.js @@ -5137,7 +5267,6 @@ msgstr "" #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Trades" msgstr "Operaciones" @@ -5240,7 +5369,6 @@ msgstr "Activador" #: src/components/Synthetics/OrderList/OrderList.tsx #: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Trigger Price" msgstr "" @@ -5252,10 +5380,6 @@ msgstr "" msgid "Trigger order disabled, pending {0} upgrade" msgstr "" -#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx -msgid "Trigger order for" -msgstr "" - #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Triggered at: {0}" msgstr "" @@ -5359,7 +5483,7 @@ msgid "Unstake submitted! <0>View status." msgstr "¡Destakeo enviado! <0>Ver estado." #: src/pages/Stake/StakeV2.js -msgid "Unstaking will burn <0>{0} Multiplier Points. {1}" +msgid "Unstaking will burn <0>{0} Multiplier Points. <1>You will earn {1}% less {nativeTokenSymbol} rewards with this action." msgstr "" #: src/pages/Stake/StakeV1.js @@ -5569,6 +5693,18 @@ msgstr "Ver" msgid "View in Explorer" msgstr "Ver en el Explorador" +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Arbitrum" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Avalanche" +msgstr "" + #: src/components/Synthetics/StatusNotification/SubaccountNotification.tsx msgid "View status" msgstr "" @@ -5799,9 +5935,12 @@ msgstr "Puede consultar su historial de reclamaciones <0>aquí." msgid "You can currently vest a maximum of {0} esGMX tokens at a ratio of {1} {stakingToken} to 1 esGMX." msgstr "Actualmente puede adquirir un máximo de {0} tokens esGMX a razón de {1} {stakingToken} por 1 esGMX\"." +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx +msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than -{0}, may result in failed orders if prices are volatile." +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than {0}, may result in failed orders if prices are volatile." msgstr "" @@ -5829,10 +5968,6 @@ msgstr "Tiene una transferencia pendiente de {sender}." msgid "You have an active Limit Order to Increase {longOrShortText} {sizeInToken} {0} (${1}) at price ${2}" msgstr "Tienes una Orden Límite para Incrementar {longOrShortText} {sizeInToken} {0} (${1}) al precio ${2}" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have an active Limit Order to Increase {longShortText} {0} {sizeText} at price {1}." -msgstr "" - #: src/components/Exchange/PositionSeller.js msgid "You have an active order to decrease {longOrShortText} {sizeInToken} {0} (${1}) at {prefix} {2}" msgstr "" @@ -5861,25 +5996,24 @@ msgstr "" msgid "You have an existing position with {0} as collateral. This action will not apply for that position." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "" -"You have an existing {longText} position with {0} as Collateral. This Order will not\n" -"be valid for that Position." -msgstr "" - #: src/components/Exchange/ConfirmationBox.js msgid "You have multiple existing Increase {longOrShortText} {0} limit orders" msgstr "Tienes múltiples órdenes límites para incrementar {longOrShortText} {0}" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have multiple existing Increase {longShortText} {0} limit orders" -msgstr "" - #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "You have not deposited any tokens for vesting." msgstr "No has depositado ningún token para su adquisición." +#: src/components/Stake/GMXAprTooltip.tsx +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points using the \"Compound\" button." +msgstr "" + +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points." +msgstr "" + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "You have selected {collateralTokenSymbol} as Collateral, the Liquidation Price will vary based on the price of {collateralTokenSymbol}." msgstr "" @@ -5928,14 +6062,19 @@ msgstr "Tu recibirás al menos {0} {1} si esta orden se ejecuta. El precio de ej msgid "You will receive at least {toAmountText} if this order is executed. This price is being updated in real time based on Swap Fees and Price Impact." msgstr "" +#: src/pages/Stake/StakeV2.js +#: src/pages/Stake/StakeV2.js +msgid "Your APR" +msgstr "" + #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "Your esGMX (IOU) balance will decrease by your claim amount after claiming, this is expected behaviour." msgstr "El saldo de su esGMX (IOU) disminuirá en la cantidad de su reclamación después de reclamar, este es el comportamiento esperado." #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "Your position's collateral after deducting fees." -msgstr "La garantía de tu posición después de descontar las comisiones." +msgid "Your position's collateral after deducting fees:" +msgstr "La garantía de tu posición después de descontar las comisiones:" #: src/pages/CompleteAccountTransfer/CompleteAccountTransfer.js msgid "Your transfer has been completed." @@ -5970,7 +6109,6 @@ msgid "from" msgstr "" #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "hide" msgstr "ocultar" @@ -5978,20 +6116,32 @@ msgstr "ocultar" msgid "in liquidity" msgstr "en liquidez" +#: src/domain/synthetics/orders/utils.ts +msgid "limit price" +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "long" +msgstr "" + #: src/pages/Dashboard/DashboardV2.js msgid "not staked" msgstr "no stakeado" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "pay" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "receive" msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "short" +msgstr "" + #: src/pages/PositionsOverview/PositionsOverview.js msgid "size" msgstr "tamaño" @@ -6004,8 +6154,11 @@ msgstr "stakeado" msgid "time to liq" msgstr "tiempo para liq." +#: src/domain/synthetics/orders/utils.ts +msgid "trigger price" +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "view" msgstr "vista" @@ -6022,6 +6175,10 @@ msgstr "" msgid "{0, plural, one {Pending {symbolsText} approval} other {Pending {symbolsText} approvals}}" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "{0, plural, one {You have an active Limit Order to Increase} other {You have multiple active Limit Orders to Increase}}" +msgstr "" + #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "{0} <0><1>{indexName}<2>[{poolName}] <3>market selected." msgstr "" @@ -6102,6 +6259,10 @@ msgstr "{0} está por debajo de su peso objetivo.<0/><1/>Consigue menores comisi msgid "{0} is required for collateral." msgstr "{0} es requerido como garantía." +#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx +msgid "{0} order for" +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "{0} pool exceeded, try different token" msgstr "{0} reserva superada, intente otro token" @@ -6202,6 +6363,22 @@ msgstr "" msgid "{longOrShortText} {0} market selected" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee and pay a borrow fee of {borrowRate} per hour." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee or a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and do not pay a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and {borrowAction} a borrow fee of {borrowRate} per hour." +msgstr "" + #: src/components/Synthetics/MarketCard/MarketCard.tsx msgid "{longShortText} {0} Open Interest" msgstr "" @@ -6218,10 +6395,6 @@ msgstr "" msgid "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR" msgstr "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "{nativeTokenSymbol} APR" -msgstr "" - #: src/components/Stake/GMXAprTooltip.tsx msgid "{nativeTokenSymbol} Base APR" msgstr "" diff --git a/src/locales/fr/messages.po b/src/locales/fr/messages.po index 0039d0b558..6563e00a7c 100644 --- a/src/locales/fr/messages.po +++ b/src/locales/fr/messages.po @@ -135,6 +135,10 @@ msgstr "" msgid "<0>{0} <1><2>{indexName}<3>[{poolName}] <4>market selected" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "A Size percentage is required." +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "A snapshot of the USD value of your {0} collateral is taken when the position is opened." msgstr "Une image instantanée de la valeur en USD de votre {0} collatéral initial est prise à l'ouverture de la position." @@ -243,6 +247,14 @@ msgstr "" msgid "Accrued Positive Funding Fees for Positions not yet claimable. They will become available to claim by using the \"Settle\" button, or after the Position is increased, decreased or closed." msgstr "" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +msgid "Accrued Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Accrued Price Impact Rebates. They will become Claimable after some time.<0/><1/><2>Read more." +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "Acknowledge epoch is ending in {minutes} minutes" msgstr "" @@ -257,6 +269,10 @@ msgstr "" msgid "Acknowledge high Swap Price Impact" msgstr "" +#: src/domain/synthetics/trade/useHighExecutionFeeConsent.tsx +msgid "Acknowledge very high network Fees" +msgstr "" + #: src/pages/Actions/Actions.js #: src/pages/SyntheticsActions/SyntheticsActions.tsx msgid "Actions" @@ -303,6 +319,10 @@ msgstr "L'ajout du code/ID de référence a échoué." msgid "Adding..." msgstr "S'ajoute..." +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +#~ msgid "Additional Execution Fee" +#~ msgstr "" + #: src/pages/Stake/StakeV2.js msgid "Additional reserve required" msgstr "Réserve additionnelle nécessaire" @@ -344,15 +364,15 @@ msgstr "" msgid "Allow {wrappedTokenSymbol} to be spent" msgstr "" -#: src/App/App.js #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/SettingsModal/SettingsModal.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Allowed Slippage" msgstr "Glissement autorisé" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Allowed Slippage below {0}% may result in failed orders." msgstr "" @@ -444,11 +464,15 @@ msgstr "Approbation {stakingTokenSymbol}..." msgid "Approving..." msgstr "Approbation..." -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Arbitrum APR:" msgstr "Taux de rendement annuels Arbitrum:" +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "As network fees have increased, an additional execution fee is needed." +msgstr "" + #: src/components/Exchange/NoLiquidityErrorModal.tsx msgid "As there is not enough liquidity in GLP to swap {0} to {swapTokenSymbol}, you can use the option below to do so:" msgstr "Comme il n'y a pas assez de liquidité dans GLP pour échanger {0} vers {swapTokenSymbol}, vous pouvez utiliser l'option ci-dessous pour le faire :" @@ -492,8 +516,8 @@ msgstr "Somme disponible pour retirer de GLP. Montant non utilisé par les poste msgid "Available on your preferred network" msgstr "Disponible sur le réseau de votre choix" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Avalanche APR:" msgstr "Taux de Rendement Annuels Avalanche:" @@ -518,6 +542,10 @@ msgstr "Balance" msgid "Base APR" msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Base {nativeTokenSymbol} APR" +msgstr "" + #: src/pages/BeginAccountTransfer/BeginAccountTransfer.js msgid "Begin Transfer" msgstr "Commencer le transfert" @@ -546,7 +574,6 @@ msgstr "" #: src/components/Exchange/PositionsList.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Borrow Fee" @@ -561,6 +588,11 @@ msgstr "Commission d'emprunt / jour" msgid "Borrow Fee Rate" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Borrowing fees help ensure available liquidity. <0>Read more." +msgstr "" + #: src/components/Synthetics/BridgingInfo/BridgingInfo.tsx msgid "Bridge {tokenSymbol} to {chainName} using any of the options below:" msgstr "" @@ -596,7 +628,7 @@ msgstr "" msgid "Buy GLP" msgstr "Acheter GLP" -#: src/pages/Buy/Buy.js +#: src/pages/Buy/Buy.tsx msgid "Buy GLP or GMX" msgstr "" @@ -649,26 +681,10 @@ msgstr "" msgid "Buy GMX using any token from any network:" msgstr "" -#: src/pages/Buy/Buy.js -msgid "Buy Protocol Tokens" -msgstr "" - #: src/components/Glp/GlpSwap.js msgid "Buy failed." msgstr "Achat échoué" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Arbitrum" -msgstr "Acheter sur Arbitrum" - -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Avalanche" -msgstr "Acheter sur Avalanche" - #: src/pages/BuyGMX/BuyGMX.tsx msgid "Buy or Transfer AVAX to Avalanche" msgstr "" @@ -729,7 +745,6 @@ msgstr "Impossible d'exécuter à cause d'une erreur" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts @@ -759,7 +774,7 @@ msgstr "Annulation soumise" msgid "Cancelling {ordersText}" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Chart positions" @@ -781,6 +796,7 @@ msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/Claims/ClaimableCard.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV1.js @@ -807,7 +823,7 @@ msgid "Claim GMX Rewards" msgstr "Réclamer les récompenses GMX" #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx -msgid "Claim Price Impact" +msgid "Claim Price Impact Rebates" msgstr "" #: src/pages/Stake/StakeV2.js @@ -853,6 +869,10 @@ msgstr "Réclamation soumise ! <0>Voir le statut." msgid "Claim submitted." msgstr "Réclamation soumise." +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "Claim {totalUsd}" +msgstr "" + #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "Claim {wrappedTokenSymbol} Rewards" @@ -864,30 +884,37 @@ msgstr "Réclamer les récompenses de {wrappedTokenSymbol}" msgid "Claimable" msgstr "Réclamable" +#: src/components/Synthetics/Claims/ClaimableCard.tsx +msgid "Claimable Price Impact Rebates.<0/><1/><2>Read more." +msgstr "" + #: src/components/Referrals/AffiliatesStats.tsx msgid "Claimable Rebates" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Claiming Price Impact Rebate..." +msgstr "" + +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Claiming failed" msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV2.js msgid "Claiming..." msgstr "Réclamation en cours..." -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Claims" msgstr "" #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx -msgid "Claims (1)" +msgid "Claims ({totalClaimables})" msgstr "" #: src/components/Exchange/PositionsList.js @@ -1044,6 +1071,7 @@ msgstr "Composition en cours..." #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx msgid "Confirm Claim" msgstr "" @@ -1350,7 +1378,6 @@ msgstr "Décentralisé <0/>Bourse perpétuelle" #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -1370,6 +1397,10 @@ msgstr "" msgid "Decrease the Leverage by using the slider. If the Leverage slider is disabled, you can increase the Pay amount or reduce the Order size." msgstr "" +#: src/components/Synthetics/ConfirmationBox/SLTPEntries.tsx +msgid "Decrease {0} Long by {1} at ${2}." +msgstr "" + #: src/components/Exchange/TradeHistory.js #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx msgid "Decreased" @@ -1463,7 +1494,7 @@ msgstr "Dépôt en cours..." msgid "Diff" msgstr "Diff" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Disable order validations" msgstr "Désactiver les validations d'ordre" @@ -1471,7 +1502,7 @@ msgstr "Désactiver les validations d'ordre" msgid "Disconnect" msgstr "Déconnecter" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Display PnL after fees" msgstr "Afficher PnL après les frais" @@ -1502,6 +1533,10 @@ msgstr "Gagner" msgid "Earn ARB tokens by purchasing GM tokens, trading, or migrating liquidity from GLP to GM. Only for GMX V2." msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Earn an extra {0}% {nativeTokenSymbol} Boosted APR by increasing your staked <0>Multiplier Points." +msgstr "" + #: src/components/Header/AppHeaderLinks.tsx msgid "Ecosystem" msgstr "Écosystème" @@ -1771,6 +1806,7 @@ msgid "Execute {orderTypeName} Order: {positionText} {sizeDeltaText}," msgstr "" #: src/components/Exchange/FeesTooltip.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx msgid "Execution Fee" msgstr "" @@ -1815,14 +1851,14 @@ msgstr "FRAIS" msgid "FUNDING FEE" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "FUNDING RATE / 1h" -msgstr "" - #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx msgid "Failed Settlement of Funding Fees" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Failed to Claim Price Impact Rebate" +msgstr "" + #: src/domain/synthetics/orders/cancelOrdersTxn.ts msgid "Failed to cancel {ordersText}" msgstr "" @@ -1847,6 +1883,7 @@ msgstr "" #: src/components/Glp/GlpSwap.js #: src/components/Glp/GlpSwap.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Fees" msgstr "FRAIS" @@ -1963,11 +2000,10 @@ msgstr "" msgid "Fulfilling order request" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts msgid "Funding Claimed" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Funding Fee" @@ -1977,14 +2013,15 @@ msgstr "" msgid "Funding Fee Rate" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Funding Rate / 1h" -msgstr "" - #: src/components/Synthetics/Claims/ClaimableCardUI.tsx msgid "Funding fees" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Funding fees help to balance longs and shorts and are exchanged between both sides. <0>Read more." +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "GBC NFTs APR tracker and rewards" msgstr "Tracker de taux de rendement annuels des NFTs GBC et récompenses" @@ -2015,7 +2052,7 @@ msgstr "" msgid "GLP buy disabled, pending {0} upgrade" msgstr "Achat GLP désactivé, en attente de {0} actualisations" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GLP is the liquidity provider token for GMX V1 markets. Accrues 70% of the V1 markets generated fees." msgstr "" @@ -2043,7 +2080,7 @@ msgstr "" msgid "GM can be sold for {0} and {1} for this market up to the specified selling caps. The remaining tokens in the pool are reserved for currently open Positions." msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GM is the liquidity provider token for GMX V2 markets. Accrues 63% of the V2 markets generated fees." msgstr "" @@ -2132,7 +2169,7 @@ msgstr "GMX est en émission direct sur Arbitrum et Avalanche." msgid "GMX is not actively looking for new hires at the moment. However, if you think you can contribute to the project, please email <0>jobs@gmx.io." msgstr "GMX ne recherche pas activement de nouveaux recrutements pour le moment. Toutefois, si vous pensez pouvoir contribuer au projet, veuillez envoyer un courriel à l'adresse suivante <0>jobs@gmx.io." -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GMX is the utility and governance token. Accrues 30% and 27% of V1 and V2 markets generated fees, respectively." msgstr "" @@ -2185,6 +2222,13 @@ msgstr "" msgid "Governance" msgstr "Gouvernance" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.tsx +#: src/components/Synthetics/PositionEditor/PositionEditor.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "High Execution Fee not yet acknowledged" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "High Slippage, Swap Anyway" msgstr "Glissement élevé, échanger quand-même" @@ -2193,6 +2237,13 @@ msgstr "Glissement élevé, échanger quand-même" msgid "High USDG Slippage, Long Anyway" msgstr "Glissement USDG élevé, longer quand-même" +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#~ msgid "High network Fee not yet acknowledged" +#~ msgstr "" + #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "I am aware of the trigger orders" @@ -2228,7 +2279,7 @@ msgstr "" msgid "Incentives are airdropped weekly." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Include PnL in leverage display" msgstr "Inclure le PnL dans le mode d'affichage Effet de Levier" @@ -2250,7 +2301,6 @@ msgstr "Réseau incorrect" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -2408,7 +2458,7 @@ msgstr "Adresse du destinataire non valide" msgid "Invalid Transfer Addresses: Please check the url." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid execution fee buffer value" msgstr "" @@ -2426,7 +2476,7 @@ msgstr "Prix de liquidation invalide" msgid "Invalid price, see warning" msgstr "Prix invalide, voir l'avertissement" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid slippage value" msgstr "Valeur de glissement invalide" @@ -2455,7 +2505,6 @@ msgid "Keep Leverage is not possible" msgstr "" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "Keep leverage at {0}" msgstr "" @@ -2464,6 +2513,10 @@ msgstr "" msgid "Keep leverage at {0}x" msgstr "" +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "Keep leverage at {keepLeverageAtValue}" +msgstr "" + #: src/components/Synthetics/ChartTokenSelector/ChartTokenSelector.tsx msgid "LONG LIQ." msgstr "" @@ -2548,7 +2601,6 @@ msgstr "" #: src/components/Synthetics/PositionItem/PositionItem.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts -#: src/domain/synthetics/orders/utils.ts msgid "Limit" msgstr "Limite" @@ -2572,7 +2624,6 @@ msgstr "" #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Limit Price" msgstr "Prix de limite" @@ -2705,8 +2756,8 @@ msgstr "Chargement..." #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -2723,7 +2774,6 @@ msgstr "Chargement..." #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -2738,14 +2788,6 @@ msgstr "Long" msgid "Long Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Long Liquidity" msgstr "" @@ -2754,14 +2796,11 @@ msgstr "" msgid "Long Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Long Positions" msgstr "Positions long" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Long positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Long {0}" msgstr "Long {0}" @@ -2778,7 +2817,9 @@ msgstr "Il semble que vous n'ayez pas de code de parrainage à partager. <0/> Cr msgid "Loss" msgstr "Perte" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/GmList/GmList.tsx msgid "MARKET" msgstr "" @@ -2894,16 +2935,15 @@ msgid "Max Capacity for {0} Reached" msgstr "Capacité max pour {0} Atteinte" #: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Max Execution Fee" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee Buffer" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee buffer below {0}% may result in failed orders." msgstr "" @@ -2945,7 +2985,7 @@ msgstr "" msgid "Max close amount exceeded" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max execution fee buffer precision is 0.01%" msgstr "" @@ -2975,9 +3015,13 @@ msgstr "Capacité maximale du pool atteinte pour {0}. Veuillez minter GLP avec u msgid "Max pool capacity reached for {0}<0/><1/>Please mint GLP using another token" msgstr "Capacité maximale du pool atteinte pour {0}<0/><1/> Veuillez minter GLP avec un autre token" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Max slippage precision is -0.01%" +msgstr "" + #: src/App/App.js -msgid "Max slippage precision is 0.01%" -msgstr "La précision maximale du glissement est de 0,01%" +#~ msgid "Max slippage precision is 0.01%" +#~ msgstr "La précision maximale du glissement est de 0,01%" #: src/components/Synthetics/MarketStats/MarketStats.tsx #: src/components/Synthetics/MarketStats/MarketStats.tsx @@ -3025,11 +3069,11 @@ msgstr "Max {0} capacité de short" msgid "Max {0} short exceeded" msgstr "Max {0} short dépassé" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Arbitrum APR:" msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Avalanche APR: {0}" msgstr "" @@ -3038,7 +3082,11 @@ msgid "Max. Leverage exceeded" msgstr "" #: src/components/Stake/GMXAprTooltip.tsx -msgid "Max. {nativeTokenSymbol} APR with 200% Boost for this week: {0}%." +msgid "Max. {nativeTokenSymbol} APR" +msgstr "" + +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Max. {nativeTokenSymbol} APR is calculated with the max. 200% Boost Percentage by staking <0>Multiplier Points." msgstr "" #: src/components/Migration/Migration.js @@ -3148,9 +3196,16 @@ msgid "Multiplier Points APR" msgstr "Points multiplicateurs APR" #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "NA" msgstr "" +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "NET FEE / 1 H" +msgstr "" + #: src/pages/NftWallet/NftWallet.js msgid "NFT Address" msgstr "Adresse NFT" @@ -3171,6 +3226,20 @@ msgstr "" msgid "Neither Collateral nor realized PnL is enough to cover pending Fees. Please close a larger position amount." msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Fee" +msgstr "" + +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Net Fee / 1h" +msgstr "" + +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Rebate" +msgstr "" + #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -3199,7 +3268,12 @@ msgstr "Réseaux" msgid "Networks and Settings" msgstr "Réseaux et paramètres" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "New Collateral" +msgstr "" + #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Next" msgstr "suivant" @@ -3275,6 +3349,10 @@ msgstr "" msgid "Note that orders are not guaranteed to be executed.<0/><1/>This can occur in a few situations including but not exclusive to:" msgstr "Notez que l'exécution des ordres n'est pas garantie d'être exécutée.<0/><1/>Cela peut se produire dans plusieurs situations, notamment, mais pas exclusivement:" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Old Collateral" +msgstr "" + #: src/components/AddressDropdown/AddressDropdown.tsx #: src/components/Synthetics/SubaccountModal/SubaccountModal.tsx msgid "One-Click Trading" @@ -3351,10 +3429,6 @@ msgstr "Ouverture..." msgid "Order" msgstr "Ordre" -#: src/domain/synthetics/orders/utils.ts -msgid "Order Trigger Price is beyond position's Liquidation Price." -msgstr "" - #: src/components/Synthetics/OrderItem/OrderItem.tsx msgid "Order Type" msgstr "" @@ -3635,7 +3709,6 @@ msgstr "Positions" msgid "Positions ({0})" msgstr "Positions ({0})" -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Positions{0}" msgstr "" @@ -3645,6 +3718,7 @@ msgid "Positive Funding Fees for a Position become claimable after the Position msgstr "" #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Prev" msgstr "Préc" @@ -3686,6 +3760,20 @@ msgstr "Prix" msgid "Price Impact" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Price Impact Rebate Claimed" +msgstr "" + +#: src/components/Synthetics/Claims/ClaimableCardUI.tsx +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates for closing trades are claimable under the Claims tab. <0>Read more." +msgstr "" + +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts @@ -3693,6 +3781,10 @@ msgstr "" msgid "Price Impact not yet acknowledged" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3700,6 +3792,10 @@ msgstr "" msgid "Price above Liq. Price" msgstr "Prix supérieur au prix de liq." +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3713,6 +3809,14 @@ msgstr "Prix supérieur au prix de liq." msgid "Price above Mark Price" msgstr "Prix supérieur à celui de la marque" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Mark Price." +msgstr "" + +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3720,6 +3824,10 @@ msgstr "Prix supérieur à celui de la marque" msgid "Price below Liq. Price" msgstr "Prix inférieur au prix de liq." +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3733,6 +3841,10 @@ msgstr "Prix inférieur au prix de liq." msgid "Price below Mark Price" msgstr "Prix inférieur à celui de la marque" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Mark Price." +msgstr "" + #: src/pages/OrdersOverview/OrdersOverview.js msgid "Price conditions are met" msgstr "Conditions de prix satisfaites" @@ -3775,6 +3887,10 @@ msgstr "" msgid "Protocol" msgstr "" +#: src/pages/Buy/Buy.tsx +msgid "Protocol Tokens" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js #: src/pages/Ecosystem/Ecosystem.js msgid "Protocol analytics" @@ -3796,9 +3912,14 @@ msgstr "" msgid "Purchase Insurance" msgstr "Acheter l'assurance" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "REBATE" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Read more" msgstr "Lire plus" @@ -4025,7 +4146,7 @@ msgstr "" msgid "Same as current active code" msgstr "Même que le code actif actuel" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Save" msgstr "Sauver" @@ -4191,10 +4312,10 @@ msgstr "" msgid "Set TP/SL" msgstr "" -#: src/App/App.js #: src/components/Header/AppHeaderLinks.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx +#: src/components/SettingsModal/SettingsModal.tsx msgid "Settings" msgstr "Paramètres" @@ -4256,8 +4377,8 @@ msgstr "Partager la Position" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4274,7 +4395,6 @@ msgstr "Partager la Position" #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -4289,14 +4409,6 @@ msgstr "Short" msgid "Short Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Short Liquidity" msgstr "" @@ -4305,14 +4417,11 @@ msgstr "" msgid "Short Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Short Positions" msgstr "Positions Shorts" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Short positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Short {0}" msgstr "Short {0}" @@ -4321,10 +4430,14 @@ msgstr "Short {0}" msgid "Shorting..." msgstr "Short en cours..." -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Show debug values" msgstr "" +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Show details" +msgstr "" + #: src/pages/Home/Home.js msgid "Simple Swaps" msgstr "Échanges simples" @@ -4350,6 +4463,7 @@ msgstr "" #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4361,14 +4475,18 @@ msgstr "Montant" #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Slippage is too high" msgstr "" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Slippage should be less than -5%" +msgstr "" + #: src/App/App.js -msgid "Slippage should be less than 5%" -msgstr "Le glissement doit être de moins de 5%." +#~ msgid "Slippage should be less than 5%" +#~ msgstr "Le glissement doit être de moins de 5%." #: src/components/Exchange/UsefulLinks.tsx msgid "Speed up page loading" @@ -4472,10 +4590,15 @@ msgstr "Stats" msgid "Stop Loss Decrease" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Stop-Loss" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Stop-Loss PnL" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "Structured Products" msgstr "Produits structurés" @@ -4524,7 +4647,7 @@ msgstr "" msgid "Submit" msgstr "Soumettre" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Success claimings" msgstr "" @@ -4550,10 +4673,6 @@ msgstr "Échanger" msgid "Swap Fee" msgstr "" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx -msgid "Swap Fees" -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Swap Order created!" msgstr "Ordre d'échange créé !" @@ -4566,7 +4685,6 @@ msgstr "Ordre d'échange échoué." msgid "Swap Order submitted!" msgstr "Ordre d'échange soumis !" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Swap Price Impact" msgstr "" @@ -4700,11 +4818,15 @@ msgstr "" msgid "TP/SL" msgstr "" -#: src/domain/synthetics/orders/utils.ts +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Take-Profit" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Take-Profit PnL" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "Take-profit and stop-loss orders can be set after opening a position. <0/><1/>There will be a \"Close\" button on each position row, clicking this will display the option to set trigger orders. <2/><3/>For screenshots and more information, please see the <4>docs." msgstr "Les ordres Take-profit et Stop-loss peuvent être définis après l'ouverture d'une position. <0/><1/>Il y aura un bouton \"Fermer\"sur chaque ligne de position, en cliquant dessus, vous afficherez l'option pour définir des ordres de déclenchement. <2/><3/> Pour des captures d'écran et pour plus informations, veuillez consulter la page ." @@ -4771,10 +4893,6 @@ msgstr "" msgid "The Bonus Rebate will be airdropped as ARB tokens on a pro-rata basis. <0>Read more." msgstr "" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "The Boosted APR is from your staked Multiplier Points." -msgstr "Le Taux de Rendement Annuel boosté provient de vos points multiplicateurs misés." - #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx msgid "The Current Price Impact is {0}. Consider adding a buffer of 0.30% to it so the order is more likely to be processed." msgstr "" @@ -4787,18 +4905,15 @@ msgstr "" msgid "The Gambit protocol is in beta, please read the <0>staking detailsbefore participating." msgstr "" +#: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "The Max Execution Fee is overestimated by {maxExecutionFeeText}%. Upon execution, the excess Execution Fee is sent back to your account." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "The Max Execution Fee is set to a higher value to handle potential increases in gas price during order execution. Any excess execution fee will be refunded to your account when the order is executed. Only applicable to GMX V2." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "The Order may not execute at the desired {priceText} as the current Price Impact {0} is higher than its Acceptable Price Impact {1}. Consider canceling and creating a new {suggestionType} Order." -msgstr "" - #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "The address of the esGMX (IOU) token is {esGmxIouAddress}." msgstr "L'adresse du token esGMX (IOU - reconnaissance de dette) est {esGmxIouAddress}." @@ -4827,11 +4942,23 @@ msgstr "Le prix du marché a changé, envisagez d'augmenter votre marge autoris msgid "The maximum number of authorized Actions has been reached. Re-authorize a higher value using the \"Max allowed actions\" field." msgstr "" +#: src/domain/synthetics/fees/utils/executionFee.ts +msgid "The network Fees are high currently, which may be due to a temporary increase in transactions on the {0} network." +msgstr "" + #: src/domain/legacy.ts #: src/domain/synthetics/fees/utils/executionFee.ts msgid "The network Fees are very high currently, which may be due to a temporary increase in transactions on the {0} network." msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "The order may not execute at the desired {priceText} as its acceptable price impact is set to {formattedOrderAcceptablePriceImpact}, which is lower than the current market price impact of {formattedCurrentAcceptablePriceImpact}. It can be edited using the \"Edit\" button." +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "The order will not be executed as its trigger price is beyond the position's liquidation price." +msgstr "" + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "The order will only execute if the Min. Receive is met and there is sufficient liquidity." msgstr "" @@ -4853,9 +4980,13 @@ msgid "The pending borrow fee will be charged on this transaction." msgstr "" #: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of -{1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#~ msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +#~ msgstr "" + #: src/components/Exchange/SwapBox.js msgid "The position will be opened at {0} USD with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "La position sera ouverte à {0} USD avec un glissement max. de {1}%.<0/><1/> La somme du glissement peut être configurée dans la rubrique Paramètres, que vous trouverez en cliquant sur votre adresse en haut à droite de la page après avoir connecté votre portefeuille. <2/><3/><4>Plus d'infos" @@ -4964,9 +5095,8 @@ msgstr "Ce code n'est pas encore enregistré sur {0}, vous ne recevrez pas de re msgid "This is the maximum top-up amount that will be sent from your Main account to your Subaccount after each transaction. The actual amount sent will depend on the final transaction fee." msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "This market uses an Adaptive Funding Rate. The Funding Rate will adjust over time depending on the ratio of longs and shorts. <0>Read more." +#: src/domain/synthetics/orders/utils.ts +msgid "This order using {collateralSymbol} as collateral will not be valid for the existing {longText} position using {symbol} as collateral." msgstr "" #: src/components/Exchange/TradeHistory.js @@ -5137,7 +5267,6 @@ msgstr "" #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Trades" msgstr "Opérations" @@ -5240,7 +5369,6 @@ msgstr "Déclencheur" #: src/components/Synthetics/OrderList/OrderList.tsx #: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Trigger Price" msgstr "" @@ -5252,10 +5380,6 @@ msgstr "" msgid "Trigger order disabled, pending {0} upgrade" msgstr "" -#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx -msgid "Trigger order for" -msgstr "" - #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Triggered at: {0}" msgstr "" @@ -5359,7 +5483,7 @@ msgid "Unstake submitted! <0>View status." msgstr "Arrêt du staking soumis! <0>Voir le statut." #: src/pages/Stake/StakeV2.js -msgid "Unstaking will burn <0>{0} Multiplier Points. {1}" +msgid "Unstaking will burn <0>{0} Multiplier Points. <1>You will earn {1}% less {nativeTokenSymbol} rewards with this action." msgstr "" #: src/pages/Stake/StakeV1.js @@ -5569,6 +5693,18 @@ msgstr "Voir" msgid "View in Explorer" msgstr "Voir dans Explorer" +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Arbitrum" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Avalanche" +msgstr "" + #: src/components/Synthetics/StatusNotification/SubaccountNotification.tsx msgid "View status" msgstr "" @@ -5799,9 +5935,12 @@ msgstr "Vous pouvez vérifier l'historique de vos réclamations <0>ici." msgid "You can currently vest a maximum of {0} esGMX tokens at a ratio of {1} {stakingToken} to 1 esGMX." msgstr "Vous pouvez vester un maximum de {0} tokens esGMX à un ratio de {1} {stakingToken} vers 1 esGMX." +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx +msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than -{0}, may result in failed orders if prices are volatile." +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than {0}, may result in failed orders if prices are volatile." msgstr "" @@ -5829,10 +5968,6 @@ msgstr "Vous avez un transfert en attente de {expéditeur}." msgid "You have an active Limit Order to Increase {longOrShortText} {sizeInToken} {0} (${1}) at price ${2}" msgstr "Vous avez un ordre limite actif à augmenter {longOrShortText} {sizeInToken} {0} (${1}) au prix ${2}" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have an active Limit Order to Increase {longShortText} {0} {sizeText} at price {1}." -msgstr "" - #: src/components/Exchange/PositionSeller.js msgid "You have an active order to decrease {longOrShortText} {sizeInToken} {0} (${1}) at {prefix} {2}" msgstr "" @@ -5861,25 +5996,24 @@ msgstr "" msgid "You have an existing position with {0} as collateral. This action will not apply for that position." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "" -"You have an existing {longText} position with {0} as Collateral. This Order will not\n" -"be valid for that Position." -msgstr "" - #: src/components/Exchange/ConfirmationBox.js msgid "You have multiple existing Increase {longOrShortText} {0} limit orders" msgstr "Vous avez plusieurs augmentations {longOrShortText} {0} ordres limités existantes" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have multiple existing Increase {longShortText} {0} limit orders" -msgstr "" - #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "You have not deposited any tokens for vesting." msgstr "Vous n'avez pas déposé de tokens pour vester." +#: src/components/Stake/GMXAprTooltip.tsx +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points using the \"Compound\" button." +msgstr "" + +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points." +msgstr "" + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "You have selected {collateralTokenSymbol} as Collateral, the Liquidation Price will vary based on the price of {collateralTokenSymbol}." msgstr "" @@ -5928,14 +6062,19 @@ msgstr "Vous recevrez au moins {0} {1}, si cet ordre est exécuté. Le prix d'ex msgid "You will receive at least {toAmountText} if this order is executed. This price is being updated in real time based on Swap Fees and Price Impact." msgstr "" +#: src/pages/Stake/StakeV2.js +#: src/pages/Stake/StakeV2.js +msgid "Your APR" +msgstr "" + #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "Your esGMX (IOU) balance will decrease by your claim amount after claiming, this is expected behaviour." msgstr "Le montant de vos esGMX (IOU - reconnaissance de dette) diminuera du montant total après la réclamation, c'est un comportement prévu." #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "Your position's collateral after deducting fees." -msgstr "Le collatéral de votre position après déduction des frais." +msgid "Your position's collateral after deducting fees:" +msgstr "Le collatéral de votre position après déduction des frais:" #: src/pages/CompleteAccountTransfer/CompleteAccountTransfer.js msgid "Your transfer has been completed." @@ -5970,7 +6109,6 @@ msgid "from" msgstr "" #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "hide" msgstr "cacher" @@ -5978,20 +6116,32 @@ msgstr "cacher" msgid "in liquidity" msgstr "en liquidité" +#: src/domain/synthetics/orders/utils.ts +msgid "limit price" +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "long" +msgstr "" + #: src/pages/Dashboard/DashboardV2.js msgid "not staked" msgstr "non staké" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "pay" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "receive" msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "short" +msgstr "" + #: src/pages/PositionsOverview/PositionsOverview.js msgid "size" msgstr "montant" @@ -6004,8 +6154,11 @@ msgstr "staké" msgid "time to liq" msgstr "temps de liquider" +#: src/domain/synthetics/orders/utils.ts +msgid "trigger price" +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "view" msgstr "voir" @@ -6022,6 +6175,10 @@ msgstr "" msgid "{0, plural, one {Pending {symbolsText} approval} other {Pending {symbolsText} approvals}}" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "{0, plural, one {You have an active Limit Order to Increase} other {You have multiple active Limit Orders to Increase}}" +msgstr "" + #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "{0} <0><1>{indexName}<2>[{poolName}] <3>market selected." msgstr "" @@ -6102,6 +6259,10 @@ msgstr "{0} est en dessous de son poids cible.<0/><1/>Obtenez une réduction des msgid "{0} is required for collateral." msgstr "{0} est requis comme collatéral." +#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx +msgid "{0} order for" +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "{0} pool exceeded, try different token" msgstr "{0} pool dépassé, essayez un autre token" @@ -6202,6 +6363,22 @@ msgstr "" msgid "{longOrShortText} {0} market selected" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee and pay a borrow fee of {borrowRate} per hour." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee or a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and do not pay a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and {borrowAction} a borrow fee of {borrowRate} per hour." +msgstr "" + #: src/components/Synthetics/MarketCard/MarketCard.tsx msgid "{longShortText} {0} Open Interest" msgstr "" @@ -6218,10 +6395,6 @@ msgstr "" msgid "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR" msgstr "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "{nativeTokenSymbol} APR" -msgstr "" - #: src/components/Stake/GMXAprTooltip.tsx msgid "{nativeTokenSymbol} Base APR" msgstr "" diff --git a/src/locales/ja/messages.po b/src/locales/ja/messages.po index d13bf25f7d..bd357858ed 100644 --- a/src/locales/ja/messages.po +++ b/src/locales/ja/messages.po @@ -135,6 +135,10 @@ msgstr "" msgid "<0>{0} <1><2>{indexName}<3>[{poolName}] <4>market selected" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "A Size percentage is required." +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "A snapshot of the USD value of your {0} collateral is taken when the position is opened." msgstr "{0}の担保のUSドル建の価値は、ポジションがオープンされた時点でスナップショットされ確定します。" @@ -243,6 +247,14 @@ msgstr "" msgid "Accrued Positive Funding Fees for Positions not yet claimable. They will become available to claim by using the \"Settle\" button, or after the Position is increased, decreased or closed." msgstr "" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +msgid "Accrued Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Accrued Price Impact Rebates. They will become Claimable after some time.<0/><1/><2>Read more." +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "Acknowledge epoch is ending in {minutes} minutes" msgstr "" @@ -257,6 +269,10 @@ msgstr "" msgid "Acknowledge high Swap Price Impact" msgstr "" +#: src/domain/synthetics/trade/useHighExecutionFeeConsent.tsx +msgid "Acknowledge very high network Fees" +msgstr "" + #: src/pages/Actions/Actions.js #: src/pages/SyntheticsActions/SyntheticsActions.tsx msgid "Actions" @@ -303,6 +319,10 @@ msgstr "紹介コードが追加できませんでした" msgid "Adding..." msgstr "追加中" +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +#~ msgid "Additional Execution Fee" +#~ msgstr "" + #: src/pages/Stake/StakeV2.js msgid "Additional reserve required" msgstr "必要な追加リザーブ額" @@ -344,15 +364,15 @@ msgstr "" msgid "Allow {wrappedTokenSymbol} to be spent" msgstr "" -#: src/App/App.js #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/SettingsModal/SettingsModal.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Allowed Slippage" msgstr "最大スリッページ" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Allowed Slippage below {0}% may result in failed orders." msgstr "" @@ -444,11 +464,15 @@ msgstr "{stakingTokenSymbol}を承認中..." msgid "Approving..." msgstr "承認中" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Arbitrum APR:" msgstr "ArbitrumのAPR(実質年利)" +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "As network fees have increased, an additional execution fee is needed." +msgstr "" + #: src/components/Exchange/NoLiquidityErrorModal.tsx msgid "As there is not enough liquidity in GLP to swap {0} to {swapTokenSymbol}, you can use the option below to do so:" msgstr "{0}から{swapTokenSymbol}に交換するための流動性がGLPに十分ないため、以下の選択肢を利用してください:" @@ -492,8 +516,8 @@ msgstr "GLPから引き出し可能な金額。現在オープンなポジショ msgid "Available on your preferred network" msgstr "選択されたネットワークにて利用可能" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Avalanche APR:" msgstr "AvalancheでのAPR(実質年利)" @@ -518,6 +542,10 @@ msgstr "残高" msgid "Base APR" msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Base {nativeTokenSymbol} APR" +msgstr "" + #: src/pages/BeginAccountTransfer/BeginAccountTransfer.js msgid "Begin Transfer" msgstr "移転開始" @@ -546,7 +574,6 @@ msgstr "マルチプライヤーポイントで報酬をブーストする。<0> #: src/components/Exchange/PositionsList.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Borrow Fee" @@ -561,6 +588,11 @@ msgstr "1日あたり借入手数料" msgid "Borrow Fee Rate" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Borrowing fees help ensure available liquidity. <0>Read more." +msgstr "" + #: src/components/Synthetics/BridgingInfo/BridgingInfo.tsx msgid "Bridge {tokenSymbol} to {chainName} using any of the options below:" msgstr "" @@ -596,7 +628,7 @@ msgstr "" msgid "Buy GLP" msgstr "GLPを購入" -#: src/pages/Buy/Buy.js +#: src/pages/Buy/Buy.tsx msgid "Buy GLP or GMX" msgstr "" @@ -649,26 +681,10 @@ msgstr "" msgid "Buy GMX using any token from any network:" msgstr "" -#: src/pages/Buy/Buy.js -msgid "Buy Protocol Tokens" -msgstr "" - #: src/components/Glp/GlpSwap.js msgid "Buy failed." msgstr "購入できませんでした。" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Arbitrum" -msgstr "Arbitrumで購入" - -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Avalanche" -msgstr "Avalancheで購入" - #: src/pages/BuyGMX/BuyGMX.tsx msgid "Buy or Transfer AVAX to Avalanche" msgstr "" @@ -729,7 +745,6 @@ msgstr "エラーにより執行できません" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts @@ -759,7 +774,7 @@ msgstr "キャンセル申し込み完了" msgid "Cancelling {ordersText}" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Chart positions" @@ -781,6 +796,7 @@ msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/Claims/ClaimableCard.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV1.js @@ -807,7 +823,7 @@ msgid "Claim GMX Rewards" msgstr "GMX報酬の請求" #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx -msgid "Claim Price Impact" +msgid "Claim Price Impact Rebates" msgstr "" #: src/pages/Stake/StakeV2.js @@ -853,6 +869,10 @@ msgstr "請求申し込み完了! <0>状況を確認する。" msgid "Claim submitted." msgstr "請求申し込み完了" +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "Claim {totalUsd}" +msgstr "" + #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "Claim {wrappedTokenSymbol} Rewards" @@ -864,30 +884,37 @@ msgstr "{wrappedTokenSymbol}報酬の請求" msgid "Claimable" msgstr "請求可能" +#: src/components/Synthetics/Claims/ClaimableCard.tsx +msgid "Claimable Price Impact Rebates.<0/><1/><2>Read more." +msgstr "" + #: src/components/Referrals/AffiliatesStats.tsx msgid "Claimable Rebates" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Claiming Price Impact Rebate..." +msgstr "" + +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Claiming failed" msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV2.js msgid "Claiming..." msgstr "請求中..." -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Claims" msgstr "" #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx -msgid "Claims (1)" +msgid "Claims ({totalClaimables})" msgstr "" #: src/components/Exchange/PositionsList.js @@ -1044,6 +1071,7 @@ msgstr "請求およびステーク中..." #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx msgid "Confirm Claim" msgstr "" @@ -1350,7 +1378,6 @@ msgstr "分散型<0/>パーペチュアル取引所" #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -1370,6 +1397,10 @@ msgstr "" msgid "Decrease the Leverage by using the slider. If the Leverage slider is disabled, you can increase the Pay amount or reduce the Order size." msgstr "" +#: src/components/Synthetics/ConfirmationBox/SLTPEntries.tsx +msgid "Decrease {0} Long by {1} at ${2}." +msgstr "" + #: src/components/Exchange/TradeHistory.js #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx msgid "Decreased" @@ -1463,7 +1494,7 @@ msgstr "入金中..." msgid "Diff" msgstr "差異" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Disable order validations" msgstr "注文のバリデーションの無効化" @@ -1471,7 +1502,7 @@ msgstr "注文のバリデーションの無効化" msgid "Disconnect" msgstr "接続停止" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Display PnL after fees" msgstr "手数料込損益の表示" @@ -1502,6 +1533,10 @@ msgstr "報酬獲得" msgid "Earn ARB tokens by purchasing GM tokens, trading, or migrating liquidity from GLP to GM. Only for GMX V2." msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Earn an extra {0}% {nativeTokenSymbol} Boosted APR by increasing your staked <0>Multiplier Points." +msgstr "" + #: src/components/Header/AppHeaderLinks.tsx msgid "Ecosystem" msgstr "エコシステム" @@ -1771,6 +1806,7 @@ msgid "Execute {orderTypeName} Order: {positionText} {sizeDeltaText}," msgstr "" #: src/components/Exchange/FeesTooltip.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx msgid "Execution Fee" msgstr "" @@ -1815,14 +1851,14 @@ msgstr "手数料" msgid "FUNDING FEE" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "FUNDING RATE / 1h" -msgstr "" - #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx msgid "Failed Settlement of Funding Fees" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Failed to Claim Price Impact Rebate" +msgstr "" + #: src/domain/synthetics/orders/cancelOrdersTxn.ts msgid "Failed to cancel {ordersText}" msgstr "" @@ -1847,6 +1883,7 @@ msgstr "" #: src/components/Glp/GlpSwap.js #: src/components/Glp/GlpSwap.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Fees" msgstr "手数料" @@ -1963,11 +2000,10 @@ msgstr "" msgid "Fulfilling order request" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts msgid "Funding Claimed" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Funding Fee" @@ -1977,14 +2013,15 @@ msgstr "" msgid "Funding Fee Rate" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Funding Rate / 1h" -msgstr "" - #: src/components/Synthetics/Claims/ClaimableCardUI.tsx msgid "Funding fees" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Funding fees help to balance longs and shorts and are exchanged between both sides. <0>Read more." +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "GBC NFTs APR tracker and rewards" msgstr "GBC NFTのAPRトラッカーおよび報酬" @@ -2015,7 +2052,7 @@ msgstr "" msgid "GLP buy disabled, pending {0} upgrade" msgstr "{0}アップグレード未完了のためGLP購入は停止中です" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GLP is the liquidity provider token for GMX V1 markets. Accrues 70% of the V1 markets generated fees." msgstr "" @@ -2043,7 +2080,7 @@ msgstr "" msgid "GM can be sold for {0} and {1} for this market up to the specified selling caps. The remaining tokens in the pool are reserved for currently open Positions." msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GM is the liquidity provider token for GMX V2 markets. Accrues 63% of the V2 markets generated fees." msgstr "" @@ -2132,7 +2169,7 @@ msgstr "GMXは現在ArbitrumとAvalancheで稼働中です。" msgid "GMX is not actively looking for new hires at the moment. However, if you think you can contribute to the project, please email <0>jobs@gmx.io." msgstr "GMXは現在積極的には求人を行っていませんが、プロジェクトに貢献できると思われる方は、<0>jobs@gmx.ioにメールをしてください。" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GMX is the utility and governance token. Accrues 30% and 27% of V1 and V2 markets generated fees, respectively." msgstr "" @@ -2185,6 +2222,13 @@ msgstr "" msgid "Governance" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.tsx +#: src/components/Synthetics/PositionEditor/PositionEditor.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "High Execution Fee not yet acknowledged" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "High Slippage, Swap Anyway" msgstr "スリッページが大きいです。ともかく交換する" @@ -2193,6 +2237,13 @@ msgstr "スリッページが大きいです。ともかく交換する" msgid "High USDG Slippage, Long Anyway" msgstr "USDGスリッページが大きいです。ともかくロングする" +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#~ msgid "High network Fee not yet acknowledged" +#~ msgstr "" + #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "I am aware of the trigger orders" @@ -2228,7 +2279,7 @@ msgstr "" msgid "Incentives are airdropped weekly." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Include PnL in leverage display" msgstr "レバレッジ表示に損益を含める" @@ -2250,7 +2301,6 @@ msgstr "誤ったネットワーク" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -2408,7 +2458,7 @@ msgstr "無効な受け取りアドレス" msgid "Invalid Transfer Addresses: Please check the url." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid execution fee buffer value" msgstr "" @@ -2426,7 +2476,7 @@ msgstr "無効な清算価格" msgid "Invalid price, see warning" msgstr "無効な価格につき、警告を確認してください" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid slippage value" msgstr "無効なスリッページ値" @@ -2455,7 +2505,6 @@ msgid "Keep Leverage is not possible" msgstr "" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "Keep leverage at {0}" msgstr "" @@ -2464,6 +2513,10 @@ msgstr "" msgid "Keep leverage at {0}x" msgstr "" +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "Keep leverage at {keepLeverageAtValue}" +msgstr "" + #: src/components/Synthetics/ChartTokenSelector/ChartTokenSelector.tsx msgid "LONG LIQ." msgstr "" @@ -2548,7 +2601,6 @@ msgstr "" #: src/components/Synthetics/PositionItem/PositionItem.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts -#: src/domain/synthetics/orders/utils.ts msgid "Limit" msgstr "指値" @@ -2572,7 +2624,6 @@ msgstr "" #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Limit Price" msgstr "指値" @@ -2705,8 +2756,8 @@ msgstr "ロード中" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -2723,7 +2774,6 @@ msgstr "ロード中" #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -2738,14 +2788,6 @@ msgstr "ロング" msgid "Long Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Long Liquidity" msgstr "" @@ -2754,14 +2796,11 @@ msgstr "" msgid "Long Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Long Positions" msgstr "ロングポジション" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Long positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Long {0}" msgstr "ロング {0}" @@ -2778,7 +2817,9 @@ msgstr "シェアできる紹介コードがないようです。<0/> コード msgid "Loss" msgstr "損失" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/GmList/GmList.tsx msgid "MARKET" msgstr "" @@ -2894,16 +2935,15 @@ msgid "Max Capacity for {0} Reached" msgstr "{0}の最大キャパシティに到達しています" #: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Max Execution Fee" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee Buffer" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee buffer below {0}% may result in failed orders." msgstr "" @@ -2945,7 +2985,7 @@ msgstr "" msgid "Max close amount exceeded" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max execution fee buffer precision is 0.01%" msgstr "" @@ -2975,9 +3015,13 @@ msgstr "{0}の最大プールキャパシティ到達。別のトークンを使 msgid "Max pool capacity reached for {0}<0/><1/>Please mint GLP using another token" msgstr "{0}の最大プールキャパシティ到達<0/><1/>別のトークンを使用してGLPをミントしてください" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Max slippage precision is -0.01%" +msgstr "" + #: src/App/App.js -msgid "Max slippage precision is 0.01%" -msgstr "スリッページの最大精度は0.01%です" +#~ msgid "Max slippage precision is 0.01%" +#~ msgstr "スリッページの最大精度は0.01%です" #: src/components/Synthetics/MarketStats/MarketStats.tsx #: src/components/Synthetics/MarketStats/MarketStats.tsx @@ -3025,11 +3069,11 @@ msgstr "{0}の最大ショートキャパシティ" msgid "Max {0} short exceeded" msgstr "{0}の最大ショート値を超過しています" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Arbitrum APR:" msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Avalanche APR: {0}" msgstr "" @@ -3038,7 +3082,11 @@ msgid "Max. Leverage exceeded" msgstr "" #: src/components/Stake/GMXAprTooltip.tsx -msgid "Max. {nativeTokenSymbol} APR with 200% Boost for this week: {0}%." +msgid "Max. {nativeTokenSymbol} APR" +msgstr "" + +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Max. {nativeTokenSymbol} APR is calculated with the max. 200% Boost Percentage by staking <0>Multiplier Points." msgstr "" #: src/components/Migration/Migration.js @@ -3148,9 +3196,16 @@ msgid "Multiplier Points APR" msgstr "マルチプライヤーポイントのAPR(実質年利)" #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "NA" msgstr "" +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "NET FEE / 1 H" +msgstr "" + #: src/pages/NftWallet/NftWallet.js msgid "NFT Address" msgstr "NFTアドレス" @@ -3171,6 +3226,20 @@ msgstr "" msgid "Neither Collateral nor realized PnL is enough to cover pending Fees. Please close a larger position amount." msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Fee" +msgstr "" + +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Net Fee / 1h" +msgstr "" + +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Rebate" +msgstr "" + #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -3199,7 +3268,12 @@ msgstr "ネットワーク" msgid "Networks and Settings" msgstr "ネットワークと設定" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "New Collateral" +msgstr "" + #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Next" msgstr "次へ" @@ -3275,6 +3349,10 @@ msgstr "" msgid "Note that orders are not guaranteed to be executed.<0/><1/>This can occur in a few situations including but not exclusive to:" msgstr "注文が必ず執行される保証がないことに注意してください。<0/><1/>これは例えば以下のような状況で起こりえます:" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Old Collateral" +msgstr "" + #: src/components/AddressDropdown/AddressDropdown.tsx #: src/components/Synthetics/SubaccountModal/SubaccountModal.tsx msgid "One-Click Trading" @@ -3351,10 +3429,6 @@ msgstr "オープン中..." msgid "Order" msgstr "注文" -#: src/domain/synthetics/orders/utils.ts -msgid "Order Trigger Price is beyond position's Liquidation Price." -msgstr "" - #: src/components/Synthetics/OrderItem/OrderItem.tsx msgid "Order Type" msgstr "" @@ -3635,7 +3709,6 @@ msgstr "ポジション" msgid "Positions ({0})" msgstr "ポジション ({0})" -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Positions{0}" msgstr "" @@ -3645,6 +3718,7 @@ msgid "Positive Funding Fees for a Position become claimable after the Position msgstr "" #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Prev" msgstr "前へ" @@ -3686,6 +3760,20 @@ msgstr "価格" msgid "Price Impact" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Price Impact Rebate Claimed" +msgstr "" + +#: src/components/Synthetics/Claims/ClaimableCardUI.tsx +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates for closing trades are claimable under the Claims tab. <0>Read more." +msgstr "" + +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts @@ -3693,6 +3781,10 @@ msgstr "" msgid "Price Impact not yet acknowledged" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3700,6 +3792,10 @@ msgstr "" msgid "Price above Liq. Price" msgstr "清算価格を上回る価格" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3713,6 +3809,14 @@ msgstr "清算価格を上回る価格" msgid "Price above Mark Price" msgstr "マーク価格を上回る価格" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Mark Price." +msgstr "" + +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3720,6 +3824,10 @@ msgstr "マーク価格を上回る価格" msgid "Price below Liq. Price" msgstr "清算価格を下回る価格" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3733,6 +3841,10 @@ msgstr "清算価格を下回る価格" msgid "Price below Mark Price" msgstr "マーク価格を下回る価格" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Mark Price." +msgstr "" + #: src/pages/OrdersOverview/OrdersOverview.js msgid "Price conditions are met" msgstr "価格の条件が満たされていません" @@ -3775,6 +3887,10 @@ msgstr "貯蓄証明" msgid "Protocol" msgstr "" +#: src/pages/Buy/Buy.tsx +msgid "Protocol Tokens" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js #: src/pages/Ecosystem/Ecosystem.js msgid "Protocol analytics" @@ -3796,9 +3912,14 @@ msgstr "" msgid "Purchase Insurance" msgstr "保険購入" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "REBATE" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Read more" msgstr "詳細について読む" @@ -4025,7 +4146,7 @@ msgstr "" msgid "Same as current active code" msgstr "現在アクティブなコードと同じです" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Save" msgstr "保存" @@ -4191,10 +4312,10 @@ msgstr "" msgid "Set TP/SL" msgstr "" -#: src/App/App.js #: src/components/Header/AppHeaderLinks.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx +#: src/components/SettingsModal/SettingsModal.tsx msgid "Settings" msgstr "設定" @@ -4256,8 +4377,8 @@ msgstr "ポジションをシェアする" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4274,7 +4395,6 @@ msgstr "ポジションをシェアする" #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -4289,14 +4409,6 @@ msgstr "ショート" msgid "Short Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Short Liquidity" msgstr "" @@ -4305,14 +4417,11 @@ msgstr "" msgid "Short Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Short Positions" msgstr "ショートポジション" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Short positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Short {0}" msgstr "{0}をショート" @@ -4321,10 +4430,14 @@ msgstr "{0}をショート" msgid "Shorting..." msgstr "ショート中..." -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Show debug values" msgstr "" +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Show details" +msgstr "" + #: src/pages/Home/Home.js msgid "Simple Swaps" msgstr "シンプルなスワップ" @@ -4350,6 +4463,7 @@ msgstr "" #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4361,14 +4475,18 @@ msgstr "サイズ" #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Slippage is too high" msgstr "" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Slippage should be less than -5%" +msgstr "" + #: src/App/App.js -msgid "Slippage should be less than 5%" -msgstr "スリッページは5%未満であること" +#~ msgid "Slippage should be less than 5%" +#~ msgstr "スリッページは5%未満であること" #: src/components/Exchange/UsefulLinks.tsx msgid "Speed up page loading" @@ -4472,10 +4590,15 @@ msgstr "統計" msgid "Stop Loss Decrease" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Stop-Loss" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Stop-Loss PnL" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "Structured Products" msgstr "ストラクチャードプロダクト" @@ -4524,7 +4647,7 @@ msgstr "" msgid "Submit" msgstr "提出" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Success claimings" msgstr "" @@ -4550,10 +4673,6 @@ msgstr "スワップ" msgid "Swap Fee" msgstr "" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx -msgid "Swap Fees" -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Swap Order created!" msgstr "スワップ注文作成完了!" @@ -4566,7 +4685,6 @@ msgstr "スワップ注文が作成できませんでした。" msgid "Swap Order submitted!" msgstr "スワップ注文提出済!" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Swap Price Impact" msgstr "" @@ -4700,11 +4818,15 @@ msgstr "" msgid "TP/SL" msgstr "" -#: src/domain/synthetics/orders/utils.ts +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Take-Profit" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Take-Profit PnL" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "Take-profit and stop-loss orders can be set after opening a position. <0/><1/>There will be a \"Close\" button on each position row, clicking this will display the option to set trigger orders. <2/><3/>For screenshots and more information, please see the <4>docs." msgstr "テイクプロフィット注文とストップロス注文はポジションをオープンしてからセットすることができます。<0/><1/>それぞれのポジションの行に\"クローズ\"ボタンが表れ、それをクリックするとトリガー注文をセットするための選択肢が表示されます。<2/><3/>スクリーンショットや詳細情報については<4>文書を読んでください。" @@ -4771,10 +4893,6 @@ msgstr "" msgid "The Bonus Rebate will be airdropped as ARB tokens on a pro-rata basis. <0>Read more." msgstr "" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "The Boosted APR is from your staked Multiplier Points." -msgstr "APRブーストはステーク済マルチプライヤーポイントによるものです。" - #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx msgid "The Current Price Impact is {0}. Consider adding a buffer of 0.30% to it so the order is more likely to be processed." msgstr "" @@ -4787,18 +4905,15 @@ msgstr "" msgid "The Gambit protocol is in beta, please read the <0>staking detailsbefore participating." msgstr "Gambitプロトコルはベータ版であり、参加する前に<0>ステーキングの詳細を読んでください。" +#: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "The Max Execution Fee is overestimated by {maxExecutionFeeText}%. Upon execution, the excess Execution Fee is sent back to your account." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "The Max Execution Fee is set to a higher value to handle potential increases in gas price during order execution. Any excess execution fee will be refunded to your account when the order is executed. Only applicable to GMX V2." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "The Order may not execute at the desired {priceText} as the current Price Impact {0} is higher than its Acceptable Price Impact {1}. Consider canceling and creating a new {suggestionType} Order." -msgstr "" - #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "The address of the esGMX (IOU) token is {esGmxIouAddress}." msgstr "esGMX (IOU)トークンのアドレスは{esGmxIouAddress}です。" @@ -4827,11 +4942,23 @@ msgstr "マーク価格が変化したため、アドレスの横に表示され msgid "The maximum number of authorized Actions has been reached. Re-authorize a higher value using the \"Max allowed actions\" field." msgstr "" +#: src/domain/synthetics/fees/utils/executionFee.ts +msgid "The network Fees are high currently, which may be due to a temporary increase in transactions on the {0} network." +msgstr "" + #: src/domain/legacy.ts #: src/domain/synthetics/fees/utils/executionFee.ts msgid "The network Fees are very high currently, which may be due to a temporary increase in transactions on the {0} network." msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "The order may not execute at the desired {priceText} as its acceptable price impact is set to {formattedOrderAcceptablePriceImpact}, which is lower than the current market price impact of {formattedCurrentAcceptablePriceImpact}. It can be edited using the \"Edit\" button." +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "The order will not be executed as its trigger price is beyond the position's liquidation price." +msgstr "" + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "The order will only execute if the Min. Receive is met and there is sufficient liquidity." msgstr "" @@ -4853,9 +4980,13 @@ msgid "The pending borrow fee will be charged on this transaction." msgstr "" #: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of -{1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#~ msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +#~ msgstr "" + #: src/components/Exchange/SwapBox.js msgid "The position will be opened at {0} USD with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "ポジションは最大スリッページ {1}%で{0} USDでオープンされます。<0/><1/>スリッページを変更するには、ウォレット接続後にページの右上に表示されるアドレスをクリックしたときに表れる設定メニューで設定してください。<2/><3/><4>詳細情報" @@ -4964,9 +5095,8 @@ msgstr "このコードは{0}上ではまだ登録されていないため、紹 msgid "This is the maximum top-up amount that will be sent from your Main account to your Subaccount after each transaction. The actual amount sent will depend on the final transaction fee." msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "This market uses an Adaptive Funding Rate. The Funding Rate will adjust over time depending on the ratio of longs and shorts. <0>Read more." +#: src/domain/synthetics/orders/utils.ts +msgid "This order using {collateralSymbol} as collateral will not be valid for the existing {longText} position using {symbol} as collateral." msgstr "" #: src/components/Exchange/TradeHistory.js @@ -5137,7 +5267,6 @@ msgstr "" #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Trades" msgstr "トレード" @@ -5240,7 +5369,6 @@ msgstr "トリガー" #: src/components/Synthetics/OrderList/OrderList.tsx #: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Trigger Price" msgstr "" @@ -5252,10 +5380,6 @@ msgstr "" msgid "Trigger order disabled, pending {0} upgrade" msgstr "" -#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx -msgid "Trigger order for" -msgstr "" - #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Triggered at: {0}" msgstr "" @@ -5359,7 +5483,7 @@ msgid "Unstake submitted! <0>View status." msgstr "アンステーク申し込み完了! <0>状況を確認する。" #: src/pages/Stake/StakeV2.js -msgid "Unstaking will burn <0>{0} Multiplier Points. {1}" +msgid "Unstaking will burn <0>{0} Multiplier Points. <1>You will earn {1}% less {nativeTokenSymbol} rewards with this action." msgstr "" #: src/pages/Stake/StakeV1.js @@ -5569,6 +5693,18 @@ msgstr "見る" msgid "View in Explorer" msgstr "Explorerで見る" +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Arbitrum" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Avalanche" +msgstr "" + #: src/components/Synthetics/StatusNotification/SubaccountNotification.tsx msgid "View status" msgstr "" @@ -5799,9 +5935,12 @@ msgstr "<0>こちらで請求履歴を確認できます。" msgid "You can currently vest a maximum of {0} esGMX tokens at a ratio of {1} {stakingToken} to 1 esGMX." msgstr "{1} {stakingToken}対1 esGMXの比率で最大{0} esGMXトークンを現在べスティングすることができます。" +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx +msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than -{0}, may result in failed orders if prices are volatile." +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than {0}, may result in failed orders if prices are volatile." msgstr "" @@ -5829,10 +5968,6 @@ msgstr "{sender}からの未完了の移転があります。" msgid "You have an active Limit Order to Increase {longOrShortText} {sizeInToken} {0} (${1}) at price ${2}" msgstr "{longOrShortText} {sizeInToken} {0} (${1})を${2}の価格で増額するアクティブなリミット注文があります" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have an active Limit Order to Increase {longShortText} {0} {sizeText} at price {1}." -msgstr "" - #: src/components/Exchange/PositionSeller.js msgid "You have an active order to decrease {longOrShortText} {sizeInToken} {0} (${1}) at {prefix} {2}" msgstr "" @@ -5861,25 +5996,24 @@ msgstr "" msgid "You have an existing position with {0} as collateral. This action will not apply for that position." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "" -"You have an existing {longText} position with {0} as Collateral. This Order will not\n" -"be valid for that Position." -msgstr "" - #: src/components/Exchange/ConfirmationBox.js msgid "You have multiple existing Increase {longOrShortText} {0} limit orders" msgstr "{longOrShortText} {0}のリミット注文を増額する複数の注文があります" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have multiple existing Increase {longShortText} {0} limit orders" -msgstr "" - #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "You have not deposited any tokens for vesting." msgstr "べスティング用のトークンが入金されていません。" +#: src/components/Stake/GMXAprTooltip.tsx +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points using the \"Compound\" button." +msgstr "" + +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points." +msgstr "" + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "You have selected {collateralTokenSymbol} as Collateral, the Liquidation Price will vary based on the price of {collateralTokenSymbol}." msgstr "" @@ -5928,13 +6062,18 @@ msgstr "この注文が執行された場合、少なくとも{0} {1}を受け msgid "You will receive at least {toAmountText} if this order is executed. This price is being updated in real time based on Swap Fees and Price Impact." msgstr "" +#: src/pages/Stake/StakeV2.js +#: src/pages/Stake/StakeV2.js +msgid "Your APR" +msgstr "" + #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "Your esGMX (IOU) balance will decrease by your claim amount after claiming, this is expected behaviour." msgstr "あなたのesGMX (IOU)残高は請求後に請求額分だけ減少しますが、これは想定通りの挙動です。" #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "Your position's collateral after deducting fees." +msgid "Your position's collateral after deducting fees:" msgstr "手数料差引後のあなたのポジションの担保" #: src/pages/CompleteAccountTransfer/CompleteAccountTransfer.js @@ -5970,7 +6109,6 @@ msgid "from" msgstr "" #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "hide" msgstr "隠す" @@ -5978,20 +6116,32 @@ msgstr "隠す" msgid "in liquidity" msgstr "流動性" +#: src/domain/synthetics/orders/utils.ts +msgid "limit price" +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "long" +msgstr "" + #: src/pages/Dashboard/DashboardV2.js msgid "not staked" msgstr "ステークされていない" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "pay" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "receive" msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "short" +msgstr "" + #: src/pages/PositionsOverview/PositionsOverview.js msgid "size" msgstr "サイズ" @@ -6004,8 +6154,11 @@ msgstr "ステーク済" msgid "time to liq" msgstr "清算までの時間" +#: src/domain/synthetics/orders/utils.ts +msgid "trigger price" +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "view" msgstr "見る" @@ -6022,6 +6175,10 @@ msgstr "" msgid "{0, plural, one {Pending {symbolsText} approval} other {Pending {symbolsText} approvals}}" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "{0, plural, one {You have an active Limit Order to Increase} other {You have multiple active Limit Orders to Increase}}" +msgstr "" + #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "{0} <0><1>{indexName}<2>[{poolName}] <3>market selected." msgstr "" @@ -6102,6 +6259,10 @@ msgstr "{0}はターゲットウェイトより低くなっています。<0/><1 msgid "{0} is required for collateral." msgstr "担保に{0}が必要です。" +#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx +msgid "{0} order for" +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "{0} pool exceeded, try different token" msgstr "{0}プールは超過しています。別のトークンを試してください。" @@ -6202,6 +6363,22 @@ msgstr "" msgid "{longOrShortText} {0} market selected" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee and pay a borrow fee of {borrowRate} per hour." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee or a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and do not pay a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and {borrowAction} a borrow fee of {borrowRate} per hour." +msgstr "" + #: src/components/Synthetics/MarketCard/MarketCard.tsx msgid "{longShortText} {0} Open Interest" msgstr "" @@ -6218,10 +6395,6 @@ msgstr "" msgid "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR" msgstr "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR(実質年利)" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "{nativeTokenSymbol} APR" -msgstr "" - #: src/components/Stake/GMXAprTooltip.tsx msgid "{nativeTokenSymbol} Base APR" msgstr "" diff --git a/src/locales/ko/messages.po b/src/locales/ko/messages.po index 7f60ca15ad..0051840372 100644 --- a/src/locales/ko/messages.po +++ b/src/locales/ko/messages.po @@ -135,6 +135,10 @@ msgstr "" msgid "<0>{0} <1><2>{indexName}<3>[{poolName}] <4>market selected" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "A Size percentage is required." +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "A snapshot of the USD value of your {0} collateral is taken when the position is opened." msgstr "{0}담보의 USD가치 스냅샷은 해당 포지션이 열려있을 때 결정됩니다." @@ -243,6 +247,14 @@ msgstr "" msgid "Accrued Positive Funding Fees for Positions not yet claimable. They will become available to claim by using the \"Settle\" button, or after the Position is increased, decreased or closed." msgstr "" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +msgid "Accrued Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Accrued Price Impact Rebates. They will become Claimable after some time.<0/><1/><2>Read more." +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "Acknowledge epoch is ending in {minutes} minutes" msgstr "" @@ -257,6 +269,10 @@ msgstr "" msgid "Acknowledge high Swap Price Impact" msgstr "" +#: src/domain/synthetics/trade/useHighExecutionFeeConsent.tsx +msgid "Acknowledge very high network Fees" +msgstr "" + #: src/pages/Actions/Actions.js #: src/pages/SyntheticsActions/SyntheticsActions.tsx msgid "Actions" @@ -303,6 +319,10 @@ msgstr "추천 코드 추가 실패" msgid "Adding..." msgstr "추가중..." +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +#~ msgid "Additional Execution Fee" +#~ msgstr "" + #: src/pages/Stake/StakeV2.js msgid "Additional reserve required" msgstr "추가의 리저브양이 필요합니다" @@ -344,15 +364,15 @@ msgstr "" msgid "Allow {wrappedTokenSymbol} to be spent" msgstr "" -#: src/App/App.js #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/SettingsModal/SettingsModal.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Allowed Slippage" msgstr "허용 가능한 슬리피지" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Allowed Slippage below {0}% may result in failed orders." msgstr "" @@ -444,11 +464,15 @@ msgstr "{stakingTokenSymbol} 승인중..." msgid "Approving..." msgstr "승인중..." -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Arbitrum APR:" msgstr "Arbitrum APR:" +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "As network fees have increased, an additional execution fee is needed." +msgstr "" + #: src/components/Exchange/NoLiquidityErrorModal.tsx msgid "As there is not enough liquidity in GLP to swap {0} to {swapTokenSymbol}, you can use the option below to do so:" msgstr "{0}에서 {swapTokenSymbol}로 교환할 수 있는 유동성이 GLP에 충분하지 않기 때문에, 이하의 옵션을 사용해주세요:" @@ -492,8 +516,8 @@ msgstr "GLP로부터 인출가능한 수량. 현재 포지션에 의해 활용 msgid "Available on your preferred network" msgstr "선택한 네트워크에서 이용가능" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Avalanche APR:" msgstr "Avalanche APR:" @@ -518,6 +542,10 @@ msgstr "잔고" msgid "Base APR" msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Base {nativeTokenSymbol} APR" +msgstr "" + #: src/pages/BeginAccountTransfer/BeginAccountTransfer.js msgid "Begin Transfer" msgstr "전송시작" @@ -546,7 +574,6 @@ msgstr "멀티플라이어 포인트를 사용해서 보상을 증가시키세 #: src/components/Exchange/PositionsList.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Borrow Fee" @@ -561,6 +588,11 @@ msgstr "차용 수수료 / 일" msgid "Borrow Fee Rate" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Borrowing fees help ensure available liquidity. <0>Read more." +msgstr "" + #: src/components/Synthetics/BridgingInfo/BridgingInfo.tsx msgid "Bridge {tokenSymbol} to {chainName} using any of the options below:" msgstr "" @@ -596,7 +628,7 @@ msgstr "" msgid "Buy GLP" msgstr "GLP 구매" -#: src/pages/Buy/Buy.js +#: src/pages/Buy/Buy.tsx msgid "Buy GLP or GMX" msgstr "" @@ -649,26 +681,10 @@ msgstr "" msgid "Buy GMX using any token from any network:" msgstr "" -#: src/pages/Buy/Buy.js -msgid "Buy Protocol Tokens" -msgstr "" - #: src/components/Glp/GlpSwap.js msgid "Buy failed." msgstr "구매 실패" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Arbitrum" -msgstr "Arbitrum에서 구매" - -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Avalanche" -msgstr "Avalanche에서 구매" - #: src/pages/BuyGMX/BuyGMX.tsx msgid "Buy or Transfer AVAX to Avalanche" msgstr "" @@ -729,7 +745,6 @@ msgstr "에러로 인해 실행되지 못했습니다" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts @@ -759,7 +774,7 @@ msgstr "취소 제출 완료" msgid "Cancelling {ordersText}" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Chart positions" @@ -781,6 +796,7 @@ msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/Claims/ClaimableCard.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV1.js @@ -807,7 +823,7 @@ msgid "Claim GMX Rewards" msgstr "GMX 보상 수령하기" #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx -msgid "Claim Price Impact" +msgid "Claim Price Impact Rebates" msgstr "" #: src/pages/Stake/StakeV2.js @@ -853,6 +869,10 @@ msgstr "수령 제출완료! <0>상태 보기." msgid "Claim submitted." msgstr "수령 제출 완료." +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "Claim {totalUsd}" +msgstr "" + #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "Claim {wrappedTokenSymbol} Rewards" @@ -864,30 +884,37 @@ msgstr "{wrappedTokenSymbol} 보상 수령하기" msgid "Claimable" msgstr "수령가능" +#: src/components/Synthetics/Claims/ClaimableCard.tsx +msgid "Claimable Price Impact Rebates.<0/><1/><2>Read more." +msgstr "" + #: src/components/Referrals/AffiliatesStats.tsx msgid "Claimable Rebates" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Claiming Price Impact Rebate..." +msgstr "" + +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Claiming failed" msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV2.js msgid "Claiming..." msgstr "수령중..." -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Claims" msgstr "" #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx -msgid "Claims (1)" +msgid "Claims ({totalClaimables})" msgstr "" #: src/components/Exchange/PositionsList.js @@ -1044,6 +1071,7 @@ msgstr "수령 및 스테이킹중..." #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx msgid "Confirm Claim" msgstr "" @@ -1350,7 +1378,6 @@ msgstr "탈중앙화<0/>퍼페추얼 거래소" #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -1370,6 +1397,10 @@ msgstr "" msgid "Decrease the Leverage by using the slider. If the Leverage slider is disabled, you can increase the Pay amount or reduce the Order size." msgstr "" +#: src/components/Synthetics/ConfirmationBox/SLTPEntries.tsx +msgid "Decrease {0} Long by {1} at ${2}." +msgstr "" + #: src/components/Exchange/TradeHistory.js #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx msgid "Decreased" @@ -1463,7 +1494,7 @@ msgstr "예치중..." msgid "Diff" msgstr "차이" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Disable order validations" msgstr "주문 밸리데이션 무효화" @@ -1471,7 +1502,7 @@ msgstr "주문 밸리데이션 무효화" msgid "Disconnect" msgstr "연결 끊기" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Display PnL after fees" msgstr "수수료포함 손익 표시" @@ -1502,6 +1533,10 @@ msgstr "보상" msgid "Earn ARB tokens by purchasing GM tokens, trading, or migrating liquidity from GLP to GM. Only for GMX V2." msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Earn an extra {0}% {nativeTokenSymbol} Boosted APR by increasing your staked <0>Multiplier Points." +msgstr "" + #: src/components/Header/AppHeaderLinks.tsx msgid "Ecosystem" msgstr "이코시스템" @@ -1771,6 +1806,7 @@ msgid "Execute {orderTypeName} Order: {positionText} {sizeDeltaText}," msgstr "" #: src/components/Exchange/FeesTooltip.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx msgid "Execution Fee" msgstr "" @@ -1815,14 +1851,14 @@ msgstr "수수료" msgid "FUNDING FEE" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "FUNDING RATE / 1h" -msgstr "" - #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx msgid "Failed Settlement of Funding Fees" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Failed to Claim Price Impact Rebate" +msgstr "" + #: src/domain/synthetics/orders/cancelOrdersTxn.ts msgid "Failed to cancel {ordersText}" msgstr "" @@ -1847,6 +1883,7 @@ msgstr "" #: src/components/Glp/GlpSwap.js #: src/components/Glp/GlpSwap.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Fees" msgstr "수수료" @@ -1963,11 +2000,10 @@ msgstr "" msgid "Fulfilling order request" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts msgid "Funding Claimed" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Funding Fee" @@ -1977,14 +2013,15 @@ msgstr "" msgid "Funding Fee Rate" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Funding Rate / 1h" -msgstr "" - #: src/components/Synthetics/Claims/ClaimableCardUI.tsx msgid "Funding fees" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Funding fees help to balance longs and shorts and are exchanged between both sides. <0>Read more." +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "GBC NFTs APR tracker and rewards" msgstr "GBC NFT의 APR 트래커 및 보상" @@ -2015,7 +2052,7 @@ msgstr "" msgid "GLP buy disabled, pending {0} upgrade" msgstr "{0} 업그레이드를 위해 GLP 구매가 비활성화되었습니다" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GLP is the liquidity provider token for GMX V1 markets. Accrues 70% of the V1 markets generated fees." msgstr "" @@ -2043,7 +2080,7 @@ msgstr "" msgid "GM can be sold for {0} and {1} for this market up to the specified selling caps. The remaining tokens in the pool are reserved for currently open Positions." msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GM is the liquidity provider token for GMX V2 markets. Accrues 63% of the V2 markets generated fees." msgstr "" @@ -2132,7 +2169,7 @@ msgstr "GMX는 현재 Arbitrum과 Avalanche에서 이용할 수 있습니다." msgid "GMX is not actively looking for new hires at the moment. However, if you think you can contribute to the project, please email <0>jobs@gmx.io." msgstr "GMX는 현재 구인하고 있지 않습니다. 하지만 해당 프로젝트에 기여할 수 있다고 생각하시면 email <0>jobs@gmx.io으로 연락해주세요." -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GMX is the utility and governance token. Accrues 30% and 27% of V1 and V2 markets generated fees, respectively." msgstr "" @@ -2185,6 +2222,13 @@ msgstr "" msgid "Governance" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.tsx +#: src/components/Synthetics/PositionEditor/PositionEditor.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "High Execution Fee not yet acknowledged" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "High Slippage, Swap Anyway" msgstr "높은 슬리피지 상관 없이 스왑" @@ -2193,6 +2237,13 @@ msgstr "높은 슬리피지 상관 없이 스왑" msgid "High USDG Slippage, Long Anyway" msgstr "높은 USDG 슬리피지 상관 없이 롱 포지션 체결" +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#~ msgid "High network Fee not yet acknowledged" +#~ msgstr "" + #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "I am aware of the trigger orders" @@ -2228,7 +2279,7 @@ msgstr "" msgid "Incentives are airdropped weekly." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Include PnL in leverage display" msgstr "레버리지 표시창에 손익 포함하기" @@ -2250,7 +2301,6 @@ msgstr "잘못된 네트워크입니다" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -2408,7 +2458,7 @@ msgstr "유효하지 않은 수령 주소" msgid "Invalid Transfer Addresses: Please check the url." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid execution fee buffer value" msgstr "" @@ -2426,7 +2476,7 @@ msgstr "유효하지 않은 청산가" msgid "Invalid price, see warning" msgstr "유효하지 않은 가격, 경고문을 보세요" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid slippage value" msgstr "유효하지 않은 슬리피지 값" @@ -2455,7 +2505,6 @@ msgid "Keep Leverage is not possible" msgstr "" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "Keep leverage at {0}" msgstr "" @@ -2464,6 +2513,10 @@ msgstr "" msgid "Keep leverage at {0}x" msgstr "" +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "Keep leverage at {keepLeverageAtValue}" +msgstr "" + #: src/components/Synthetics/ChartTokenSelector/ChartTokenSelector.tsx msgid "LONG LIQ." msgstr "" @@ -2548,7 +2601,6 @@ msgstr "" #: src/components/Synthetics/PositionItem/PositionItem.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts -#: src/domain/synthetics/orders/utils.ts msgid "Limit" msgstr "지정가" @@ -2572,7 +2624,6 @@ msgstr "" #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Limit Price" msgstr "지정가" @@ -2705,8 +2756,8 @@ msgstr "로딩중..." #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -2723,7 +2774,6 @@ msgstr "로딩중..." #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -2738,14 +2788,6 @@ msgstr "롱" msgid "Long Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Long Liquidity" msgstr "" @@ -2754,14 +2796,11 @@ msgstr "" msgid "Long Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Long Positions" msgstr "롱 포지션" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Long positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Long {0}" msgstr "롱 {0}" @@ -2778,7 +2817,9 @@ msgstr "공유할 수 있는 추천인 코드가 없는 것 같습니다. <0/> msgid "Loss" msgstr "손실" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/GmList/GmList.tsx msgid "MARKET" msgstr "" @@ -2894,16 +2935,15 @@ msgid "Max Capacity for {0} Reached" msgstr "{0}의 최대치에 도달했습니다." #: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Max Execution Fee" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee Buffer" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee buffer below {0}% may result in failed orders." msgstr "" @@ -2945,7 +2985,7 @@ msgstr "" msgid "Max close amount exceeded" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max execution fee buffer precision is 0.01%" msgstr "" @@ -2975,9 +3015,13 @@ msgstr "{0}의 최대 풀 수용량에 도달했습니다" msgid "Max pool capacity reached for {0}<0/><1/>Please mint GLP using another token" msgstr "최대 풀 수용량인 {0}에 도달했습니다<0/><1/>다른 토큰을 이용행 GLP를 민트해주세요" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Max slippage precision is -0.01%" +msgstr "" + #: src/App/App.js -msgid "Max slippage precision is 0.01%" -msgstr "허용 가능한 최대 슬리피지는 0.01%입니다" +#~ msgid "Max slippage precision is 0.01%" +#~ msgstr "허용 가능한 최대 슬리피지는 0.01%입니다" #: src/components/Synthetics/MarketStats/MarketStats.tsx #: src/components/Synthetics/MarketStats/MarketStats.tsx @@ -3025,11 +3069,11 @@ msgstr "최대 {0} 숏 수용량" msgid "Max {0} short exceeded" msgstr "{0} 숏 최대치를 초과했습니다." -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Arbitrum APR:" msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Avalanche APR: {0}" msgstr "" @@ -3038,7 +3082,11 @@ msgid "Max. Leverage exceeded" msgstr "" #: src/components/Stake/GMXAprTooltip.tsx -msgid "Max. {nativeTokenSymbol} APR with 200% Boost for this week: {0}%." +msgid "Max. {nativeTokenSymbol} APR" +msgstr "" + +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Max. {nativeTokenSymbol} APR is calculated with the max. 200% Boost Percentage by staking <0>Multiplier Points." msgstr "" #: src/components/Migration/Migration.js @@ -3148,9 +3196,16 @@ msgid "Multiplier Points APR" msgstr "멀티플라이어 포인트 APR" #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "NA" msgstr "" +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "NET FEE / 1 H" +msgstr "" + #: src/pages/NftWallet/NftWallet.js msgid "NFT Address" msgstr "NFT 주소" @@ -3171,6 +3226,20 @@ msgstr "" msgid "Neither Collateral nor realized PnL is enough to cover pending Fees. Please close a larger position amount." msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Fee" +msgstr "" + +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Net Fee / 1h" +msgstr "" + +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Rebate" +msgstr "" + #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -3199,7 +3268,12 @@ msgstr "네트워크" msgid "Networks and Settings" msgstr "네트워크 및 설정" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "New Collateral" +msgstr "" + #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Next" msgstr "다음" @@ -3275,6 +3349,10 @@ msgstr "" msgid "Note that orders are not guaranteed to be executed.<0/><1/>This can occur in a few situations including but not exclusive to:" msgstr "주문 실행은 보장되지 않습니다.<0/><1/>이것은 다음과 같은 상황에 일어날 수 있습니다:" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Old Collateral" +msgstr "" + #: src/components/AddressDropdown/AddressDropdown.tsx #: src/components/Synthetics/SubaccountModal/SubaccountModal.tsx msgid "One-Click Trading" @@ -3351,10 +3429,6 @@ msgstr "여는 중..." msgid "Order" msgstr "주문" -#: src/domain/synthetics/orders/utils.ts -msgid "Order Trigger Price is beyond position's Liquidation Price." -msgstr "" - #: src/components/Synthetics/OrderItem/OrderItem.tsx msgid "Order Type" msgstr "" @@ -3635,7 +3709,6 @@ msgstr "포지션" msgid "Positions ({0})" msgstr "포지션 ({0})" -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Positions{0}" msgstr "" @@ -3645,6 +3718,7 @@ msgid "Positive Funding Fees for a Position become claimable after the Position msgstr "" #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Prev" msgstr "이전" @@ -3686,6 +3760,20 @@ msgstr "가격" msgid "Price Impact" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Price Impact Rebate Claimed" +msgstr "" + +#: src/components/Synthetics/Claims/ClaimableCardUI.tsx +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates for closing trades are claimable under the Claims tab. <0>Read more." +msgstr "" + +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts @@ -3693,6 +3781,10 @@ msgstr "" msgid "Price Impact not yet acknowledged" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3700,6 +3792,10 @@ msgstr "" msgid "Price above Liq. Price" msgstr "청산가 초과 가격" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3713,6 +3809,14 @@ msgstr "청산가 초과 가격" msgid "Price above Mark Price" msgstr "시장 평균가 초과 가격" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Mark Price." +msgstr "" + +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3720,6 +3824,10 @@ msgstr "시장 평균가 초과 가격" msgid "Price below Liq. Price" msgstr "청산가 미만 가격" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3733,6 +3841,10 @@ msgstr "청산가 미만 가격" msgid "Price below Mark Price" msgstr "시장 평균가 미만 가격" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Mark Price." +msgstr "" + #: src/pages/OrdersOverview/OrdersOverview.js msgid "Price conditions are met" msgstr "가격 조건에 충족되었습니다" @@ -3775,6 +3887,10 @@ msgstr "예비구두 증명" msgid "Protocol" msgstr "" +#: src/pages/Buy/Buy.tsx +msgid "Protocol Tokens" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js #: src/pages/Ecosystem/Ecosystem.js msgid "Protocol analytics" @@ -3796,9 +3912,14 @@ msgstr "" msgid "Purchase Insurance" msgstr "보험 구입" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "REBATE" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Read more" msgstr "더 알아보기" @@ -4025,7 +4146,7 @@ msgstr "" msgid "Same as current active code" msgstr "현재 유효한 코드와 같음" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Save" msgstr "저장" @@ -4191,10 +4312,10 @@ msgstr "" msgid "Set TP/SL" msgstr "" -#: src/App/App.js #: src/components/Header/AppHeaderLinks.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx +#: src/components/SettingsModal/SettingsModal.tsx msgid "Settings" msgstr "설정" @@ -4256,8 +4377,8 @@ msgstr "포지션 공유" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4274,7 +4395,6 @@ msgstr "포지션 공유" #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -4289,14 +4409,6 @@ msgstr "숏" msgid "Short Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Short Liquidity" msgstr "" @@ -4305,14 +4417,11 @@ msgstr "" msgid "Short Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Short Positions" msgstr "숏 포지션" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Short positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Short {0}" msgstr "{0} 숏" @@ -4321,10 +4430,14 @@ msgstr "{0} 숏" msgid "Shorting..." msgstr "숏 실행중..." -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Show debug values" msgstr "" +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Show details" +msgstr "" + #: src/pages/Home/Home.js msgid "Simple Swaps" msgstr "간단한 스왑" @@ -4350,6 +4463,7 @@ msgstr "" #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4361,14 +4475,18 @@ msgstr "사이즈" #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Slippage is too high" msgstr "" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Slippage should be less than -5%" +msgstr "" + #: src/App/App.js -msgid "Slippage should be less than 5%" -msgstr "슬리피지는 5%미만이어야 합니다." +#~ msgid "Slippage should be less than 5%" +#~ msgstr "슬리피지는 5%미만이어야 합니다." #: src/components/Exchange/UsefulLinks.tsx msgid "Speed up page loading" @@ -4472,10 +4590,15 @@ msgstr "통계" msgid "Stop Loss Decrease" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Stop-Loss" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Stop-Loss PnL" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "Structured Products" msgstr "구조화금융 프로덕트" @@ -4524,7 +4647,7 @@ msgstr "" msgid "Submit" msgstr "제출" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Success claimings" msgstr "" @@ -4550,10 +4673,6 @@ msgstr "스왑" msgid "Swap Fee" msgstr "" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx -msgid "Swap Fees" -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Swap Order created!" msgstr "스완 주문 생성!" @@ -4566,7 +4685,6 @@ msgstr "스왑 주문 생성 실패." msgid "Swap Order submitted!" msgstr "스왑 주문 제출 완료!" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Swap Price Impact" msgstr "" @@ -4700,11 +4818,15 @@ msgstr "" msgid "TP/SL" msgstr "" -#: src/domain/synthetics/orders/utils.ts +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Take-Profit" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Take-Profit PnL" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "Take-profit and stop-loss orders can be set after opening a position. <0/><1/>There will be a \"Close\" button on each position row, clicking this will display the option to set trigger orders. <2/><3/>For screenshots and more information, please see the <4>docs." msgstr "TP/SL 주문은 포지션을 연 후 가능합니다. <0/><1/>각 행의 \"닫기\" 버튼을 클리하면 트리거 주문 설정 화면을 표시합니다. <2/><3/>더 자세한 스크린샷과 정보는 <4>docs를 참고해주세요." @@ -4771,10 +4893,6 @@ msgstr "" msgid "The Bonus Rebate will be airdropped as ARB tokens on a pro-rata basis. <0>Read more." msgstr "" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "The Boosted APR is from your staked Multiplier Points." -msgstr "\"APR 부스트는 스테이킹된 멀티플라이어 포인트로부터 적용됩니다." - #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx msgid "The Current Price Impact is {0}. Consider adding a buffer of 0.30% to it so the order is more likely to be processed." msgstr "" @@ -4787,18 +4905,15 @@ msgstr "" msgid "The Gambit protocol is in beta, please read the <0>staking detailsbefore participating." msgstr "해당 Gambit 프로토콜은 베타 버전입니다. 참여하기 전에 <0>스테이킹 세부사항을 참조해주세요." +#: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "The Max Execution Fee is overestimated by {maxExecutionFeeText}%. Upon execution, the excess Execution Fee is sent back to your account." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "The Max Execution Fee is set to a higher value to handle potential increases in gas price during order execution. Any excess execution fee will be refunded to your account when the order is executed. Only applicable to GMX V2." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "The Order may not execute at the desired {priceText} as the current Price Impact {0} is higher than its Acceptable Price Impact {1}. Consider canceling and creating a new {suggestionType} Order." -msgstr "" - #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "The address of the esGMX (IOU) token is {esGmxIouAddress}." msgstr "esGMX (IOU) 토큰의 주소는 {esGmxIouAddress}입니다." @@ -4827,11 +4942,23 @@ msgstr "시장 평균가가 변화되었습니다. 귀하의 주소 옆에 \"... msgid "The maximum number of authorized Actions has been reached. Re-authorize a higher value using the \"Max allowed actions\" field." msgstr "" +#: src/domain/synthetics/fees/utils/executionFee.ts +msgid "The network Fees are high currently, which may be due to a temporary increase in transactions on the {0} network." +msgstr "" + #: src/domain/legacy.ts #: src/domain/synthetics/fees/utils/executionFee.ts msgid "The network Fees are very high currently, which may be due to a temporary increase in transactions on the {0} network." msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "The order may not execute at the desired {priceText} as its acceptable price impact is set to {formattedOrderAcceptablePriceImpact}, which is lower than the current market price impact of {formattedCurrentAcceptablePriceImpact}. It can be edited using the \"Edit\" button." +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "The order will not be executed as its trigger price is beyond the position's liquidation price." +msgstr "" + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "The order will only execute if the Min. Receive is met and there is sufficient liquidity." msgstr "" @@ -4853,9 +4980,13 @@ msgid "The pending borrow fee will be charged on this transaction." msgstr "" #: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of -{1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#~ msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +#~ msgstr "" + #: src/components/Exchange/SwapBox.js msgid "The position will be opened at {0} USD with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "해당 포지션은 최대 슬리피지 {1}%의 {0} USD에서 열리게 됩니다.<0/><1/>슬리피지 설정은 지갑 연동 후 최상단 우측, 귀하의 지갑주소 우측의 세팅을 통해서 설정할 수 있습니다.<2/><3/><4>더 자세한 정보<4/>" @@ -4964,9 +5095,8 @@ msgstr "해당 코드는 {0}에 아직 등록되지 않았기때문에, 소개 msgid "This is the maximum top-up amount that will be sent from your Main account to your Subaccount after each transaction. The actual amount sent will depend on the final transaction fee." msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "This market uses an Adaptive Funding Rate. The Funding Rate will adjust over time depending on the ratio of longs and shorts. <0>Read more." +#: src/domain/synthetics/orders/utils.ts +msgid "This order using {collateralSymbol} as collateral will not be valid for the existing {longText} position using {symbol} as collateral." msgstr "" #: src/components/Exchange/TradeHistory.js @@ -5137,7 +5267,6 @@ msgstr "" #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Trades" msgstr "트레이드" @@ -5240,7 +5369,6 @@ msgstr "트리거" #: src/components/Synthetics/OrderList/OrderList.tsx #: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Trigger Price" msgstr "" @@ -5252,10 +5380,6 @@ msgstr "" msgid "Trigger order disabled, pending {0} upgrade" msgstr "" -#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx -msgid "Trigger order for" -msgstr "" - #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Triggered at: {0}" msgstr "" @@ -5359,7 +5483,7 @@ msgid "Unstake submitted! <0>View status." msgstr "언스테이킹 제출완료! <0>상태 보기." #: src/pages/Stake/StakeV2.js -msgid "Unstaking will burn <0>{0} Multiplier Points. {1}" +msgid "Unstaking will burn <0>{0} Multiplier Points. <1>You will earn {1}% less {nativeTokenSymbol} rewards with this action." msgstr "" #: src/pages/Stake/StakeV1.js @@ -5569,6 +5693,18 @@ msgstr "보기" msgid "View in Explorer" msgstr "Explorer에서 보기" +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Arbitrum" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Avalanche" +msgstr "" + #: src/components/Synthetics/StatusNotification/SubaccountNotification.tsx msgid "View status" msgstr "" @@ -5799,9 +5935,12 @@ msgstr "<0>여기에서 수령한 내역을 확인할 수 있습니다." msgid "You can currently vest a maximum of {0} esGMX tokens at a ratio of {1} {stakingToken} to 1 esGMX." msgstr "{1} {stakingToken} 대 1 esGMX 비율로 최대 {0} esGMX 토큰을 현재 베스팅 할 수 있습니다." +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx +msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than -{0}, may result in failed orders if prices are volatile." +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than {0}, may result in failed orders if prices are volatile." msgstr "" @@ -5829,10 +5968,6 @@ msgstr "{sender}로부터 보류중인 전송이 있습니다." msgid "You have an active Limit Order to Increase {longOrShortText} {sizeInToken} {0} (${1}) at price ${2}" msgstr "{longOrShortText} {sizeInToken} {0} (${1})를 ${2} 가격에서 증가시키는 액티브한 지정가 주문이 존재합니다." -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have an active Limit Order to Increase {longShortText} {0} {sizeText} at price {1}." -msgstr "" - #: src/components/Exchange/PositionSeller.js msgid "You have an active order to decrease {longOrShortText} {sizeInToken} {0} (${1}) at {prefix} {2}" msgstr "" @@ -5861,25 +5996,24 @@ msgstr "" msgid "You have an existing position with {0} as collateral. This action will not apply for that position." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "" -"You have an existing {longText} position with {0} as Collateral. This Order will not\n" -"be valid for that Position." -msgstr "" - #: src/components/Exchange/ConfirmationBox.js msgid "You have multiple existing Increase {longOrShortText} {0} limit orders" msgstr "{longOrShortText} {0}에 대한 복수의 지정가 주문이 존재합니다." -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have multiple existing Increase {longShortText} {0} limit orders" -msgstr "" - #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "You have not deposited any tokens for vesting." msgstr "베스트팅을 위한 토큰이 예치되지 않았습니다." +#: src/components/Stake/GMXAprTooltip.tsx +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points using the \"Compound\" button." +msgstr "" + +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points." +msgstr "" + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "You have selected {collateralTokenSymbol} as Collateral, the Liquidation Price will vary based on the price of {collateralTokenSymbol}." msgstr "" @@ -5928,14 +6062,19 @@ msgstr "해당 주문이 실행되게 되면 최소 {0} {1}을 받을 수 있습 msgid "You will receive at least {toAmountText} if this order is executed. This price is being updated in real time based on Swap Fees and Price Impact." msgstr "" +#: src/pages/Stake/StakeV2.js +#: src/pages/Stake/StakeV2.js +msgid "Your APR" +msgstr "" + #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "Your esGMX (IOU) balance will decrease by your claim amount after claiming, this is expected behaviour." msgstr "귀하의 esGMX(IOU) 잔액은 수령 후 수령액만큼 감소하는데 이는 상정된 행동입니다." #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "Your position's collateral after deducting fees." -msgstr "수수료를 제외한 귀하의 포지션 담보입니다." +msgid "Your position's collateral after deducting fees:" +msgstr "수수료를 제외한 귀하의 포지션 담보입니다:" #: src/pages/CompleteAccountTransfer/CompleteAccountTransfer.js msgid "Your transfer has been completed." @@ -5970,7 +6109,6 @@ msgid "from" msgstr "" #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "hide" msgstr "숨기기" @@ -5978,20 +6116,32 @@ msgstr "숨기기" msgid "in liquidity" msgstr "유동성" +#: src/domain/synthetics/orders/utils.ts +msgid "limit price" +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "long" +msgstr "" + #: src/pages/Dashboard/DashboardV2.js msgid "not staked" msgstr "스테이킹되지 않음" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "pay" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "receive" msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "short" +msgstr "" + #: src/pages/PositionsOverview/PositionsOverview.js msgid "size" msgstr "사이즈" @@ -6004,8 +6154,11 @@ msgstr "스테이킹됨" msgid "time to liq" msgstr "청산까지의 시간" +#: src/domain/synthetics/orders/utils.ts +msgid "trigger price" +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "view" msgstr "보기" @@ -6022,6 +6175,10 @@ msgstr "" msgid "{0, plural, one {Pending {symbolsText} approval} other {Pending {symbolsText} approvals}}" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "{0, plural, one {You have an active Limit Order to Increase} other {You have multiple active Limit Orders to Increase}}" +msgstr "" + #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "{0} <0><1>{indexName}<2>[{poolName}] <3>market selected." msgstr "" @@ -6102,6 +6259,10 @@ msgstr "{0}은 목표 가중치를 미달합니다.<0/><1/>{1}로 <2>GLP 구매< msgid "{0} is required for collateral." msgstr "담보를 위해 {0}이 필요합니다." +#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx +msgid "{0} order for" +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "{0} pool exceeded, try different token" msgstr "{0} 풀이 초과되었습니다. 다른 자산으로 시도해보세요" @@ -6202,6 +6363,22 @@ msgstr "" msgid "{longOrShortText} {0} market selected" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee and pay a borrow fee of {borrowRate} per hour." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee or a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and do not pay a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and {borrowAction} a borrow fee of {borrowRate} per hour." +msgstr "" + #: src/components/Synthetics/MarketCard/MarketCard.tsx msgid "{longShortText} {0} Open Interest" msgstr "" @@ -6218,10 +6395,6 @@ msgstr "" msgid "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR" msgstr "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "{nativeTokenSymbol} APR" -msgstr "" - #: src/components/Stake/GMXAprTooltip.tsx msgid "{nativeTokenSymbol} Base APR" msgstr "" diff --git a/src/locales/pseudo/messages.po b/src/locales/pseudo/messages.po index 6d6ea76ebf..698751b7a5 100644 --- a/src/locales/pseudo/messages.po +++ b/src/locales/pseudo/messages.po @@ -135,6 +135,10 @@ msgstr "" msgid "<0>{0} <1><2>{indexName}<3>[{poolName}] <4>market selected" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "A Size percentage is required." +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "A snapshot of the USD value of your {0} collateral is taken when the position is opened." msgstr "" @@ -243,6 +247,14 @@ msgstr "" msgid "Accrued Positive Funding Fees for Positions not yet claimable. They will become available to claim by using the \"Settle\" button, or after the Position is increased, decreased or closed." msgstr "" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +msgid "Accrued Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Accrued Price Impact Rebates. They will become Claimable after some time.<0/><1/><2>Read more." +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "Acknowledge epoch is ending in {minutes} minutes" msgstr "" @@ -257,6 +269,10 @@ msgstr "" msgid "Acknowledge high Swap Price Impact" msgstr "" +#: src/domain/synthetics/trade/useHighExecutionFeeConsent.tsx +msgid "Acknowledge very high network Fees" +msgstr "" + #: src/pages/Actions/Actions.js #: src/pages/SyntheticsActions/SyntheticsActions.tsx msgid "Actions" @@ -303,6 +319,10 @@ msgstr "" msgid "Adding..." msgstr "" +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +#~ msgid "Additional Execution Fee" +#~ msgstr "" + #: src/pages/Stake/StakeV2.js msgid "Additional reserve required" msgstr "" @@ -344,15 +364,15 @@ msgstr "" msgid "Allow {wrappedTokenSymbol} to be spent" msgstr "" -#: src/App/App.js #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/SettingsModal/SettingsModal.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Allowed Slippage" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Allowed Slippage below {0}% may result in failed orders." msgstr "" @@ -444,11 +464,15 @@ msgstr "" msgid "Approving..." msgstr "" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Arbitrum APR:" msgstr "" +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "As network fees have increased, an additional execution fee is needed." +msgstr "" + #: src/components/Exchange/NoLiquidityErrorModal.tsx msgid "As there is not enough liquidity in GLP to swap {0} to {swapTokenSymbol}, you can use the option below to do so:" msgstr "" @@ -492,8 +516,8 @@ msgstr "" msgid "Available on your preferred network" msgstr "" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Avalanche APR:" msgstr "" @@ -518,6 +542,10 @@ msgstr "" msgid "Base APR" msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Base {nativeTokenSymbol} APR" +msgstr "" + #: src/pages/BeginAccountTransfer/BeginAccountTransfer.js msgid "Begin Transfer" msgstr "" @@ -546,7 +574,6 @@ msgstr "" #: src/components/Exchange/PositionsList.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Borrow Fee" @@ -561,6 +588,11 @@ msgstr "" msgid "Borrow Fee Rate" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Borrowing fees help ensure available liquidity. <0>Read more." +msgstr "" + #: src/components/Synthetics/BridgingInfo/BridgingInfo.tsx msgid "Bridge {tokenSymbol} to {chainName} using any of the options below:" msgstr "" @@ -596,7 +628,7 @@ msgstr "" msgid "Buy GLP" msgstr "" -#: src/pages/Buy/Buy.js +#: src/pages/Buy/Buy.tsx msgid "Buy GLP or GMX" msgstr "" @@ -649,26 +681,10 @@ msgstr "" msgid "Buy GMX using any token from any network:" msgstr "" -#: src/pages/Buy/Buy.js -msgid "Buy Protocol Tokens" -msgstr "" - #: src/components/Glp/GlpSwap.js msgid "Buy failed." msgstr "" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Arbitrum" -msgstr "" - -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Avalanche" -msgstr "" - #: src/pages/BuyGMX/BuyGMX.tsx msgid "Buy or Transfer AVAX to Avalanche" msgstr "" @@ -729,7 +745,6 @@ msgstr "" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts @@ -759,7 +774,7 @@ msgstr "" msgid "Cancelling {ordersText}" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Chart positions" @@ -781,6 +796,7 @@ msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/Claims/ClaimableCard.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV1.js @@ -807,7 +823,7 @@ msgid "Claim GMX Rewards" msgstr "" #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx -msgid "Claim Price Impact" +msgid "Claim Price Impact Rebates" msgstr "" #: src/pages/Stake/StakeV2.js @@ -853,6 +869,10 @@ msgstr "" msgid "Claim submitted." msgstr "" +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "Claim {totalUsd}" +msgstr "" + #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "Claim {wrappedTokenSymbol} Rewards" @@ -864,30 +884,37 @@ msgstr "" msgid "Claimable" msgstr "" +#: src/components/Synthetics/Claims/ClaimableCard.tsx +msgid "Claimable Price Impact Rebates.<0/><1/><2>Read more." +msgstr "" + #: src/components/Referrals/AffiliatesStats.tsx msgid "Claimable Rebates" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Claiming Price Impact Rebate..." +msgstr "" + +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Claiming failed" msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV2.js msgid "Claiming..." msgstr "" -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Claims" msgstr "" #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx -msgid "Claims (1)" +msgid "Claims ({totalClaimables})" msgstr "" #: src/components/Exchange/PositionsList.js @@ -1044,6 +1071,7 @@ msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx msgid "Confirm Claim" msgstr "" @@ -1350,7 +1378,6 @@ msgstr "" #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -1370,6 +1397,10 @@ msgstr "" msgid "Decrease the Leverage by using the slider. If the Leverage slider is disabled, you can increase the Pay amount or reduce the Order size." msgstr "" +#: src/components/Synthetics/ConfirmationBox/SLTPEntries.tsx +msgid "Decrease {0} Long by {1} at ${2}." +msgstr "" + #: src/components/Exchange/TradeHistory.js #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx msgid "Decreased" @@ -1463,7 +1494,7 @@ msgstr "" msgid "Diff" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Disable order validations" msgstr "" @@ -1471,7 +1502,7 @@ msgstr "" msgid "Disconnect" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Display PnL after fees" msgstr "" @@ -1502,6 +1533,10 @@ msgstr "" msgid "Earn ARB tokens by purchasing GM tokens, trading, or migrating liquidity from GLP to GM. Only for GMX V2." msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Earn an extra {0}% {nativeTokenSymbol} Boosted APR by increasing your staked <0>Multiplier Points." +msgstr "" + #: src/components/Header/AppHeaderLinks.tsx msgid "Ecosystem" msgstr "" @@ -1771,6 +1806,7 @@ msgid "Execute {orderTypeName} Order: {positionText} {sizeDeltaText}," msgstr "" #: src/components/Exchange/FeesTooltip.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx msgid "Execution Fee" msgstr "" @@ -1815,14 +1851,14 @@ msgstr "" msgid "FUNDING FEE" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "FUNDING RATE / 1h" -msgstr "" - #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx msgid "Failed Settlement of Funding Fees" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Failed to Claim Price Impact Rebate" +msgstr "" + #: src/domain/synthetics/orders/cancelOrdersTxn.ts msgid "Failed to cancel {ordersText}" msgstr "" @@ -1847,6 +1883,7 @@ msgstr "" #: src/components/Glp/GlpSwap.js #: src/components/Glp/GlpSwap.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Fees" msgstr "" @@ -1963,11 +2000,10 @@ msgstr "" msgid "Fulfilling order request" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts msgid "Funding Claimed" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Funding Fee" @@ -1977,14 +2013,15 @@ msgstr "" msgid "Funding Fee Rate" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Funding Rate / 1h" -msgstr "" - #: src/components/Synthetics/Claims/ClaimableCardUI.tsx msgid "Funding fees" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Funding fees help to balance longs and shorts and are exchanged between both sides. <0>Read more." +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "GBC NFTs APR tracker and rewards" msgstr "" @@ -2015,7 +2052,7 @@ msgstr "" msgid "GLP buy disabled, pending {0} upgrade" msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GLP is the liquidity provider token for GMX V1 markets. Accrues 70% of the V1 markets generated fees." msgstr "" @@ -2043,7 +2080,7 @@ msgstr "" msgid "GM can be sold for {0} and {1} for this market up to the specified selling caps. The remaining tokens in the pool are reserved for currently open Positions." msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GM is the liquidity provider token for GMX V2 markets. Accrues 63% of the V2 markets generated fees." msgstr "" @@ -2132,7 +2169,7 @@ msgstr "" msgid "GMX is not actively looking for new hires at the moment. However, if you think you can contribute to the project, please email <0>jobs@gmx.io." msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GMX is the utility and governance token. Accrues 30% and 27% of V1 and V2 markets generated fees, respectively." msgstr "" @@ -2185,6 +2222,13 @@ msgstr "" msgid "Governance" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.tsx +#: src/components/Synthetics/PositionEditor/PositionEditor.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "High Execution Fee not yet acknowledged" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "High Slippage, Swap Anyway" msgstr "" @@ -2193,6 +2237,13 @@ msgstr "" msgid "High USDG Slippage, Long Anyway" msgstr "" +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#~ msgid "High network Fee not yet acknowledged" +#~ msgstr "" + #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "I am aware of the trigger orders" @@ -2228,7 +2279,7 @@ msgstr "" msgid "Incentives are airdropped weekly." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Include PnL in leverage display" msgstr "" @@ -2250,7 +2301,6 @@ msgstr "" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -2408,7 +2458,7 @@ msgstr "" msgid "Invalid Transfer Addresses: Please check the url." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid execution fee buffer value" msgstr "" @@ -2426,7 +2476,7 @@ msgstr "" msgid "Invalid price, see warning" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid slippage value" msgstr "" @@ -2455,7 +2505,6 @@ msgid "Keep Leverage is not possible" msgstr "" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "Keep leverage at {0}" msgstr "" @@ -2464,6 +2513,10 @@ msgstr "" msgid "Keep leverage at {0}x" msgstr "" +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "Keep leverage at {keepLeverageAtValue}" +msgstr "" + #: src/components/Synthetics/ChartTokenSelector/ChartTokenSelector.tsx msgid "LONG LIQ." msgstr "" @@ -2548,7 +2601,6 @@ msgstr "" #: src/components/Synthetics/PositionItem/PositionItem.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts -#: src/domain/synthetics/orders/utils.ts msgid "Limit" msgstr "" @@ -2572,7 +2624,6 @@ msgstr "" #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Limit Price" msgstr "" @@ -2705,8 +2756,8 @@ msgstr "" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -2723,7 +2774,6 @@ msgstr "" #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -2738,14 +2788,6 @@ msgstr "" msgid "Long Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Long Liquidity" msgstr "" @@ -2754,14 +2796,11 @@ msgstr "" msgid "Long Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Long Positions" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Long positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Long {0}" msgstr "" @@ -2778,7 +2817,9 @@ msgstr "" msgid "Loss" msgstr "" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/GmList/GmList.tsx msgid "MARKET" msgstr "" @@ -2894,16 +2935,15 @@ msgid "Max Capacity for {0} Reached" msgstr "" #: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Max Execution Fee" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee Buffer" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee buffer below {0}% may result in failed orders." msgstr "" @@ -2945,7 +2985,7 @@ msgstr "" msgid "Max close amount exceeded" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max execution fee buffer precision is 0.01%" msgstr "" @@ -2975,10 +3015,14 @@ msgstr "" msgid "Max pool capacity reached for {0}<0/><1/>Please mint GLP using another token" msgstr "" -#: src/App/App.js -msgid "Max slippage precision is 0.01%" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Max slippage precision is -0.01%" msgstr "" +#: src/App/App.js +#~ msgid "Max slippage precision is 0.01%" +#~ msgstr "" + #: src/components/Synthetics/MarketStats/MarketStats.tsx #: src/components/Synthetics/MarketStats/MarketStats.tsx #: src/components/Synthetics/MarketStats/MarketStats.tsx @@ -3025,11 +3069,11 @@ msgstr "" msgid "Max {0} short exceeded" msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Arbitrum APR:" msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Avalanche APR: {0}" msgstr "" @@ -3038,7 +3082,11 @@ msgid "Max. Leverage exceeded" msgstr "" #: src/components/Stake/GMXAprTooltip.tsx -msgid "Max. {nativeTokenSymbol} APR with 200% Boost for this week: {0}%." +msgid "Max. {nativeTokenSymbol} APR" +msgstr "" + +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Max. {nativeTokenSymbol} APR is calculated with the max. 200% Boost Percentage by staking <0>Multiplier Points." msgstr "" #: src/components/Migration/Migration.js @@ -3148,9 +3196,16 @@ msgid "Multiplier Points APR" msgstr "" #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "NA" msgstr "" +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "NET FEE / 1 H" +msgstr "" + #: src/pages/NftWallet/NftWallet.js msgid "NFT Address" msgstr "" @@ -3171,6 +3226,20 @@ msgstr "" msgid "Neither Collateral nor realized PnL is enough to cover pending Fees. Please close a larger position amount." msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Fee" +msgstr "" + +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Net Fee / 1h" +msgstr "" + +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Rebate" +msgstr "" + #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -3199,7 +3268,12 @@ msgstr "" msgid "Networks and Settings" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "New Collateral" +msgstr "" + #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Next" msgstr "" @@ -3275,6 +3349,10 @@ msgstr "" msgid "Note that orders are not guaranteed to be executed.<0/><1/>This can occur in a few situations including but not exclusive to:" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Old Collateral" +msgstr "" + #: src/components/AddressDropdown/AddressDropdown.tsx #: src/components/Synthetics/SubaccountModal/SubaccountModal.tsx msgid "One-Click Trading" @@ -3351,10 +3429,6 @@ msgstr "" msgid "Order" msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "Order Trigger Price is beyond position's Liquidation Price." -msgstr "" - #: src/components/Synthetics/OrderItem/OrderItem.tsx msgid "Order Type" msgstr "" @@ -3635,7 +3709,6 @@ msgstr "" msgid "Positions ({0})" msgstr "" -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Positions{0}" msgstr "" @@ -3645,6 +3718,7 @@ msgid "Positive Funding Fees for a Position become claimable after the Position msgstr "" #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Prev" msgstr "" @@ -3686,6 +3760,20 @@ msgstr "" msgid "Price Impact" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Price Impact Rebate Claimed" +msgstr "" + +#: src/components/Synthetics/Claims/ClaimableCardUI.tsx +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates for closing trades are claimable under the Claims tab. <0>Read more." +msgstr "" + +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts @@ -3693,6 +3781,10 @@ msgstr "" msgid "Price Impact not yet acknowledged" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3700,6 +3792,10 @@ msgstr "" msgid "Price above Liq. Price" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3713,6 +3809,14 @@ msgstr "" msgid "Price above Mark Price" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Mark Price." +msgstr "" + +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3720,6 +3824,10 @@ msgstr "" msgid "Price below Liq. Price" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3733,6 +3841,10 @@ msgstr "" msgid "Price below Mark Price" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Mark Price." +msgstr "" + #: src/pages/OrdersOverview/OrdersOverview.js msgid "Price conditions are met" msgstr "" @@ -3775,6 +3887,10 @@ msgstr "" msgid "Protocol" msgstr "" +#: src/pages/Buy/Buy.tsx +msgid "Protocol Tokens" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js #: src/pages/Ecosystem/Ecosystem.js msgid "Protocol analytics" @@ -3796,9 +3912,14 @@ msgstr "" msgid "Purchase Insurance" msgstr "" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "REBATE" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Read more" msgstr "" @@ -4025,7 +4146,7 @@ msgstr "" msgid "Same as current active code" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Save" msgstr "" @@ -4191,10 +4312,10 @@ msgstr "" msgid "Set TP/SL" msgstr "" -#: src/App/App.js #: src/components/Header/AppHeaderLinks.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx +#: src/components/SettingsModal/SettingsModal.tsx msgid "Settings" msgstr "" @@ -4256,8 +4377,8 @@ msgstr "" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4274,7 +4395,6 @@ msgstr "" #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -4289,14 +4409,6 @@ msgstr "" msgid "Short Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Short Liquidity" msgstr "" @@ -4305,14 +4417,11 @@ msgstr "" msgid "Short Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Short Positions" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Short positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Short {0}" msgstr "" @@ -4321,10 +4430,14 @@ msgstr "" msgid "Shorting..." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Show debug values" msgstr "" +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Show details" +msgstr "" + #: src/pages/Home/Home.js msgid "Simple Swaps" msgstr "" @@ -4350,6 +4463,7 @@ msgstr "" #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4361,15 +4475,19 @@ msgstr "" #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Slippage is too high" msgstr "" -#: src/App/App.js -msgid "Slippage should be less than 5%" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Slippage should be less than -5%" msgstr "" +#: src/App/App.js +#~ msgid "Slippage should be less than 5%" +#~ msgstr "" + #: src/components/Exchange/UsefulLinks.tsx msgid "Speed up page loading" msgstr "" @@ -4472,10 +4590,15 @@ msgstr "" msgid "Stop Loss Decrease" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Stop-Loss" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Stop-Loss PnL" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "Structured Products" msgstr "" @@ -4524,7 +4647,7 @@ msgstr "" msgid "Submit" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Success claimings" msgstr "" @@ -4550,10 +4673,6 @@ msgstr "" msgid "Swap Fee" msgstr "" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx -msgid "Swap Fees" -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Swap Order created!" msgstr "" @@ -4566,7 +4685,6 @@ msgstr "" msgid "Swap Order submitted!" msgstr "" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Swap Price Impact" msgstr "" @@ -4700,11 +4818,15 @@ msgstr "" msgid "TP/SL" msgstr "" -#: src/domain/synthetics/orders/utils.ts +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Take-Profit" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Take-Profit PnL" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "Take-profit and stop-loss orders can be set after opening a position. <0/><1/>There will be a \"Close\" button on each position row, clicking this will display the option to set trigger orders. <2/><3/>For screenshots and more information, please see the <4>docs." msgstr "" @@ -4771,10 +4893,6 @@ msgstr "" msgid "The Bonus Rebate will be airdropped as ARB tokens on a pro-rata basis. <0>Read more." msgstr "" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "The Boosted APR is from your staked Multiplier Points." -msgstr "" - #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx msgid "The Current Price Impact is {0}. Consider adding a buffer of 0.30% to it so the order is more likely to be processed." msgstr "" @@ -4787,18 +4905,15 @@ msgstr "" msgid "The Gambit protocol is in beta, please read the <0>staking detailsbefore participating." msgstr "" +#: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "The Max Execution Fee is overestimated by {maxExecutionFeeText}%. Upon execution, the excess Execution Fee is sent back to your account." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "The Max Execution Fee is set to a higher value to handle potential increases in gas price during order execution. Any excess execution fee will be refunded to your account when the order is executed. Only applicable to GMX V2." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "The Order may not execute at the desired {priceText} as the current Price Impact {0} is higher than its Acceptable Price Impact {1}. Consider canceling and creating a new {suggestionType} Order." -msgstr "" - #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "The address of the esGMX (IOU) token is {esGmxIouAddress}." msgstr "" @@ -4827,11 +4942,23 @@ msgstr "" msgid "The maximum number of authorized Actions has been reached. Re-authorize a higher value using the \"Max allowed actions\" field." msgstr "" +#: src/domain/synthetics/fees/utils/executionFee.ts +msgid "The network Fees are high currently, which may be due to a temporary increase in transactions on the {0} network." +msgstr "" + #: src/domain/legacy.ts #: src/domain/synthetics/fees/utils/executionFee.ts msgid "The network Fees are very high currently, which may be due to a temporary increase in transactions on the {0} network." msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "The order may not execute at the desired {priceText} as its acceptable price impact is set to {formattedOrderAcceptablePriceImpact}, which is lower than the current market price impact of {formattedCurrentAcceptablePriceImpact}. It can be edited using the \"Edit\" button." +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "The order will not be executed as its trigger price is beyond the position's liquidation price." +msgstr "" + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "The order will only execute if the Min. Receive is met and there is sufficient liquidity." msgstr "" @@ -4853,9 +4980,13 @@ msgid "The pending borrow fee will be charged on this transaction." msgstr "" #: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of -{1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#~ msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +#~ msgstr "" + #: src/components/Exchange/SwapBox.js msgid "The position will be opened at {0} USD with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "" @@ -4964,9 +5095,8 @@ msgstr "" msgid "This is the maximum top-up amount that will be sent from your Main account to your Subaccount after each transaction. The actual amount sent will depend on the final transaction fee." msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "This market uses an Adaptive Funding Rate. The Funding Rate will adjust over time depending on the ratio of longs and shorts. <0>Read more." +#: src/domain/synthetics/orders/utils.ts +msgid "This order using {collateralSymbol} as collateral will not be valid for the existing {longText} position using {symbol} as collateral." msgstr "" #: src/components/Exchange/TradeHistory.js @@ -5137,7 +5267,6 @@ msgstr "" #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Trades" msgstr "" @@ -5240,7 +5369,6 @@ msgstr "" #: src/components/Synthetics/OrderList/OrderList.tsx #: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Trigger Price" msgstr "" @@ -5252,10 +5380,6 @@ msgstr "" msgid "Trigger order disabled, pending {0} upgrade" msgstr "" -#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx -msgid "Trigger order for" -msgstr "" - #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Triggered at: {0}" msgstr "" @@ -5359,7 +5483,7 @@ msgid "Unstake submitted! <0>View status." msgstr "" #: src/pages/Stake/StakeV2.js -msgid "Unstaking will burn <0>{0} Multiplier Points. {1}" +msgid "Unstaking will burn <0>{0} Multiplier Points. <1>You will earn {1}% less {nativeTokenSymbol} rewards with this action." msgstr "" #: src/pages/Stake/StakeV1.js @@ -5569,6 +5693,18 @@ msgstr "" msgid "View in Explorer" msgstr "" +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Arbitrum" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Avalanche" +msgstr "" + #: src/components/Synthetics/StatusNotification/SubaccountNotification.tsx msgid "View status" msgstr "" @@ -5799,9 +5935,12 @@ msgstr "" msgid "You can currently vest a maximum of {0} esGMX tokens at a ratio of {1} {stakingToken} to 1 esGMX." msgstr "" +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx +msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than -{0}, may result in failed orders if prices are volatile." +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than {0}, may result in failed orders if prices are volatile." msgstr "" @@ -5829,10 +5968,6 @@ msgstr "" msgid "You have an active Limit Order to Increase {longOrShortText} {sizeInToken} {0} (${1}) at price ${2}" msgstr "" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have an active Limit Order to Increase {longShortText} {0} {sizeText} at price {1}." -msgstr "" - #: src/components/Exchange/PositionSeller.js msgid "You have an active order to decrease {longOrShortText} {sizeInToken} {0} (${1}) at {prefix} {2}" msgstr "" @@ -5861,23 +5996,22 @@ msgstr "" msgid "You have an existing position with {0} as collateral. This action will not apply for that position." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "" -"You have an existing {longText} position with {0} as Collateral. This Order will not\n" -"be valid for that Position." -msgstr "" - #: src/components/Exchange/ConfirmationBox.js msgid "You have multiple existing Increase {longOrShortText} {0} limit orders" msgstr "" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have multiple existing Increase {longShortText} {0} limit orders" +#: src/pages/Stake/StakeV2.js +#: src/pages/Stake/StakeV2.js +msgid "You have not deposited any tokens for vesting." msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx #: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points using the \"Compound\" button." +msgstr "" + #: src/pages/Stake/StakeV2.js -msgid "You have not deposited any tokens for vesting." +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points." msgstr "" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx @@ -5928,13 +6062,18 @@ msgstr "" msgid "You will receive at least {toAmountText} if this order is executed. This price is being updated in real time based on Swap Fees and Price Impact." msgstr "" +#: src/pages/Stake/StakeV2.js +#: src/pages/Stake/StakeV2.js +msgid "Your APR" +msgstr "" + #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "Your esGMX (IOU) balance will decrease by your claim amount after claiming, this is expected behaviour." msgstr "" #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "Your position's collateral after deducting fees." +msgid "Your position's collateral after deducting fees:" msgstr "" #: src/pages/CompleteAccountTransfer/CompleteAccountTransfer.js @@ -5970,7 +6109,6 @@ msgid "from" msgstr "" #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "hide" msgstr "" @@ -5978,20 +6116,32 @@ msgstr "" msgid "in liquidity" msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "limit price" +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "long" +msgstr "" + #: src/pages/Dashboard/DashboardV2.js msgid "not staked" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "pay" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "receive" msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "short" +msgstr "" + #: src/pages/PositionsOverview/PositionsOverview.js msgid "size" msgstr "" @@ -6004,8 +6154,11 @@ msgstr "" msgid "time to liq" msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "trigger price" +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "view" msgstr "" @@ -6022,6 +6175,10 @@ msgstr "" msgid "{0, plural, one {Pending {symbolsText} approval} other {Pending {symbolsText} approvals}}" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "{0, plural, one {You have an active Limit Order to Increase} other {You have multiple active Limit Orders to Increase}}" +msgstr "" + #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "{0} <0><1>{indexName}<2>[{poolName}] <3>market selected." msgstr "" @@ -6102,6 +6259,10 @@ msgstr "" msgid "{0} is required for collateral." msgstr "" +#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx +msgid "{0} order for" +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "{0} pool exceeded, try different token" msgstr "" @@ -6202,6 +6363,22 @@ msgstr "" msgid "{longOrShortText} {0} market selected" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee and pay a borrow fee of {borrowRate} per hour." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee or a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and do not pay a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and {borrowAction} a borrow fee of {borrowRate} per hour." +msgstr "" + #: src/components/Synthetics/MarketCard/MarketCard.tsx msgid "{longShortText} {0} Open Interest" msgstr "" @@ -6218,10 +6395,6 @@ msgstr "" msgid "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR" msgstr "" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "{nativeTokenSymbol} APR" -msgstr "" - #: src/components/Stake/GMXAprTooltip.tsx msgid "{nativeTokenSymbol} Base APR" msgstr "" diff --git a/src/locales/ru/messages.po b/src/locales/ru/messages.po index 15f71fb426..71ab96c98d 100644 --- a/src/locales/ru/messages.po +++ b/src/locales/ru/messages.po @@ -135,6 +135,10 @@ msgstr "" msgid "<0>{0} <1><2>{indexName}<3>[{poolName}] <4>market selected" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "A Size percentage is required." +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "A snapshot of the USD value of your {0} collateral is taken when the position is opened." msgstr "Снимок долларовой стоимости вашего залога {0} делается в момент открытия позиции." @@ -243,6 +247,14 @@ msgstr "" msgid "Accrued Positive Funding Fees for Positions not yet claimable. They will become available to claim by using the \"Settle\" button, or after the Position is increased, decreased or closed." msgstr "" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +msgid "Accrued Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Accrued Price Impact Rebates. They will become Claimable after some time.<0/><1/><2>Read more." +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "Acknowledge epoch is ending in {minutes} minutes" msgstr "" @@ -257,6 +269,10 @@ msgstr "" msgid "Acknowledge high Swap Price Impact" msgstr "" +#: src/domain/synthetics/trade/useHighExecutionFeeConsent.tsx +msgid "Acknowledge very high network Fees" +msgstr "" + #: src/pages/Actions/Actions.js #: src/pages/SyntheticsActions/SyntheticsActions.tsx msgid "Actions" @@ -303,6 +319,10 @@ msgstr "Добавить реферальный код не удалось." msgid "Adding..." msgstr "Добавление..." +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +#~ msgid "Additional Execution Fee" +#~ msgstr "" + #: src/pages/Stake/StakeV2.js msgid "Additional reserve required" msgstr "Требуется дополнительный резерв" @@ -344,15 +364,15 @@ msgstr "" msgid "Allow {wrappedTokenSymbol} to be spent" msgstr "" -#: src/App/App.js #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/SettingsModal/SettingsModal.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Allowed Slippage" msgstr "Допустимое Скольжение" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Allowed Slippage below {0}% may result in failed orders." msgstr "" @@ -444,11 +464,15 @@ msgstr "Одобрение {stakingTokenSymbol}..." msgid "Approving..." msgstr "Одобрение..." -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Arbitrum APR:" msgstr "Arbitrum APR:" +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "As network fees have increased, an additional execution fee is needed." +msgstr "" + #: src/components/Exchange/NoLiquidityErrorModal.tsx msgid "As there is not enough liquidity in GLP to swap {0} to {swapTokenSymbol}, you can use the option below to do so:" msgstr "Поскольку в GLP недостаточно ликвидности для обмена {0} на {swapTokenSymbol}, вы можете воспользоваться приведенной ниже опцией, чтобы сделать это:" @@ -492,8 +516,8 @@ msgstr "Доступная сумма для вывода средств из GL msgid "Available on your preferred network" msgstr "Доступно в предпочитаемой сети" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Avalanche APR:" msgstr "Avalanche APR:" @@ -518,6 +542,10 @@ msgstr "Баланс" msgid "Base APR" msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Base {nativeTokenSymbol} APR" +msgstr "" + #: src/pages/BeginAccountTransfer/BeginAccountTransfer.js msgid "Begin Transfer" msgstr "Начать перевод" @@ -546,7 +574,6 @@ msgstr "Повышайте свои вознаграждения с помощь #: src/components/Exchange/PositionsList.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Borrow Fee" @@ -561,6 +588,11 @@ msgstr "Комиссия за пользование кредитом / день msgid "Borrow Fee Rate" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Borrowing fees help ensure available liquidity. <0>Read more." +msgstr "" + #: src/components/Synthetics/BridgingInfo/BridgingInfo.tsx msgid "Bridge {tokenSymbol} to {chainName} using any of the options below:" msgstr "" @@ -596,7 +628,7 @@ msgstr "" msgid "Buy GLP" msgstr "Купить GLP" -#: src/pages/Buy/Buy.js +#: src/pages/Buy/Buy.tsx msgid "Buy GLP or GMX" msgstr "" @@ -649,26 +681,10 @@ msgstr "" msgid "Buy GMX using any token from any network:" msgstr "" -#: src/pages/Buy/Buy.js -msgid "Buy Protocol Tokens" -msgstr "" - #: src/components/Glp/GlpSwap.js msgid "Buy failed." msgstr "Покупка не удалась." -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Arbitrum" -msgstr "Купить на Arbitrum" - -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Avalanche" -msgstr "Купить на Avalanche" - #: src/pages/BuyGMX/BuyGMX.tsx msgid "Buy or Transfer AVAX to Avalanche" msgstr "" @@ -729,7 +745,6 @@ msgstr "Невозможно выполнить из-за ошибки" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts @@ -759,7 +774,7 @@ msgstr "Отмена завершена." msgid "Cancelling {ordersText}" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Chart positions" @@ -781,6 +796,7 @@ msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/Claims/ClaimableCard.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV1.js @@ -807,7 +823,7 @@ msgid "Claim GMX Rewards" msgstr "Запрос на получение Вознаграждения GMX" #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx -msgid "Claim Price Impact" +msgid "Claim Price Impact Rebates" msgstr "" #: src/pages/Stake/StakeV2.js @@ -853,6 +869,10 @@ msgstr "Запрос завершен! <0>Увидеть статус." msgid "Claim submitted." msgstr "Запрос завершен." +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "Claim {totalUsd}" +msgstr "" + #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "Claim {wrappedTokenSymbol} Rewards" @@ -864,30 +884,37 @@ msgstr "Запрос на получение {wrappedTokenSymbol} Вознагр msgid "Claimable" msgstr "Заявленный" +#: src/components/Synthetics/Claims/ClaimableCard.tsx +msgid "Claimable Price Impact Rebates.<0/><1/><2>Read more." +msgstr "" + #: src/components/Referrals/AffiliatesStats.tsx msgid "Claimable Rebates" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Claiming Price Impact Rebate..." +msgstr "" + +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Claiming failed" msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV2.js msgid "Claiming..." msgstr "Утверждение..." -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Claims" msgstr "" #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx -msgid "Claims (1)" +msgid "Claims ({totalClaimables})" msgstr "" #: src/components/Exchange/PositionsList.js @@ -1044,6 +1071,7 @@ msgstr "Компаунд..." #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx msgid "Confirm Claim" msgstr "" @@ -1350,7 +1378,6 @@ msgstr "Децентрализованная<0/>Бессрочная Биржа" #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -1370,6 +1397,10 @@ msgstr "" msgid "Decrease the Leverage by using the slider. If the Leverage slider is disabled, you can increase the Pay amount or reduce the Order size." msgstr "" +#: src/components/Synthetics/ConfirmationBox/SLTPEntries.tsx +msgid "Decrease {0} Long by {1} at ${2}." +msgstr "" + #: src/components/Exchange/TradeHistory.js #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx msgid "Decreased" @@ -1463,7 +1494,7 @@ msgstr "Пополнение..." msgid "Diff" msgstr "Раз" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Disable order validations" msgstr "Отключить проверку ордеров" @@ -1471,7 +1502,7 @@ msgstr "Отключить проверку ордеров" msgid "Disconnect" msgstr "Разъединить" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Display PnL after fees" msgstr "Отображение PnL после комиссии" @@ -1502,6 +1533,10 @@ msgstr "Зарабатывать" msgid "Earn ARB tokens by purchasing GM tokens, trading, or migrating liquidity from GLP to GM. Only for GMX V2." msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Earn an extra {0}% {nativeTokenSymbol} Boosted APR by increasing your staked <0>Multiplier Points." +msgstr "" + #: src/components/Header/AppHeaderLinks.tsx msgid "Ecosystem" msgstr "Экосистема" @@ -1771,6 +1806,7 @@ msgid "Execute {orderTypeName} Order: {positionText} {sizeDeltaText}," msgstr "" #: src/components/Exchange/FeesTooltip.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx msgid "Execution Fee" msgstr "" @@ -1815,14 +1851,14 @@ msgstr "СБОРЫ" msgid "FUNDING FEE" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "FUNDING RATE / 1h" -msgstr "" - #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx msgid "Failed Settlement of Funding Fees" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Failed to Claim Price Impact Rebate" +msgstr "" + #: src/domain/synthetics/orders/cancelOrdersTxn.ts msgid "Failed to cancel {ordersText}" msgstr "" @@ -1847,6 +1883,7 @@ msgstr "" #: src/components/Glp/GlpSwap.js #: src/components/Glp/GlpSwap.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Fees" msgstr "Сборы" @@ -1963,11 +2000,10 @@ msgstr "" msgid "Fulfilling order request" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts msgid "Funding Claimed" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Funding Fee" @@ -1977,14 +2013,15 @@ msgstr "" msgid "Funding Fee Rate" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Funding Rate / 1h" -msgstr "" - #: src/components/Synthetics/Claims/ClaimableCardUI.tsx msgid "Funding fees" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Funding fees help to balance longs and shorts and are exchanged between both sides. <0>Read more." +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "GBC NFTs APR tracker and rewards" msgstr "GBC NFTs APR отслеживание и вознаграждения" @@ -2015,7 +2052,7 @@ msgstr "" msgid "GLP buy disabled, pending {0} upgrade" msgstr "Покупка GLP приостановлена, ожидается {0} обновление" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GLP is the liquidity provider token for GMX V1 markets. Accrues 70% of the V1 markets generated fees." msgstr "" @@ -2043,7 +2080,7 @@ msgstr "" msgid "GM can be sold for {0} and {1} for this market up to the specified selling caps. The remaining tokens in the pool are reserved for currently open Positions." msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GM is the liquidity provider token for GMX V2 markets. Accrues 63% of the V2 markets generated fees." msgstr "" @@ -2132,7 +2169,7 @@ msgstr "В настоящее время GMX работает на Arbitrum и A msgid "GMX is not actively looking for new hires at the moment. However, if you think you can contribute to the project, please email <0>jobs@gmx.io." msgstr "В настоящее время GMX не ведет активного поиска новых сотрудников. Однако, если вы считаете, что можете внести свой вклад в проект, пожалуйста, напишите <0>jobs@gmx.io." -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GMX is the utility and governance token. Accrues 30% and 27% of V1 and V2 markets generated fees, respectively." msgstr "" @@ -2185,6 +2222,13 @@ msgstr "" msgid "Governance" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.tsx +#: src/components/Synthetics/PositionEditor/PositionEditor.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "High Execution Fee not yet acknowledged" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "High Slippage, Swap Anyway" msgstr "Высокий уровень Скольжения, Обмен в Любом случае" @@ -2193,6 +2237,13 @@ msgstr "Высокий уровень Скольжения, Обмен в Люб msgid "High USDG Slippage, Long Anyway" msgstr "Высокое Скольжение USDG, Лонг в Любом случае" +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#~ msgid "High network Fee not yet acknowledged" +#~ msgstr "" + #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "I am aware of the trigger orders" @@ -2228,7 +2279,7 @@ msgstr "" msgid "Incentives are airdropped weekly." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Include PnL in leverage display" msgstr "Включить PnL в индикатор рычага" @@ -2250,7 +2301,6 @@ msgstr "Неправильная сеть" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -2408,7 +2458,7 @@ msgstr "Неверный адрес получателя" msgid "Invalid Transfer Addresses: Please check the url." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid execution fee buffer value" msgstr "" @@ -2426,7 +2476,7 @@ msgstr "Неверная цена лик." msgid "Invalid price, see warning" msgstr "Недопустимая цена, смотрите предупреждение" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid slippage value" msgstr "Недопустимое значение скольжения" @@ -2455,7 +2505,6 @@ msgid "Keep Leverage is not possible" msgstr "" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "Keep leverage at {0}" msgstr "" @@ -2464,6 +2513,10 @@ msgstr "" msgid "Keep leverage at {0}x" msgstr "" +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "Keep leverage at {keepLeverageAtValue}" +msgstr "" + #: src/components/Synthetics/ChartTokenSelector/ChartTokenSelector.tsx msgid "LONG LIQ." msgstr "" @@ -2548,7 +2601,6 @@ msgstr "" #: src/components/Synthetics/PositionItem/PositionItem.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts -#: src/domain/synthetics/orders/utils.ts msgid "Limit" msgstr "Ограничение" @@ -2572,7 +2624,6 @@ msgstr "" #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Limit Price" msgstr "Предельная Цена" @@ -2705,8 +2756,8 @@ msgstr "Загрузка..." #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -2723,7 +2774,6 @@ msgstr "Загрузка..." #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -2738,14 +2788,6 @@ msgstr "Лонг" msgid "Long Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Long Liquidity" msgstr "" @@ -2754,14 +2796,11 @@ msgstr "" msgid "Long Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Long Positions" msgstr "Лонг позиции" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Long positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Long {0}" msgstr "Лонг {0}" @@ -2778,7 +2817,9 @@ msgstr "Похоже, у вас нет реферального кода, кот msgid "Loss" msgstr "Убыток" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/GmList/GmList.tsx msgid "MARKET" msgstr "" @@ -2894,16 +2935,15 @@ msgid "Max Capacity for {0} Reached" msgstr "Максимальная Вместимость для {0} Достигнута" #: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Max Execution Fee" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee Buffer" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee buffer below {0}% may result in failed orders." msgstr "" @@ -2945,7 +2985,7 @@ msgstr "" msgid "Max close amount exceeded" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max execution fee buffer precision is 0.01%" msgstr "" @@ -2975,9 +3015,13 @@ msgstr "Достигнута максимальная вместимость п msgid "Max pool capacity reached for {0}<0/><1/>Please mint GLP using another token" msgstr "Достигнута максимальная вместимость пула для {0}<0/><1/>Пожалуйста, монетизируйте GLP, используя другой токен" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Max slippage precision is -0.01%" +msgstr "" + #: src/App/App.js -msgid "Max slippage precision is 0.01%" -msgstr "Максимальная точность скольжения составляет 0,01%" +#~ msgid "Max slippage precision is 0.01%" +#~ msgstr "Максимальная точность скольжения составляет 0,01%" #: src/components/Synthetics/MarketStats/MarketStats.tsx #: src/components/Synthetics/MarketStats/MarketStats.tsx @@ -3025,11 +3069,11 @@ msgstr "Максимальная {0} вместимость шорта" msgid "Max {0} short exceeded" msgstr "Максимальное {0} превышение шорта" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Arbitrum APR:" msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Avalanche APR: {0}" msgstr "" @@ -3038,7 +3082,11 @@ msgid "Max. Leverage exceeded" msgstr "" #: src/components/Stake/GMXAprTooltip.tsx -msgid "Max. {nativeTokenSymbol} APR with 200% Boost for this week: {0}%." +msgid "Max. {nativeTokenSymbol} APR" +msgstr "" + +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Max. {nativeTokenSymbol} APR is calculated with the max. 200% Boost Percentage by staking <0>Multiplier Points." msgstr "" #: src/components/Migration/Migration.js @@ -3148,9 +3196,16 @@ msgid "Multiplier Points APR" msgstr "Множитель баллов APR" #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "NA" msgstr "" +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "NET FEE / 1 H" +msgstr "" + #: src/pages/NftWallet/NftWallet.js msgid "NFT Address" msgstr "Адрес NFT" @@ -3171,6 +3226,20 @@ msgstr "" msgid "Neither Collateral nor realized PnL is enough to cover pending Fees. Please close a larger position amount." msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Fee" +msgstr "" + +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Net Fee / 1h" +msgstr "" + +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Rebate" +msgstr "" + #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -3199,7 +3268,12 @@ msgstr "Сети" msgid "Networks and Settings" msgstr "Сети и Настройки" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "New Collateral" +msgstr "" + #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Next" msgstr "Далее" @@ -3275,6 +3349,10 @@ msgstr "" msgid "Note that orders are not guaranteed to be executed.<0/><1/>This can occur in a few situations including but not exclusive to:" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Old Collateral" +msgstr "" + #: src/components/AddressDropdown/AddressDropdown.tsx #: src/components/Synthetics/SubaccountModal/SubaccountModal.tsx msgid "One-Click Trading" @@ -3351,10 +3429,6 @@ msgstr "" msgid "Order" msgstr "Ордер" -#: src/domain/synthetics/orders/utils.ts -msgid "Order Trigger Price is beyond position's Liquidation Price." -msgstr "" - #: src/components/Synthetics/OrderItem/OrderItem.tsx msgid "Order Type" msgstr "" @@ -3635,7 +3709,6 @@ msgstr "Позиции" msgid "Positions ({0})" msgstr "Позиции ({0})" -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Positions{0}" msgstr "" @@ -3645,6 +3718,7 @@ msgid "Positive Funding Fees for a Position become claimable after the Position msgstr "" #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Prev" msgstr "Предыдущий" @@ -3686,6 +3760,20 @@ msgstr "Цена" msgid "Price Impact" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Price Impact Rebate Claimed" +msgstr "" + +#: src/components/Synthetics/Claims/ClaimableCardUI.tsx +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates for closing trades are claimable under the Claims tab. <0>Read more." +msgstr "" + +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts @@ -3693,6 +3781,10 @@ msgstr "" msgid "Price Impact not yet acknowledged" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3700,6 +3792,10 @@ msgstr "" msgid "Price above Liq. Price" msgstr "Цена выше Ликв. Цены" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3713,6 +3809,14 @@ msgstr "Цена выше Ликв. Цены" msgid "Price above Mark Price" msgstr "Цена выше Маркированной Цены" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Mark Price." +msgstr "" + +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3720,6 +3824,10 @@ msgstr "Цена выше Маркированной Цены" msgid "Price below Liq. Price" msgstr "Цена ниже Ликв. Цены" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3733,6 +3841,10 @@ msgstr "Цена ниже Ликв. Цены" msgid "Price below Mark Price" msgstr "Цена ниже Маркированной Цены" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Mark Price." +msgstr "" + #: src/pages/OrdersOverview/OrdersOverview.js msgid "Price conditions are met" msgstr "Ценовые условия выполнены" @@ -3775,6 +3887,10 @@ msgstr "Доказательство резервов" msgid "Protocol" msgstr "" +#: src/pages/Buy/Buy.tsx +msgid "Protocol Tokens" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js #: src/pages/Ecosystem/Ecosystem.js msgid "Protocol analytics" @@ -3796,9 +3912,14 @@ msgstr "" msgid "Purchase Insurance" msgstr "Приобрести Страховку" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "REBATE" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Read more" msgstr "Читать больше" @@ -4025,7 +4146,7 @@ msgstr "" msgid "Same as current active code" msgstr "Такой же, как и текущий действующий код" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Save" msgstr "Сохранить" @@ -4191,10 +4312,10 @@ msgstr "" msgid "Set TP/SL" msgstr "" -#: src/App/App.js #: src/components/Header/AppHeaderLinks.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx +#: src/components/SettingsModal/SettingsModal.tsx msgid "Settings" msgstr "Настройки" @@ -4256,8 +4377,8 @@ msgstr "Позиция Акции" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4274,7 +4395,6 @@ msgstr "Позиция Акции" #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -4289,14 +4409,6 @@ msgstr "Шорт" msgid "Short Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Short Liquidity" msgstr "" @@ -4305,14 +4417,11 @@ msgstr "" msgid "Short Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Short Positions" msgstr "Позиция Шорта" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Short positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Short {0}" msgstr "Шорт {0}" @@ -4321,10 +4430,14 @@ msgstr "Шорт {0}" msgid "Shorting..." msgstr "Шортинг..." -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Show debug values" msgstr "" +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Show details" +msgstr "" + #: src/pages/Home/Home.js msgid "Simple Swaps" msgstr "Простые Обмены" @@ -4350,6 +4463,7 @@ msgstr "" #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4361,14 +4475,18 @@ msgstr "Размер" #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Slippage is too high" msgstr "" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Slippage should be less than -5%" +msgstr "" + #: src/App/App.js -msgid "Slippage should be less than 5%" -msgstr "Скольжение должно составлять менее 5%" +#~ msgid "Slippage should be less than 5%" +#~ msgstr "Скольжение должно составлять менее 5%" #: src/components/Exchange/UsefulLinks.tsx msgid "Speed up page loading" @@ -4472,10 +4590,15 @@ msgstr "Статистика" msgid "Stop Loss Decrease" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Stop-Loss" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Stop-Loss PnL" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "Structured Products" msgstr "Структурированные продукты" @@ -4524,7 +4647,7 @@ msgstr "" msgid "Submit" msgstr "Подать" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Success claimings" msgstr "" @@ -4550,10 +4673,6 @@ msgstr "Обмен" msgid "Swap Fee" msgstr "" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx -msgid "Swap Fees" -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Swap Order created!" msgstr "Создан Обменный Ордер" @@ -4566,7 +4685,6 @@ msgstr "Обменный Ордер не создан" msgid "Swap Order submitted!" msgstr "Обменный Ордер подан!" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Swap Price Impact" msgstr "" @@ -4700,11 +4818,15 @@ msgstr "" msgid "TP/SL" msgstr "" -#: src/domain/synthetics/orders/utils.ts +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Take-Profit" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Take-Profit PnL" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "Take-profit and stop-loss orders can be set after opening a position. <0/><1/>There will be a \"Close\" button on each position row, clicking this will display the option to set trigger orders. <2/><3/>For screenshots and more information, please see the <4>docs." msgstr "Ордера тейк-профит и стоп-лосс могут быть установлены после открытия позиции. <0/><1/>В каждой строке позиции будет кнопка \"Закрыть\", нажав на которую, можно установить триггерные ордера. <2/><3/> Для получения скриншотов и дополнительной информации, пожалуйста, смотрите <4>документы." @@ -4771,10 +4893,6 @@ msgstr "" msgid "The Bonus Rebate will be airdropped as ARB tokens on a pro-rata basis. <0>Read more." msgstr "" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "The Boosted APR is from your staked Multiplier Points." -msgstr "Повышенный APR рассчитывается из поставленных вами Баллов Множителя." - #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx msgid "The Current Price Impact is {0}. Consider adding a buffer of 0.30% to it so the order is more likely to be processed." msgstr "" @@ -4787,18 +4905,15 @@ msgstr "" msgid "The Gambit protocol is in beta, please read the <0>staking detailsbefore participating." msgstr "Протокол Gambit находится в стадии бета-тестирования, пожалуйста, прочитайте <0>детали стакингаперед участием." +#: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "The Max Execution Fee is overestimated by {maxExecutionFeeText}%. Upon execution, the excess Execution Fee is sent back to your account." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "The Max Execution Fee is set to a higher value to handle potential increases in gas price during order execution. Any excess execution fee will be refunded to your account when the order is executed. Only applicable to GMX V2." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "The Order may not execute at the desired {priceText} as the current Price Impact {0} is higher than its Acceptable Price Impact {1}. Consider canceling and creating a new {suggestionType} Order." -msgstr "" - #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "The address of the esGMX (IOU) token is {esGmxIouAddress}." msgstr "Адрес токена esGMX называется {esGmxIouAddress}." @@ -4827,11 +4942,23 @@ msgstr "Цена отметки изменилась, подумайте об у msgid "The maximum number of authorized Actions has been reached. Re-authorize a higher value using the \"Max allowed actions\" field." msgstr "" +#: src/domain/synthetics/fees/utils/executionFee.ts +msgid "The network Fees are high currently, which may be due to a temporary increase in transactions on the {0} network." +msgstr "" + #: src/domain/legacy.ts #: src/domain/synthetics/fees/utils/executionFee.ts msgid "The network Fees are very high currently, which may be due to a temporary increase in transactions on the {0} network." msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "The order may not execute at the desired {priceText} as its acceptable price impact is set to {formattedOrderAcceptablePriceImpact}, which is lower than the current market price impact of {formattedCurrentAcceptablePriceImpact}. It can be edited using the \"Edit\" button." +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "The order will not be executed as its trigger price is beyond the position's liquidation price." +msgstr "" + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "The order will only execute if the Min. Receive is met and there is sufficient liquidity." msgstr "" @@ -4853,9 +4980,13 @@ msgid "The pending borrow fee will be charged on this transaction." msgstr "" #: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of -{1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#~ msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +#~ msgstr "" + #: src/components/Exchange/SwapBox.js msgid "The position will be opened at {0} USD with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "Позиция будет открыта на {0} USD с максимальным скольжением в {1}%.<0/><1/>Сумма скольжения может быть настроена в разделе Настройки, который можно найти, нажав на свой адрес в правом верхнем углу страницы после подключения кошелька.<2/><3/><4>Более подробная информация" @@ -4964,9 +5095,8 @@ msgstr "Этот код еще не зарегистрирован на {0}, в msgid "This is the maximum top-up amount that will be sent from your Main account to your Subaccount after each transaction. The actual amount sent will depend on the final transaction fee." msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "This market uses an Adaptive Funding Rate. The Funding Rate will adjust over time depending on the ratio of longs and shorts. <0>Read more." +#: src/domain/synthetics/orders/utils.ts +msgid "This order using {collateralSymbol} as collateral will not be valid for the existing {longText} position using {symbol} as collateral." msgstr "" #: src/components/Exchange/TradeHistory.js @@ -5137,7 +5267,6 @@ msgstr "" #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Trades" msgstr "Торги" @@ -5240,7 +5369,6 @@ msgstr "Триггер" #: src/components/Synthetics/OrderList/OrderList.tsx #: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Trigger Price" msgstr "" @@ -5252,10 +5380,6 @@ msgstr "" msgid "Trigger order disabled, pending {0} upgrade" msgstr "" -#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx -msgid "Trigger order for" -msgstr "" - #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Triggered at: {0}" msgstr "" @@ -5359,7 +5483,7 @@ msgid "Unstake submitted! <0>View status." msgstr "Снятие стакинга подтверждено! <0>Посмотреть статус." #: src/pages/Stake/StakeV2.js -msgid "Unstaking will burn <0>{0} Multiplier Points. {1}" +msgid "Unstaking will burn <0>{0} Multiplier Points. <1>You will earn {1}% less {nativeTokenSymbol} rewards with this action." msgstr "" #: src/pages/Stake/StakeV1.js @@ -5569,6 +5693,18 @@ msgstr "" msgid "View in Explorer" msgstr "Просмотреть в Проводнике" +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Arbitrum" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Avalanche" +msgstr "" + #: src/components/Synthetics/StatusNotification/SubaccountNotification.tsx msgid "View status" msgstr "" @@ -5799,9 +5935,12 @@ msgstr "Вы можете проверить историю своих обра msgid "You can currently vest a maximum of {0} esGMX tokens at a ratio of {1} {stakingToken} to 1 esGMX." msgstr "В настоящее время вы можете вестить максимум {0} токенов esGMX в соотношении {1} {stakingToken} к 1 esGMX." +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx +msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than -{0}, may result in failed orders if prices are volatile." +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than {0}, may result in failed orders if prices are volatile." msgstr "" @@ -5829,10 +5968,6 @@ msgstr "У вас есть незавершенный перевод от {от msgid "You have an active Limit Order to Increase {longOrShortText} {sizeInToken} {0} (${1}) at price ${2}" msgstr "У вас есть активный Лимитный Ордер на увеличение {longOrShortText} {sizeInToken} {0} (${1}) по цене ${2}" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have an active Limit Order to Increase {longShortText} {0} {sizeText} at price {1}." -msgstr "" - #: src/components/Exchange/PositionSeller.js msgid "You have an active order to decrease {longOrShortText} {sizeInToken} {0} (${1}) at {prefix} {2}" msgstr "" @@ -5861,25 +5996,24 @@ msgstr "" msgid "You have an existing position with {0} as collateral. This action will not apply for that position." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "" -"You have an existing {longText} position with {0} as Collateral. This Order will not\n" -"be valid for that Position." -msgstr "" - #: src/components/Exchange/ConfirmationBox.js msgid "You have multiple existing Increase {longOrShortText} {0} limit orders" msgstr "У вас есть несколько существующих на увеличение {longOrShortText} {0} лимитных ордеров" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have multiple existing Increase {longShortText} {0} limit orders" -msgstr "" - #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "You have not deposited any tokens for vesting." msgstr "Вы не внесли ни одного токена для вестнига." +#: src/components/Stake/GMXAprTooltip.tsx +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points using the \"Compound\" button." +msgstr "" + +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points." +msgstr "" + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "You have selected {collateralTokenSymbol} as Collateral, the Liquidation Price will vary based on the price of {collateralTokenSymbol}." msgstr "" @@ -5928,14 +6062,19 @@ msgstr "Вы получите не менее {0} {1}, если этот орд msgid "You will receive at least {toAmountText} if this order is executed. This price is being updated in real time based on Swap Fees and Price Impact." msgstr "" +#: src/pages/Stake/StakeV2.js +#: src/pages/Stake/StakeV2.js +msgid "Your APR" +msgstr "" + #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "Your esGMX (IOU) balance will decrease by your claim amount after claiming, this is expected behaviour." msgstr "После подачи требования ваш баланс esGMX уменьшится на сумму вашего требования, это ожидаемое поведение." #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "Your position's collateral after deducting fees." -msgstr "Обеспечение вашей позиции после вычета комиссий." +msgid "Your position's collateral after deducting fees:" +msgstr "Обеспечение вашей позиции после вычета комиссий:" #: src/pages/CompleteAccountTransfer/CompleteAccountTransfer.js msgid "Your transfer has been completed." @@ -5970,7 +6109,6 @@ msgid "from" msgstr "" #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "hide" msgstr "скрыть" @@ -5978,20 +6116,32 @@ msgstr "скрыть" msgid "in liquidity" msgstr "используется для обеспечения ликвидности" +#: src/domain/synthetics/orders/utils.ts +msgid "limit price" +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "long" +msgstr "" + #: src/pages/Dashboard/DashboardV2.js msgid "not staked" msgstr "без стейкинга" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "pay" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "receive" msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "short" +msgstr "" + #: src/pages/PositionsOverview/PositionsOverview.js msgid "size" msgstr "размер" @@ -6004,8 +6154,11 @@ msgstr "в стейкинги" msgid "time to liq" msgstr "время ликвидировать" +#: src/domain/synthetics/orders/utils.ts +msgid "trigger price" +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "view" msgstr "смотреть" @@ -6022,6 +6175,10 @@ msgstr "" msgid "{0, plural, one {Pending {symbolsText} approval} other {Pending {symbolsText} approvals}}" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "{0, plural, one {You have an active Limit Order to Increase} other {You have multiple active Limit Orders to Increase}}" +msgstr "" + #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "{0} <0><1>{indexName}<2>[{poolName}] <3>market selected." msgstr "" @@ -6102,6 +6259,10 @@ msgstr "{0} liegt unter der Zielgewichtung.<0/><1/>Erhalte niedrigere Gebühren, msgid "{0} is required for collateral." msgstr "{0} требуется для обеспечения залога." +#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx +msgid "{0} order for" +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "{0} pool exceeded, try different token" msgstr "{0} пул превышен, попробуйте другой токен" @@ -6202,6 +6363,22 @@ msgstr "" msgid "{longOrShortText} {0} market selected" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee and pay a borrow fee of {borrowRate} per hour." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee or a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and do not pay a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and {borrowAction} a borrow fee of {borrowRate} per hour." +msgstr "" + #: src/components/Synthetics/MarketCard/MarketCard.tsx msgid "{longShortText} {0} Open Interest" msgstr "" @@ -6218,10 +6395,6 @@ msgstr "" msgid "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR" msgstr "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "{nativeTokenSymbol} APR" -msgstr "" - #: src/components/Stake/GMXAprTooltip.tsx msgid "{nativeTokenSymbol} Base APR" msgstr "" diff --git a/src/locales/zh/messages.po b/src/locales/zh/messages.po index 0f54150a2f..ec20a2904c 100644 --- a/src/locales/zh/messages.po +++ b/src/locales/zh/messages.po @@ -135,6 +135,10 @@ msgstr "" msgid "<0>{0} <1><2>{indexName}<3>[{poolName}] <4>market selected" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "A Size percentage is required." +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "A snapshot of the USD value of your {0} collateral is taken when the position is opened." msgstr "您的{0}抵押品快照在您开启头寸时已以USD价值被存取" @@ -243,6 +247,14 @@ msgstr "" msgid "Accrued Positive Funding Fees for Positions not yet claimable. They will become available to claim by using the \"Settle\" button, or after the Position is increased, decreased or closed." msgstr "" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +msgid "Accrued Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Accrued Price Impact Rebates. They will become Claimable after some time.<0/><1/><2>Read more." +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "Acknowledge epoch is ending in {minutes} minutes" msgstr "" @@ -257,6 +269,10 @@ msgstr "" msgid "Acknowledge high Swap Price Impact" msgstr "" +#: src/domain/synthetics/trade/useHighExecutionFeeConsent.tsx +msgid "Acknowledge very high network Fees" +msgstr "" + #: src/pages/Actions/Actions.js #: src/pages/SyntheticsActions/SyntheticsActions.tsx msgid "Actions" @@ -303,6 +319,10 @@ msgstr "添加推荐代码失败" msgid "Adding..." msgstr "添加中" +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +#~ msgid "Additional Execution Fee" +#~ msgstr "" + #: src/pages/Stake/StakeV2.js msgid "Additional reserve required" msgstr "额外保留需求" @@ -344,15 +364,15 @@ msgstr "" msgid "Allow {wrappedTokenSymbol} to be spent" msgstr "" -#: src/App/App.js #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/SettingsModal/SettingsModal.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Allowed Slippage" msgstr "允许的滑点" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Allowed Slippage below {0}% may result in failed orders." msgstr "" @@ -444,11 +464,15 @@ msgstr "核准中" msgid "Approving..." msgstr "核准中" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Arbitrum APR:" msgstr "Arbitrum年利率" +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx +msgid "As network fees have increased, an additional execution fee is needed." +msgstr "" + #: src/components/Exchange/NoLiquidityErrorModal.tsx msgid "As there is not enough liquidity in GLP to swap {0} to {swapTokenSymbol}, you can use the option below to do so:" msgstr "若流动率不足以交换GLP {0} 成 {swapTokenSymbol}, 您可使用下方其他选项:" @@ -492,8 +516,8 @@ msgstr "可提取的GLP数量. 资金未被当前开仓所使用." msgid "Available on your preferred network" msgstr "可在您的首选网络上使用" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Avalanche APR:" msgstr "Avalanche年利率" @@ -518,6 +542,10 @@ msgstr "余额" msgid "Base APR" msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Base {nativeTokenSymbol} APR" +msgstr "" + #: src/pages/BeginAccountTransfer/BeginAccountTransfer.js msgid "Begin Transfer" msgstr "开始转移" @@ -546,7 +574,6 @@ msgstr "用点数提升你的奖励。 <0>更多信息" #: src/components/Exchange/PositionsList.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Borrow Fee" @@ -561,6 +588,11 @@ msgstr "借款费用/天" msgid "Borrow Fee Rate" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Borrowing fees help ensure available liquidity. <0>Read more." +msgstr "" + #: src/components/Synthetics/BridgingInfo/BridgingInfo.tsx msgid "Bridge {tokenSymbol} to {chainName} using any of the options below:" msgstr "" @@ -596,7 +628,7 @@ msgstr "" msgid "Buy GLP" msgstr "购买GLP" -#: src/pages/Buy/Buy.js +#: src/pages/Buy/Buy.tsx msgid "Buy GLP or GMX" msgstr "" @@ -649,26 +681,10 @@ msgstr "" msgid "Buy GMX using any token from any network:" msgstr "" -#: src/pages/Buy/Buy.js -msgid "Buy Protocol Tokens" -msgstr "" - #: src/components/Glp/GlpSwap.js msgid "Buy failed." msgstr "买入失败" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Arbitrum" -msgstr "在Arbitrum上购买" - -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -msgid "Buy on Avalanche" -msgstr "在Avalanche上购买" - #: src/pages/BuyGMX/BuyGMX.tsx msgid "Buy or Transfer AVAX to Avalanche" msgstr "" @@ -729,7 +745,6 @@ msgstr "错误,无法执行" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts @@ -759,7 +774,7 @@ msgstr "送出取消" msgid "Cancelling {ordersText}" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Chart positions" @@ -781,6 +796,7 @@ msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/Claims/ClaimableCard.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV1.js @@ -807,7 +823,7 @@ msgid "Claim GMX Rewards" msgstr "领取GMX奖励" #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx -msgid "Claim Price Impact" +msgid "Claim Price Impact Rebates" msgstr "" #: src/pages/Stake/StakeV2.js @@ -853,6 +869,10 @@ msgstr "送出领取!<0>查看状态" msgid "Claim submitted." msgstr "送出领取" +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "Claim {totalUsd}" +msgstr "" + #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "Claim {wrappedTokenSymbol} Rewards" @@ -864,30 +884,37 @@ msgstr "领取{wrappedTokenSymbol}奖励" msgid "Claimable" msgstr "可领取" +#: src/components/Synthetics/Claims/ClaimableCard.tsx +msgid "Claimable Price Impact Rebates.<0/><1/><2>Read more." +msgstr "" + #: src/components/Referrals/AffiliatesStats.tsx msgid "Claimable Rebates" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Claiming Price Impact Rebate..." +msgstr "" + +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Claiming failed" msgstr "" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/pages/ClaimEsGmx/ClaimEsGmx.js #: src/pages/Stake/StakeV2.js msgid "Claiming..." msgstr "领取中" -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Claims" msgstr "" #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx -msgid "Claims (1)" +msgid "Claims ({totalClaimables})" msgstr "" #: src/components/Exchange/PositionsList.js @@ -1044,6 +1071,7 @@ msgstr "复利中" #: src/components/Referrals/ClaimAffiliatesModal/ClaimAffiliatesModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx msgid "Confirm Claim" msgstr "" @@ -1350,7 +1378,6 @@ msgstr "去中心化<0/>永续交易所" #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -1370,6 +1397,10 @@ msgstr "" msgid "Decrease the Leverage by using the slider. If the Leverage slider is disabled, you can increase the Pay amount or reduce the Order size." msgstr "" +#: src/components/Synthetics/ConfirmationBox/SLTPEntries.tsx +msgid "Decrease {0} Long by {1} at ${2}." +msgstr "" + #: src/components/Exchange/TradeHistory.js #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx msgid "Decreased" @@ -1463,7 +1494,7 @@ msgstr "存款中..." msgid "Diff" msgstr "差异" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Disable order validations" msgstr "关闭订单验证" @@ -1471,7 +1502,7 @@ msgstr "关闭订单验证" msgid "Disconnect" msgstr "连线中断" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Display PnL after fees" msgstr "收费后显示PnL" @@ -1502,6 +1533,10 @@ msgstr "赚取" msgid "Earn ARB tokens by purchasing GM tokens, trading, or migrating liquidity from GLP to GM. Only for GMX V2." msgstr "" +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Earn an extra {0}% {nativeTokenSymbol} Boosted APR by increasing your staked <0>Multiplier Points." +msgstr "" + #: src/components/Header/AppHeaderLinks.tsx msgid "Ecosystem" msgstr "生态系统" @@ -1771,6 +1806,7 @@ msgid "Execute {orderTypeName} Order: {positionText} {sizeDeltaText}," msgstr "" #: src/components/Exchange/FeesTooltip.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx msgid "Execution Fee" msgstr "" @@ -1815,14 +1851,14 @@ msgstr "费用" msgid "FUNDING FEE" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "FUNDING RATE / 1h" -msgstr "" - #: src/components/Synthetics/ClaimHistoryRow/ClaimHistoryRow.tsx msgid "Failed Settlement of Funding Fees" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Failed to Claim Price Impact Rebate" +msgstr "" + #: src/domain/synthetics/orders/cancelOrdersTxn.ts msgid "Failed to cancel {ordersText}" msgstr "" @@ -1847,6 +1883,7 @@ msgstr "" #: src/components/Glp/GlpSwap.js #: src/components/Glp/GlpSwap.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Fees" msgstr "费用" @@ -1963,11 +2000,10 @@ msgstr "" msgid "Fulfilling order request" msgstr "" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts msgid "Funding Claimed" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Funding Fee" @@ -1977,14 +2013,15 @@ msgstr "" msgid "Funding Fee Rate" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Funding Rate / 1h" -msgstr "" - #: src/components/Synthetics/Claims/ClaimableCardUI.tsx msgid "Funding fees" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Funding fees help to balance longs and shorts and are exchanged between both sides. <0>Read more." +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "GBC NFTs APR tracker and rewards" msgstr "GBC NFTs 年利率跟踪器和奖励" @@ -2015,7 +2052,7 @@ msgstr "" msgid "GLP buy disabled, pending {0} upgrade" msgstr "GLP购买已禁止,等待{0}升级" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GLP is the liquidity provider token for GMX V1 markets. Accrues 70% of the V1 markets generated fees." msgstr "" @@ -2043,7 +2080,7 @@ msgstr "" msgid "GM can be sold for {0} and {1} for this market up to the specified selling caps. The remaining tokens in the pool are reserved for currently open Positions." msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GM is the liquidity provider token for GMX V2 markets. Accrues 63% of the V2 markets generated fees." msgstr "" @@ -2132,7 +2169,7 @@ msgstr "GMX目前在Arbitrum和Avalanche上线" msgid "GMX is not actively looking for new hires at the moment. However, if you think you can contribute to the project, please email <0>jobs@gmx.io." msgstr "GMX目前没有积极寻找新员工。但是,如果你认为你能为项目做出贡献,请发电子邮件到<0>jobs@gmx.io" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "GMX is the utility and governance token. Accrues 30% and 27% of V1 and V2 markets generated fees, respectively." msgstr "" @@ -2185,6 +2222,13 @@ msgstr "" msgid "Governance" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/GmSwap/GmConfirmationBox/GmConfirmationBox.tsx +#: src/components/Synthetics/PositionEditor/PositionEditor.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "High Execution Fee not yet acknowledged" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "High Slippage, Swap Anyway" msgstr "高滑点,继续交易" @@ -2193,6 +2237,13 @@ msgstr "高滑点,继续交易" msgid "High USDG Slippage, Long Anyway" msgstr "高 USDG 滑点,继续做多" +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#: src/domain/synthetics/trade/utils/validation.ts +#~ msgid "High network Fee not yet acknowledged" +#~ msgstr "" + #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "I am aware of the trigger orders" @@ -2228,7 +2279,7 @@ msgstr "" msgid "Incentives are airdropped weekly." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Include PnL in leverage display" msgstr "在杠杆显示中包括PnL" @@ -2250,7 +2301,6 @@ msgstr "网络错误" #: src/components/Exchange/OrdersList.js #: src/components/Exchange/TradeHistory.js #: src/components/Exchange/TradeHistory.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts #: src/domain/synthetics/orders/utils.ts @@ -2408,7 +2458,7 @@ msgstr "无效的接收地址" msgid "Invalid Transfer Addresses: Please check the url." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid execution fee buffer value" msgstr "" @@ -2426,7 +2476,7 @@ msgstr "无效的流动资金价格" msgid "Invalid price, see warning" msgstr "无效的价格,请参阅警告" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Invalid slippage value" msgstr "无效的滑点值" @@ -2455,7 +2505,6 @@ msgid "Keep Leverage is not possible" msgstr "" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "Keep leverage at {0}" msgstr "" @@ -2464,6 +2513,10 @@ msgstr "" msgid "Keep leverage at {0}x" msgstr "" +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +msgid "Keep leverage at {keepLeverageAtValue}" +msgstr "" + #: src/components/Synthetics/ChartTokenSelector/ChartTokenSelector.tsx msgid "LONG LIQ." msgstr "" @@ -2548,7 +2601,6 @@ msgstr "" #: src/components/Synthetics/PositionItem/PositionItem.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx #: src/components/Synthetics/TradeHistoryRow/utils.ts -#: src/domain/synthetics/orders/utils.ts msgid "Limit" msgstr "限制" @@ -2572,7 +2624,6 @@ msgstr "" #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Limit Price" msgstr "限制价格" @@ -2705,8 +2756,8 @@ msgstr "加载中..." #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -2723,7 +2774,6 @@ msgstr "加载中..." #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -2738,14 +2788,6 @@ msgstr "做多" msgid "Long Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Long Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Long Liquidity" msgstr "" @@ -2754,14 +2796,11 @@ msgstr "" msgid "Long Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Long Positions" msgstr "开仓做多" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Long positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Long {0}" msgstr "做多 {0}" @@ -2778,7 +2817,9 @@ msgstr "看来你没有推荐代码可以分享。<0/> 创建一个,开始赚 msgid "Loss" msgstr "亏损" +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx #: src/components/Synthetics/ClaimModal/ClaimModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx #: src/components/Synthetics/GmList/GmList.tsx msgid "MARKET" msgstr "" @@ -2894,16 +2935,15 @@ msgid "Max Capacity for {0} Reached" msgstr "达到{0}的最高上限" #: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Max Execution Fee" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee Buffer" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max Execution Fee buffer below {0}% may result in failed orders." msgstr "" @@ -2945,7 +2985,7 @@ msgstr "" msgid "Max close amount exceeded" msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Max execution fee buffer precision is 0.01%" msgstr "" @@ -2975,9 +3015,13 @@ msgstr "已达到{0}池的最大容量。请使用另一个代币挖GLP" msgid "Max pool capacity reached for {0}<0/><1/>Please mint GLP using another token" msgstr "已达到{0}<0/><1/>池的最大容量,请使用另一个代币铸币GLP" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Max slippage precision is -0.01%" +msgstr "" + #: src/App/App.js -msgid "Max slippage precision is 0.01%" -msgstr "最大滑点精准度为0.01%" +#~ msgid "Max slippage precision is 0.01%" +#~ msgstr "最大滑点精准度为0.01%" #: src/components/Synthetics/MarketStats/MarketStats.tsx #: src/components/Synthetics/MarketStats/MarketStats.tsx @@ -3025,11 +3069,11 @@ msgstr "最大{0}做空范围" msgid "Max {0} short exceeded" msgstr "超过了最大{0}做空范围" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Arbitrum APR:" msgstr "" -#: src/components/TokenCard/TokenCard.js +#: src/components/TokenCard/TokenCard.tsx msgid "Max. Avalanche APR: {0}" msgstr "" @@ -3038,7 +3082,11 @@ msgid "Max. Leverage exceeded" msgstr "" #: src/components/Stake/GMXAprTooltip.tsx -msgid "Max. {nativeTokenSymbol} APR with 200% Boost for this week: {0}%." +msgid "Max. {nativeTokenSymbol} APR" +msgstr "" + +#: src/components/Stake/GMXAprTooltip.tsx +msgid "Max. {nativeTokenSymbol} APR is calculated with the max. 200% Boost Percentage by staking <0>Multiplier Points." msgstr "" #: src/components/Migration/Migration.js @@ -3148,9 +3196,16 @@ msgid "Multiplier Points APR" msgstr "积分点数年利率" #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/TradeBox/TradeBox.tsx msgid "NA" msgstr "" +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "NET FEE / 1 H" +msgstr "" + #: src/pages/NftWallet/NftWallet.js msgid "NFT Address" msgstr "NFT地址" @@ -3171,6 +3226,20 @@ msgstr "" msgid "Neither Collateral nor realized PnL is enough to cover pending Fees. Please close a larger position amount." msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Fee" +msgstr "" + +#: src/components/Synthetics/MarketsList/MarketsList.tsx +msgid "Net Fee / 1h" +msgstr "" + +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "Net Rebate" +msgstr "" + #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -3199,7 +3268,12 @@ msgstr "网络" msgid "Networks and Settings" msgstr "网络和设定" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "New Collateral" +msgstr "" + #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Next" msgstr "下一步" @@ -3275,6 +3349,10 @@ msgstr "" msgid "Note that orders are not guaranteed to be executed.<0/><1/>This can occur in a few situations including but not exclusive to:" msgstr "请注意,订单不保证被执行。<0/><1/>可能发生在几种情况下,包括但不限于:" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Old Collateral" +msgstr "" + #: src/components/AddressDropdown/AddressDropdown.tsx #: src/components/Synthetics/SubaccountModal/SubaccountModal.tsx msgid "One-Click Trading" @@ -3351,10 +3429,6 @@ msgstr "开仓中" msgid "Order" msgstr "订单" -#: src/domain/synthetics/orders/utils.ts -msgid "Order Trigger Price is beyond position's Liquidation Price." -msgstr "" - #: src/components/Synthetics/OrderItem/OrderItem.tsx msgid "Order Type" msgstr "" @@ -3635,7 +3709,6 @@ msgstr "仓位" msgid "Positions ({0})" msgstr "仓位({0})" -#: src/pages/SyntheticsPage/SyntheticsPage.tsx #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Positions{0}" msgstr "" @@ -3645,6 +3718,7 @@ msgid "Positive Funding Fees for a Position become claimable after the Position msgstr "" #: src/components/Synthetics/Claims/Claims.tsx +#: src/pages/PriceImpactRebatesStats/PriceImpactRebatesStats.tsx msgid "Prev" msgstr "上一页" @@ -3686,6 +3760,20 @@ msgstr "价钱" msgid "Price Impact" msgstr "" +#: src/domain/synthetics/claimHistory/claimPriceImpactRebate.ts +msgid "Price Impact Rebate Claimed" +msgstr "" + +#: src/components/Synthetics/Claims/ClaimableCardUI.tsx +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates" +msgstr "" + +#: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx +msgid "Price Impact Rebates for closing trades are claimable under the Claims tab. <0>Read more." +msgstr "" + +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts #: src/domain/synthetics/trade/utils/validation.ts @@ -3693,6 +3781,10 @@ msgstr "" msgid "Price Impact not yet acknowledged" msgstr "" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3700,6 +3792,10 @@ msgstr "" msgid "Price above Liq. Price" msgstr "价格高于流动资金价格" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3713,6 +3809,14 @@ msgstr "价格高于流动资金价格" msgid "Price above Mark Price" msgstr "价格高于标价" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price above Mark Price." +msgstr "" + +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Limit Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/PositionSeller.js #: src/components/Synthetics/OrderEditor/OrderEditor.tsx @@ -3720,6 +3824,10 @@ msgstr "价格高于标价" msgid "Price below Liq. Price" msgstr "价格低于流动资金价格" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Liq. Price." +msgstr "" + #: src/components/Exchange/OrderEditor.js #: src/components/Exchange/SwapBox.js #: src/components/Exchange/SwapBox.js @@ -3733,6 +3841,10 @@ msgstr "价格低于流动资金价格" msgid "Price below Mark Price" msgstr "价格低于标价" +#: src/domain/synthetics/orders/useSLTPEntries.ts +msgid "Price below Mark Price." +msgstr "" + #: src/pages/OrdersOverview/OrdersOverview.js msgid "Price conditions are met" msgstr "符合价格条件" @@ -3775,6 +3887,10 @@ msgstr "储备证明" msgid "Protocol" msgstr "" +#: src/pages/Buy/Buy.tsx +msgid "Protocol Tokens" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js #: src/pages/Ecosystem/Ecosystem.js msgid "Protocol analytics" @@ -3796,9 +3912,14 @@ msgstr "" msgid "Purchase Insurance" msgstr "购买保险" -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js -#: src/components/TokenCard/TokenCard.js +#: src/components/Synthetics/AccruedPositionPriceImpactRebateModal/AccruedPositionPriceImpactRebateModal.tsx +#: src/components/Synthetics/ClaimablePositionPriceImpactRebateModal/ClaimablePositionPriceImpactRebateModal.tsx +msgid "REBATE" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx msgid "Read more" msgstr "了解更多" @@ -4025,7 +4146,7 @@ msgstr "" msgid "Same as current active code" msgstr "与当前的有效代码相同" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Save" msgstr "储存" @@ -4191,10 +4312,10 @@ msgstr "" msgid "Set TP/SL" msgstr "" -#: src/App/App.js #: src/components/Header/AppHeaderLinks.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx #: src/components/NetworkDropdown/NetworkDropdown.tsx +#: src/components/SettingsModal/SettingsModal.tsx msgid "Settings" msgstr "设置" @@ -4256,8 +4377,8 @@ msgstr "分享仓位" #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/components/Synthetics/OrderItem/OrderItem.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4274,7 +4395,6 @@ msgstr "分享仓位" #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/context/SyntheticsEvents/SyntheticsEventsProvider.tsx #: src/domain/synthetics/orders/utils.ts -#: src/domain/synthetics/orders/utils.ts #: src/pages/Actions/Actions.js #: src/pages/Actions/Actions.js #: src/pages/Exchange/Exchange.js @@ -4289,14 +4409,6 @@ msgstr "做空" msgid "Short Collateral" msgstr "" -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Payments" -msgstr "" - -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "Short Funding Rewards" -msgstr "" - #: src/components/Exchange/ChartTokenSelector.tsx msgid "Short Liquidity" msgstr "" @@ -4305,14 +4417,11 @@ msgstr "" msgid "Short Open Interest" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx #: src/pages/Dashboard/DashboardV2.js msgid "Short Positions" msgstr "做空仓位" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "Short positions {0} a Funding Fee of <0>{1}{2}% per hour." -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Short {0}" msgstr "做空{0}" @@ -4321,10 +4430,14 @@ msgstr "做空{0}" msgid "Shorting..." msgstr "做空中..." -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "Show debug values" msgstr "" +#: src/components/Synthetics/Claims/SettleAccruedCard.tsx +msgid "Show details" +msgstr "" + #: src/pages/Home/Home.js msgid "Simple Swaps" msgstr "简易交易" @@ -4350,6 +4463,7 @@ msgstr "" #: src/components/Exchange/PositionsList.js #: src/components/Exchange/PositionsList.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/PositionEditor/PositionEditor.tsx #: src/components/Synthetics/PositionItem/PositionItem.tsx @@ -4361,14 +4475,18 @@ msgstr "规模" #: src/components/Exchange/ConfirmationBox.js #: src/components/Exchange/PositionSeller.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx msgid "Slippage is too high" msgstr "" +#: src/components/SettingsModal/SettingsModal.tsx +msgid "Slippage should be less than -5%" +msgstr "" + #: src/App/App.js -msgid "Slippage should be less than 5%" -msgstr "滑点应低于5%" +#~ msgid "Slippage should be less than 5%" +#~ msgstr "滑点应低于5%" #: src/components/Exchange/UsefulLinks.tsx msgid "Speed up page loading" @@ -4472,10 +4590,15 @@ msgstr "统计数据" msgid "Stop Loss Decrease" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Stop-Loss" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Stop-Loss PnL" +msgstr "" + #: src/pages/Ecosystem/Ecosystem.js msgid "Structured Products" msgstr "结构化产品" @@ -4524,7 +4647,7 @@ msgstr "" msgid "Submit" msgstr "送出" -#: src/domain/synthetics/markets/claimCollateralTxn.ts +#: src/domain/synthetics/markets/claimFundingFeesTxn.ts #: src/domain/synthetics/referrals/claimAffiliateRewardsTxn.ts msgid "Success claimings" msgstr "" @@ -4550,10 +4673,6 @@ msgstr "交易" msgid "Swap Fee" msgstr "" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx -msgid "Swap Fees" -msgstr "" - #: src/components/Exchange/SwapBox.js msgid "Swap Order created!" msgstr "创建了交易订单" @@ -4566,7 +4685,6 @@ msgstr "创建交易订单失败" msgid "Swap Order submitted!" msgstr "交易订单送出" -#: src/components/Synthetics/OrderEditor/OrderEditor.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "Swap Price Impact" msgstr "" @@ -4700,11 +4818,15 @@ msgstr "" msgid "TP/SL" msgstr "" -#: src/domain/synthetics/orders/utils.ts +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx #: src/domain/synthetics/positions/utils.ts msgid "Take-Profit" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "Take-Profit PnL" +msgstr "" + #: src/components/Exchange/SwapBox.js msgid "Take-profit and stop-loss orders can be set after opening a position. <0/><1/>There will be a \"Close\" button on each position row, clicking this will display the option to set trigger orders. <2/><3/>For screenshots and more information, please see the <4>docs." msgstr "获利和止损订单可以在开仓后设置 <0/><1/>每一行仓位上都会有一个 \"Close/\"按钮, 点击它将会显示设置触发订单的选项 <2/><3/>屏幕截图和更多信息,请参见<4>文档" @@ -4771,10 +4893,6 @@ msgstr "" msgid "The Bonus Rebate will be airdropped as ARB tokens on a pro-rata basis. <0>Read more." msgstr "" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "The Boosted APR is from your staked Multiplier Points." -msgstr "提升的年利率来自于你所投注的乘数点" - #: src/components/Synthetics/AcceptablePriceImpactInputRow/AcceptablePriceImpactInputRow.tsx msgid "The Current Price Impact is {0}. Consider adding a buffer of 0.30% to it so the order is more likely to be processed." msgstr "" @@ -4787,18 +4905,15 @@ msgstr "" msgid "The Gambit protocol is in beta, please read the <0>staking detailsbefore participating." msgstr "Gambit协议处于测试阶段,请在参与之前阅读<0>质押细节" +#: src/components/Synthetics/GmSwap/GmFees/GmFees.tsx #: src/components/Synthetics/TradeFeesRow/TradeFeesRow.tsx msgid "The Max Execution Fee is overestimated by {maxExecutionFeeText}%. Upon execution, the excess Execution Fee is sent back to your account." msgstr "" -#: src/App/App.js +#: src/components/SettingsModal/SettingsModal.tsx msgid "The Max Execution Fee is set to a higher value to handle potential increases in gas price during order execution. Any excess execution fee will be refunded to your account when the order is executed. Only applicable to GMX V2." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "The Order may not execute at the desired {priceText} as the current Price Impact {0} is higher than its Acceptable Price Impact {1}. Consider canceling and creating a new {suggestionType} Order." -msgstr "" - #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "The address of the esGMX (IOU) token is {esGmxIouAddress}." msgstr "esGMX(IOU)代币的地址是{esGmxIouAddress}" @@ -4827,11 +4942,23 @@ msgstr "标价已改变, 请考虑点击你地址旁的 \"...\" 图示来增加 msgid "The maximum number of authorized Actions has been reached. Re-authorize a higher value using the \"Max allowed actions\" field." msgstr "" +#: src/domain/synthetics/fees/utils/executionFee.ts +msgid "The network Fees are high currently, which may be due to a temporary increase in transactions on the {0} network." +msgstr "" + #: src/domain/legacy.ts #: src/domain/synthetics/fees/utils/executionFee.ts msgid "The network Fees are very high currently, which may be due to a temporary increase in transactions on the {0} network." msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "The order may not execute at the desired {priceText} as its acceptable price impact is set to {formattedOrderAcceptablePriceImpact}, which is lower than the current market price impact of {formattedCurrentAcceptablePriceImpact}. It can be edited using the \"Edit\" button." +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "The order will not be executed as its trigger price is beyond the position's liquidation price." +msgstr "" + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "The order will only execute if the Min. Receive is met and there is sufficient liquidity." msgstr "" @@ -4853,9 +4980,13 @@ msgid "The pending borrow fee will be charged on this transaction." msgstr "" #: src/components/Synthetics/MarketCard/MarketCard.tsx -msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of -{1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "" +#: src/components/Synthetics/MarketCard/MarketCard.tsx +#~ msgid "The position will be opened at a reference price of {0}, not accounting for price impact, with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" +#~ msgstr "" + #: src/components/Exchange/SwapBox.js msgid "The position will be opened at {0} USD with a max slippage of {1}%.<0/><1/>The slippage amount can be configured under Settings, found by clicking on your address at the top right of the page after connecting your wallet.<2/><3/><4>More Info" msgstr "该仓位将在 {0} USD 开仓,最大滑点为{1}%.<0/><1/>滑点金额可在设置下配置, 在连接你的钱包后,点击页面右上方的地址即可找到<2/><3/><4>更多资讯" @@ -4964,9 +5095,8 @@ msgstr "此代码尚未在{0}上注册,你将不会收到回扣<0/><1/>切换 msgid "This is the maximum top-up amount that will be sent from your Main account to your Subaccount after each transaction. The actual amount sent will depend on the final transaction fee." msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketsList/MarketsList.tsx -msgid "This market uses an Adaptive Funding Rate. The Funding Rate will adjust over time depending on the ratio of longs and shorts. <0>Read more." +#: src/domain/synthetics/orders/utils.ts +msgid "This order using {collateralSymbol} as collateral will not be valid for the existing {longText} position using {symbol} as collateral." msgstr "" #: src/components/Exchange/TradeHistory.js @@ -5137,7 +5267,6 @@ msgstr "" #: src/pages/Exchange/Exchange.js #: src/pages/SyntheticsPage/SyntheticsPage.tsx -#: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "Trades" msgstr "交易" @@ -5240,7 +5369,6 @@ msgstr "触发" #: src/components/Synthetics/OrderList/OrderList.tsx #: src/components/Synthetics/PositionSeller/PositionSeller.tsx #: src/components/Synthetics/TradeBox/TradeBox.tsx -#: src/domain/synthetics/orders/utils.ts msgid "Trigger Price" msgstr "" @@ -5252,10 +5380,6 @@ msgstr "" msgid "Trigger order disabled, pending {0} upgrade" msgstr "" -#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx -msgid "Trigger order for" -msgstr "" - #: src/components/Synthetics/TradeHistoryRow/utils.ts msgid "Triggered at: {0}" msgstr "" @@ -5359,7 +5483,7 @@ msgid "Unstake submitted! <0>View status." msgstr "解除质押送出!<0>查看状况" #: src/pages/Stake/StakeV2.js -msgid "Unstaking will burn <0>{0} Multiplier Points. {1}" +msgid "Unstaking will burn <0>{0} Multiplier Points. <1>You will earn {1}% less {nativeTokenSymbol} rewards with this action." msgstr "" #: src/pages/Stake/StakeV1.js @@ -5569,6 +5693,18 @@ msgstr "浏览" msgid "View in Explorer" msgstr "在浏览器中查看" +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Arbitrum" +msgstr "" + +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +#: src/components/TokenCard/TokenCard.tsx +msgid "View on Avalanche" +msgstr "" + #: src/components/Synthetics/StatusNotification/SubaccountNotification.tsx msgid "View status" msgstr "" @@ -5799,9 +5935,12 @@ msgstr "你可以在这里查看你的提领历史<0>" msgid "You can currently vest a maximum of {0} esGMX tokens at a ratio of {1} {stakingToken} to 1 esGMX." msgstr "目前,您最多可以授权{0}个esGMX代币,比例为{1}个esGMX。 {stakingToken}对1esGMX" +#: src/components/Synthetics/ConfirmationBox/rows/AllowedSlippageRow.tsx +#: src/components/Synthetics/PositionSeller/rows/AllowedSlippageRow.tsx +msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than -{0}, may result in failed orders if prices are volatile." +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -#: src/components/Synthetics/PositionSeller/PositionSeller.tsx msgid "You can edit the default Allowed Slippage in the settings menu on the top right of the page.<0/><1/>Note that a low allowed slippage, e.g. less than {0}, may result in failed orders if prices are volatile." msgstr "" @@ -5829,10 +5968,6 @@ msgstr "您有一个来自{sender}的待处理转账" msgid "You have an active Limit Order to Increase {longOrShortText} {sizeInToken} {0} (${1}) at price ${2}" msgstr "您有一个有效的限价订单,{longOrShortText} {sizeInToken} {0} (${1}) 以{2}美元的价格增加" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have an active Limit Order to Increase {longShortText} {0} {sizeText} at price {1}." -msgstr "" - #: src/components/Exchange/PositionSeller.js msgid "You have an active order to decrease {longOrShortText} {sizeInToken} {0} (${1}) at {prefix} {2}" msgstr "" @@ -5861,25 +5996,24 @@ msgstr "" msgid "You have an existing position with {0} as collateral. This action will not apply for that position." msgstr "" -#: src/domain/synthetics/orders/utils.ts -msgid "" -"You have an existing {longText} position with {0} as Collateral. This Order will not\n" -"be valid for that Position." -msgstr "" - #: src/components/Exchange/ConfirmationBox.js msgid "You have multiple existing Increase {longOrShortText} {0} limit orders" msgstr "你现有多个增加 {longOrShortText} {0} 限价订单" -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "You have multiple existing Increase {longShortText} {0} limit orders" -msgstr "" - #: src/pages/Stake/StakeV2.js #: src/pages/Stake/StakeV2.js msgid "You have not deposited any tokens for vesting." msgstr "你尚未存入任何可用于授权的代币" +#: src/components/Stake/GMXAprTooltip.tsx +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points using the \"Compound\" button." +msgstr "" + +#: src/pages/Stake/StakeV2.js +msgid "You have reached the maximum Boost Percentage. Stake an additional {0} GMX or esGMX to be able to stake your unstaked {1} Multiplier Points." +msgstr "" + #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "You have selected {collateralTokenSymbol} as Collateral, the Liquidation Price will vary based on the price of {collateralTokenSymbol}." msgstr "" @@ -5928,13 +6062,18 @@ msgstr "如果该订单被执行,您将至少收到{0} {1} 确切的执行价 msgid "You will receive at least {toAmountText} if this order is executed. This price is being updated in real time based on Swap Fees and Price Impact." msgstr "" +#: src/pages/Stake/StakeV2.js +#: src/pages/Stake/StakeV2.js +msgid "Your APR" +msgstr "" + #: src/pages/ClaimEsGmx/ClaimEsGmx.js msgid "Your esGMX (IOU) balance will decrease by your claim amount after claiming, this is expected behaviour." msgstr "你的esGMX(IOU)余额在提领后将减少您的领回金额,这是可预期的" #: src/components/Exchange/ConfirmationBox.js #: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx -msgid "Your position's collateral after deducting fees." +msgid "Your position's collateral after deducting fees:" msgstr "扣除费用后,你的头寸的抵押品" #: src/pages/CompleteAccountTransfer/CompleteAccountTransfer.js @@ -5970,7 +6109,6 @@ msgid "from" msgstr "" #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "hide" msgstr "隐藏" @@ -5978,20 +6116,32 @@ msgstr "隐藏" msgid "in liquidity" msgstr "流动性中" +#: src/domain/synthetics/orders/utils.ts +msgid "limit price" +msgstr "" + +#: src/domain/synthetics/orders/utils.ts +msgid "long" +msgstr "" + #: src/pages/Dashboard/DashboardV2.js msgid "not staked" msgstr "未质押的" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "pay" msgstr "" -#: src/components/Synthetics/MarketCard/MarketCard.tsx -#: src/components/Synthetics/MarketCard/MarketCard.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx msgid "receive" msgstr "" +#: src/domain/synthetics/orders/utils.ts +msgid "short" +msgstr "" + #: src/pages/PositionsOverview/PositionsOverview.js msgid "size" msgstr "大小" @@ -6004,8 +6154,11 @@ msgstr "已质押" msgid "time to liq" msgstr "流动性时间将至" +#: src/domain/synthetics/orders/utils.ts +msgid "trigger price" +msgstr "" + #: src/components/Exchange/ConfirmationBox.js -#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx msgid "view" msgstr "查看" @@ -6022,6 +6175,10 @@ msgstr "" msgid "{0, plural, one {Pending {symbolsText} approval} other {Pending {symbolsText} approvals}}" msgstr "" +#: src/components/Synthetics/ConfirmationBox/ConfirmationBox.tsx +msgid "{0, plural, one {You have an active Limit Order to Increase} other {You have multiple active Limit Orders to Increase}}" +msgstr "" + #: src/pages/SyntheticsPage/SyntheticsPage.tsx msgid "{0} <0><1>{indexName}<2>[{poolName}] <3>market selected." msgstr "" @@ -6102,6 +6259,10 @@ msgstr "{0}低于其目标重量。<0/><1/>获取较低的费用,以<2>用{1} msgid "{0} is required for collateral." msgstr "{0}是需要抵押品的" +#: src/components/Synthetics/StatusNotification/OrderStatusNotification.tsx +msgid "{0} order for" +msgstr "" + #: src/components/Glp/GlpSwap.js msgid "{0} pool exceeded, try different token" msgstr "{0}池超量,请尝试不同的代币" @@ -6202,6 +6363,22 @@ msgstr "" msgid "{longOrShortText} {0} market selected" msgstr "" +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee and pay a borrow fee of {borrowRate} per hour." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions do not pay a funding fee or a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and do not pay a borrow fee." +msgstr "" + +#: src/components/Synthetics/MarketNetFee/MarketNetFee.tsx +msgid "{longOrShort} positions {fundingAction} a funding fee of {fundingRate} per hour and {borrowAction} a borrow fee of {borrowRate} per hour." +msgstr "" + #: src/components/Synthetics/MarketCard/MarketCard.tsx msgid "{longShortText} {0} Open Interest" msgstr "" @@ -6218,10 +6395,6 @@ msgstr "" msgid "{nativeTokenSymbol} ({wrappedTokenSymbol}) APR" msgstr "{nativeTokenSymbol} ({wrappedTokenSymbol}) 年利率" -#: src/components/Stake/GMXAprTooltip.tsx -msgid "{nativeTokenSymbol} APR" -msgstr "" - #: src/components/Stake/GMXAprTooltip.tsx msgid "{nativeTokenSymbol} Base APR" msgstr "" diff --git a/src/pages/Buy/Buy.js b/src/pages/Buy/Buy.tsx similarity index 84% rename from src/pages/Buy/Buy.js rename to src/pages/Buy/Buy.tsx index 28e778d478..244c6bc896 100644 --- a/src/pages/Buy/Buy.js +++ b/src/pages/Buy/Buy.tsx @@ -1,18 +1,20 @@ -import React from "react"; import { t } from "@lingui/macro"; -import Footer from "components/Footer/Footer"; -import "./Buy.css"; -import TokenCard from "components/TokenCard/TokenCard"; -import SEO from "components/Common/SEO"; + import { getPageTitle } from "lib/legacy"; + +import SEO from "components/Common/SEO"; +import Footer from "components/Footer/Footer"; import PageTitle from "components/PageTitle/PageTitle"; +import TokenCard from "components/TokenCard/TokenCard"; + +import "./Buy.css"; export default function BuyGMXGLP() { return (
    - +
    diff --git a/src/pages/BuyGMX/BuyGMX.tsx b/src/pages/BuyGMX/BuyGMX.tsx index d5e2116d20..0b61f78b9e 100644 --- a/src/pages/BuyGMX/BuyGMX.tsx +++ b/src/pages/BuyGMX/BuyGMX.tsx @@ -131,6 +131,7 @@ export default function BuyGMX() { textAlign="left" key={exchange.name} to={link} + // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop imgInfo={{ src: icon, alt: exchange.name }} newTab > @@ -162,6 +163,7 @@ export default function BuyGMX() { textAlign="left" key={exchange.name} to={link} + // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop imgInfo={{ src: icon, alt: exchange.name }} newTab > @@ -179,6 +181,10 @@ export default function BuyGMX() { ); } +const UNISWAP_IMG_INFO = { src: uniswapArbitrumIcon, alt: "Uniswap" }; +const TRADERJOE_IMG_INFO = { src: traderjoeIcon, alt: "Traderjoe" }; +const BOND_PROTOCOL_IMG_INFO = { src: bondProtocolIcon, alt: "Bond Protocol" }; + function DecentralisedExchanges({ chainId, externalLinks }) { const isArbitrum = chainId === ARBITRUM; return ( @@ -193,7 +199,7 @@ function DecentralisedExchanges({ chainId, externalLinks }) {
    @@ -599,16 +690,7 @@ export default function DashboardV2() { 0, true )}`} - renderContent={() => ( - - )} + renderContent={() => } />
    @@ -629,16 +711,7 @@ export default function DashboardV2() { 0, true )}`} - renderContent={() => ( - - )} + renderContent={() => } />
    @@ -659,16 +732,7 @@ export default function DashboardV2() { 0, true )}`} - renderContent={() => ( - - )} + renderContent={() => } />
    @@ -687,16 +751,7 @@ export default function DashboardV2() { 2, true )}`} - renderContent={() => ( - - )} + renderContent={() => } />
    @@ -724,19 +779,7 @@ export default function DashboardV2() { ) )}`} renderContent={() => ( - + )} />
    @@ -755,16 +798,7 @@ export default function DashboardV2() { 0, true )}`} - renderContent={() => ( - - )} + renderContent={() => } />
    @@ -783,16 +817,7 @@ export default function DashboardV2() { true )} renderContent={() => ( - + )} />
    @@ -875,10 +900,7 @@ export default function DashboardV2() { )} /> @@ -914,6 +936,7 @@ export default function DashboardV2() { Price conditions are met
    - + Close to execution price
    diff --git a/src/pages/PositionsOverview/PositionsOverview.js b/src/pages/PositionsOverview/PositionsOverview.js index c724991d13..0f5484bd9c 100644 --- a/src/pages/PositionsOverview/PositionsOverview.js +++ b/src/pages/PositionsOverview/PositionsOverview.js @@ -49,7 +49,7 @@ export default function PositionsOverview() { {positions && positions .filter((p) => p.danger) - .map((position) => { + .map((position, i) => { const { size, account, collateral, fee, danger } = position; const diffToLiq = position.collateral.sub(position.fee); @@ -58,7 +58,7 @@ export default function PositionsOverview() { const hoursToLiq = diffToLiq.div(feesPerHour); const liqTime = hoursToLiq.toNumber() * 60 * 60 + Date.now() / 1000; return ( -
    {account} ${formatAmount(size, USD_DECIMALS, 2, true)} ${formatAmount(collateral, USD_DECIMALS, 2, true)}
    {tokenInfo.symbol} <>${formatAmountHuman(tokenInfo.managedUsd, 30)} diff --git a/src/pages/SyntheticsActions/SyntheticsActions.tsx b/src/pages/SyntheticsActions/SyntheticsActions.tsx index b73328d9c3..0fce2cbaf9 100644 --- a/src/pages/SyntheticsActions/SyntheticsActions.tsx +++ b/src/pages/SyntheticsActions/SyntheticsActions.tsx @@ -1,52 +1,26 @@ -import { ethers } from "ethers"; -import { useParams } from "react-router-dom"; - import "./Actions.scss"; import { Trans, t } from "@lingui/macro"; +import ExternalLink from "components/ExternalLink/ExternalLink"; +import Footer from "components/Footer/Footer"; +import PageTitle from "components/PageTitle/PageTitle"; import { OrderList } from "components/Synthetics/OrderList/OrderList"; import { PositionList } from "components/Synthetics/PositionList/PositionList"; import { TradeHistory } from "components/Synthetics/TradeHistory/TradeHistory"; -import { useMarketsInfo } from "domain/synthetics/markets"; -import { useOrdersInfo } from "domain/synthetics/orders/useOrdersInfo"; -import { usePositionsInfo } from "domain/synthetics/positions"; -import { useChainId } from "lib/chains"; -import PageTitle from "components/PageTitle/PageTitle"; -import ExternalLink from "components/ExternalLink/ExternalLink"; -import Footer from "components/Footer/Footer"; - -export default function SyntheticsActions({ - savedIsPnlInLeverage, - savedShowPnlAfterFees, -}: { - savedIsPnlInLeverage: boolean; - savedShowPnlAfterFees: boolean; -}) { - const { account: paramsAccount } = useParams<{ account?: string }>(); - - const { chainId } = useChainId(); - - let checkSummedAccount: string | undefined; - - if (paramsAccount && ethers.utils.isAddress(paramsAccount)) { - checkSummedAccount = ethers.utils.getAddress(paramsAccount); - } +import { + useAccount, + useIsOrdersLoading, + useIsPositionsLoading, + useSavedShowPnlAfterFees, +} from "context/SyntheticsStateContext/hooks/globalsHooks"; +import { useTradeboxAvailableTokensOptions } from "context/SyntheticsStateContext/hooks/tradeboxHooks"; - const { marketsInfoData, tokensData, pricesUpdatedAt } = useMarketsInfo(chainId); - const { positionsInfoData, isLoading: isPositionsLoading } = usePositionsInfo(chainId, { - marketsInfoData, - tokensData, - pricesUpdatedAt, - showPnlInLeverage: savedIsPnlInLeverage, - account: checkSummedAccount, - skipLocalReferralCode: true, - }); - const { ordersInfoData, isLoading: isOrdersLoading } = useOrdersInfo(chainId, { - account: checkSummedAccount, - marketsInfoData, - positionsInfoData, - tokensData, - }); +export default function SyntheticsActions() { + const savedShowPnlAfterFees = useSavedShowPnlAfterFees(); + const checkSummedAccount = useAccount(); + const isPositionsLoading = useIsPositionsLoading(); + const isOrdersLoading = useIsOrdersLoading(); + const availableTokensOptions = useTradeboxAvailableTokensOptions(); return (
    @@ -75,17 +49,13 @@ export default function SyntheticsActions({ Positions
    null} onSelectPositionClick={() => null} onClosePositionClick={() => null} onEditCollateralClick={() => null} onSettlePositionFeesClick={() => null} showPnlAfterFees={savedShowPnlAfterFees} - savedShowPnlAfterFees={savedShowPnlAfterFees} openSettings={() => null} hideActions /> @@ -97,14 +67,11 @@ export default function SyntheticsActions({ Orders null} isLoading={isOrdersLoading} setPendingTxns={() => null} hideActions + availableTokensOptions={availableTokensOptions} /> )} @@ -130,13 +97,7 @@ export default function SyntheticsActions({ /> )} - +
    diff --git a/src/pages/SyntheticsPage/SyntheticsPage.tsx b/src/pages/SyntheticsPage/SyntheticsPage.tsx index 575af81175..a05a0e6e1a 100644 --- a/src/pages/SyntheticsPage/SyntheticsPage.tsx +++ b/src/pages/SyntheticsPage/SyntheticsPage.tsx @@ -2,7 +2,6 @@ import { Plural, Trans, t } from "@lingui/macro"; import cx from "classnames"; import Checkbox from "components/Checkbox/Checkbox"; import Footer from "components/Footer/Footer"; -import { ClaimModal } from "components/Synthetics/ClaimModal/ClaimModal"; import { Claims } from "components/Synthetics/Claims/Claims"; import { OrderList } from "components/Synthetics/OrderList/OrderList"; import { PositionEditor } from "components/Synthetics/PositionEditor/PositionEditor"; @@ -15,11 +14,8 @@ import Tab from "components/Tab/Tab"; import { DEFAULT_HIGHER_SLIPPAGE_AMOUNT } from "config/factors"; import { getSyntheticsListSectionKey } from "config/localStorage"; import { getToken } from "config/tokens"; -import { isSwapOrderType } from "domain/synthetics/orders"; import { cancelOrdersTxn } from "domain/synthetics/orders/cancelOrdersTxn"; -import { useOrdersInfo } from "domain/synthetics/orders/useOrdersInfo"; -import { PositionInfo, getPositionKey } from "domain/synthetics/positions"; -import { usePositionsInfo } from "domain/synthetics/positions/usePositionsInfo"; +import { PositionInfo } from "domain/synthetics/positions"; import { useChainId } from "lib/chains"; import { getPageTitle } from "lib/legacy"; import { useLocalStorageSerializeKey } from "lib/localStorage"; @@ -27,28 +23,41 @@ import { formatUsd } from "lib/numbers"; import { getByKey } from "lib/objects"; import { useCallback, useEffect, useMemo, useState } from "react"; -import { useMarketsInfo } from "domain/synthetics/markets"; import Helmet from "react-helmet"; -import { SettleAccruedFundingFeeModal } from "components/Synthetics/SettleAccruedFundingFeeModal/SettleAccruedFundingFeeModal"; import { useIsLastSubaccountAction, useSubaccount, useSubaccountCancelOrdersDetailsMessage, } from "context/SubaccountContext/SubaccountContext"; +import { + useIsOrdersLoading, + useIsPositionsLoading, + useMarketsInfoData, + useOrdersInfoData, + usePositionsInfoData, + useSavedIsPnlInLeverage, + useTokensData, +} from "context/SyntheticsStateContext/hooks/globalsHooks"; +import { + useTradeboxAvailableTokensOptions, + useTradeboxFromTokenAddress, + useTradeboxSetActivePosition, + useTradeboxToTokenAddress, + useTradeboxTradeFlags, +} from "context/SyntheticsStateContext/hooks/tradeboxHooks"; import { getMarketIndexName, getMarketPoolName, getTotalClaimableFundingUsd } from "domain/synthetics/markets"; import { TradeMode } from "domain/synthetics/trade"; -import { useSelectedTradeOption } from "domain/synthetics/trade/useSelectedTradeOption"; import { getMidPrice } from "domain/tokens"; import { helperToast } from "lib/helperToast"; import useWallet from "lib/wallets/useWallet"; +import { useRebatesInfo } from "domain/synthetics/fees/useRebatesInfo"; +import { calcTotalRebateUsd } from "components/Synthetics/Claims/utils"; export type Props = { - savedIsPnlInLeverage: boolean; shouldDisableValidation: boolean; savedShouldShowPositionLines: boolean; showPnlAfterFees: boolean; - savedShowPnlAfterFees: boolean; savedSlippageAmount: number; setSavedShouldShowPositionLines: (value: boolean) => void; setPendingTxns: (txns: any) => void; @@ -66,7 +75,6 @@ enum ListSection { export function SyntheticsPage(p: Props) { const { - savedIsPnlInLeverage, shouldDisableValidation, savedShouldShowPositionLines, showPnlAfterFees, @@ -74,61 +82,32 @@ export function SyntheticsPage(p: Props) { setSavedShouldShowPositionLines, setPendingTxns, setTradePageVersion, - savedShowPnlAfterFees, savedSlippageAmount, openSettings, } = p; const { chainId } = useChainId(); const { signer, account } = useWallet(); - const { marketsInfoData, tokensData, pricesUpdatedAt } = useMarketsInfo(chainId); - - const { positionsInfoData, isLoading: isPositionsLoading } = usePositionsInfo(chainId, { - marketsInfoData, - tokensData, - pricesUpdatedAt, - showPnlInLeverage: savedIsPnlInLeverage, - account, - }); - - const { ordersInfoData, isLoading: isOrdersLoading } = useOrdersInfo(chainId, { - account, - marketsInfoData, - positionsInfoData, - tokensData, - }); - const [isSettling, setIsSettling] = useState(false); + const savedIsPnlInLeverage = useSavedIsPnlInLeverage(); + const marketsInfoData = useMarketsInfoData(); + const tokensData = useTokensData(); + const positionsInfoData = usePositionsInfoData(); + const isPositionsLoading = useIsPositionsLoading(); + const ordersInfoData = useOrdersInfoData(); + const isOrdersLoading = useIsOrdersLoading(); - const { - tradeType, - tradeMode, - tradeFlags, - isWrapOrUnwrap, - fromTokenAddress, - fromToken, - toTokenAddress, - toToken, - marketAddress, - marketInfo, - collateralAddress, - collateralToken, - availableTokensOptions, - avaialbleTradeModes, - setTradeType, - setTradeMode, - setFromTokenAddress, - setToTokenAddress, - setMarketAddress, - setCollateralAddress, - setActivePosition, - switchTokenAddresses, - } = useSelectedTradeOption(chainId, { marketsInfoData, tokensData }); + const { accruedPositionPriceImpactFees, claimablePositionPriceImpactFees } = useRebatesInfo(chainId); + const [isSettling, setIsSettling] = useState(false); const [listSection, setListSection] = useLocalStorageSerializeKey( getSyntheticsListSectionKey(chainId), ListSection.Positions ); - const { isSwap, isLong } = tradeFlags; + const { isSwap } = useTradeboxTradeFlags(); + const fromTokenAddress = useTradeboxFromTokenAddress(); + const toTokenAddress = useTradeboxToTokenAddress(); + const availableTokensOptions = useTradeboxAvailableTokensOptions(); + const setActivePosition = useTradeboxSetActivePosition(); const { indexTokens, sortedIndexTokensWithPoolValue, swapTokens, sortedLongAndShortTokens } = availableTokensOptions; const { chartToken, availableChartTokens } = useMemo(() => { @@ -158,54 +137,29 @@ export function SyntheticsPage(p: Props) { return {}; } }, [ - chainId, fromTokenAddress, - indexTokens, - isSwap, toTokenAddress, - sortedIndexTokensWithPoolValue, + chainId, + isSwap, swapTokens, + indexTokens, + sortedIndexTokensWithPoolValue, sortedLongAndShortTokens, ]); const [closingPositionKey, setClosingPositionKey] = useState(); const closingPosition = getByKey(positionsInfoData, closingPositionKey); + const [selectedPositionOrderKey, setSelectedPositionOrderKey] = useState(); + const [editingPositionKey, setEditingPositionKey] = useState(); const editingPosition = getByKey(positionsInfoData, editingPositionKey); const [gettingPendingFeePositionKeys, setGettingPendingFeePositionKeys] = useState([]); - const selectedPositionKey = useMemo(() => { - if (!account || !collateralAddress || !marketAddress || !tradeType) { - return undefined; - } - - return getPositionKey(account, marketAddress, collateralAddress, isLong); - }, [account, collateralAddress, marketAddress, tradeType, isLong]); - const selectedPosition = getByKey(positionsInfoData, selectedPositionKey); - const [selectedOrdersKeys, setSelectedOrdersKeys] = useState<{ [key: string]: boolean }>({}); const selectedOrdersKeysArr = Object.keys(selectedOrdersKeys).filter((key) => selectedOrdersKeys[key]); const [isCancelOrdersProcessig, setIsCancelOrdersProcessig] = useState(false); - const existingOrder = useMemo(() => { - if (!selectedPositionKey) { - return undefined; - } - - return Object.values(ordersInfoData || {}) - .filter((order) => !isSwapOrderType(order.orderType)) - .find((order) => { - if (isSwapOrderType(order.orderType)) { - return false; - } - - return ( - getPositionKey(order.account, order.marketAddress, order.targetCollateralToken.address, order.isLong) === - selectedPositionKey - ); - }); - }, [ordersInfoData, selectedPositionKey]); const { positionsCount, ordersCount, ordersErrorsCount, ordersWarningsCount } = useMemo(() => { const positions = Object.values(positionsInfoData || {}); @@ -218,13 +172,21 @@ export function SyntheticsPage(p: Props) { ordersWarningsCount: orders.filter((order) => order.errorLevel === "warning").length, }; }, [ordersInfoData, positionsInfoData]); - const hasClaimables = useMemo(() => { + const hasClaimableFees = useMemo(() => { const markets = Object.values(marketsInfoData ?? {}); const totalClaimableFundingUsd = getTotalClaimableFundingUsd(markets); return totalClaimableFundingUsd.gt(0); }, [marketsInfoData]); - const [isClaiming, setIsClaiming] = useState(false); + const hasClaimableRebates = useMemo( + () => calcTotalRebateUsd(claimablePositionPriceImpactFees, tokensData, false).gt(0), + [claimablePositionPriceImpactFees, tokensData] + ); + + let totalClaimables = 0; + + if (hasClaimableFees) totalClaimables += 1; + if (hasClaimableRebates) totalClaimables += 1; const subaccount = useSubaccount(null, selectedOrdersKeysArr.length); const cancelOrdersDetailsMessage = useSubaccountCancelOrdersDetailsMessage(undefined, selectedOrdersKeysArr.length); @@ -264,6 +226,14 @@ export function SyntheticsPage(p: Props) { }); } + function handleOrderClick(key?: string) { + setListSection(ListSection.Orders); + setSelectedPositionOrderKey(key); + if (key) { + setSelectedOrdersKeys((prev) => ({ ...prev, [key]: true })); + } + } + useEffect(() => { const chartTokenData = getByKey(tokensData, chartToken?.address); if (!chartTokenData) return; @@ -304,7 +274,7 @@ export function SyntheticsPage(p: Props) { setIsSettling(true); } - function renderOrdersTabTitle() { + const renderOrdersTabTitle = useCallback(() => { if (!ordersCount) { return (
    @@ -323,16 +293,46 @@ export function SyntheticsPage(p: Props) {
    ); + }, [ordersCount, ordersErrorsCount, ordersWarningsCount]); + + const tabLabels = useMemo( + () => ({ + [ListSection.Positions]: t`Positions${positionsCount ? ` (${positionsCount})` : ""}`, + [ListSection.Orders]: renderOrdersTabTitle(), + [ListSection.Trades]: t`Trades`, + [ListSection.Claims]: totalClaimables > 0 ? t`Claims (${totalClaimables})` : t`Claims`, + }), + [positionsCount, renderOrdersTabTitle, totalClaimables] + ); + const tabOptions = useMemo(() => Object.keys(ListSection), []); + + function renderClaims() { + return ( + + ); } return (
    - + `} +
    @@ -343,9 +343,6 @@ export function SyntheticsPage(p: Props) { positionsInfo={positionsInfoData} chartTokenAddress={chartToken?.address} availableTokens={availableChartTokens} - onSelectChartTokenAddress={setToTokenAddress} - tradeFlags={tradeFlags} - currentTradeType={tradeType} tradePageVersion={tradePageVersion} setTradePageVersion={setTradePageVersion} avaialbleTokenOptions={availableTokensOptions} @@ -356,19 +353,14 @@ export function SyntheticsPage(p: Props) {
    setListSection(section)} type="inline" className="Exchange-list-tabs" />
    - {selectedOrdersKeysArr.length > 0 && ( + {listSection === ListSection.Orders && selectedOrdersKeysArr.length > 0 && (
    @@ -485,13 +426,8 @@ export function SyntheticsPage(p: Props) {
    setListSection(section)} type="inline" @@ -500,59 +436,34 @@ export function SyntheticsPage(p: Props) {
    {listSection === ListSection.Positions && ( setListSection(ListSection.Orders)} + onOrdersClick={handleOrderClick} onSelectPositionClick={onSelectPositionClick} onClosePositionClick={setClosingPositionKey} onEditCollateralClick={setEditingPositionKey} onSettlePositionFeesClick={handleSettlePositionFeesClick} showPnlAfterFees={showPnlAfterFees} - savedShowPnlAfterFees={savedShowPnlAfterFees} - currentMarketAddress={marketAddress} - currentCollateralAddress={collateralAddress} - currentTradeType={tradeType} openSettings={openSettings} /> )} {listSection === ListSection.Orders && ( )} - {listSection === ListSection.Trades && ( - - )} - {listSection === ListSection.Claims && ( - - )} + {listSection === ListSection.Trades && } + {listSection === ListSection.Claims && renderClaims()}
    - setIsClaiming(false)} - setPendingTxns={setPendingTxns} - /> - { - setGettingPendingFeePositionKeys([]); - setIsSettling(false); - }, [])} - />
    ); diff --git a/src/pages/SyntheticsStats/SyntheticsStats.tsx b/src/pages/SyntheticsStats/SyntheticsStats.tsx index 9b36e63a5c..6ec2930531 100644 --- a/src/pages/SyntheticsStats/SyntheticsStats.tsx +++ b/src/pages/SyntheticsStats/SyntheticsStats.tsx @@ -15,9 +15,9 @@ import { getMaxOpenInterestUsd, getMaxReservedUsd, getReservedUsd, - useMarketsInfo, + useMarketsInfoRequest, } from "domain/synthetics/markets"; -import { usePositionsConstants } from "domain/synthetics/positions"; +import { usePositionsConstantsRequest } from "domain/synthetics/positions"; import { convertToUsd, getMidPrice } from "domain/synthetics/tokens"; import "./SyntheticsStats.scss"; import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; @@ -30,7 +30,7 @@ function pow(bn: BigNumber, exponent: BigNumber) { const n = Number(bn.toString()) / 1e30; const e = Number(exponent.toString()) / 1e30; const afterExponent = Math.pow(n, e); - return expandDecimals((afterExponent * 1e10).toFixed(0), 20); + return expandDecimals(afterExponent.toFixed(0), 30); } function formatAmountHuman(amount: BigNumberish | undefined, tokenDecimals: number, showDollar = false) { @@ -66,11 +66,19 @@ function formatFactor(factor: BigNumber) { return formatAmount(factor, 30, factorDecimals); } +const CSV_EXCLUDED_FIELDS = [ + "longToken", + "shortToken", + "indexToken", + "longPoolAmountAdjustment", + "shortPoolAmountAdjustment", +]; + export function SyntheticsStats() { const { chainId } = useChainId(); - const { marketsInfoData } = useMarketsInfo(chainId); - const { minCollateralUsd, minPositionSizeUsd } = usePositionsConstants(chainId); + const { marketsInfoData } = useMarketsInfoRequest(chainId); + const { minCollateralUsd, minPositionSizeUsd } = usePositionsConstantsRequest(chainId); const markets = Object.values(marketsInfoData || {}); markets.sort((a, b) => { @@ -1053,6 +1061,26 @@ export function SyntheticsStats() { } showDollar={false} /> + + + +
    )} @@ -1066,13 +1094,7 @@ export function SyntheticsStats() {
    , resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.1#~builtin, resolve@patch:resolve@^1.22.2#~builtin": - version: 1.22.3 - resolution: "resolve@patch:resolve@npm%3A1.22.3#~builtin::version=1.22.3&hash=07638b" - dependencies: - is-core-module: ^2.12.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: ad59734723b596d0891321c951592ed9015a77ce84907f89c9d9307dd0c06e11a67906a3e628c4cae143d3e44898603478af0ddeb2bba3f229a9373efe342665 - languageName: node - linkType: hard - -"resolve@patch:resolve@^1.12.0#~builtin, resolve@patch:resolve@^1.22.4#~builtin": +"resolve@patch:resolve@^1.1.7#~builtin, resolve@patch:resolve@^1.12.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.2#~builtin, resolve@patch:resolve@^1.22.4#~builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#~builtin::version=1.22.8&hash=07638b" dependencies: @@ -17486,19 +17103,7 @@ __metadata: languageName: node linkType: hard -"safe-array-concat@npm:^1.0.0": - version: 1.0.0 - resolution: "safe-array-concat@npm:1.0.0" - dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.2.0 - has-symbols: ^1.0.3 - isarray: ^2.0.5 - checksum: f43cb98fe3b566327d0c09284de2b15fb85ae964a89495c1b1a5d50c7c8ed484190f4e5e71aacc167e16231940079b326f2c0807aea633d47cc7322f40a6b57f - languageName: node - linkType: hard - -"safe-array-concat@npm:^1.0.1": +"safe-array-concat@npm:^1.0.0, safe-array-concat@npm:^1.0.1": version: 1.0.1 resolution: "safe-array-concat@npm:1.0.1" dependencies: @@ -18374,17 +17979,6 @@ __metadata: languageName: node linkType: hard -"string.prototype.trim@npm:^1.2.7": - version: 1.2.7 - resolution: "string.prototype.trim@npm:1.2.7" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 05b7b2d6af63648e70e44c4a8d10d8cc457536df78b55b9d6230918bde75c5987f6b8604438c4c8652eb55e4fc9725d2912789eb4ec457d6995f3495af190c09 - languageName: node - linkType: hard - "string.prototype.trim@npm:^1.2.8": version: 1.2.8 resolution: "string.prototype.trim@npm:1.2.8" @@ -18396,17 +17990,6 @@ __metadata: languageName: node linkType: hard -"string.prototype.trimend@npm:^1.0.6": - version: 1.0.6 - resolution: "string.prototype.trimend@npm:1.0.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 0fdc34645a639bd35179b5a08227a353b88dc089adf438f46be8a7c197fc3f22f8514c1c9be4629b3cd29c281582730a8cbbad6466c60f76b5f99cf2addb132e - languageName: node - linkType: hard - "string.prototype.trimend@npm:^1.0.7": version: 1.0.7 resolution: "string.prototype.trimend@npm:1.0.7" @@ -18418,17 +18001,6 @@ __metadata: languageName: node linkType: hard -"string.prototype.trimstart@npm:^1.0.6": - version: 1.0.6 - resolution: "string.prototype.trimstart@npm:1.0.6" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 - es-abstract: ^1.20.4 - checksum: 89080feef416621e6ef1279588994305477a7a91648d9436490d56010a1f7adc39167cddac7ce0b9884b8cdbef086987c4dcb2960209f2af8bac0d23ceff4f41 - languageName: node - linkType: hard - "string.prototype.trimstart@npm:^1.0.7": version: 1.0.7 resolution: "string.prototype.trimstart@npm:1.0.7" @@ -19093,7 +18665,7 @@ __metadata: languageName: node linkType: hard -"tsconfig-paths@npm:^3.14.1, tsconfig-paths@npm:^3.14.2": +"tsconfig-paths@npm:^3.14.2": version: 3.14.2 resolution: "tsconfig-paths@npm:3.14.2" dependencies: @@ -19978,20 +19550,7 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.10, which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.2": - version: 1.1.11 - resolution: "which-typed-array@npm:1.1.11" - dependencies: - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.2 - for-each: ^0.3.3 - gopd: ^1.0.1 - has-tostringtag: ^1.0.0 - checksum: 711ffc8ef891ca6597b19539075ec3e08bb9b4c2ca1f78887e3c07a977ab91ac1421940505a197758fb5939aa9524976d0a5bbcac34d07ed6faa75cedbb17206 - languageName: node - linkType: hard - -"which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.9": +"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.2, which-typed-array@npm:^1.1.9": version: 1.1.13 resolution: "which-typed-array@npm:1.1.13" dependencies: