Skip to content

Commit

Permalink
Merge pull request #1502 from gmx-io/release-55
Browse files Browse the repository at this point in the history
Release 55
  • Loading branch information
midas-myth authored Jan 15, 2025
2 parents 427da58 + 4e7bc31 commit e5c7993
Show file tree
Hide file tree
Showing 117 changed files with 1,998 additions and 1,243 deletions.
2 changes: 2 additions & 0 deletions sdk/src/configs/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ export const TOKENS: { [chainId: number]: Token[] } = {
priceDecimals: 4,
address: "0x565609fAF65B92F7be02468acF86f8979423e514",
decimals: 18,
categories: ["layer1"],
imageUrl: "https://assets.coingecko.com/coins/images/12559/small/coin-round-red.png?1604021818",
coingeckoUrl: "https://www.coingecko.com/en/coins/avalanche",
coingeckoSymbol: "AVAX",
Expand Down Expand Up @@ -722,6 +723,7 @@ export const TOKENS: { [chainId: number]: Token[] } = {
address: "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
isWrapped: true,
baseSymbol: "AVAX",
categories: ["layer1"],
imageUrl: "https://assets.coingecko.com/coins/images/12559/small/coin-round-red.png?1604021818",
coingeckoUrl: "https://www.coingecko.com/en/coins/avalanche",
explorerUrl: "https://snowtrace.io/address/0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
Expand Down
1 change: 1 addition & 0 deletions sdk/src/types/fees.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export type ExecutionFee = {
feeTokenAmount: bigint;
feeToken: Token;
warning?: string;
gasLimit: bigint;
isFeeHigh: boolean;
isFeeVeryHigh: boolean;
};
Expand Down
18 changes: 11 additions & 7 deletions sdk/src/utils/callContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,17 @@ export async function callContract(
});
});

const res = await Promise.any(txnCalls).catch((error) => {
if (error.errors && error.errors.length > 1) {
// eslint-disable-next-line no-console
console.error("All transactions failed", ...error.errors);
}
throw error.errors ? error.errors[0] : error;
});
const res = await Promise.any(txnCalls)
.catch((error) => {
if (error.errors && error.errors.length > 1) {
// eslint-disable-next-line no-console
console.error("All transactions failed", ...error.errors);
}
throw error.errors ? error.errors[0] : error;
})
.catch((error) => {
throw error;
});

return res;
}
1 change: 1 addition & 0 deletions sdk/src/utils/fees/executionFee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export function getExecutionFee(
feeUsd,
feeTokenAmount,
feeToken: nativeToken,
gasLimit,
isFeeHigh,
isFeeVeryHigh,
};
Expand Down
101 changes: 12 additions & 89 deletions src/App/App.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import "@wagmi/connectors";

import { i18n } from "@lingui/core";
import { Trans } from "@lingui/macro";
import { I18nProvider } from "@lingui/react";
import { useEffect, useState } from "react";
import { useEffect } from "react";
import { HashRouter as Router } from "react-router-dom";
import { SWRConfig } from "swr";

Expand All @@ -16,27 +15,22 @@ import "./App.scss";

import SEO from "components/Common/SEO";

import { getExplorerUrl } from "config/chains";
import { LANGUAGE_LOCALSTORAGE_KEY } from "config/localStorage";
import { GlobalStateProvider } from "context/GlobalContext/GlobalContextProvider";
import { SettingsContextProvider } from "context/SettingsContext/SettingsContextProvider";
import { SubaccountContextProvider } from "context/SubaccountContext/SubaccountContext";
import { SyntheticsEventsProvider } from "context/SyntheticsEvents";
import { WebsocketContextProvider } from "context/WebsocketContext/WebsocketContextProvider";
import { PendingTransaction } from "domain/legacy";
import { TokensFavoritesContextProvider } from "domain/synthetics/tokens/useTokensFavorites";
import { useChainId } from "lib/chains";
import { helperToast } from "lib/helperToast";
import { defaultLocale, dynamicActivate } from "lib/i18n";
import { RainbowKitProviderWrapper } from "lib/wallets/WalletProvider";
import { useEthersSigner } from "lib/wallets/useEthersSigner";
import { AppRoutes } from "./AppRoutes";
import { SWRConfigProp } from "./swrConfig";

