1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 09:57:02 +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 = () => { export const createSwapsMockStore = () => {
return { return {
confirmTransaction: {
txData: {},
},
swaps: { swaps: {
customGas: { customGas: {
limit: '0x0', limit: '0x0',
@ -144,6 +147,76 @@ export const createSwapsMockStore = () => {
showFiatInTestnets: true, showFiatInTestnets: true,
}, },
currentCurrency: 'ETH', 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, conversionRate: 1,
contractExchangeRates: { contractExchangeRates: {
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': 2, '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': 2,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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