1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 01:47:00 +01:00

Fix issue with awaiting swaps page (#16344)

* fix issue with awaiting swaps and smart-transaction-status pages when service worker dies
This commit is contained in:
Alex Donesky 2022-11-04 11:14:43 -05:00 committed by GitHub
parent 39037684d4
commit 4245f24a2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 171 additions and 39 deletions

View File

@ -103,6 +103,9 @@ const createGetSmartTransactionFeesApiResponse = () => {
export const createSwapsMockStore = () => {
return {
confirmTransaction: {
txData: {},
},
swaps: {
customGas: {
limit: '0x0',
@ -144,6 +147,76 @@ export const createSwapsMockStore = () => {
showFiatInTestnets: true,
},
currentCurrency: 'ETH',
currentNetworkTxList: [
{
id: 6571648590592143,
time: 1667403993369,
status: 'confirmed',
metamaskNetworkId: '5',
originalGasEstimate: '0x7548',
userEditedGasLimit: false,
chainId: '0x5',
loadingDefaults: false,
dappSuggestedGasFees: null,
sendFlowHistory: null,
txParams: {
from: '0x806627172af48bd5b0765d3449a7def80d6576ff',
to: '0x881d40237659c251811cec9c364ef91dc08d300c',
nonce: '0x30',
value: '0x5af3107a4000',
gas: '0x7548',
maxFeePerGas: '0x19286f704d',
maxPriorityFeePerGas: '0x77359400',
},
origin: 'metamask',
actionId: 1667403993358.877,
type: 'swap',
userFeeLevel: 'medium',
defaultGasEstimates: {
estimateType: 'medium',
gas: '0x7548',
maxFeePerGas: '0x19286f704d',
maxPriorityFeePerGas: '0x77359400',
},
sourceTokenSymbol: 'ETH',
destinationTokenSymbol: 'USDC',
destinationTokenDecimals: 6,
destinationTokenAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',
swapMetaData: {
token_from: 'ETH',
token_from_amount: '0.0001',
token_to: 'USDC',
token_to_amount: '0.15471500',
slippage: 2,
custom_slippage: false,
best_quote_source: 'pmm',
other_quote_selected: false,
other_quote_selected_source: '',
gas_fees: '3.016697',
estimated_gas: '30024',
used_gas_price: '0',
is_hardware_wallet: false,
stx_enabled: false,
current_stx_enabled: false,
stx_user_opt_in: false,
reg_tx_fee_in_usd: 3.02,
reg_tx_fee_in_eth: 0.00193,
reg_tx_max_fee_in_usd: 5.06,
reg_tx_max_fee_in_eth: 0.00324,
max_fee_per_gas: '19286f704d',
max_priority_fee_per_gas: '77359400',
base_and_priority_fee_per_gas: 'efd93d95a',
},
swapTokenValue: '0.0001',
estimatedBaseFee: 'e865e455a',
hash: '0x8216e3696e7deb7ca794703015f17d5114a09362ae98f6a1611203e4c9509243',
submittedTime: 1667403996143,
firstRetryBlockNumber: '0x7838fe',
baseFeePerGas: '0xe0ef7d207',
blockTimestamp: '636290e8',
postTxBalance: '19a61aaaf06e4bd1',
},
],
conversionRate: 1,
contractExchangeRates: {
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': 2,

View File

@ -59,7 +59,10 @@ import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
import { getGasLoadingAnimationIsShowing } from '../../ducks/app/app';
import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
import { CUSTOM_GAS_ESTIMATE } from '../../../shared/constants/gas';
import { TRANSACTION_TYPES } from '../../../shared/constants/transaction';
import {
TRANSACTION_STATUSES,
TRANSACTION_TYPES,
} from '../../../shared/constants/transaction';
import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
import { getTokenAddressParam } from '../../helpers/utils/token-util';
import { calcGasTotal } from '../../../shared/lib/transactions-controller-utils';
@ -164,7 +167,12 @@ const mapStateToProps = (state, ownProps) => {
const methodData = getKnownMethodData(state, data) || {};
const fullTxData = getFullTxData(state, txId, customTxParamsData);
const fullTxData = getFullTxData(
state,
txId,
TRANSACTION_STATUSES.UNAPPROVED,
customTxParamsData,
);
const isCollectibleTransfer = Boolean(
allCollectibleContracts?.[selectedAddress]?.[chainId]?.find((contract) => {

View File

@ -20,6 +20,7 @@ import {
getUSDConversionRate,
isHardwareWallet,
getHardwareWalletType,
getFullTxData,
} from '../../../selectors';
import {
@ -72,15 +73,16 @@ export default function AwaitingSwap({
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 { destinationTokenInfo, sourceTokenInfo } = fetchParams?.metaData || {};
const fromTokenInputValue = useSelector(getFromTokenInputValue);
const maxSlippage = useSelector(getMaxSlippage);
const usedQuote = useSelector(getUsedQuote, isEqual);
@ -103,7 +105,7 @@ export default function AwaitingSwap({
currentCurrency,
conversionRate: usdConversionRate,
tradeValue: usedQuote?.trade?.value,
sourceSymbol: sourceTokenInfo?.symbol,
sourceSymbol: swapMetaData?.token_from,
sourceAmount: usedQuote.sourceAmount,
chainId,
});
@ -120,12 +122,12 @@ export default function AwaitingSwap({
getCurrentSmartTransactionsEnabled,
);
const sensitiveProperties = {
token_from: sourceTokenInfo?.symbol,
token_from_amount: fetchParams?.value,
token_to: destinationTokenInfo?.symbol,
token_from: swapMetaData?.token_from,
token_from_amount: swapMetaData?.token_from_amount,
token_to: swapMetaData?.token_to,
request_type: fetchParams?.balanceError ? 'Quote' : 'Order',
slippage: fetchParams?.slippage,
custom_slippage: fetchParams?.slippage === 2,
slippage: swapMetaData?.slippage,
custom_slippage: swapMetaData?.slippage === 2,
gas_fees: feeinUnformattedFiat,
is_hardware_wallet: hardwareWalletUsed,
hardware_wallet_type: hardwareWalletType,
@ -227,7 +229,7 @@ export default function AwaitingSwap({
key="swapOnceTransactionHasProcess-1"
className="awaiting-swap__amount-and-symbol"
>
{destinationTokenInfo.symbol}
{swapMetaData?.token_to}
</span>,
]);
content = blockExplorerUrl && (
@ -245,7 +247,7 @@ export default function AwaitingSwap({
key="swapTokenAvailable-2"
className="awaiting-swap__amount-and-symbol"
>
{`${tokensReceived || ''} ${destinationTokenInfo.symbol}`}
{`${tokensReceived || ''} ${swapMetaData?.token_to}`}
</span>,
]);
content = blockExplorerUrl && (
@ -300,7 +302,7 @@ export default function AwaitingSwap({
} else if (errorKey) {
await dispatch(navigateBackToBuildQuote(history));
} else if (
isSwapsDefaultTokenSymbol(destinationTokenInfo?.symbol, chainId) ||
isSwapsDefaultTokenSymbol(swapMetaData?.token_to, chainId) ||
swapComplete
) {
history.push(DEFAULT_ROUTE);
@ -331,4 +333,5 @@ AwaitingSwap.propTypes = {
CONTRACT_DATA_DISABLED_ERROR,
]),
submittingSwap: PropTypes.bool,
txId: PropTypes.number,
};

View File

@ -29,6 +29,7 @@ const createProps = (customProps = {}) => {
submittingSwap: true,
inputValue: 5,
maxSlippage: SLIPPAGE.DEFAULT,
txId: 6571648590592143,
...customProps,
};
};

View File

@ -515,6 +515,7 @@ export default function Swap() {
swapComplete={false}
errorKey={swapsErrorKey}
txHash={tradeTxData?.hash}
txId={tradeTxData?.id}
submittedTime={tradeTxData?.submittedTime}
/>
);
@ -574,7 +575,7 @@ export default function Swap() {
path={SMART_TRANSACTION_STATUS_ROUTE}
exact
render={() => {
return <SmartTransactionStatus />;
return <SmartTransactionStatus txId={tradeTxData?.id} />;
}}
/>
<Route
@ -586,6 +587,7 @@ export default function Swap() {
swapComplete={tradeConfirmed}
txHash={tradeTxData?.hash}
tokensReceived={tokensReceived}
txId={tradeTxData?.id}
submittingSwap={
routeState === 'awaiting' && !(approveTxId || tradeTxId)
}

View File

@ -73,8 +73,10 @@ export default function SmartTransactionStatus() {
const history = useHistory();
const dispatch = useDispatch();
const fetchParams = useSelector(getFetchParams, isEqual) || {};
const { destinationTokenInfo = {}, sourceTokenInfo = {} } =
fetchParams?.metaData || {};
const {
destinationTokenInfo: fetchParamsDestinationTokenInfo = {},
sourceTokenInfo: fetchParamsSourceTokenInfo = {},
} = fetchParams?.metaData || {};
const hardwareWalletUsed = useSelector(isHardwareWallet);
const hardwareWalletType = useSelector(getHardwareWalletType);
const needsTwoConfirmations = true;
@ -125,9 +127,14 @@ export default function SmartTransactionStatus() {
const sensitiveProperties = {
needs_two_confirmations: needsTwoConfirmations,
token_from: sourceTokenInfo?.symbol,
token_from_amount: fetchParams?.value,
token_to: destinationTokenInfo?.symbol,
token_from:
fetchParamsSourceTokenInfo.symbol ??
latestSmartTransaction?.sourceTokenSymbol,
token_from_amount:
fetchParams?.value ?? latestSmartTransaction?.swapTokenValue,
token_to:
fetchParamsDestinationTokenInfo.symbol ??
latestSmartTransaction?.destinationTokenSymbol,
request_type: fetchParams?.balanceError ? 'Quote' : 'Order',
slippage: fetchParams?.slippage,
custom_slippage: fetchParams?.slippage === 2,
@ -142,7 +149,8 @@ export default function SmartTransactionStatus() {
if (usedQuote?.destinationAmount) {
destinationValue = calcTokenAmount(
usedQuote?.destinationAmount,
destinationTokenInfo.decimals,
fetchParamsDestinationTokenInfo.decimals ??
latestSmartTransaction?.destinationTokenDecimals,
).toPrecision(8);
}
const trackEvent = useContext(MetaMetricsContext);
@ -214,8 +222,14 @@ export default function SmartTransactionStatus() {
}
if (smartTransactionStatus === SMART_TRANSACTION_STATUSES.SUCCESS) {
headerText = t('stxSuccess');
if (destinationTokenInfo?.symbol) {
description = t('stxSuccessDescription', [destinationTokenInfo.symbol]);
if (
fetchParamsDestinationTokenInfo.symbol ||
latestSmartTransaction?.destinationTokenSymbol
) {
description = t('stxSuccessDescription', [
fetchParamsDestinationTokenInfo.symbol ??
latestSmartTransaction?.destinationTokenSymbol,
]);
}
icon = <SuccessIcon />;
} else if (
@ -325,23 +339,34 @@ export default function SmartTransactionStatus() {
fontWeight={FONT_WEIGHT.BOLD}
boxProps={{ marginLeft: 1, marginRight: 2 }}
>
{sourceTokenInfo?.symbol}
{fetchParamsSourceTokenInfo.symbol ??
latestSmartTransaction?.sourceTokenSymbol}
</Typography>
<UrlIcon
url={sourceTokenInfo.iconUrl}
className="main-quote-summary__icon"
name={sourceTokenInfo.symbol}
fallbackClassName="main-quote-summary__icon-fallback"
/>
{fetchParamsSourceTokenInfo.iconUrl ? (
<UrlIcon
url={fetchParamsSourceTokenInfo.iconUrl}
className="main-quote-summary__icon"
name={
fetchParamsSourceTokenInfo.symbol ??
latestSmartTransaction?.destinationTokenSymbol
}
fallbackClassName="main-quote-summary__icon-fallback"
/>
) : null}
<Box display={DISPLAY.BLOCK} marginLeft={2} marginRight={2}>
<ArrowIcon />
</Box>
<UrlIcon
url={destinationTokenInfo.iconUrl}
className="main-quote-summary__icon"
name={destinationTokenInfo.symbol}
fallbackClassName="main-quote-summary__icon-fallback"
/>
{fetchParamsDestinationTokenInfo.iconUrl ? (
<UrlIcon
url={fetchParamsDestinationTokenInfo.iconUrl}
className="main-quote-summary__icon"
name={
fetchParamsDestinationTokenInfo.symbol ??
latestSmartTransaction?.destinationTokenSymbol
}
fallbackClassName="main-quote-summary__icon-fallback"
/>
) : null}
<Typography
color={COLORS.TEXT_ALTERNATIVE}
variant={TYPOGRAPHY.H6}
@ -355,7 +380,8 @@ export default function SmartTransactionStatus() {
fontWeight={FONT_WEIGHT.BOLD}
boxProps={{ marginLeft: 1 }}
>
{destinationTokenInfo?.symbol}
{fetchParamsDestinationTokenInfo.symbol ??
latestSmartTransaction?.destinationTokenSymbol}
</Typography>
</Box>
<Box

View File

@ -71,6 +71,7 @@ import {
import { isEqualCaseInsensitive } from '../../shared/modules/string-utils';
import { hexToDecimal } from '../../shared/lib/metamask-controller-utils';
import { formatMoonpaySymbol } from '../helpers/utils/moonpay';
import { TRANSACTION_STATUSES } from '../../shared/constants/transaction';
///: BEGIN:ONLY_INCLUDE_IN(flask)
import { SNAPS_VIEW_ROUTE } from '../helpers/constants/routes';
import { getPermissionSubjects } from './permissions';
@ -791,6 +792,9 @@ const createDeepEqualSelector = createSelectorCreator(defaultMemoize, isEqual);
export const getUnapprovedTransactions = (state) =>
state.metamask.unapprovedTxs;
const getCurrentNetworkTransactionList = (state) =>
state.metamask.currentNetworkTxList;
export const getTxData = (state) => state.confirmTransaction.txData;
export const getUnapprovedTransaction = createDeepEqualSelector(
@ -803,11 +807,26 @@ export const getUnapprovedTransaction = createDeepEqualSelector(
},
);
export const getTransaction = createDeepEqualSelector(
getCurrentNetworkTransactionList,
(_, transactionId) => transactionId,
(unapprovedTxs, transactionId) => {
return (
Object.values(unapprovedTxs).find(({ id }) => id === transactionId) || {}
);
},
);
export const getFullTxData = createDeepEqualSelector(
getTxData,
(state, transactionId) => getUnapprovedTransaction(state, transactionId),
(_state, _transactionId, customTxParamsData) => customTxParamsData,
(txData, transaction, customTxParamsData) => {
(state, transactionId, status) => {
if (status === TRANSACTION_STATUSES.UNAPPROVED) {
return getUnapprovedTransaction(state, transactionId);
}
return getTransaction(state, transactionId);
},
(_state, _transactionId, _status, customTxParamsData) => customTxParamsData,
(txData, transaction, _status, customTxParamsData) => {
let fullTxData = { ...txData, ...transaction };
if (transaction && transaction.simulationFails) {
txData.simulationFails = transaction.simulationFails;