import EventEmitter from 'events';
import React, { useContext, useRef, useState, useEffect } from 'react';
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import { useHistory } from 'react-router-dom';
import isEqual from 'lodash/isEqual';
import { getBlockExplorerLink } from '@metamask/etherscan-link';
import { I18nContext } from '../../../contexts/i18n';
import { MetaMetricsContext } from '../../../contexts/metametrics';
import {
MetaMetricsContextProp,
MetaMetricsEventCategory,
MetaMetricsEventName,
} from '../../../../shared/constants/metametrics';
import {
getCurrentChainId,
getCurrentCurrency,
getRpcPrefsForCurrentProvider,
getUSDConversionRate,
isHardwareWallet,
getHardwareWalletType,
getFullTxData,
} from '../../../selectors';
import {
getUsedQuote,
getFetchParams,
getApproveTxParams,
getUsedSwapsGasPrice,
fetchQuotesAndSetQuoteState,
navigateBackToBuildQuote,
prepareForRetryGetQuotes,
prepareToLeaveSwaps,
getSmartTransactionsOptInStatus,
getSmartTransactionsEnabled,
getCurrentSmartTransactionsEnabled,
getFromTokenInputValue,
getMaxSlippage,
} from '../../../ducks/swaps/swaps';
import Mascot from '../../../components/ui/mascot';
import {
QUOTES_EXPIRED_ERROR,
SWAP_FAILED_ERROR,
ERROR_FETCHING_QUOTES,
QUOTES_NOT_AVAILABLE_ERROR,
CONTRACT_DATA_DISABLED_ERROR,
OFFLINE_FOR_MAINTENANCE,
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP,
} from '../../../../shared/constants/swaps';
import { isSwapsDefaultTokenSymbol } from '../../../../shared/modules/swaps.utils';
import PulseLoader from '../../../components/ui/pulse-loader';
import { DEFAULT_ROUTE } from '../../../helpers/constants/routes';
import {
stopPollingForQuotes,
setDefaultHomeActiveTabName,
} from '../../../store/actions';
import { getRenderableNetworkFeesForQuote } from '../swaps.util';
import SwapsFooter from '../swaps-footer';
import CreateNewSwap from '../create-new-swap';
import ViewOnBlockExplorer from '../view-on-block-explorer';
import { SUPPORT_LINK } from '../../../../shared/lib/ui-utils';
import SwapFailureIcon from './swap-failure-icon';
import SwapSuccessIcon from './swap-success-icon';
import QuotesTimeoutIcon from './quotes-timeout-icon';
export default function AwaitingSwap({
swapComplete,
errorKey,
txHash,
tokensReceived,
submittingSwap,
txId,
}) {
const t = useContext(I18nContext);
const trackEvent = useContext(MetaMetricsContext);
const history = useHistory();
const dispatch = useDispatch();
const animationEventEmitter = useRef(new EventEmitter());
const { swapMetaData } =
useSelector((state) => getFullTxData(state, txId)) || {};
const fetchParams = useSelector(getFetchParams, isEqual);
const fromTokenInputValue = useSelector(getFromTokenInputValue);
const maxSlippage = useSelector(getMaxSlippage);
const usedQuote = useSelector(getUsedQuote, isEqual);
const approveTxParams = useSelector(getApproveTxParams, shallowEqual);
const swapsGasPrice = useSelector(getUsedSwapsGasPrice);
const currentCurrency = useSelector(getCurrentCurrency);
const usdConversionRate = useSelector(getUSDConversionRate);
const chainId = useSelector(getCurrentChainId);
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider, shallowEqual);
const [trackedQuotesExpiredEvent, setTrackedQuotesExpiredEvent] =
useState(false);
let feeinUnformattedFiat;
if (usedQuote && swapsGasPrice) {
const renderableNetworkFees = getRenderableNetworkFeesForQuote({
tradeGas: usedQuote.gasEstimateWithRefund || usedQuote.averageGas,
approveGas: approveTxParams?.gas || '0x0',
gasPrice: swapsGasPrice,
currentCurrency,
conversionRate: usdConversionRate,
tradeValue: usedQuote?.trade?.value,
sourceSymbol: swapMetaData?.token_from,
sourceAmount: usedQuote.sourceAmount,
chainId,
});
feeinUnformattedFiat = renderableNetworkFees.rawNetworkFees;
}
const hardwareWalletUsed = useSelector(isHardwareWallet);
const hardwareWalletType = useSelector(getHardwareWalletType);
const smartTransactionsOptInStatus = useSelector(
getSmartTransactionsOptInStatus,
);
const smartTransactionsEnabled = useSelector(getSmartTransactionsEnabled);
const currentSmartTransactionsEnabled = useSelector(
getCurrentSmartTransactionsEnabled,
);
const sensitiveProperties = {
token_from: swapMetaData?.token_from,
token_from_amount: swapMetaData?.token_from_amount,
token_to: swapMetaData?.token_to,
request_type: fetchParams?.balanceError ? 'Quote' : 'Order',
slippage: swapMetaData?.slippage,
custom_slippage: swapMetaData?.slippage === 2,
gas_fees: feeinUnformattedFiat,
is_hardware_wallet: hardwareWalletUsed,
hardware_wallet_type: hardwareWalletType,
stx_enabled: smartTransactionsEnabled,
current_stx_enabled: currentSmartTransactionsEnabled,
stx_user_opt_in: smartTransactionsOptInStatus,
};
const baseNetworkUrl =
rpcPrefs.blockExplorerUrl ??
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ??
null;
const blockExplorerUrl = getBlockExplorerLink(
{ hash: txHash, chainId },
{ blockExplorerUrl: baseNetworkUrl },
);
let headerText;
let statusImage;
let descriptionText;
let submitText;
let content;
if (errorKey === OFFLINE_FOR_MAINTENANCE) {
headerText = t('offlineForMaintenance');
descriptionText = t('metamaskSwapsOfflineDescription');
submitText = t('close');
statusImage =