import ExternalLink from "components/ExternalLink/ExternalLink";
import { sendPendingOrderTxnErrorMetric } from "lib/metrics";
import { AppRoutes } from "./AppRoutes";
import { PendingTxnsContextProvider } from "context/PendingTxnsContext/PendingTxnsContext";
import { SettingsContextProvider } from "context/SettingsContext/SettingsContextProvider";
import { SorterContextProvider } from "context/SorterContext/SorterContextProvider";
import { SubaccountContextProvider } from "context/SubaccountContext/SubaccountContext";
import { SyntheticsEventsProvider } from "context/SyntheticsEvents";
import { TokensBalancesContextProvider } from "context/TokensBalancesContext/TokensBalancesContextProvider";
import { sendUserAnalyticsOrderResultEvent } from "lib/userAnalytics";
import { TokensFavoritesContextProvider } from "context/TokensFavoritesContext/TokensFavoritesContextProvider";
import { WebsocketContextProvider } from "context/WebsocketContext/WebsocketContextProvider";

// @ts-ignore
if (window?.ethereum?.autoRefreshOnNetworkChange) {
Expand All @@ -45,83 +39,15 @@ if (window?.ethereum?.autoRefreshOnNetworkChange) {
}

function App() {
const signer = useEthersSigner();
const { chainId } = useChainId();

const [pendingTxns, setPendingTxns] = useState<PendingTransaction[]>([]);

useEffect(() => {
const checkPendingTxns = async () => {
if (!signer) {
return;
}

const updatedPendingTxns: any[] = [];
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(
<div>
<Trans>
Txn failed.{" "}
<ExternalLink className="!text-white" href={txUrl}>
View
</ExternalLink>
</Trans>
<br />
</div>
);

if (pendingTxn.metricId) {
sendPendingOrderTxnErrorMetric(pendingTxn.metricId);
sendUserAnalyticsOrderResultEvent(chainId, pendingTxn.metricId, false);
}
}

if (receipt.status === 1 && pendingTxn.message) {
const txUrl = getExplorerUrl(chainId) + "tx/" + pendingTxn.hash;
helperToast.success(
<div>
<div className="px-10 py-8">
{pendingTxn.message}{" "}
<ExternalLink href={txUrl} className="!text-white">
<Trans>View</Trans>
</ExternalLink>
</div>
{pendingTxn.messageDetails && (
<div className="border-t-[1.5px] border-[#0f463d] px-10 py-8">{pendingTxn.messageDetails}</div>
)}
</div>,
{
className: "OrdersStatusNotificiation",
}
);
}
continue;
}
updatedPendingTxns.push(pendingTxn);
}

if (updatedPendingTxns.length !== pendingTxns.length) {
setPendingTxns(updatedPendingTxns);
}
};

const interval = setInterval(() => {
checkPendingTxns();
}, 2 * 1000);
return () => clearInterval(interval);
}, [signer, pendingTxns, chainId]);

useEffect(() => {
const defaultLanguage = localStorage.getItem(LANGUAGE_LOCALSTORAGE_KEY) || defaultLocale;
dynamicActivate(defaultLanguage);
}, []);

let app = <AppRoutes />;
app = <SorterContextProvider>{app}</SorterContextProvider>;
app = <TokensFavoritesContextProvider>{app}</TokensFavoritesContextProvider>;
app = <SyntheticsEventsProvider>{app}</SyntheticsEventsProvider>;
app = <SubaccountContextProvider>{app}</SubaccountContextProvider>;
Expand All @@ -130,17 +56,14 @@ function App() {
app = <SEO>{app}</SEO>;
app = <RainbowKitProviderWrapper>{app}</RainbowKitProviderWrapper>;
app = <I18nProvider i18n={i18n as any}>{app}</I18nProvider>;
app = <PendingTxnsContextProvider>{app}</PendingTxnsContextProvider>;
app = <SettingsContextProvider>{app}</SettingsContextProvider>;
app = (
<SWRConfig key={chainId} value={SWRConfigProp}>
{app}
</SWRConfig>
);
app = (
<GlobalStateProvider pendingTxns={pendingTxns} setPendingTxns={setPendingTxns}>
{app}
</GlobalStateProvider>
);
app = <GlobalStateProvider>{app}</GlobalStateProvider>;
app = <Router>{app}</Router>;

return app;
Expand Down
5 changes: 3 additions & 2 deletions src/App/AppRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { useConfigureUserAnalyticsProfile } from "lib/userAnalytics/useConfigure
import { useWalletConnectedUserAnalyticsEvent } from "lib/userAnalytics/useWalletConnectedEvent";
import { userAnalytics } from "lib/userAnalytics/UserAnalytics";
import { LandingPageAgreementConfirmationEvent } from "lib/userAnalytics/types";
import { useSettings } from "context/SettingsContext/SettingsContextProvider";

const Zoom = cssTransition({
enter: "zoomIn",
Expand Down Expand Up @@ -88,11 +89,11 @@ export function AppRoutes() {
const [shouldHideRedirectModal, setShouldHideRedirectModal] = useState(false);

const [selectedToPage, setSelectedToPage] = useState("");
const [isSettingsVisible, setIsSettingsVisible] = useState(false);
const { isSettingsVisible, setIsSettingsVisible } = useSettings();

const openSettings = useCallback(() => {
setIsSettingsVisible(true);
}, []);
}, [setIsSettingsVisible]);

const localStorageCode = window.localStorage.getItem(REFERRAL_CODE_KEY);
const baseUrl = getAppBaseUrl();
Expand Down
3 changes: 2 additions & 1 deletion src/components/FavoriteTabs/FavoriteTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
tokensFavoritesTabOptionLabels,
tokensFavoritesTabOptions,
useTokensFavorites,
} from "domain/synthetics/tokens/useTokensFavorites";
} from "context/TokensFavoritesContext/TokensFavoritesContextProvider";
import { useLocalizedMap } from "lib/i18n";

