Skip to content

Commit

Permalink
Merge pull request #816 from gmx-io/release-15
Browse files Browse the repository at this point in the history
Release 15
  • Loading branch information
onemicky committed Feb 21, 2024
2 parents f3dc420 + db2316a commit eca9543
Show file tree
Hide file tree
Showing 60 changed files with 2,918 additions and 1,552 deletions.
271 changes: 37 additions & 234 deletions src/App/App.js

Large diffs are not rendered by default.

39 changes: 0 additions & 39 deletions src/App/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -468,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;
Expand Down Expand Up @@ -931,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;
Expand Down
74 changes: 42 additions & 32 deletions src/components/Exchange/ConfirmationBox.js
Original file line number Diff line number Diff line change
@@ -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%;

Expand All @@ -58,7 +65,7 @@ function getSwapSpreadInfo(fromTokenInfo, toTokenInfo, isLong, nativeTokenAddres
}
}

function renderAllowedSlippage(setAllowedSlippage, defaultSlippage) {
function renderAllowedSlippage(setAllowedSlippage, defaultSlippage, allowedSlippage) {
return (
<ExchangeInfoRow
label={
Expand All @@ -84,6 +91,7 @@ function renderAllowedSlippage(setAllowedSlippage, defaultSlippage) {
>
<PercentageInput
onChange={setAllowedSlippage}
value={allowedSlippage}
defaultValue={defaultSlippage}
highValue={EXCESSIVE_SLIPPAGE_AMOUNT}
highValueWarningText={t`Slippage is too high`}
Expand Down Expand Up @@ -664,7 +672,7 @@ export default function ConfirmationBox(props) {
{!toAmount && leverage && leverage.gt(0) && `-`}
{leverage && leverage.eq(0) && `-`}
</ExchangeInfoRow>
{isMarketOrder && renderAllowedSlippage(setAllowedSlippage, savedSlippageAmount)}
{isMarketOrder && renderAllowedSlippage(setAllowedSlippage, savedSlippageAmount, allowedSlippage)}
{showCollateralSpread && (
<ExchangeInfoRow label={t`Collateral Spread`} isWarning={collateralSpreadInfo.isHigh} isTop>
{formatAmount(collateralSpreadInfo.value.mul(100), USD_DECIMALS, 2, true)}%
Expand Down Expand Up @@ -766,8 +774,8 @@ export default function ConfirmationBox(props) {
renderAvailableLiquidity,
hasExistingPosition,
toAmount,
existingPosition?.leverage,
existingPosition?.averagePrice,
existingPosition.leverage,
existingPosition.averagePrice,
leverage,
savedSlippageAmount,
showCollateralSpread,
Expand All @@ -789,6 +797,7 @@ export default function ConfirmationBox(props) {
isTriggerWarningAccepted,
fromUsdMin,
feesUsd,
allowedSlippage,
]);

const renderSwapSection = useCallback(() => {
Expand All @@ -803,7 +812,7 @@ export default function ConfirmationBox(props) {
</ExchangeInfoRow>
)}
{orderOption === LIMIT && renderAvailableLiquidity()}
{isMarketOrder && renderAllowedSlippage(setAllowedSlippage, savedSlippageAmount)}
{isMarketOrder && renderAllowedSlippage(setAllowedSlippage, savedSlippageAmount, allowedSlippage)}
<ExchangeInfoRow label={t`Mark Price`} isTop>
{getExchangeRateDisplay(getExchangeRate(fromTokenInfo, toTokenInfo), fromTokenInfo, toTokenInfo)}
</ExchangeInfoRow>
Expand Down Expand Up @@ -860,6 +869,7 @@ export default function ConfirmationBox(props) {
currentExecutionFees,
feesUsd,
minOut,
allowedSlippage,
]);
const submitButtonRef = useRef(null);

Expand Down
63 changes: 63 additions & 0 deletions src/components/Exchange/ExchangeInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React, { ReactNode } from "react";

interface ExchangeInfoProps {
children?: ReactNode;
divider?: ReactNode;
className?: string;
}

interface ExchangeInfoGroupProps {
children?: ReactNode;
}

const LINE_DIVIDER = <div className="line-divider" />;

function ExchangeInfo({ children, className, divider = LINE_DIVIDER }: ExchangeInfoProps) {
const childrenArr = React.Children.toArray(children) as React.ReactElement[];

return (
<div className={className}>
{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}
</>
);
})}
</div>
);
}

function ExchangeInfoGroup({ children }: ExchangeInfoGroupProps) {
return <>{children}</>;
}

function isExchangeInfoGroup(child: ReactNode) {
return React.isValidElement(child) && child.type === ExchangeInfoGroup;
}

ExchangeInfo.Group = ExchangeInfoGroup;

export { ExchangeInfo };
17 changes: 12 additions & 5 deletions src/components/Exchange/PositionSeller.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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,
Expand All @@ -58,8 +66,6 @@ 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
Expand Down Expand Up @@ -443,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
*/
Expand Down Expand Up @@ -1137,6 +1143,7 @@ export default function PositionSeller(props) {
>
<PercentageInput
onChange={setAllowedSlippage}
value={allowedSlippage}
defaultValue={savedSlippageAmount}
highValue={EXCESSIVE_SLIPPAGE_AMOUNT}
highValueWarningText={t`Slippage is too high`}
Expand Down
24 changes: 18 additions & 6 deletions src/components/Modal/Modal.js → src/components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,45 @@
import "./Modal.css";
import { useRef, useEffect, useMemo } 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";

import "./Modal.css";

const FADE_VARIANTS = {
hidden: { opacity: 0 },
visible: { opacity: 1 },
};

const VISIBLE_STYLES = {
const VISIBLE_STYLES: React.CSSProperties = {
overflow: "hidden",
position: "fixed",
};

const HIDDEN_STYLES = {
const HIDDEN_STYLES: React.CSSProperties = {
overflow: "visible",
position: "fixed",
};

const TRANSITION = { duration: 0.2 };

export default function Modal(props) {
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);
}
Expand All @@ -44,6 +55,7 @@ export default function Modal(props) {
const style = useMemo(() => ({ zIndex }), [zIndex]);

return (
// @ts-ignore
<AnimatePresence>
{isVisible && (
<motion.div
Expand Down
Original file line number Diff line number Diff line change
@@ -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 (
<Portal>
<Modal {...props} />
Expand Down
Loading

0 comments on commit eca9543

Please sign in to comment.