mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Improvements for Smart Transactions / Swaps (#14022)
- Don’t call /estimateGas if a user doesn’t have enough funds - Hardcode block explorer URLs for Swaps - Track the "stx_prev_user_opt_in" param - Add fee estimates tracking for regular txs and STX - Track estimated_gas and estimated_vs_used_gasRatio for STX - Only track the "Error Smart Transactions" event once - Don't overwrite "maxGasLimit" for STX on the View Quote page for better "balance needed" estimations - Update description for Transak - Fix styles for the input field on the Build Quote page - Refactor variables for STX error types and add translation for each STX error type - Do additional logging for the "current_stx_enabled" param - Add a close icon for an STX notification, update STX content
This commit is contained in:
parent
386a760285
commit
4c16b583c3
26
app/_locales/en/messages.json
generated
26
app/_locales/en/messages.json
generated
@ -410,15 +410,15 @@
|
|||||||
"description": "$1 represents the cypto symbol to be purchased"
|
"description": "$1 represents the cypto symbol to be purchased"
|
||||||
},
|
},
|
||||||
"buyCryptoWithMoonPayDescription": {
|
"buyCryptoWithMoonPayDescription": {
|
||||||
"message": "MoonPay supports popular payment methods, including Visa, Mastercard, Apple / Google / Samsung Pay, and bank transfers in 146+ countries. Tokens deposit into your MetaMask account."
|
"message": "MoonPay supports popular payment methods, including Visa, Mastercard, Apple / Google / Samsung Pay, and bank transfers in 145+ countries. Tokens deposit into your MetaMask account."
|
||||||
},
|
},
|
||||||
"buyCryptoWithTransak": {
|
"buyCryptoWithTransak": {
|
||||||
"message": "Buy $1 with Transak",
|
"message": "Buy $1 with Transak",
|
||||||
"description": "$1 represents the cypto symbol to be purchased"
|
"description": "$1 represents the cypto symbol to be purchased"
|
||||||
},
|
},
|
||||||
"buyCryptoWithTransakDescription": {
|
"buyCryptoWithTransakDescription": {
|
||||||
"message": "Transak supports debit card and bank transfers (depending on location) in 59+ countries. $1 deposits into your MetaMask account.",
|
"message": "Transak supports credit & debit cards, Apple Pay, MobiKwik, and bank transfers (depending on location) in 100+ countries. $1 deposits directly into your MetaMask account.",
|
||||||
"description": "$1 represents the cypto symbol to be purchased"
|
"description": "$1 represents the crypto symbol to be purchased"
|
||||||
},
|
},
|
||||||
"buyEth": {
|
"buyEth": {
|
||||||
"message": "Buy ETH"
|
"message": "Buy ETH"
|
||||||
@ -2857,7 +2857,7 @@
|
|||||||
"message": "Slow"
|
"message": "Slow"
|
||||||
},
|
},
|
||||||
"smartTransaction": {
|
"smartTransaction": {
|
||||||
"message": "Smart transaction"
|
"message": "Smart Transaction"
|
||||||
},
|
},
|
||||||
"snapAccess": {
|
"snapAccess": {
|
||||||
"message": "$1 snap has access to:",
|
"message": "$1 snap has access to:",
|
||||||
@ -3047,6 +3047,12 @@
|
|||||||
"stxDescription": {
|
"stxDescription": {
|
||||||
"message": "MetaMask Swaps just got a whole lot smarter! Enabling Smart Transactions will allow MetaMask to programmatically optimize your Swap to help:"
|
"message": "MetaMask Swaps just got a whole lot smarter! Enabling Smart Transactions will allow MetaMask to programmatically optimize your Swap to help:"
|
||||||
},
|
},
|
||||||
|
"stxErrorNotEnoughFunds": {
|
||||||
|
"message": "Not enough funds for a smart transaction."
|
||||||
|
},
|
||||||
|
"stxErrorUnavailable": {
|
||||||
|
"message": "Smart Transactions are temporarily unavailable."
|
||||||
|
},
|
||||||
"stxFailure": {
|
"stxFailure": {
|
||||||
"message": "Swap failed"
|
"message": "Swap failed"
|
||||||
},
|
},
|
||||||
@ -3054,8 +3060,11 @@
|
|||||||
"message": "Sudden market changes can cause failures. If the problem persists, please reach out to $1.",
|
"message": "Sudden market changes can cause failures. If the problem persists, please reach out to $1.",
|
||||||
"description": "This message is shown to a user if their swap fails. The $1 will be replaced by support.metamask.io"
|
"description": "This message is shown to a user if their swap fails. The $1 will be replaced by support.metamask.io"
|
||||||
},
|
},
|
||||||
"stxFallbackToNormal": {
|
"stxFallbackPendingTx": {
|
||||||
"message": "You can still swap using the normal method or wait for cheaper gas fees and less failures with smart transactions."
|
"message": "Smart Transactions are temporarily unavailable because you have a pending transaction."
|
||||||
|
},
|
||||||
|
"stxFallbackUnavailable": {
|
||||||
|
"message": "You can still swap your tokens even while Smart Transactions are unavailable."
|
||||||
},
|
},
|
||||||
"stxPendingFinalizing": {
|
"stxPendingFinalizing": {
|
||||||
"message": "Finalizing..."
|
"message": "Finalizing..."
|
||||||
@ -3082,8 +3091,11 @@
|
|||||||
"stxTryRegular": {
|
"stxTryRegular": {
|
||||||
"message": "Try a regular swap."
|
"message": "Try a regular swap."
|
||||||
},
|
},
|
||||||
|
"stxTryingToCancel": {
|
||||||
|
"message": "Trying to cancel your transaction..."
|
||||||
|
},
|
||||||
"stxUnavailable": {
|
"stxUnavailable": {
|
||||||
"message": "Smart transactions temporarily unavailable"
|
"message": "Smart Transactions are disabled"
|
||||||
},
|
},
|
||||||
"stxUnknown": {
|
"stxUnknown": {
|
||||||
"message": "Status unknown"
|
"message": "Status unknown"
|
||||||
|
@ -33,6 +33,7 @@ import {
|
|||||||
fetchSmartTransactionFees,
|
fetchSmartTransactionFees,
|
||||||
estimateSmartTransactionsGas,
|
estimateSmartTransactionsGas,
|
||||||
cancelSmartTransaction,
|
cancelSmartTransaction,
|
||||||
|
getTransactions,
|
||||||
} from '../../store/actions';
|
} from '../../store/actions';
|
||||||
import {
|
import {
|
||||||
AWAITING_SIGNATURES_ROUTE,
|
AWAITING_SIGNATURES_ROUTE,
|
||||||
@ -81,6 +82,7 @@ import {
|
|||||||
} from '../../../shared/constants/swaps';
|
} from '../../../shared/constants/swaps';
|
||||||
import {
|
import {
|
||||||
TRANSACTION_TYPES,
|
TRANSACTION_TYPES,
|
||||||
|
TRANSACTION_STATUSES,
|
||||||
SMART_TRANSACTION_STATUSES,
|
SMART_TRANSACTION_STATUSES,
|
||||||
} from '../../../shared/constants/transaction';
|
} from '../../../shared/constants/transaction';
|
||||||
import { getGasFeeEstimates } from '../metamask/metamask';
|
import { getGasFeeEstimates } from '../metamask/metamask';
|
||||||
@ -199,9 +201,9 @@ const slice = createSlice({
|
|||||||
state.customGas.fallBackPrice = action.payload;
|
state.customGas.fallBackPrice = action.payload;
|
||||||
},
|
},
|
||||||
setCurrentSmartTransactionsError: (state, action) => {
|
setCurrentSmartTransactionsError: (state, action) => {
|
||||||
const errorType = stxErrorTypes.includes(action.payload)
|
const errorType = Object.values(stxErrorTypes).includes(action.payload)
|
||||||
? action.payload
|
? action.payload
|
||||||
: stxErrorTypes[0];
|
: stxErrorTypes.UNAVAILABLE;
|
||||||
state.currentSmartTransactionsError = errorType;
|
state.currentSmartTransactionsError = errorType;
|
||||||
},
|
},
|
||||||
dismissCurrentSmartTransactionsErrorMessage: (state) => {
|
dismissCurrentSmartTransactionsErrorMessage: (state) => {
|
||||||
@ -554,12 +556,24 @@ export const fetchSwapsLivenessAndFeatureFlags = () => {
|
|||||||
let swapsLivenessForNetwork = {
|
let swapsLivenessForNetwork = {
|
||||||
swapsFeatureIsLive: false,
|
swapsFeatureIsLive: false,
|
||||||
};
|
};
|
||||||
const chainId = getCurrentChainId(getState());
|
const state = getState();
|
||||||
|
const chainId = getCurrentChainId(state);
|
||||||
try {
|
try {
|
||||||
const swapsFeatureFlags = await fetchSwapsFeatureFlags();
|
const swapsFeatureFlags = await fetchSwapsFeatureFlags();
|
||||||
await dispatch(setSwapsFeatureFlags(swapsFeatureFlags));
|
await dispatch(setSwapsFeatureFlags(swapsFeatureFlags));
|
||||||
if (ALLOWED_SMART_TRANSACTIONS_CHAIN_IDS.includes(chainId)) {
|
if (ALLOWED_SMART_TRANSACTIONS_CHAIN_IDS.includes(chainId)) {
|
||||||
await dispatch(fetchSmartTransactionsLiveness());
|
await dispatch(fetchSmartTransactionsLiveness());
|
||||||
|
const pendingTransactions = await getTransactions({
|
||||||
|
searchCriteria: {
|
||||||
|
status: TRANSACTION_STATUSES.PENDING,
|
||||||
|
from: state.metamask?.selectedAddress,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (pendingTransactions?.length > 0) {
|
||||||
|
dispatch(
|
||||||
|
setCurrentSmartTransactionsError(stxErrorTypes.REGULAR_TX_PENDING),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
swapsLivenessForNetwork = getSwapsLivenessForNetwork(
|
swapsLivenessForNetwork = getSwapsLivenessForNetwork(
|
||||||
swapsFeatureFlags,
|
swapsFeatureFlags,
|
||||||
@ -820,6 +834,7 @@ export const signAndSendSwapsSmartTransaction = ({
|
|||||||
unsignedTransaction,
|
unsignedTransaction,
|
||||||
metaMetricsEvent,
|
metaMetricsEvent,
|
||||||
history,
|
history,
|
||||||
|
additionalTrackingParams,
|
||||||
}) => {
|
}) => {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
dispatch(setSwapsSTXSubmitLoading(true));
|
dispatch(setSwapsSTXSubmitLoading(true));
|
||||||
@ -871,6 +886,7 @@ export const signAndSendSwapsSmartTransaction = ({
|
|||||||
stx_enabled: smartTransactionsEnabled,
|
stx_enabled: smartTransactionsEnabled,
|
||||||
current_stx_enabled: currentSmartTransactionsEnabled,
|
current_stx_enabled: currentSmartTransactionsEnabled,
|
||||||
stx_user_opt_in: smartTransactionsOptInStatus,
|
stx_user_opt_in: smartTransactionsOptInStatus,
|
||||||
|
...additionalTrackingParams,
|
||||||
};
|
};
|
||||||
metaMetricsEvent({
|
metaMetricsEvent({
|
||||||
event: 'STX Swap Started',
|
event: 'STX Swap Started',
|
||||||
@ -966,7 +982,11 @@ export const signAndSendSwapsSmartTransaction = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const signAndSendTransactions = (history, metaMetricsEvent) => {
|
export const signAndSendTransactions = (
|
||||||
|
history,
|
||||||
|
metaMetricsEvent,
|
||||||
|
additionalTrackingParams,
|
||||||
|
) => {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const chainId = getCurrentChainId(state);
|
const chainId = getCurrentChainId(state);
|
||||||
@ -1079,6 +1099,9 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
|
|||||||
});
|
});
|
||||||
const smartTransactionsOptInStatus = getSmartTransactionsOptInStatus(state);
|
const smartTransactionsOptInStatus = getSmartTransactionsOptInStatus(state);
|
||||||
const smartTransactionsEnabled = getSmartTransactionsEnabled(state);
|
const smartTransactionsEnabled = getSmartTransactionsEnabled(state);
|
||||||
|
const currentSmartTransactionsEnabled = getCurrentSmartTransactionsEnabled(
|
||||||
|
state,
|
||||||
|
);
|
||||||
const swapMetaData = {
|
const swapMetaData = {
|
||||||
token_from: sourceTokenInfo.symbol,
|
token_from: sourceTokenInfo.symbol,
|
||||||
token_from_amount: String(swapTokenValue),
|
token_from_amount: String(swapTokenValue),
|
||||||
@ -1105,7 +1128,9 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => {
|
|||||||
is_hardware_wallet: hardwareWalletUsed,
|
is_hardware_wallet: hardwareWalletUsed,
|
||||||
hardware_wallet_type: getHardwareWalletType(state),
|
hardware_wallet_type: getHardwareWalletType(state),
|
||||||
stx_enabled: smartTransactionsEnabled,
|
stx_enabled: smartTransactionsEnabled,
|
||||||
|
current_stx_enabled: currentSmartTransactionsEnabled,
|
||||||
stx_user_opt_in: smartTransactionsOptInStatus,
|
stx_user_opt_in: smartTransactionsOptInStatus,
|
||||||
|
...additionalTrackingParams,
|
||||||
};
|
};
|
||||||
if (networkAndAccountSupports1559) {
|
if (networkAndAccountSupports1559) {
|
||||||
swapMetaData.max_fee_per_gas = maxFeePerGas;
|
swapMetaData.max_fee_per_gas = maxFeePerGas;
|
||||||
|
@ -15,6 +15,7 @@ jest.mock('../../store/actions.js', () => ({
|
|||||||
setSwapsLiveness: jest.fn(),
|
setSwapsLiveness: jest.fn(),
|
||||||
setSwapsFeatureFlags: jest.fn(),
|
setSwapsFeatureFlags: jest.fn(),
|
||||||
fetchSmartTransactionsLiveness: jest.fn(),
|
fetchSmartTransactionsLiveness: jest.fn(),
|
||||||
|
getTransactions: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const providerState = {
|
const providerState = {
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
prepareToLeaveSwaps,
|
prepareToLeaveSwaps,
|
||||||
getSmartTransactionsOptInStatus,
|
getSmartTransactionsOptInStatus,
|
||||||
getSmartTransactionsEnabled,
|
getSmartTransactionsEnabled,
|
||||||
|
getCurrentSmartTransactionsEnabled,
|
||||||
} from '../../../ducks/swaps/swaps';
|
} from '../../../ducks/swaps/swaps';
|
||||||
import {
|
import {
|
||||||
isHardwareWallet,
|
isHardwareWallet,
|
||||||
@ -47,6 +48,9 @@ export default function AwaitingSignatures() {
|
|||||||
getSmartTransactionsOptInStatus,
|
getSmartTransactionsOptInStatus,
|
||||||
);
|
);
|
||||||
const smartTransactionsEnabled = useSelector(getSmartTransactionsEnabled);
|
const smartTransactionsEnabled = useSelector(getSmartTransactionsEnabled);
|
||||||
|
const currentSmartTransactionsEnabled = useSelector(
|
||||||
|
getCurrentSmartTransactionsEnabled,
|
||||||
|
);
|
||||||
const needsTwoConfirmations = Boolean(approveTxParams);
|
const needsTwoConfirmations = Boolean(approveTxParams);
|
||||||
|
|
||||||
const awaitingSignaturesEvent = useNewMetricEvent({
|
const awaitingSignaturesEvent = useNewMetricEvent({
|
||||||
@ -62,6 +66,7 @@ export default function AwaitingSignatures() {
|
|||||||
is_hardware_wallet: hardwareWalletUsed,
|
is_hardware_wallet: hardwareWalletUsed,
|
||||||
hardware_wallet_type: hardwareWalletType,
|
hardware_wallet_type: hardwareWalletType,
|
||||||
stx_enabled: smartTransactionsEnabled,
|
stx_enabled: smartTransactionsEnabled,
|
||||||
|
current_stx_enabled: currentSmartTransactionsEnabled,
|
||||||
stx_user_opt_in: smartTransactionsOptInStatus,
|
stx_user_opt_in: smartTransactionsOptInStatus,
|
||||||
},
|
},
|
||||||
category: 'swaps',
|
category: 'swaps',
|
||||||
|
@ -31,6 +31,7 @@ import {
|
|||||||
prepareToLeaveSwaps,
|
prepareToLeaveSwaps,
|
||||||
getSmartTransactionsOptInStatus,
|
getSmartTransactionsOptInStatus,
|
||||||
getSmartTransactionsEnabled,
|
getSmartTransactionsEnabled,
|
||||||
|
getCurrentSmartTransactionsEnabled,
|
||||||
getFromTokenInputValue,
|
getFromTokenInputValue,
|
||||||
getMaxSlippage,
|
getMaxSlippage,
|
||||||
setSwapsFromToken,
|
setSwapsFromToken,
|
||||||
@ -113,6 +114,9 @@ export default function AwaitingSwap({
|
|||||||
getSmartTransactionsOptInStatus,
|
getSmartTransactionsOptInStatus,
|
||||||
);
|
);
|
||||||
const smartTransactionsEnabled = useSelector(getSmartTransactionsEnabled);
|
const smartTransactionsEnabled = useSelector(getSmartTransactionsEnabled);
|
||||||
|
const currentSmartTransactionsEnabled = useSelector(
|
||||||
|
getCurrentSmartTransactionsEnabled,
|
||||||
|
);
|
||||||
const sensitiveProperties = {
|
const sensitiveProperties = {
|
||||||
token_from: sourceTokenInfo?.symbol,
|
token_from: sourceTokenInfo?.symbol,
|
||||||
token_from_amount: fetchParams?.value,
|
token_from_amount: fetchParams?.value,
|
||||||
@ -124,6 +128,7 @@ export default function AwaitingSwap({
|
|||||||
is_hardware_wallet: hardwareWalletUsed,
|
is_hardware_wallet: hardwareWalletUsed,
|
||||||
hardware_wallet_type: hardwareWalletType,
|
hardware_wallet_type: hardwareWalletType,
|
||||||
stx_enabled: smartTransactionsEnabled,
|
stx_enabled: smartTransactionsEnabled,
|
||||||
|
current_stx_enabled: currentSmartTransactionsEnabled,
|
||||||
stx_user_opt_in: smartTransactionsOptInStatus,
|
stx_user_opt_in: smartTransactionsOptInStatus,
|
||||||
};
|
};
|
||||||
const quotesExpiredEvent = useNewMetricEvent({
|
const quotesExpiredEvent = useNewMetricEvent({
|
||||||
|
@ -177,11 +177,11 @@ export default function BuildQuote({
|
|||||||
|
|
||||||
const onCloseSmartTransactionsOptInPopover = (e) => {
|
const onCloseSmartTransactionsOptInPopover = (e) => {
|
||||||
e?.preventDefault();
|
e?.preventDefault();
|
||||||
setSmartTransactionsOptInStatus(false);
|
setSmartTransactionsOptInStatus(false, smartTransactionsOptInStatus);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onEnableSmartTransactionsClick = () =>
|
const onEnableSmartTransactionsClick = () =>
|
||||||
setSmartTransactionsOptInStatus(true);
|
setSmartTransactionsOptInStatus(true, smartTransactionsOptInStatus);
|
||||||
|
|
||||||
const fetchParamsFromToken = isSwapsDefaultTokenSymbol(
|
const fetchParamsFromToken = isSwapsDefaultTokenSymbol(
|
||||||
sourceTokenInfo?.symbol,
|
sourceTokenInfo?.symbol,
|
||||||
@ -338,9 +338,7 @@ export default function BuildQuote({
|
|||||||
null, // no holderAddress
|
null, // no holderAddress
|
||||||
{
|
{
|
||||||
blockExplorerUrl:
|
blockExplorerUrl:
|
||||||
rpcPrefs.blockExplorerUrl ??
|
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ?? null,
|
||||||
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ??
|
|
||||||
null,
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -129,6 +129,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__input {
|
||||||
|
div {
|
||||||
|
border: 1px solid var(--color-border-default);
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__open-to-dropdown {
|
&__open-to-dropdown {
|
||||||
|
@ -27,6 +27,7 @@ import { getURLHostName } from '../../../helpers/utils/util';
|
|||||||
import {
|
import {
|
||||||
getSmartTransactionsOptInStatus,
|
getSmartTransactionsOptInStatus,
|
||||||
getSmartTransactionsEnabled,
|
getSmartTransactionsEnabled,
|
||||||
|
getCurrentSmartTransactionsEnabled,
|
||||||
} from '../../../ducks/swaps/swaps';
|
} from '../../../ducks/swaps/swaps';
|
||||||
|
|
||||||
export default function DropdownSearchList({
|
export default function DropdownSearchList({
|
||||||
@ -63,6 +64,9 @@ export default function DropdownSearchList({
|
|||||||
getSmartTransactionsOptInStatus,
|
getSmartTransactionsOptInStatus,
|
||||||
);
|
);
|
||||||
const smartTransactionsEnabled = useSelector(getSmartTransactionsEnabled);
|
const smartTransactionsEnabled = useSelector(getSmartTransactionsEnabled);
|
||||||
|
const currentSmartTransactionsEnabled = useSelector(
|
||||||
|
getCurrentSmartTransactionsEnabled,
|
||||||
|
);
|
||||||
|
|
||||||
const tokenImportedEvent = useNewMetricEvent({
|
const tokenImportedEvent = useNewMetricEvent({
|
||||||
event: 'Token Imported',
|
event: 'Token Imported',
|
||||||
@ -73,6 +77,7 @@ export default function DropdownSearchList({
|
|||||||
is_hardware_wallet: hardwareWalletUsed,
|
is_hardware_wallet: hardwareWalletUsed,
|
||||||
hardware_wallet_type: hardwareWalletType,
|
hardware_wallet_type: hardwareWalletType,
|
||||||
stx_enabled: smartTransactionsEnabled,
|
stx_enabled: smartTransactionsEnabled,
|
||||||
|
current_stx_enabled: currentSmartTransactionsEnabled,
|
||||||
stx_user_opt_in: smartTransactionsOptInStatus,
|
stx_user_opt_in: smartTransactionsOptInStatus,
|
||||||
},
|
},
|
||||||
category: 'swaps',
|
category: 'swaps',
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useRef, useContext } from 'react';
|
import React, { useEffect, useRef, useContext, useState } from 'react';
|
||||||
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
Switch,
|
Switch,
|
||||||
@ -37,6 +37,7 @@ import {
|
|||||||
getPendingSmartTransactions,
|
getPendingSmartTransactions,
|
||||||
getSmartTransactionsOptInStatus,
|
getSmartTransactionsOptInStatus,
|
||||||
getSmartTransactionsEnabled,
|
getSmartTransactionsEnabled,
|
||||||
|
getCurrentSmartTransactionsEnabled,
|
||||||
getCurrentSmartTransactionsError,
|
getCurrentSmartTransactionsError,
|
||||||
dismissCurrentSmartTransactionsErrorMessage,
|
dismissCurrentSmartTransactionsErrorMessage,
|
||||||
getCurrentSmartTransactionsErrorMessageDismissed,
|
getCurrentSmartTransactionsErrorMessageDismissed,
|
||||||
@ -84,6 +85,7 @@ import {
|
|||||||
fetchTopAssets,
|
fetchTopAssets,
|
||||||
getSwapsTokensReceivedFromTxMeta,
|
getSwapsTokensReceivedFromTxMeta,
|
||||||
fetchAggregatorMetadata,
|
fetchAggregatorMetadata,
|
||||||
|
stxErrorTypes,
|
||||||
} from './swaps.util';
|
} from './swaps.util';
|
||||||
import AwaitingSignatures from './awaiting-signatures';
|
import AwaitingSignatures from './awaiting-signatures';
|
||||||
import SmartTransactionStatus from './smart-transaction-status';
|
import SmartTransactionStatus from './smart-transaction-status';
|
||||||
@ -106,6 +108,7 @@ export default function Swap() {
|
|||||||
pathname === SMART_TRANSACTION_STATUS_ROUTE;
|
pathname === SMART_TRANSACTION_STATUS_ROUTE;
|
||||||
const isViewQuoteRoute = pathname === VIEW_QUOTE_ROUTE;
|
const isViewQuoteRoute = pathname === VIEW_QUOTE_ROUTE;
|
||||||
|
|
||||||
|
const [currentStxErrorTracked, setCurrentStxErrorTracked] = useState(false);
|
||||||
const fetchParams = useSelector(getFetchParams, isEqual);
|
const fetchParams = useSelector(getFetchParams, isEqual);
|
||||||
const { destinationTokenInfo = {} } = fetchParams?.metaData || {};
|
const { destinationTokenInfo = {} } = fetchParams?.metaData || {};
|
||||||
|
|
||||||
@ -134,6 +137,9 @@ export default function Swap() {
|
|||||||
getSmartTransactionsOptInStatus,
|
getSmartTransactionsOptInStatus,
|
||||||
);
|
);
|
||||||
const smartTransactionsEnabled = useSelector(getSmartTransactionsEnabled);
|
const smartTransactionsEnabled = useSelector(getSmartTransactionsEnabled);
|
||||||
|
const currentSmartTransactionsEnabled = useSelector(
|
||||||
|
getCurrentSmartTransactionsEnabled,
|
||||||
|
);
|
||||||
const currentSmartTransactionsError = useSelector(
|
const currentSmartTransactionsError = useSelector(
|
||||||
getCurrentSmartTransactionsError,
|
getCurrentSmartTransactionsError,
|
||||||
);
|
);
|
||||||
@ -244,6 +250,7 @@ export default function Swap() {
|
|||||||
is_hardware_wallet: hardwareWalletUsed,
|
is_hardware_wallet: hardwareWalletUsed,
|
||||||
hardware_wallet_type: hardwareWalletType,
|
hardware_wallet_type: hardwareWalletType,
|
||||||
stx_enabled: smartTransactionsEnabled,
|
stx_enabled: smartTransactionsEnabled,
|
||||||
|
current_stx_enabled: currentSmartTransactionsEnabled,
|
||||||
stx_user_opt_in: smartTransactionsOptInStatus,
|
stx_user_opt_in: smartTransactionsOptInStatus,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -302,22 +309,26 @@ export default function Swap() {
|
|||||||
is_hardware_wallet: hardwareWalletUsed,
|
is_hardware_wallet: hardwareWalletUsed,
|
||||||
hardware_wallet_type: hardwareWalletType,
|
hardware_wallet_type: hardwareWalletType,
|
||||||
stx_enabled: smartTransactionsEnabled,
|
stx_enabled: smartTransactionsEnabled,
|
||||||
|
current_stx_enabled: currentSmartTransactionsEnabled,
|
||||||
stx_user_opt_in: smartTransactionsOptInStatus,
|
stx_user_opt_in: smartTransactionsOptInStatus,
|
||||||
stx_error: currentSmartTransactionsError,
|
stx_error: currentSmartTransactionsError,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentSmartTransactionsError) {
|
if (currentSmartTransactionsError && !currentStxErrorTracked) {
|
||||||
|
setCurrentStxErrorTracked(true);
|
||||||
errorStxEvent();
|
errorStxEvent();
|
||||||
}
|
}
|
||||||
}, [errorStxEvent, currentSmartTransactionsError]);
|
}, [errorStxEvent, currentSmartTransactionsError, currentStxErrorTracked]);
|
||||||
|
|
||||||
if (!isSwapsChain) {
|
if (!isSwapsChain) {
|
||||||
return <Redirect to={{ pathname: DEFAULT_ROUTE }} />;
|
return <Redirect to={{ pathname: DEFAULT_ROUTE }} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isStxNotEnoughFundsError =
|
const isStxNotEnoughFundsError =
|
||||||
currentSmartTransactionsError === 'not_enough_funds';
|
currentSmartTransactionsError === stxErrorTypes.NOT_ENOUGH_FUNDS;
|
||||||
|
const isStxRegularTxPendingError =
|
||||||
|
currentSmartTransactionsError === stxErrorTypes.REGULAR_TX_PENDING;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="swaps">
|
<div className="swaps">
|
||||||
@ -371,10 +382,20 @@ export default function Swap() {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="build-quote__token-verification-warning-message">
|
<div className="build-quote__token-verification-warning-message">
|
||||||
<div className="build-quote__bold">
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
dispatch(dismissCurrentSmartTransactionsErrorMessage());
|
||||||
|
}}
|
||||||
|
className="swaps__notification-close-button"
|
||||||
|
/>
|
||||||
|
<div className="swaps__notification-title">
|
||||||
{t('stxUnavailable')}
|
{t('stxUnavailable')}
|
||||||
</div>
|
</div>
|
||||||
<div>{t('stxFallbackToNormal')}</div>
|
<div>
|
||||||
|
{isStxRegularTxPendingError
|
||||||
|
? t('stxFallbackPendingTx')
|
||||||
|
: t('stxFallbackUnavailable')}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -383,16 +404,6 @@ export default function Swap() {
|
|||||||
? 'swaps__error-message'
|
? 'swaps__error-message'
|
||||||
: 'actionable-message--left-aligned actionable-message--warning swaps__error-message'
|
: 'actionable-message--left-aligned actionable-message--warning swaps__error-message'
|
||||||
}
|
}
|
||||||
primaryAction={
|
|
||||||
isStxNotEnoughFundsError
|
|
||||||
? null
|
|
||||||
: {
|
|
||||||
label: t('dismiss'),
|
|
||||||
onClick: () =>
|
|
||||||
dispatch(dismissCurrentSmartTransactionsErrorMessage()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
withRightButton
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Switch>
|
<Switch>
|
||||||
|
@ -120,4 +120,28 @@
|
|||||||
padding-left: 24px;
|
padding-left: 24px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__notification-close-button {
|
||||||
|
background-color: transparent;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 2px;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
position: absolute;
|
||||||
|
content: '\00D7';
|
||||||
|
font-size: 29px;
|
||||||
|
font-weight: 200;
|
||||||
|
color: var(--color-text-default);
|
||||||
|
background-color: transparent;
|
||||||
|
top: 0;
|
||||||
|
right: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__notification-title {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-right: 14px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
getQuotesFetchStartTime,
|
getQuotesFetchStartTime,
|
||||||
getSmartTransactionsOptInStatus,
|
getSmartTransactionsOptInStatus,
|
||||||
getSmartTransactionsEnabled,
|
getSmartTransactionsEnabled,
|
||||||
|
getCurrentSmartTransactionsEnabled,
|
||||||
} from '../../../ducks/swaps/swaps';
|
} from '../../../ducks/swaps/swaps';
|
||||||
import {
|
import {
|
||||||
isHardwareWallet,
|
isHardwareWallet,
|
||||||
@ -41,6 +42,9 @@ export default function LoadingSwapsQuotes({
|
|||||||
getSmartTransactionsOptInStatus,
|
getSmartTransactionsOptInStatus,
|
||||||
);
|
);
|
||||||
const smartTransactionsEnabled = useSelector(getSmartTransactionsEnabled);
|
const smartTransactionsEnabled = useSelector(getSmartTransactionsEnabled);
|
||||||
|
const currentSmartTransactionsEnabled = useSelector(
|
||||||
|
getCurrentSmartTransactionsEnabled,
|
||||||
|
);
|
||||||
const quotesRequestCancelledEventConfig = {
|
const quotesRequestCancelledEventConfig = {
|
||||||
event: 'Quotes Request Cancelled',
|
event: 'Quotes Request Cancelled',
|
||||||
category: 'swaps',
|
category: 'swaps',
|
||||||
@ -55,6 +59,7 @@ export default function LoadingSwapsQuotes({
|
|||||||
is_hardware_wallet: hardwareWalletUsed,
|
is_hardware_wallet: hardwareWalletUsed,
|
||||||
hardware_wallet_type: hardwareWalletType,
|
hardware_wallet_type: hardwareWalletType,
|
||||||
stx_enabled: smartTransactionsEnabled,
|
stx_enabled: smartTransactionsEnabled,
|
||||||
|
current_stx_enabled: currentSmartTransactionsEnabled,
|
||||||
stx_user_opt_in: smartTransactionsOptInStatus,
|
stx_user_opt_in: smartTransactionsOptInStatus,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -14,7 +14,7 @@ import {
|
|||||||
ALIGN_ITEMS,
|
ALIGN_ITEMS,
|
||||||
DISPLAY,
|
DISPLAY,
|
||||||
} from '../../../helpers/constants/design-system';
|
} from '../../../helpers/constants/design-system';
|
||||||
import { smartTransactionsErrorMessages } from '../swaps.util';
|
import { getTranslatedStxErrorMessage } from '../swaps.util';
|
||||||
|
|
||||||
export default function SlippageButtons({
|
export default function SlippageButtons({
|
||||||
onSelect,
|
onSelect,
|
||||||
@ -208,8 +208,9 @@ export default function SlippageButtons({
|
|||||||
{currentSmartTransactionsError ? (
|
{currentSmartTransactionsError ? (
|
||||||
<InfoTooltip
|
<InfoTooltip
|
||||||
position="top"
|
position="top"
|
||||||
contentText={smartTransactionsErrorMessages(
|
contentText={getTranslatedStxErrorMessage(
|
||||||
currentSmartTransactionsError,
|
currentSmartTransactionsError,
|
||||||
|
t,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@ -219,7 +220,7 @@ export default function SlippageButtons({
|
|||||||
<ToggleButton
|
<ToggleButton
|
||||||
value={smartTransactionsOptInStatus}
|
value={smartTransactionsOptInStatus}
|
||||||
onToggle={(value) => {
|
onToggle={(value) => {
|
||||||
setSmartTransactionsOptInStatus(!value);
|
setSmartTransactionsOptInStatus(!value, value);
|
||||||
}}
|
}}
|
||||||
offLabel={t('off')}
|
offLabel={t('off')}
|
||||||
onLabel={t('on')}
|
onLabel={t('on')}
|
||||||
|
@ -45,6 +45,6 @@ describe('SlippageButtons', () => {
|
|||||||
expect(
|
expect(
|
||||||
document.querySelector('.slippage-buttons__button-group'),
|
document.querySelector('.slippage-buttons__button-group'),
|
||||||
).toMatchSnapshot();
|
).toMatchSnapshot();
|
||||||
expect(getByText('Smart transaction')).toBeInTheDocument();
|
expect(getByText('Smart Transaction')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -184,6 +184,8 @@ export default function SmartTransactionStatus() {
|
|||||||
headerText = t('stxPendingFinalizing');
|
headerText = t('stxPendingFinalizing');
|
||||||
} else if (timeLeftForPendingStxInSec < 150) {
|
} else if (timeLeftForPendingStxInSec < 150) {
|
||||||
headerText = t('stxPendingPrivatelySubmitting');
|
headerText = t('stxPendingPrivatelySubmitting');
|
||||||
|
} else if (cancelSwapLinkClicked) {
|
||||||
|
headerText = t('stxTryingToCancel');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (smartTransactionStatus === SMART_TRANSACTION_STATUSES.SUCCESS) {
|
if (smartTransactionStatus === SMART_TRANSACTION_STATUSES.SUCCESS) {
|
||||||
@ -192,7 +194,11 @@ export default function SmartTransactionStatus() {
|
|||||||
description = t('stxSuccessDescription', [destinationTokenInfo.symbol]);
|
description = t('stxSuccessDescription', [destinationTokenInfo.symbol]);
|
||||||
}
|
}
|
||||||
icon = <SuccessIcon />;
|
icon = <SuccessIcon />;
|
||||||
} else if (smartTransactionStatus === 'cancelled_user_cancelled') {
|
} else if (
|
||||||
|
smartTransactionStatus === 'cancelled_user_cancelled' ||
|
||||||
|
latestSmartTransaction?.statusMetadata?.minedTx ===
|
||||||
|
SMART_TRANSACTION_STATUSES.CANCELLED
|
||||||
|
) {
|
||||||
headerText = t('stxUserCancelled');
|
headerText = t('stxUserCancelled');
|
||||||
description = t('stxUserCancelledDescription');
|
description = t('stxUserCancelledDescription');
|
||||||
icon = <CanceledIcon />;
|
icon = <CanceledIcon />;
|
||||||
|
@ -55,6 +55,7 @@ const TOKEN_TRANSFER_LOG_TOPIC_HASH =
|
|||||||
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
|
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
|
||||||
|
|
||||||
const CACHE_REFRESH_FIVE_MINUTES = 300000;
|
const CACHE_REFRESH_FIVE_MINUTES = 300000;
|
||||||
|
const USD_CURRENCY_CODE = 'usd';
|
||||||
|
|
||||||
const clientIdHeader = { 'X-Client-Id': SWAPS_CLIENT_ID };
|
const clientIdHeader = { 'X-Client-Id': SWAPS_CLIENT_ID };
|
||||||
|
|
||||||
@ -514,12 +515,25 @@ export const getFeeForSmartTransaction = ({
|
|||||||
conversionRate,
|
conversionRate,
|
||||||
numberOfDecimals: 2,
|
numberOfDecimals: 2,
|
||||||
});
|
});
|
||||||
|
let feeInUsd;
|
||||||
|
if (currentCurrency === USD_CURRENCY_CODE) {
|
||||||
|
feeInUsd = rawNetworkFees;
|
||||||
|
} else {
|
||||||
|
feeInUsd = getValueFromWeiHex({
|
||||||
|
value: feeInWeiHex,
|
||||||
|
toCurrency: USD_CURRENCY_CODE,
|
||||||
|
conversionRate,
|
||||||
|
numberOfDecimals: 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
const formattedNetworkFee = formatCurrency(rawNetworkFees, currentCurrency);
|
const formattedNetworkFee = formatCurrency(rawNetworkFees, currentCurrency);
|
||||||
const chainCurrencySymbolToUse =
|
const chainCurrencySymbolToUse =
|
||||||
nativeCurrencySymbol || SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId].symbol;
|
nativeCurrencySymbol || SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId].symbol;
|
||||||
return {
|
return {
|
||||||
|
feeInUsd,
|
||||||
feeInFiat: formattedNetworkFee,
|
feeInFiat: formattedNetworkFee,
|
||||||
feeInEth: `${ethFee} ${chainCurrencySymbolToUse}`,
|
feeInEth: `${ethFee} ${chainCurrencySymbolToUse}`,
|
||||||
|
rawEthFee: ethFee,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -564,11 +578,24 @@ export function getRenderableNetworkFeesForQuote({
|
|||||||
});
|
});
|
||||||
const formattedNetworkFee = formatCurrency(rawNetworkFees, currentCurrency);
|
const formattedNetworkFee = formatCurrency(rawNetworkFees, currentCurrency);
|
||||||
|
|
||||||
|
let feeInUsd;
|
||||||
|
if (currentCurrency === USD_CURRENCY_CODE) {
|
||||||
|
feeInUsd = rawNetworkFees;
|
||||||
|
} else {
|
||||||
|
feeInUsd = getValueFromWeiHex({
|
||||||
|
value: totalWeiCost,
|
||||||
|
toCurrency: USD_CURRENCY_CODE,
|
||||||
|
conversionRate,
|
||||||
|
numberOfDecimals: 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const chainCurrencySymbolToUse =
|
const chainCurrencySymbolToUse =
|
||||||
nativeCurrencySymbol || SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId].symbol;
|
nativeCurrencySymbol || SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId].symbol;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
rawNetworkFees,
|
rawNetworkFees,
|
||||||
|
feeInUsd,
|
||||||
rawEthFee: ethFee,
|
rawEthFee: ethFee,
|
||||||
feeInFiat: formattedNetworkFee,
|
feeInFiat: formattedNetworkFee,
|
||||||
feeInEth: `${ethFee} ${chainCurrencySymbolToUse}`,
|
feeInEth: `${ethFee} ${chainCurrencySymbolToUse}`,
|
||||||
@ -903,18 +930,22 @@ export const showRemainingTimeInMinAndSec = (remainingTimeInSec) => {
|
|||||||
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const stxErrorTypes = ['unavailable', 'not_enough_funds'];
|
export const stxErrorTypes = {
|
||||||
|
UNAVAILABLE: 'unavailable',
|
||||||
const smartTransactionsErrorMap = {
|
NOT_ENOUGH_FUNDS: 'not_enough_funds',
|
||||||
unavailable: 'Smart Transactions are temporarily unavailable.',
|
REGULAR_TX_PENDING: 'regular_tx_pending',
|
||||||
not_enough_funds: 'Not enough funds for a smart transaction.',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const smartTransactionsErrorMessages = (errorType) => {
|
export const getTranslatedStxErrorMessage = (errorType, t) => {
|
||||||
return (
|
switch (errorType) {
|
||||||
smartTransactionsErrorMap[errorType] ||
|
case stxErrorTypes.UNAVAILABLE:
|
||||||
smartTransactionsErrorMap.unavailable
|
case stxErrorTypes.REGULAR_TX_PENDING:
|
||||||
);
|
return t('stxErrorUnavailable');
|
||||||
|
case stxErrorTypes.NOT_ENOUGH_FUNDS:
|
||||||
|
return t('stxErrorNotEnoughFunds');
|
||||||
|
default:
|
||||||
|
return t('stxErrorUnavailable');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const parseSmartTransactionsError = (errorMessage) => {
|
export const parseSmartTransactionsError = (errorMessage) => {
|
||||||
|
@ -205,40 +205,6 @@ export default function ViewQuote() {
|
|||||||
const swapsRefreshRates = useSelector(getSwapsRefreshStates);
|
const swapsRefreshRates = useSelector(getSwapsRefreshStates);
|
||||||
const unsignedTransaction = usedQuote.trade;
|
const unsignedTransaction = usedQuote.trade;
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (currentSmartTransactionsEnabled && smartTransactionsOptInStatus) {
|
|
||||||
const unsignedTx = {
|
|
||||||
from: unsignedTransaction.from,
|
|
||||||
to: unsignedTransaction.to,
|
|
||||||
value: unsignedTransaction.value,
|
|
||||||
data: unsignedTransaction.data,
|
|
||||||
gas: unsignedTransaction.gas,
|
|
||||||
chainId,
|
|
||||||
};
|
|
||||||
intervalId = setInterval(() => {
|
|
||||||
dispatch(
|
|
||||||
estimateSwapsSmartTransactionsGas(unsignedTx, approveTxParams),
|
|
||||||
);
|
|
||||||
}, swapsRefreshRates.stxGetTransactionsRefreshTime);
|
|
||||||
dispatch(estimateSwapsSmartTransactionsGas(unsignedTx, approveTxParams));
|
|
||||||
} else if (intervalId) {
|
|
||||||
clearInterval(intervalId);
|
|
||||||
}
|
|
||||||
return () => clearInterval(intervalId);
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, [
|
|
||||||
dispatch,
|
|
||||||
currentSmartTransactionsEnabled,
|
|
||||||
smartTransactionsOptInStatus,
|
|
||||||
unsignedTransaction.data,
|
|
||||||
unsignedTransaction.from,
|
|
||||||
unsignedTransaction.value,
|
|
||||||
unsignedTransaction.gas,
|
|
||||||
unsignedTransaction.to,
|
|
||||||
chainId,
|
|
||||||
swapsRefreshRates.stxGetTransactionsRefreshTime,
|
|
||||||
]);
|
|
||||||
|
|
||||||
let gasFeeInputs;
|
let gasFeeInputs;
|
||||||
if (networkAndAccountSupports1559) {
|
if (networkAndAccountSupports1559) {
|
||||||
// For Swaps we want to get 'high' estimations by default.
|
// For Swaps we want to get 'high' estimations by default.
|
||||||
@ -252,6 +218,17 @@ export default function ViewQuote() {
|
|||||||
|
|
||||||
const fetchParamsSourceToken = fetchParams?.sourceToken;
|
const fetchParamsSourceToken = fetchParams?.sourceToken;
|
||||||
|
|
||||||
|
const additionalTrackingParams = {
|
||||||
|
reg_tx_fee_in_usd: undefined,
|
||||||
|
reg_tx_fee_in_eth: undefined,
|
||||||
|
reg_tx_max_fee_in_usd: undefined,
|
||||||
|
reg_tx_max_fee_in_eth: undefined,
|
||||||
|
stx_fee_in_usd: undefined,
|
||||||
|
stx_fee_in_eth: undefined,
|
||||||
|
stx_max_fee_in_usd: undefined,
|
||||||
|
stx_max_fee_in_eth: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
const usedGasLimit =
|
const usedGasLimit =
|
||||||
usedQuote?.gasEstimateWithRefund ||
|
usedQuote?.gasEstimateWithRefund ||
|
||||||
`0x${decimalToHex(usedQuote?.averageGas || 0)}`;
|
`0x${decimalToHex(usedQuote?.averageGas || 0)}`;
|
||||||
@ -266,7 +243,7 @@ export default function ViewQuote() {
|
|||||||
const nonCustomMaxGasLimit = usedQuote?.gasEstimate
|
const nonCustomMaxGasLimit = usedQuote?.gasEstimate
|
||||||
? usedGasLimitWithMultiplier
|
? usedGasLimitWithMultiplier
|
||||||
: `0x${decimalToHex(usedQuote?.maxGas || 0)}`;
|
: `0x${decimalToHex(usedQuote?.maxGas || 0)}`;
|
||||||
let maxGasLimit = customMaxGas || nonCustomMaxGasLimit;
|
const maxGasLimit = customMaxGas || nonCustomMaxGasLimit;
|
||||||
|
|
||||||
let maxFeePerGas;
|
let maxFeePerGas;
|
||||||
let maxPriorityFeePerGas;
|
let maxPriorityFeePerGas;
|
||||||
@ -289,17 +266,6 @@ export default function ViewQuote() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Smart Transactions gas fees.
|
|
||||||
if (
|
|
||||||
currentSmartTransactionsEnabled &&
|
|
||||||
smartTransactionsOptInStatus &&
|
|
||||||
smartTransactionEstimatedGas?.txData
|
|
||||||
) {
|
|
||||||
maxGasLimit = `0x${decimalToHex(
|
|
||||||
smartTransactionEstimatedGas?.txData.gasLimit || 0,
|
|
||||||
)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const gasTotalInWeiHex = calcGasTotal(maxGasLimit, maxFeePerGas || gasPrice);
|
const gasTotalInWeiHex = calcGasTotal(maxGasLimit, maxFeePerGas || gasPrice);
|
||||||
|
|
||||||
const { tokensWithBalances } = useTokenTracker(swapsTokens, true);
|
const { tokensWithBalances } = useTokenTracker(swapsTokens, true);
|
||||||
@ -374,7 +340,12 @@ export default function ViewQuote() {
|
|||||||
sourceTokenIconUrl,
|
sourceTokenIconUrl,
|
||||||
} = renderableDataForUsedQuote;
|
} = renderableDataForUsedQuote;
|
||||||
|
|
||||||
let { feeInFiat, feeInEth } = getRenderableNetworkFeesForQuote({
|
let {
|
||||||
|
feeInFiat,
|
||||||
|
feeInEth,
|
||||||
|
rawEthFee,
|
||||||
|
feeInUsd,
|
||||||
|
} = getRenderableNetworkFeesForQuote({
|
||||||
tradeGas: usedGasLimit,
|
tradeGas: usedGasLimit,
|
||||||
approveGas,
|
approveGas,
|
||||||
gasPrice: networkAndAccountSupports1559
|
gasPrice: networkAndAccountSupports1559
|
||||||
@ -388,6 +359,8 @@ export default function ViewQuote() {
|
|||||||
chainId,
|
chainId,
|
||||||
nativeCurrencySymbol,
|
nativeCurrencySymbol,
|
||||||
});
|
});
|
||||||
|
additionalTrackingParams.reg_tx_fee_in_usd = Number(feeInUsd);
|
||||||
|
additionalTrackingParams.reg_tx_fee_in_eth = Number(rawEthFee);
|
||||||
|
|
||||||
const renderableMaxFees = getRenderableNetworkFeesForQuote({
|
const renderableMaxFees = getRenderableNetworkFeesForQuote({
|
||||||
tradeGas: maxGasLimit,
|
tradeGas: maxGasLimit,
|
||||||
@ -401,8 +374,15 @@ export default function ViewQuote() {
|
|||||||
chainId,
|
chainId,
|
||||||
nativeCurrencySymbol,
|
nativeCurrencySymbol,
|
||||||
});
|
});
|
||||||
let { feeInFiat: maxFeeInFiat, feeInEth: maxFeeInEth } = renderableMaxFees;
|
let {
|
||||||
|
feeInFiat: maxFeeInFiat,
|
||||||
|
feeInEth: maxFeeInEth,
|
||||||
|
rawEthFee: maxRawEthFee,
|
||||||
|
feeInUsd: maxFeeInUsd,
|
||||||
|
} = renderableMaxFees;
|
||||||
const { nonGasFee } = renderableMaxFees;
|
const { nonGasFee } = renderableMaxFees;
|
||||||
|
additionalTrackingParams.reg_tx_max_fee_in_usd = Number(maxFeeInUsd);
|
||||||
|
additionalTrackingParams.reg_tx_max_fee_in_eth = Number(maxRawEthFee);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
currentSmartTransactionsEnabled &&
|
currentSmartTransactionsEnabled &&
|
||||||
@ -413,16 +393,22 @@ export default function ViewQuote() {
|
|||||||
smartTransactionEstimatedGas.txData.feeEstimate +
|
smartTransactionEstimatedGas.txData.feeEstimate +
|
||||||
(smartTransactionEstimatedGas.approvalTxData?.feeEstimate || 0);
|
(smartTransactionEstimatedGas.approvalTxData?.feeEstimate || 0);
|
||||||
const stxMaxFeeInWeiDec = stxEstimatedFeeInWeiDec * 2;
|
const stxMaxFeeInWeiDec = stxEstimatedFeeInWeiDec * 2;
|
||||||
({ feeInFiat, feeInEth } = getFeeForSmartTransaction({
|
({ feeInFiat, feeInEth, rawEthFee, feeInUsd } = getFeeForSmartTransaction({
|
||||||
chainId,
|
chainId,
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
conversionRate,
|
conversionRate,
|
||||||
nativeCurrencySymbol,
|
nativeCurrencySymbol,
|
||||||
feeInWeiDec: stxEstimatedFeeInWeiDec,
|
feeInWeiDec: stxEstimatedFeeInWeiDec,
|
||||||
}));
|
}));
|
||||||
|
additionalTrackingParams.stx_fee_in_usd = Number(feeInUsd);
|
||||||
|
additionalTrackingParams.stx_fee_in_eth = Number(rawEthFee);
|
||||||
|
additionalTrackingParams.estimated_gas =
|
||||||
|
smartTransactionEstimatedGas.txData.gasLimit;
|
||||||
({
|
({
|
||||||
feeInFiat: maxFeeInFiat,
|
feeInFiat: maxFeeInFiat,
|
||||||
feeInEth: maxFeeInEth,
|
feeInEth: maxFeeInEth,
|
||||||
|
rawEthFee: maxRawEthFee,
|
||||||
|
feeInUsd: maxFeeInUsd,
|
||||||
} = getFeeForSmartTransaction({
|
} = getFeeForSmartTransaction({
|
||||||
chainId,
|
chainId,
|
||||||
currentCurrency,
|
currentCurrency,
|
||||||
@ -430,6 +416,8 @@ export default function ViewQuote() {
|
|||||||
nativeCurrencySymbol,
|
nativeCurrencySymbol,
|
||||||
feeInWeiDec: stxMaxFeeInWeiDec,
|
feeInWeiDec: stxMaxFeeInWeiDec,
|
||||||
}));
|
}));
|
||||||
|
additionalTrackingParams.stx_max_fee_in_usd = Number(maxFeeInUsd);
|
||||||
|
additionalTrackingParams.stx_max_fee_in_eth = Number(maxRawEthFee);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tokenCost = new BigNumber(usedQuote.sourceAmount);
|
const tokenCost = new BigNumber(usedQuote.sourceAmount);
|
||||||
@ -520,7 +508,7 @@ export default function ViewQuote() {
|
|||||||
available_quotes: numberOfQuotes,
|
available_quotes: numberOfQuotes,
|
||||||
is_hardware_wallet: hardwareWalletUsed,
|
is_hardware_wallet: hardwareWalletUsed,
|
||||||
hardware_wallet_type: hardwareWalletType,
|
hardware_wallet_type: hardwareWalletType,
|
||||||
stx_enabled: currentSmartTransactionsEnabled,
|
stx_enabled: smartTransactionsEnabled,
|
||||||
current_stx_enabled: currentSmartTransactionsEnabled,
|
current_stx_enabled: currentSmartTransactionsEnabled,
|
||||||
stx_user_opt_in: smartTransactionsOptInStatus,
|
stx_user_opt_in: smartTransactionsOptInStatus,
|
||||||
};
|
};
|
||||||
@ -782,6 +770,55 @@ export default function ViewQuote() {
|
|||||||
const isShowingWarning =
|
const isShowingWarning =
|
||||||
showInsufficientWarning || shouldShowPriceDifferenceWarning;
|
showInsufficientWarning || shouldShowPriceDifferenceWarning;
|
||||||
|
|
||||||
|
const isSwapButtonDisabled =
|
||||||
|
submitClicked ||
|
||||||
|
balanceError ||
|
||||||
|
tokenBalanceUnavailable ||
|
||||||
|
disableSubmissionDueToPriceWarning ||
|
||||||
|
(networkAndAccountSupports1559 && baseAndPriorityFeePerGas === undefined) ||
|
||||||
|
(!networkAndAccountSupports1559 &&
|
||||||
|
(gasPrice === null || gasPrice === undefined)) ||
|
||||||
|
(currentSmartTransactionsEnabled && currentSmartTransactionsError);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
currentSmartTransactionsEnabled &&
|
||||||
|
smartTransactionsOptInStatus &&
|
||||||
|
!isSwapButtonDisabled
|
||||||
|
) {
|
||||||
|
const unsignedTx = {
|
||||||
|
from: unsignedTransaction.from,
|
||||||
|
to: unsignedTransaction.to,
|
||||||
|
value: unsignedTransaction.value,
|
||||||
|
data: unsignedTransaction.data,
|
||||||
|
gas: unsignedTransaction.gas,
|
||||||
|
chainId,
|
||||||
|
};
|
||||||
|
intervalId = setInterval(() => {
|
||||||
|
dispatch(
|
||||||
|
estimateSwapsSmartTransactionsGas(unsignedTx, approveTxParams),
|
||||||
|
);
|
||||||
|
}, swapsRefreshRates.stxGetTransactionsRefreshTime);
|
||||||
|
dispatch(estimateSwapsSmartTransactionsGas(unsignedTx, approveTxParams));
|
||||||
|
} else if (intervalId) {
|
||||||
|
clearInterval(intervalId);
|
||||||
|
}
|
||||||
|
return () => clearInterval(intervalId);
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, [
|
||||||
|
dispatch,
|
||||||
|
currentSmartTransactionsEnabled,
|
||||||
|
smartTransactionsOptInStatus,
|
||||||
|
unsignedTransaction.data,
|
||||||
|
unsignedTransaction.from,
|
||||||
|
unsignedTransaction.value,
|
||||||
|
unsignedTransaction.gas,
|
||||||
|
unsignedTransaction.to,
|
||||||
|
chainId,
|
||||||
|
swapsRefreshRates.stxGetTransactionsRefreshTime,
|
||||||
|
isSwapButtonDisabled,
|
||||||
|
]);
|
||||||
|
|
||||||
const onCloseEditGasPopover = () => {
|
const onCloseEditGasPopover = () => {
|
||||||
setShowEditGasPopover(false);
|
setShowEditGasPopover(false);
|
||||||
};
|
};
|
||||||
@ -967,10 +1004,17 @@ export default function ViewQuote() {
|
|||||||
unsignedTransaction,
|
unsignedTransaction,
|
||||||
metaMetricsEvent,
|
metaMetricsEvent,
|
||||||
history,
|
history,
|
||||||
|
additionalTrackingParams,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
dispatch(signAndSendTransactions(history, metaMetricsEvent));
|
dispatch(
|
||||||
|
signAndSendTransactions(
|
||||||
|
history,
|
||||||
|
metaMetricsEvent,
|
||||||
|
additionalTrackingParams,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if (destinationToken.symbol === defaultSwapsToken.symbol) {
|
} else if (destinationToken.symbol === defaultSwapsToken.symbol) {
|
||||||
history.push(DEFAULT_ROUTE);
|
history.push(DEFAULT_ROUTE);
|
||||||
@ -986,17 +1030,7 @@ export default function ViewQuote() {
|
|||||||
: t('swap')
|
: t('swap')
|
||||||
}
|
}
|
||||||
hideCancel
|
hideCancel
|
||||||
disabled={
|
disabled={isSwapButtonDisabled}
|
||||||
submitClicked ||
|
|
||||||
balanceError ||
|
|
||||||
tokenBalanceUnavailable ||
|
|
||||||
disableSubmissionDueToPriceWarning ||
|
|
||||||
(networkAndAccountSupports1559 &&
|
|
||||||
baseAndPriorityFeePerGas === undefined) ||
|
|
||||||
(!networkAndAccountSupports1559 &&
|
|
||||||
(gasPrice === null || gasPrice === undefined)) ||
|
|
||||||
(currentSmartTransactionsEnabled && currentSmartTransactionsError)
|
|
||||||
}
|
|
||||||
className={isShowingWarning && 'view-quote__thin-swaps-footer'}
|
className={isShowingWarning && 'view-quote__thin-swaps-footer'}
|
||||||
showTopBorder
|
showTopBorder
|
||||||
/>
|
/>
|
||||||
|
@ -3230,7 +3230,10 @@ export async function setWeb3ShimUsageAlertDismissed(origin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Smart Transactions Controller
|
// Smart Transactions Controller
|
||||||
export async function setSmartTransactionsOptInStatus(optInState) {
|
export async function setSmartTransactionsOptInStatus(
|
||||||
|
optInState,
|
||||||
|
prevOptInState,
|
||||||
|
) {
|
||||||
trackMetaMetricsEvent({
|
trackMetaMetricsEvent({
|
||||||
event: 'STX OptIn',
|
event: 'STX OptIn',
|
||||||
category: 'swaps',
|
category: 'swaps',
|
||||||
@ -3238,6 +3241,7 @@ export async function setSmartTransactionsOptInStatus(optInState) {
|
|||||||
stx_enabled: true,
|
stx_enabled: true,
|
||||||
current_stx_enabled: true,
|
current_stx_enabled: true,
|
||||||
stx_user_opt_in: optInState,
|
stx_user_opt_in: optInState,
|
||||||
|
stx_prev_user_opt_in: prevOptInState,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await promisifiedBackground.setSmartTransactionsOptInStatus(optInState);
|
await promisifiedBackground.setSmartTransactionsOptInStatus(optInState);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user