import Button from "components/Button/Button";
Expand All @@ -26,6 +26,7 @@ export function FavoriteTabs({ favoritesKey }: { favoritesKey: TokenFavoriteKey
"!bg-cold-blue-500": tab === option,
})}
onClick={() => setTab(option)}
data-selected={tab === option}
>
{localizedTabOptionLabels[option]}
</Button>
Expand Down
26 changes: 15 additions & 11 deletions src/components/Glp/GlpSwap.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
SECONDS_PER_YEAR,
USDG_DECIMALS,
} from "lib/legacy";
import { formatBalanceAmount, formatBalanceAmountWithUsd } from "lib/numbers";
import { useEffect, useMemo, useState } from "react";
import { useHistory } from "react-router-dom";
import useSWR from "swr";
Expand Down Expand Up @@ -67,7 +68,7 @@ import {
limitDecimals,
parseValue,
} from "lib/numbers";
import { usePendingTxns } from "lib/usePendingTxns";
import { usePendingTxns } from "context/PendingTxnsContext/PendingTxnsContext";
import useSearchParams from "lib/useSearchParams";
import useIsMetamaskMobile from "lib/wallets/useIsMetamaskMobile";
import useWallet from "lib/wallets/useWallet";
Expand Down Expand Up @@ -161,7 +162,7 @@ function getTooltipContent(managedUsd, tokenInfo, token) {
export default function GlpSwap(props) {
const { isBuying, setIsBuying } = props;
const { savedAllowedSlippage, shouldDisableValidationForTesting } = useSettings();
const [, setPendingTxns] = usePendingTxns();
const { setPendingTxns } = usePendingTxns();
const history = useHistory();
const searchParams = useSearchParams();
const isMetamaskMobile = useIsMetamaskMobile();
Expand Down Expand Up @@ -978,17 +979,19 @@ export default function GlpSwap(props) {
<Trans>Wallet</Trans>
</div>
<div className="value">
{formatAmount(glpBalance, GLP_DECIMALS, 4, true)} GLP ($
{formatAmount(glpBalanceUsd, USD_DECIMALS, 2, true)})
{glpBalance === undefined || glpBalanceUsd === undefined
? "..."
: formatBalanceAmountWithUsd(glpBalance, glpBalanceUsd, GLP_DECIMALS, "GLP", true)}
</div>
</div>
<div className="App-card-row">
<div className="label">
<Trans>Staked</Trans>
</div>
<div className="value">
{formatAmount(glpBalance, GLP_DECIMALS, 4, true)} GLP ($
{formatAmount(glpBalanceUsd, USD_DECIMALS, 2, true)})
{glpBalance === undefined || glpBalanceUsd === undefined
? "..."
: formatBalanceAmountWithUsd(glpBalance, glpBalanceUsd, GLP_DECIMALS, "GLP", true)}
</div>
</div>
</div>
Expand Down Expand Up @@ -1073,7 +1076,7 @@ export default function GlpSwap(props) {
<BuyInputSection
topLeftLabel={payLabel}
topRightLabel={t`Balance`}
topRightValue={`${formatAmount(swapTokenBalance, swapToken.decimals, 4, true)}`}
topRightValue={formatBalanceAmount(swapTokenBalance, swapToken.decimals)}
inputValue={swapValue}
onInputValueChange={onSwapValueChange}
showMaxButton={
Expand Down Expand Up @@ -1102,7 +1105,7 @@ export default function GlpSwap(props) {
<BuyInputSection
topLeftLabel={payLabel}
topRightLabel={t`Available`}
topRightValue={`${formatAmount(maxSellAmount, GLP_DECIMALS, 4, true)}`}
topRightValue={glpBalance === undefined ? "..." : formatBalanceAmount(maxSellAmount, GLP_DECIMALS)}
inputValue={glpValue}
onInputValueChange={onGlpValueChange}
showMaxButton={glpValue !== formatAmountFree(maxSellAmount, GLP_DECIMALS, GLP_DECIMALS)}
Expand Down Expand Up @@ -1135,7 +1138,7 @@ export default function GlpSwap(props) {
topLeftLabel={receiveLabel}
topRightLabel={t`Balance`}
topLeftValue={receiveBalance}
topRightValue={`${formatAmount(glpBalance, GLP_DECIMALS, 4, true)}`}
topRightValue={glpBalance === undefined ? "..." : formatBalanceAmount(glpBalance, GLP_DECIMALS)}
inputValue={glpValue}
onInputValueChange={onGlpValueChange}
defaultTokenName="GLP"
Expand Down Expand Up @@ -1464,8 +1467,9 @@ export default function GlpSwap(props) {
)}
</td>
<td>
{formatKeyAmount(tokenInfo, "balance", tokenInfo.decimals, 2, true)} {tokenInfo.symbol} ($
{formatAmount(balanceUsd, USD_DECIMALS, 2, true)})
{tokenInfo.balance === undefined || balanceUsd === undefined
? "..."
: formatBalanceAmountWithUsd(tokenInfo.balance, balanceUsd, tokenInfo.decimals, tokenInfo.symbol)}
</td>
<td>{renderFees()}</td>
<td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { useGlvGmMarketsWithComposition } from "components/Synthetics/MarketStat
import { ButtonRowScrollFadeContainer } from "components/TableScrollFade/TableScrollFade";
import TokenIcon from "components/TokenIcon/TokenIcon";

import { useTokensFavorites } from "context/TokensFavoritesContext/TokensFavoritesContextProvider";
import {
GlvInfo,
MarketInfo,
Expand All @@ -24,7 +25,6 @@ import {
} from "domain/synthetics/markets";
import { isGlvInfo } from "domain/synthetics/markets/glv";
import { convertToUsd } from "domain/synthetics/tokens";
import { useTokensFavorites } from "domain/synthetics/tokens/useTokensFavorites";
import { stripBlacklistedWords } from "domain/tokens/utils";

import Modal from "../Modal/Modal";
Expand Down
4 changes: 2 additions & 2 deletions src/components/MarketSelector/MarketSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import cx from "classnames";
import { ReactNode, useCallback, useMemo, useState } from "react";
import { BiChevronDown } from "react-icons/bi";

import { getCategoryTokenAddresses } from "sdk/configs/tokens";
import { useTokensFavorites } from "context/TokensFavoritesContext/TokensFavoritesContextProvider";
import { MarketInfo, getMarketIndexName } from "domain/synthetics/markets";
import { TokenData, TokensData, convertToUsd } from "domain/synthetics/tokens";
import { useTokensFavorites } from "domain/synthetics/tokens/useTokensFavorites";
import { MissedCoinsPlace } from "domain/synthetics/userFeedback";
import { useMissedCoinsSearch } from "domain/synthetics/userFeedback/useMissedCoinsSearch";
import { stripBlacklistedWords } from "domain/tokens/utils";
import { importImage } from "lib/legacy";
import { formatTokenAmount, formatUsd } from "lib/numbers";
import { getByKey } from "lib/objects";
import { searchBy } from "lib/searchBy";
import { getCategoryTokenAddresses } from "sdk/configs/tokens";

import FavoriteStar from "components/FavoriteStar/FavoriteStar";
import { FavoriteTabs } from "components/FavoriteTabs/FavoriteTabs";
Expand Down
Loading

0 comments on commit e5c7993

Please sign in to comment.