diff --git a/app/components/Nav/Main/RootRPCMethodsUI.js b/app/components/Nav/Main/RootRPCMethodsUI.js
index 85beb32120bc..2ee97ad6753c 100644
--- a/app/components/Nav/Main/RootRPCMethodsUI.js
+++ b/app/components/Nav/Main/RootRPCMethodsUI.js
@@ -23,7 +23,7 @@ import {
getTokenAddressParam,
calcTokenAmount,
getTokenValueParamAsHex,
- getIsInSwapFlowTransaction,
+ getIsSwapApproveOrSwapTransaction,
} from '../../../util/transactions';
import { BN } from 'ethereumjs-util';
import Logger from '../../../util/Logger';
@@ -63,8 +63,9 @@ import { getLedgerKeyring } from '../../../core/Ledger/Ledger';
import { createLedgerTransactionModalNavDetails } from '../../UI/LedgerModals/LedgerTransactionModal';
import ExtendedKeyringTypes from '../../../constants/keyringTypes';
import { useMetrics } from '../../../components/hooks/useMetrics';
-import { getIsSmartTransaction } from '../../../selectors/smartTransactionsController';
-import { STX_NO_HASH_ERROR } from '../../../util/smart-transactions/smart-tx';
+import { selectShouldUseSmartTransaction } from '../../../selectors/smartTransactionsController';
+import { STX_NO_HASH_ERROR } from '../../../util/smart-transactions/smart-publish-hook';
+import { getSmartTransactionMetricsProperties } from '../../../util/smart-transactions';
///: BEGIN:ONLY_INCLUDE_IF(snaps)
import InstallSnapApproval from '../../Approvals/InstallSnapApproval';
@@ -169,21 +170,11 @@ const RootRPCMethodsUI = (props) => {
delete newSwapsTransactions[transactionMeta.id].analytics;
delete newSwapsTransactions[transactionMeta.id].paramsForAnalytics;
- let smartTransactionMetadata = {};
- if (transactionMeta) {
- const smartTransaction =
- SmartTransactionsController.getSmartTransactionByMinedTxHash(
- transactionMeta.transactionHash,
- );
-
- if (smartTransaction) {
- smartTransactionMetadata = {
- duplicated: smartTransaction.statusMetadata.duplicated,
- timedOut: smartTransaction.statusMetadata.timedOut,
- proxied: smartTransaction.statusMetadata.proxied,
- };
- }
- }
+ const smartTransactionMetricsProperties =
+ getSmartTransactionMetricsProperties(
+ SmartTransactionsController,
+ transactionMeta,
+ );
const parameters = {
...analyticsParams,
@@ -191,8 +182,8 @@ const RootRPCMethodsUI = (props) => {
estimated_vs_used_gasRatio: estimatedVsUsedGasRatio,
quote_vs_executionRatio: quoteVsExecutionRatio,
token_to_amount_received: tokenToAmountReceived.toString(),
- is_smart_transaction: props.isSmartTransaction,
- ...smartTransactionMetadata,
+ is_smart_transaction: props.shouldUseSmartTransaction,
+ ...smartTransactionMetricsProperties,
};
trackAnonymousEvent(event, parameters);
@@ -205,7 +196,7 @@ const RootRPCMethodsUI = (props) => {
},
[
props.selectedAddress,
- props.isSmartTransaction,
+ props.shouldUseSmartTransaction,
trackEvent,
trackAnonymousEvent,
],
@@ -214,8 +205,7 @@ const RootRPCMethodsUI = (props) => {
const autoSign = useCallback(
async (transactionMeta) => {
const { TransactionController, KeyringController } = Engine.context;
- const swapsTransactions =
- Engine.context.TransactionController.state.swapsTransactions;
+ const swapsTransactions = TransactionController.state.swapsTransactions;
try {
TransactionController.hub.once(
`${transactionMeta.id}:finished`,
@@ -302,7 +292,7 @@ const RootRPCMethodsUI = (props) => {
const { data } = transactionMeta.txParams;
if (
- getIsInSwapFlowTransaction(
+ getIsSwapApproveOrSwapTransaction(
data,
transactionMeta.origin,
to,
@@ -485,9 +475,9 @@ RootRPCMethodsUI.propTypes = {
*/
chainId: PropTypes.string,
/**
- * If the transaction is a smart transaction
+ * If smart tranactions should be used
*/
- isSmartTransaction: PropTypes.bool,
+ shouldUseSmartTransaction: PropTypes.bool,
};
const mapStateToProps = (state) => ({
@@ -495,7 +485,7 @@ const mapStateToProps = (state) => ({
chainId: selectChainId(state),
tokens: selectTokens(state),
providerType: selectProviderType(state),
- isSmartTransaction: getIsSmartTransaction(state),
+ shouldUseSmartTransaction: selectShouldUseSmartTransaction(state),
});
const mapDispatchToProps = (dispatch) => ({
diff --git a/app/components/UI/Notification/TransactionNotification/index.js b/app/components/UI/Notification/TransactionNotification/index.js
index cc7a92f50420..46d0a25a856f 100644
--- a/app/components/UI/Notification/TransactionNotification/index.js
+++ b/app/components/UI/Notification/TransactionNotification/index.js
@@ -277,9 +277,7 @@ function TransactionNotification(props) {
// Don't show submitted notification for STX b/c we only know when it's confirmed,
// o/w a submitted notification will show up after it's confirmed, then a confirmed notification will show up immediately after
if (tx.status === 'submitted') {
- const smartTx = smartTransactions.find(
- (stx) => stx.transactionHash === tx.transactionHash,
- );
+ const smartTx = smartTransactions.find((stx) => stx.txHash === tx.hash);
if (smartTx) {
return null;
}
@@ -435,15 +433,22 @@ TransactionNotification.propTypes = {
const mapStateToProps = (state) => {
const chainId = selectChainId(state);
+
+ const {
+ SmartTransactionsController,
+ TransactionController,
+ SwapsController,
+ } = state.engine.backgroundState;
+
const smartTransactions =
- state.engine.backgroundState.SmartTransactionsController
- ?.smartTransactionsState?.smartTransactions?.[chainId] || [];
+ SmartTransactionsController?.smartTransactionsState?.smartTransactions?.[
+ chainId
+ ] || [];
return {
accounts: selectAccounts(state),
selectedAddress: selectSelectedAddress(state),
- transactions:
- state.engine.backgroundState.TransactionController.transactions,
+ transactions: TransactionController.transactions,
ticker: selectTicker(state),
chainId,
tokens: selectTokensByAddress(state),
@@ -452,10 +457,8 @@ const mapStateToProps = (state) => {
conversionRate: selectConversionRate(state),
currentCurrency: selectCurrentCurrency(state),
primaryCurrency: state.settings.primaryCurrency,
- swapsTransactions:
- state.engine.backgroundState.TransactionController.swapsTransactions ||
- {},
- swapsTokens: state.engine.backgroundState.SwapsController.tokens,
+ swapsTransactions: TransactionController.swapsTransactions || {},
+ swapsTokens: SwapsController.tokens,
smartTransactions,
};
};
diff --git a/app/components/UI/Swaps/QuotesView.js b/app/components/UI/Swaps/QuotesView.js
index 9e928b55d418..ce56a8fba5f9 100644
--- a/app/components/UI/Swaps/QuotesView.js
+++ b/app/components/UI/Swaps/QuotesView.js
@@ -100,6 +100,7 @@ import { useMetrics } from '../../../components/hooks/useMetrics';
import { addTransaction } from '../../../util/transaction-controller';
import trackErrorAsAnalytics from '../../../util/metrics/TrackError/trackErrorAsAnalytics';
import { selectGasFeeEstimates } from '../../../selectors/confirmTransaction';
+import { selectShouldUseSmartTransaction } from '../../../selectors/smartTransactionsController';
const POLLING_INTERVAL = 30000;
const SLIPPAGE_BUCKETS = {
@@ -388,6 +389,7 @@ function SwapsQuotesView({
usedCustomGas,
setRecipient,
resetTransaction,
+ shouldUseSmartTransaction,
}) {
const navigation = useNavigation();
/* Get params from navigation */
@@ -992,7 +994,7 @@ function SwapsQuotesView({
16,
).toString(10),
};
- if (isHardwareAddress) {
+ if (isHardwareAddress || shouldUseSmartTransaction) {
TransactionController.hub.once(
`${transactionMeta.id}:confirmed`,
(transactionMeta) => {
@@ -1021,6 +1023,7 @@ function SwapsQuotesView({
selectedAddress,
setRecipient,
resetTransaction,
+ shouldUseSmartTransaction,
],
);
@@ -1053,12 +1056,17 @@ function SwapsQuotesView({
}
}
- handleSwapTransaction(
- TransactionController,
- newSwapsTransactions,
- approvalTransactionMetaId,
- isHardwareAddress,
- );
+ if (
+ !shouldUseSmartTransaction ||
+ (shouldUseSmartTransaction && !approvalTransaction)
+ ) {
+ handleSwapTransaction(
+ TransactionController,
+ newSwapsTransactions,
+ approvalTransactionMetaId,
+ isHardwareAddress,
+ );
+ }
navigation.dangerouslyGetParent()?.pop();
}, [
@@ -1069,6 +1077,7 @@ function SwapsQuotesView({
handleApprovaltransaction,
handleSwapTransaction,
navigation,
+ shouldUseSmartTransaction,
]);
const onEditQuoteTransactionsGas = useCallback(() => {
@@ -2302,6 +2311,7 @@ SwapsQuotesView.propTypes = {
usedCustomGas: PropTypes.object,
setRecipient: PropTypes.func,
resetTransaction: PropTypes.func,
+ shouldUseSmartTransaction: PropTypes.bool,
};
const mapStateToProps = (state) => ({
@@ -2334,6 +2344,7 @@ const mapStateToProps = (state) => ({
usedCustomGas: state.engine.backgroundState.SwapsController.usedCustomGas,
primaryCurrency: state.settings.primaryCurrency,
swapsTokens: swapsTokensSelector(state),
+ shouldUseSmartTransaction: selectShouldUseSmartTransaction(state),
});
const mapDispatchToProps = (dispatch) => ({
diff --git a/app/components/UI/Swaps/components/TokenSelectModal.js b/app/components/UI/Swaps/components/TokenSelectModal.js
index 61a860b52932..0236d5a44ecf 100644
--- a/app/components/UI/Swaps/components/TokenSelectModal.js
+++ b/app/components/UI/Swaps/components/TokenSelectModal.js
@@ -184,12 +184,11 @@ function TokenSelectModal({
const filteredInitialTokens = useMemo(
() =>
initialTokens?.length > 0
- ? initialTokens
- .filter((token) => token !== undefined)
- .filter(
- (token) =>
- !excludedAddresses.includes(token?.address?.toLowerCase()),
- )
+ ? initialTokens.filter(
+ (token) =>
+ typeof token !== 'undefined' &&
+ !excludedAddresses.includes(token?.address?.toLowerCase()),
+ )
: filteredTokens,
[excludedAddresses, filteredTokens, initialTokens],
);
diff --git a/app/components/UI/TemplateRenderer/SafeComponentList.ts b/app/components/UI/TemplateRenderer/SafeComponentList.ts
index b2514e070684..35751a2064ca 100644
--- a/app/components/UI/TemplateRenderer/SafeComponentList.ts
+++ b/app/components/UI/TemplateRenderer/SafeComponentList.ts
@@ -12,9 +12,9 @@ export const safeComponentList = {
Button,
Icon,
SheetHeader,
+ SmartTransactionStatus,
Text,
View,
- SmartTransactionStatus,
};
export type SafeComponentListValues = typeof safeComponentList;
diff --git a/app/components/UI/TransactionElement/TransactionDetails/index.js b/app/components/UI/TransactionElement/TransactionDetails/index.js
index bba0f8a85196..ded80f167bd6 100644
--- a/app/components/UI/TransactionElement/TransactionDetails/index.js
+++ b/app/components/UI/TransactionElement/TransactionDetails/index.js
@@ -40,7 +40,7 @@ import { selectTokensByAddress } from '../../../../selectors/tokensController';
import { selectContractExchangeRates } from '../../../../selectors/tokenRatesController';
import { selectSelectedAddress } from '../../../../selectors/preferencesController';
import { regex } from '../../../../../app/util/regex';
-import { getIsSmartTransaction } from '../../../../selectors/smartTransactionsController';
+import { selectShouldUseSmartTransaction } from '../../../../selectors/smartTransactionsController';
const createStyles = (colors) =>
StyleSheet.create({
@@ -126,9 +126,9 @@ class TransactionDetails extends PureComponent {
primaryCurrency: PropTypes.string,
/**
- * Boolean that indicates if the transaction is a smart transaction
+ * Boolean that indicates if smart transaction should be used
*/
- isSmartTransaction: PropTypes.bool,
+ shouldUseSmartTransaction: PropTypes.bool,
};
state = {
@@ -306,12 +306,14 @@ class TransactionDetails extends PureComponent {
const {
chainId,
transactionObject: { status, time, txParams },
- isSmartTransaction,
+ shouldUseSmartTransaction,
} = this.props;
const { updatedTransactionDetails } = this.state;
const styles = this.getStyles();
- const renderTxActions = status === 'submitted' || status === 'approved';
+ const renderTxActions =
+ (status === 'submitted' || status === 'approved') &&
+ !shouldUseSmartTransaction;
const { rpcBlockExplorer } = this.state;
return updatedTransactionDetails ? (
@@ -322,7 +324,7 @@ class TransactionDetails extends PureComponent {
{strings('transactions.status')}
- {!!renderTxActions && !isSmartTransaction && (
+ {!!renderTxActions && (
{this.renderSpeedUpButton()}
{this.renderCancelButton()}
@@ -432,7 +434,7 @@ const mapStateToProps = (state) => ({
swapsTransactions:
state.engine.backgroundState.TransactionController.swapsTransactions || {},
swapsTokens: state.engine.backgroundState.SwapsController.tokens,
- isSmartTransaction: getIsSmartTransaction(state),
+ shouldUseSmartTransaction: selectShouldUseSmartTransaction(state),
});
TransactionDetails.contextType = ThemeContext;
diff --git a/app/components/UI/TransactionElement/index.js b/app/components/UI/TransactionElement/index.js
index 6ab1002cc82b..a916b87399e2 100644
--- a/app/components/UI/TransactionElement/index.js
+++ b/app/components/UI/TransactionElement/index.js
@@ -323,8 +323,9 @@ class TransactionElement extends PureComponent {
const styles = createStyles(colors, typography);
const { value, fiatValue = false, actionKey } = transactionElement;
const renderNormalActions =
- status === 'submitted' ||
- (status === 'approved' && !isQRHardwareAccount && !isLedgerAccount);
+ (status === 'submitted' ||
+ (status === 'approved' && !isQRHardwareAccount && !isLedgerAccount)) &&
+ !isSmartTransaction;
const renderUnsignedQRActions =
status === 'approved' && isQRHardwareAccount;
const renderLedgerActions = status === 'approved' && isLedgerAccount;
@@ -359,7 +360,7 @@ class TransactionElement extends PureComponent {
)}
- {renderNormalActions && !isSmartTransaction && (
+ {renderNormalActions && (
{this.renderSpeedUpButton()}
{this.renderCancelButton()}
diff --git a/app/components/UI/TransactionElement/utils.js b/app/components/UI/TransactionElement/utils.js
index a3ead34f35a9..bc391969aa10 100644
--- a/app/components/UI/TransactionElement/utils.js
+++ b/app/components/UI/TransactionElement/utils.js
@@ -681,10 +681,7 @@ function decodeSwapsTx(args) {
contractExchangeRates,
assetSymbol,
} = args;
- const swapTransaction =
- (swapsTransactions &&
- (swapsTransactions[id] || swapsTransactions[transactionHash])) ||
- {};
+ const swapTransaction = swapsTransactions?.[id] || {};
const totalGas = calculateTotalGas({
...txParams,
gas: swapTransaction.gasUsed || gas,
diff --git a/app/components/Views/Asset/index.js b/app/components/Views/Asset/index.js
index 2efe470a9965..49c19a649869 100644
--- a/app/components/Views/Asset/index.js
+++ b/app/components/Views/Asset/index.js
@@ -485,7 +485,9 @@ class Asset extends PureComponent {
};
const goToSwaps = () => {
+ // Pop asset screen first as it's very slow when trying to load the STX status modal if we don't
navigation.pop();
+
navigation.navigate(Routes.SWAPS, {
screen: 'SwapsAmountView',
params: {
diff --git a/app/components/Views/Settings/AdvancedSettings/index.js b/app/components/Views/Settings/AdvancedSettings/index.js
index 025ac5fa7243..14dd6b069a01 100644
--- a/app/components/Views/Settings/AdvancedSettings/index.js
+++ b/app/components/Views/Settings/AdvancedSettings/index.js
@@ -36,7 +36,7 @@ import {
selectSmartTransactionsOptInStatus,
selectUseTokenDetection,
} from '../../../../selectors/preferencesController';
-import { getSmartTransactionsEnabled } from '../../../../selectors/smartTransactionsController';
+import { selectSmartTransactionsEnabled } from '../../../../selectors/smartTransactionsController';
import Routes from '../../../../constants/navigation/Routes';
import { MetaMetricsEvents } from '../../../../core/Analytics';
@@ -369,6 +369,7 @@ class AdvancedSettings extends PureComponent {
this.props.metrics.trackEvent(MetaMetricsEvents.SMART_TRANSACTION_OPT_IN, {
stx_opt_in: smartTransactionsOptInStatus,
+ location: 'Advanced Settings',
});
};
@@ -620,7 +621,7 @@ const mapStateToProps = (state) => ({
isTokenDetectionEnabled: selectUseTokenDetection(state),
chainId: selectChainId(state),
smartTransactionsOptInStatus: selectSmartTransactionsOptInStatus(state),
- smartTransactionsEnabled: getSmartTransactionsEnabled(state),
+ smartTransactionsEnabled: selectSmartTransactionsEnabled(state),
});
const mapDispatchToProps = (dispatch) => ({
diff --git a/app/components/Views/Settings/AdvancedSettings/index.test.tsx b/app/components/Views/Settings/AdvancedSettings/index.test.tsx
index 0ce6ba84c4ae..0010d40fc65a 100644
--- a/app/components/Views/Settings/AdvancedSettings/index.test.tsx
+++ b/app/components/Views/Settings/AdvancedSettings/index.test.tsx
@@ -176,7 +176,7 @@ describe('AdvancedSettings', () => {
);
expect(switchElement.props.value).toBe(false);
});
- it('should call PreferencesController.setSmartTransactionsOptInStatus when smart transactions opt in is pressed', async () => {
+ it('should update smartTransactionsOptInStatus when smart transactions opt in is pressed', async () => {
const { findByLabelText } = renderWithProvider(
{
};
});
-const PendingApprovals = {
+const PENDING_APPROVALS = {
Dapp: {
pending: {
id: '8pJ0jVaREyCysgt8DeHcO',
@@ -306,14 +306,14 @@ describe('SmartTransactionStatus', () => {
,
{ state: initialState },
@@ -329,15 +329,15 @@ describe('SmartTransactionStatus', () => {
,
{ state: initialState },
@@ -356,8 +356,8 @@ describe('SmartTransactionStatus', () => {
it('should render success when STX has success status', () => {
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -373,8 +373,8 @@ describe('SmartTransactionStatus', () => {
it('should navigate to Activity page on press of primary button', () => {
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -390,8 +390,8 @@ describe('SmartTransactionStatus', () => {
const onConfirm = jest.fn();
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -399,7 +399,7 @@ describe('SmartTransactionStatus', () => {
const secondaryButton = getByText(
strings('smart_transactions.return_to_dapp', {
- dappName: PendingApprovals.Dapp.success.origin,
+ dappName: PENDING_APPROVALS.Dapp.success.origin,
}),
);
fireEvent.press(secondaryButton);
@@ -412,8 +412,8 @@ describe('SmartTransactionStatus', () => {
it('should navigate to Send page on press of primary button', () => {
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -430,8 +430,8 @@ describe('SmartTransactionStatus', () => {
it('should navigate to Activity page on press of secondary button', () => {
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -449,8 +449,8 @@ describe('SmartTransactionStatus', () => {
it('should navigate to Swaps page on press of primary button', () => {
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -467,8 +467,8 @@ describe('SmartTransactionStatus', () => {
it('should navigate to Activity page on press of secondary button', () => {
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -487,8 +487,8 @@ describe('SmartTransactionStatus', () => {
it('should render cancelled when STX has cancelled status', () => {
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -505,8 +505,10 @@ describe('SmartTransactionStatus', () => {
const onConfirm = jest.fn();
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -514,7 +516,7 @@ describe('SmartTransactionStatus', () => {
const secondaryButton = getByText(
strings('smart_transactions.return_to_dapp', {
- dappName: PendingApprovals.Dapp.cancelled.origin,
+ dappName: PENDING_APPROVALS.Dapp.cancelled.origin,
}),
);
fireEvent.press(secondaryButton);
@@ -526,8 +528,10 @@ describe('SmartTransactionStatus', () => {
it('should navigate to Send page on press of primary button', () => {
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -542,8 +546,10 @@ describe('SmartTransactionStatus', () => {
it('should navigate to Activity page on press of secondary button', () => {
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -560,8 +566,10 @@ describe('SmartTransactionStatus', () => {
it('should navigate to Swaps page on press of primary button', () => {
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -576,8 +584,10 @@ describe('SmartTransactionStatus', () => {
it('should navigate to Activity page on press of secondary button', () => {
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -596,8 +606,8 @@ describe('SmartTransactionStatus', () => {
it('should render failed when STX has unknown status', () => {
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -614,8 +624,8 @@ describe('SmartTransactionStatus', () => {
const onConfirm = jest.fn();
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -623,7 +633,7 @@ describe('SmartTransactionStatus', () => {
const secondaryButton = getByText(
strings('smart_transactions.return_to_dapp', {
- dappName: PendingApprovals.Dapp.unknown.origin,
+ dappName: PENDING_APPROVALS.Dapp.unknown.origin,
}),
);
fireEvent.press(secondaryButton);
@@ -636,8 +646,8 @@ describe('SmartTransactionStatus', () => {
const onConfirm = jest.fn();
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -653,8 +663,8 @@ describe('SmartTransactionStatus', () => {
it('should navigate to Activity page on press of secondary button', () => {
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -672,8 +682,8 @@ describe('SmartTransactionStatus', () => {
const onConfirm = jest.fn();
const { getByText } = renderWithProvider(
,
{ state: initialState },
@@ -689,8 +699,8 @@ describe('SmartTransactionStatus', () => {
it('should navigate to Activity page on press of secondary button', () => {
const { getByText } = renderWithProvider(
,
{ state: initialState },
diff --git a/app/components/Views/SmartTransactionStatus/SmartTransactionStatus.tsx b/app/components/Views/SmartTransactionStatus/SmartTransactionStatus.tsx
index 69e4f1072678..135549d82bce 100644
--- a/app/components/Views/SmartTransactionStatus/SmartTransactionStatus.tsx
+++ b/app/components/Views/SmartTransactionStatus/SmartTransactionStatus.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from 'react';
+import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
import { strings } from '../../../../locales/i18n';
import Icon, {
@@ -16,7 +16,6 @@ import {
import { useSelector } from 'react-redux';
import { selectProviderConfig } from '../../../selectors/networkController';
import { useNavigation } from '@react-navigation/native';
-import { getSwapsChainFeatureFlags } from '../../../reducers/swaps';
import Button, {
ButtonVariants,
} from '../../../component-library/components/Buttons/Button';
@@ -25,6 +24,7 @@ import TransactionBackgroundTop from '../../../images/transaction-background-top
import TransactionBackgroundBottom from '../../../images/transaction-background-bottom.svg';
import LoopingScrollAnimation from './LoopingScrollAnimation';
import { hexToDecimal } from '../../../util/conversions';
+import useRemainingTime from './useRemainingTime';
const getPortfolioStxLink = (chainId: Hex, uuid: string) => {
const chainIdDec = hexToDecimal(chainId);
@@ -56,6 +56,145 @@ export const showRemainingTimeInMinAndSec = (
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
};
+interface getDisplayValuesArgs {
+ status: string | undefined;
+ isStxPending: boolean;
+ isStxPastEstimatedDeadline: boolean;
+ timeLeftForPendingStxInSec: number;
+ isDapp: boolean;
+ isInSwapFlow: boolean;
+ origin: string;
+ viewActivity: () => void;
+ closeStatusPage: () => void;
+ createNewSwap: () => void;
+ createNewSend: () => void;
+}
+
+const getDisplayValuesAndHandlers = ({
+ status,
+ isStxPending,
+ isStxPastEstimatedDeadline,
+ timeLeftForPendingStxInSec,
+ isDapp,
+ isInSwapFlow,
+ origin,
+ viewActivity,
+ closeStatusPage,
+ createNewSwap,
+ createNewSend,
+}: getDisplayValuesArgs) => {
+ const returnTextDapp = strings('smart_transactions.return_to_dapp', {
+ dappName: origin,
+ });
+ const returnTextMM = strings('smart_transactions.try_again');
+
+ // Set icon, header, desc, and buttons
+ let icon;
+ let iconColor;
+ let header;
+ let description;
+ let primaryButtonText;
+ let secondaryButtonText;
+ let handlePrimaryButtonPress;
+ let handleSecondaryButtonPress;
+
+ if (isStxPending && isStxPastEstimatedDeadline) {
+ icon = IconName.Clock;
+ iconColor = IconColor.Primary;
+ header = strings(
+ 'smart_transactions.status_submitting_past_estimated_deadline_header',
+ );
+ description = strings(
+ 'smart_transactions.status_submitting_past_estimated_deadline_description',
+ {
+ timeLeft: showRemainingTimeInMinAndSec(timeLeftForPendingStxInSec),
+ },
+ );
+ } else if (isStxPending) {
+ icon = IconName.Clock;
+ iconColor = IconColor.Primary;
+ header = strings('smart_transactions.status_submitting_header');
+ description = strings('smart_transactions.status_submitting_description', {
+ timeLeft: showRemainingTimeInMinAndSec(timeLeftForPendingStxInSec),
+ });
+ } else if (status === SmartTransactionStatuses.SUCCESS) {
+ icon = IconName.Confirmation;
+ iconColor = IconColor.Success;
+ header = strings('smart_transactions.status_success_header');
+ description = undefined;
+
+ if (isDapp) {
+ primaryButtonText = strings('smart_transactions.view_activity');
+ handlePrimaryButtonPress = viewActivity;
+ secondaryButtonText = returnTextDapp;
+ handleSecondaryButtonPress = closeStatusPage;
+ } else {
+ if (isInSwapFlow) {
+ primaryButtonText = strings('smart_transactions.create_new', {
+ txType: strings('smart_transactions.swap'),
+ });
+ handlePrimaryButtonPress = createNewSwap;
+ } else {
+ primaryButtonText = strings('smart_transactions.create_new', {
+ txType: strings('smart_transactions.send'),
+ });
+ handlePrimaryButtonPress = createNewSend;
+ }
+
+ secondaryButtonText = strings('smart_transactions.view_activity');
+ handleSecondaryButtonPress = viewActivity;
+ }
+ } else if (status?.startsWith(SmartTransactionStatuses.CANCELLED)) {
+ icon = IconName.Danger;
+ iconColor = IconColor.Error;
+ header = strings('smart_transactions.status_cancelled_header');
+ description = strings('smart_transactions.status_cancelled_description');
+
+ if (isDapp) {
+ secondaryButtonText = returnTextDapp;
+ handleSecondaryButtonPress = closeStatusPage;
+ } else {
+ primaryButtonText = returnTextMM;
+
+ if (isInSwapFlow) {
+ handlePrimaryButtonPress = createNewSwap;
+ } else {
+ handlePrimaryButtonPress = createNewSend;
+ }
+
+ secondaryButtonText = strings('smart_transactions.view_activity');
+ handleSecondaryButtonPress = viewActivity;
+ }
+ } else {
+ // Reverted or unknown statuses (tx failed)
+ icon = IconName.Danger;
+ iconColor = IconColor.Error;
+ header = strings('smart_transactions.status_failed_header');
+ description = strings('smart_transactions.status_failed_description');
+
+ if (isDapp) {
+ secondaryButtonText = returnTextDapp;
+ handleSecondaryButtonPress = closeStatusPage;
+ } else {
+ primaryButtonText = returnTextMM;
+ handlePrimaryButtonPress = closeStatusPage;
+ secondaryButtonText = strings('smart_transactions.view_activity');
+ handleSecondaryButtonPress = viewActivity;
+ }
+ }
+
+ return {
+ icon,
+ iconColor,
+ header,
+ description,
+ primaryButtonText,
+ secondaryButtonText,
+ handlePrimaryButtonPress,
+ handleSecondaryButtonPress,
+ };
+};
+
const SmartTransactionStatus = ({
requestState: { smartTransaction, isDapp, isInSwapFlow },
origin,
@@ -63,24 +202,10 @@ const SmartTransactionStatus = ({
}: Props) => {
const { status, creationTime, uuid } = smartTransaction;
const providerConfig = useSelector(selectProviderConfig);
- const swapFeatureFlags = useSelector(getSwapsChainFeatureFlags);
const navigation = useNavigation();
const { colors } = useTheme();
- const stxEstimatedDeadlineSec =
- swapFeatureFlags?.smartTransactions?.expectedDeadline ||
- FALLBACK_STX_ESTIMATED_DEADLINE_SEC;
- const stxMaxDeadlineSec =
- swapFeatureFlags?.smartTransactions?.maxDeadline ||
- FALLBACK_STX_MAX_DEADLINE_SEC;
-
- const [isStxPastEstimatedDeadline, setIsStxPastEstimatedDeadline] =
- useState(false);
- const [timeLeftForPendingStxInSec, setTimeLeftForPendingStxInSec] = useState(
- stxEstimatedDeadlineSec,
- );
-
// Setup styles
const styles = StyleSheet.create({
wrapper: {
@@ -134,60 +259,14 @@ const SmartTransactionStatus = ({
const isStxPending = status === SmartTransactionStatuses.PENDING;
- // Calc time left for progress bar and timer display
- const stxDeadlineSec = isStxPastEstimatedDeadline
- ? stxMaxDeadlineSec
- : stxEstimatedDeadlineSec;
-
- useEffect(() => {
- let intervalId: NodeJS.Timeout;
- if (isStxPending && creationTime) {
- const calculateRemainingTime = () => {
- const secondsAfterStxSubmission = Math.round(
- (Date.now() - creationTime) / 1000,
- );
- if (secondsAfterStxSubmission > stxDeadlineSec) {
- if (isStxPastEstimatedDeadline) {
- setTimeLeftForPendingStxInSec(0);
- clearInterval(intervalId);
- return;
- }
- setIsStxPastEstimatedDeadline(true);
- }
- setTimeLeftForPendingStxInSec(
- stxDeadlineSec - secondsAfterStxSubmission,
- );
- };
- intervalId = setInterval(calculateRemainingTime, 1000);
- calculateRemainingTime();
- }
-
- return () => clearInterval(intervalId);
- }, [isStxPending, isStxPastEstimatedDeadline, creationTime, stxDeadlineSec]);
-
- // Set block explorer link and show explorer on click
- const txUrl = getPortfolioStxLink(providerConfig.chainId, uuid);
-
- const onViewTransaction = () => {
- navigation.navigate('Webview', {
- screen: 'SimpleWebview',
- params: {
- url: txUrl,
- },
- });
- // Close SmartTransactionStatus
- onConfirm();
- };
-
- // Set icon, header, desc, and buttons
- let icon;
- let iconColor;
- let header;
- let description;
- let primaryButtonText;
- let secondaryButtonText;
- let onPrimaryButtonPress;
- let onSecondaryButtonPress;
+ const {
+ timeLeftForPendingStxInSec,
+ stxDeadlineSec,
+ isStxPastEstimatedDeadline,
+ } = useRemainingTime({
+ creationTime,
+ isStxPending,
+ });
const viewActivity = () => {
onConfirm();
@@ -208,99 +287,78 @@ const SmartTransactionStatus = ({
navigation.navigate('SendFlowView');
};
- const returnTextDapp = strings('smart_transactions.return_to_dapp', {
- dappName: origin,
+ const {
+ icon,
+ iconColor,
+ header,
+ description,
+ primaryButtonText,
+ secondaryButtonText,
+ handlePrimaryButtonPress,
+ handleSecondaryButtonPress,
+ } = getDisplayValuesAndHandlers({
+ status,
+ isStxPending,
+ isStxPastEstimatedDeadline,
+ timeLeftForPendingStxInSec,
+ isDapp,
+ isInSwapFlow,
+ origin,
+ viewActivity,
+ closeStatusPage,
+ createNewSwap,
+ createNewSend,
});
- const returnTextMM = strings('smart_transactions.try_again');
- if (isStxPending && isStxPastEstimatedDeadline) {
- icon = IconName.Clock;
- iconColor = IconColor.Primary;
- header = strings(
- 'smart_transactions.status_submitting_past_estimated_deadline_header',
- );
- description = strings(
- 'smart_transactions.status_submitting_past_estimated_deadline_description',
- {
- timeLeft: showRemainingTimeInMinAndSec(timeLeftForPendingStxInSec),
+ // Set block explorer link and show explorer on click
+ const txUrl = getPortfolioStxLink(providerConfig.chainId, uuid);
+
+ const onViewTransaction = () => {
+ navigation.navigate('Webview', {
+ screen: 'SimpleWebview',
+ params: {
+ url: txUrl,
},
- );
- } else if (isStxPending) {
- icon = IconName.Clock;
- iconColor = IconColor.Primary;
- header = strings('smart_transactions.status_submitting_header');
- description = strings('smart_transactions.status_submitting_description', {
- timeLeft: showRemainingTimeInMinAndSec(timeLeftForPendingStxInSec),
});
- } else if (status === SmartTransactionStatuses.SUCCESS) {
- icon = IconName.Confirmation;
- iconColor = IconColor.Success;
- header = strings('smart_transactions.status_success_header');
- description = undefined;
-
- if (isDapp) {
- primaryButtonText = strings('smart_transactions.view_activity');
- onPrimaryButtonPress = viewActivity;
- secondaryButtonText = returnTextDapp;
- onSecondaryButtonPress = closeStatusPage;
- } else {
- if (isInSwapFlow) {
- primaryButtonText = strings('smart_transactions.create_new', {
- txType: strings('smart_transactions.swap'),
- });
- onPrimaryButtonPress = createNewSwap;
- } else {
- primaryButtonText = strings('smart_transactions.create_new', {
- txType: strings('smart_transactions.send'),
- });
- onPrimaryButtonPress = createNewSend;
- }
-
- secondaryButtonText = strings('smart_transactions.view_activity');
- onSecondaryButtonPress = viewActivity;
- }
- } else if (status?.startsWith(SmartTransactionStatuses.CANCELLED)) {
- icon = IconName.Danger;
- iconColor = IconColor.Error;
- header = strings('smart_transactions.status_cancelled_header');
- description = strings('smart_transactions.status_cancelled_description');
-
- if (isDapp) {
- secondaryButtonText = returnTextDapp;
- onSecondaryButtonPress = closeStatusPage;
- } else {
- primaryButtonText = returnTextMM;
-
- if (isInSwapFlow) {
- onPrimaryButtonPress = createNewSwap;
- } else {
- onPrimaryButtonPress = createNewSend;
- }
-
- secondaryButtonText = strings('smart_transactions.view_activity');
- onSecondaryButtonPress = viewActivity;
- }
- } else {
- // Reverted or unknown statuses (tx failed)
- icon = IconName.Danger;
- iconColor = IconColor.Error;
- header = strings('smart_transactions.status_failed_header');
- description = strings('smart_transactions.status_failed_description');
-
- if (isDapp) {
- secondaryButtonText = returnTextDapp;
- onSecondaryButtonPress = closeStatusPage;
- } else {
- primaryButtonText = returnTextMM;
- onPrimaryButtonPress = closeStatusPage;
- secondaryButtonText = strings('smart_transactions.view_activity');
- onSecondaryButtonPress = viewActivity;
- }
- }
+ // Close SmartTransactionStatus
+ onConfirm();
+ };
const percentComplete =
(1 - timeLeftForPendingStxInSec / stxDeadlineSec) * 100;
+ const PrimaryButton = () =>
+ handlePrimaryButtonPress ? (
+
+ ) : null;
+
+ const SecondaryButton = () =>
+ handleSecondaryButtonPress ? (
+
+ ) : null;
+
+ const ViewTransactionLink = () => (
+
+
+ {strings('smart_transactions.view_transaction')}
+
+
+ );
+
return (
@@ -318,11 +376,7 @@ const SmartTransactionStatus = ({
{description && {description}}
-
-
- {strings('smart_transactions.view_transaction')}
-
-
+
@@ -330,26 +384,8 @@ const SmartTransactionStatus = ({
- {onPrimaryButtonPress && (
-
- )}
- {onSecondaryButtonPress && (
-
- )}
+
+
);
diff --git a/app/components/Views/SmartTransactionsOptInModal/SmartTranactionsOptInModal.tsx b/app/components/Views/SmartTransactionsOptInModal/SmartTranactionsOptInModal.tsx
index a20e46f54e8d..ae80df6d0723 100644
--- a/app/components/Views/SmartTransactionsOptInModal/SmartTranactionsOptInModal.tsx
+++ b/app/components/Views/SmartTransactionsOptInModal/SmartTranactionsOptInModal.tsx
@@ -31,12 +31,13 @@ import Button, {
} from '../../../component-library/components/Buttons/Button';
import AppConstants from '../../../core/AppConstants';
import backgroundImage from '../../../images/smart-transactions-opt-in-bg.png';
+import { MetaMetricsEvents, useMetrics } from '../../hooks/useMetrics';
-const modalMargin = 24;
-const modalPadding = 24;
+const MODAL_MARGIN = 24;
+const MODAL_PADDING = 24;
const screenWidth = Device.getDeviceWidth();
const screenHeight = Device.getDeviceHeight();
-const itemWidth = screenWidth - modalMargin * 2;
+const itemWidth = screenWidth - MODAL_MARGIN * 2;
const maxItemHeight = screenHeight - 200;
const createStyles = (colors: Colors) =>
@@ -46,7 +47,7 @@ const createStyles = (colors: Colors) =>
},
content: {
gap: 16,
- paddingHorizontal: modalPadding,
+ paddingHorizontal: MODAL_PADDING,
},
buttons: {
gap: 10,
@@ -56,6 +57,9 @@ const createStyles = (colors: Colors) =>
width: '100%',
textAlign: 'center',
},
+ secondaryButtonText: {
+ color: colors.text.alternative,
+ },
header: {
alignItems: 'center',
},
@@ -66,7 +70,7 @@ const createStyles = (colors: Colors) =>
modal: {
backgroundColor: colors.background.default,
borderRadius: 10,
- marginHorizontal: modalMargin,
+ marginHorizontal: MODAL_MARGIN,
},
bodyContainer: {
width: itemWidth,
@@ -118,7 +122,7 @@ const Benefit = ({ iconName, text }: Props) => {
{t}
@@ -132,6 +136,8 @@ const Benefit = ({ iconName, text }: Props) => {
const SmartTransactionsOptInModal = () => {
const modalRef = useRef(null);
const { colors } = useTheme();
+ const { trackEvent } = useMetrics();
+
const styles = createStyles(colors);
const hasOptedIn = useRef(null);
@@ -142,17 +148,27 @@ const SmartTransactionsOptInModal = () => {
const optIn = () => {
Engine.context.PreferencesController.setSmartTransactionsOptInStatus(true);
+ trackEvent(MetaMetricsEvents.SMART_TRANSACTION_OPT_IN, {
+ stx_opt_in: true,
+ location: 'SmartTransactionsOptInModal',
+ });
+
hasOptedIn.current = true;
dismissModal();
};
const optOut = () => {
Engine.context.PreferencesController.setSmartTransactionsOptInStatus(false);
+ trackEvent(MetaMetricsEvents.SMART_TRANSACTION_OPT_IN, {
+ stx_opt_in: false,
+ location: 'SmartTransactionsOptInModal',
+ });
+
hasOptedIn.current = false;
dismissModal();
};
- const onDismiss = async () => {
+ const handleDismiss = async () => {
// Opt out of STX if no prior decision made
if (hasOptedIn.current === null) {
optOut();
@@ -166,8 +182,89 @@ const SmartTransactionsOptInModal = () => {
);
};
+ const Header = () => (
+
+
+ {strings('whats_new.stx.header')}
+
+
+ );
+
+ const Benefits = () => (
+
+
+
+
+
+ );
+
+ const Descriptions = () => (
+
+ {strings('whats_new.stx.description_1')}
+
+ {strings('whats_new.stx.description_2')}{' '}
+ {
+ Linking.openURL(AppConstants.URLS.SMART_TXS);
+ }}
+ >
+ {strings('whats_new.stx.learn_more')}
+
+
+
+ );
+
+ const PrimaryButton = () => (
+
+ );
+
+ const SecondaryButton = () => (
+
+ }
+ >
+ {strings('whats_new.stx.secondary_button')}
+
+ );
+
return (
-
+
{
resizeMode="cover"
style={styles.backgroundImage}
>
- {/* Header */}
-
-
- {strings('whats_new.stx.header')}
-
-
-
- {/* Benefits */}
-
-
-
-
-
+
+
{/* Content */}
-
- {strings('whats_new.stx.description_1')}
- {strings('whats_new.stx.description_2')}
-
- {strings('whats_new.stx.description_3')}{' '}
- {
- Linking.openURL(AppConstants.URLS.SMART_TXS);
- }}
- >
- {strings('whats_new.stx.learn_more')}
-
-
-
+
-
-
-
+
+
diff --git a/app/components/Views/SmartTransactionsOptInModal/SmartTransactionsOptInModal.test.tsx b/app/components/Views/SmartTransactionsOptInModal/SmartTransactionsOptInModal.test.tsx
index 512e8fccf080..7a8a685c7d41 100644
--- a/app/components/Views/SmartTransactionsOptInModal/SmartTransactionsOptInModal.test.tsx
+++ b/app/components/Views/SmartTransactionsOptInModal/SmartTransactionsOptInModal.test.tsx
@@ -67,13 +67,10 @@ describe('SmartTransactionsOptInModal', () => {
const description1 = getByText(strings('whats_new.stx.description_1'));
expect(description1).toBeDefined();
- const description2 = getByText(strings('whats_new.stx.description_2'));
- expect(description2).toBeDefined();
-
- const description3 = getByText(strings('whats_new.stx.description_3'), {
+ const description2 = getByText(strings('whats_new.stx.description_2'), {
exact: false,
});
- expect(description3).toBeDefined();
+ expect(description2).toBeDefined();
const primaryButton = getByText(strings('whats_new.stx.primary_button'));
expect(primaryButton).toBeDefined();
diff --git a/app/components/Views/TransactionsView/index.js b/app/components/Views/TransactionsView/index.js
index b5d6c6d976db..c86ae07e68de 100644
--- a/app/components/Views/TransactionsView/index.js
+++ b/app/components/Views/TransactionsView/index.js
@@ -35,7 +35,8 @@ import {
import { WalletViewSelectorsIDs } from '../../../../e2e/selectors/WalletView.selectors';
import { store } from '../../../store';
import { NETWORK_ID_LOADING } from '../../../core/redux/slices/inpageProvider';
-import { SmartTransactionStatuses } from '@metamask/smart-transactions-controller/dist/types';
+import { selectPendingSmartTransactionsBySender } from '../../../selectors/smartTransactionsController';
+import { selectNonReplacedTransactions } from '../../../selectors/transactionController';
const styles = StyleSheet.create({
wrapper: {
@@ -221,42 +222,13 @@ TransactionsView.propTypes = {
const mapStateToProps = (state) => {
const selectedAddress = selectSelectedAddress(state);
const chainId = selectChainId(state);
- const nonSmartTransactions =
- state.engine.backgroundState.TransactionController.transactions; // these are transactionMeta objs
- const smartTransactions =
- state.engine.backgroundState.SmartTransactionsController
- ?.smartTransactionsState?.smartTransactions?.[chainId] || [];
// Remove duplicate confirmed STX
-
// for replaced txs, only hide the ones that are confirmed
- const filteredNonSmartTransactions = nonSmartTransactions.filter(
- (tx) => !(tx.replacedBy && tx.replacedById && tx.transactionHash),
- );
+ const nonReplacedTransactions = selectNonReplacedTransactions(state);
- const filteredPendingSmartTransactions =
- smartTransactions
- ?.filter((stx) => {
- const { transaction } = stx;
- return (
- transaction?.from.toLowerCase() === selectedAddress.toLowerCase() &&
- stx.status &&
- stx.status !== SmartTransactionStatuses.SUCCESS &&
- stx.status !== SmartTransactionStatuses.CANCELLED
- );
- })
- .map((stx) => ({
- ...stx,
- // stx.uuid is one from sentinel API, not the same as tx.id which is generated client side
- // Doesn't matter too much because we only care about the pending stx, confirmed txs are handled like normal
- // However, this does make it impossible to read Swap data from TxController.swapsTransactions as that relies on client side tx.id
- // To fix that we do transactionController.update({ swapsTransactions: newSwapsTransactions }) in app/util/smart-transactions/smart-tx.ts
- id: stx.uuid,
- status: stx.status?.startsWith(SmartTransactionStatuses.CANCELLED)
- ? SmartTransactionStatuses.CANCELLED
- : stx.status,
- isSmartTransaction: true,
- })) ?? [];
+ const pendingSmartTransactions =
+ selectPendingSmartTransactionsBySender(state);
return {
conversionRate: selectConversionRate(state),
@@ -265,8 +237,8 @@ const mapStateToProps = (state) => {
selectedAddress,
identities: selectIdentities(state),
transactions: [
- ...filteredNonSmartTransactions,
- ...filteredPendingSmartTransactions,
+ ...nonReplacedTransactions,
+ ...pendingSmartTransactions,
].sort((a, b) => b.time - a.time),
networkType: selectProviderType(state),
chainId,
diff --git a/app/components/Views/Wallet/index.tsx b/app/components/Views/Wallet/index.tsx
index 86e0464a9bcf..e393395628b0 100644
--- a/app/components/Views/Wallet/index.tsx
+++ b/app/components/Views/Wallet/index.tsx
@@ -479,7 +479,7 @@ const Wallet = ({ navigation }: any) => {
*/
const renderOnboardingWizard = useCallback(
() =>
- [1, 2, 3].includes(wizardStep) && (
+ [1, 2, 3, 4, 5, 6, 7].includes(wizardStep) && (
{
try {
- const { chainId, transaction, selectedAddress, isSmartTransaction } =
- this.props;
+ const {
+ chainId,
+ transaction,
+ selectedAddress,
+ shouldUseSmartTransaction,
+ } = this.props;
const { selectedAsset } = transaction;
const { TransactionController, SmartTransactionsController } =
Engine.context;
@@ -319,21 +324,11 @@ class Approval extends PureComponent {
transaction.id,
);
- let smartTransactionMetadata = {};
- if (transactionMeta) {
- const smartTransaction =
- SmartTransactionsController.getSmartTransactionByMinedTxHash(
- transactionMeta.transactionHash,
- );
-
- if (smartTransaction) {
- smartTransactionMetadata = {
- duplicated: smartTransaction.statusMetadata.duplicated,
- timedOut: smartTransaction.statusMetadata.timedOut,
- proxied: smartTransaction.statusMetadata.proxied,
- };
- }
- }
+ const smartTransactionMetricsProperties =
+ getSmartTransactionMetricsProperties(
+ SmartTransactionsController,
+ transactionMeta,
+ );
return {
account_type: getAddressAccountType(selectedAddress),
@@ -349,8 +344,8 @@ class Approval extends PureComponent {
: this.originIsWalletConnect
? AppConstants.REQUEST_SOURCES.WC
: AppConstants.REQUEST_SOURCES.IN_APP_BROWSER,
- is_smart_transaction: isSmartTransaction,
- ...smartTransactionMetadata,
+ is_smart_transaction: shouldUseSmartTransaction,
+ ...smartTransactionMetricsProperties,
};
} catch (error) {
return {};
@@ -434,7 +429,7 @@ class Approval extends PureComponent {
transaction: { assetType, selectedAsset },
showCustomNonce,
chainId,
- isSmartTransaction,
+ shouldUseSmartTransaction,
} = this.props;
let { transaction } = this.props;
const { nonce } = transaction;
@@ -471,7 +466,7 @@ class Approval extends PureComponent {
}
// For STX, don't wait for TxController to get finished event, since it will take some time to get hash for STX
- if (isSmartTransaction) {
+ if (shouldUseSmartTransaction) {
this.setState({ transactionHandled: true });
this.props.hideModal();
}
@@ -698,7 +693,7 @@ const mapStateToProps = (state) => ({
showCustomNonce: state.settings.showCustomNonce,
chainId: selectChainId(state),
activeTabUrl: getActiveTabUrl(state),
- isSmartTransaction: getIsSmartTransaction(state),
+ shouldUseSmartTransaction: selectShouldUseSmartTransaction(state),
});
const mapDispatchToProps = (dispatch) => ({
diff --git a/app/components/Views/confirmations/ApproveView/Approve/index.js b/app/components/Views/confirmations/ApproveView/Approve/index.js
index 7ecf3758fe21..7f5459a12b38 100644
--- a/app/components/Views/confirmations/ApproveView/Approve/index.js
+++ b/app/components/Views/confirmations/ApproveView/Approve/index.js
@@ -75,8 +75,8 @@ import { updateTransaction } from '../../../../../util/transaction-controller';
import { withMetricsAwareness } from '../../../../../components/hooks/useMetrics';
import { selectGasFeeEstimates } from '../../../../../selectors/confirmTransaction';
import { selectGasFeeControllerEstimateType } from '../../../../../selectors/gasFeeController';
-import { getIsSmartTransaction } from '../../../../../selectors/smartTransactionsController';
-import { STX_NO_HASH_ERROR } from '../../../../../util/smart-transactions/smart-tx';
+import { selectShouldUseSmartTransaction } from '../../../../../selectors/smartTransactionsController';
+import { STX_NO_HASH_ERROR } from '../../../../../util/smart-transactions/smart-publish-hook';
const EDIT = 'edit';
const REVIEW = 'review';
@@ -174,9 +174,9 @@ class Approve extends PureComponent {
*/
metrics: PropTypes.object,
/**
- * Indicates if a transaction is going to be routed through smart tx
+ * Boolean that indicates if smart transaction should be used
*/
- isSmartTransaction: PropTypes.bool,
+ shouldUseSmartTransaction: PropTypes.bool,
};
state = {
@@ -509,9 +509,9 @@ class Approve extends PureComponent {
const {
transactions,
gasEstimateType,
- isSmartTransaction,
metrics,
chainId,
+ shouldUseSmartTransaction,
} = this.props;
const {
legacyGasTransaction,
@@ -586,15 +586,11 @@ class Approve extends PureComponent {
return;
}
- if (isSmartTransaction) {
- await ApprovalController.accept(transaction.id, undefined, {
- waitForResult: false,
- });
+ await ApprovalController.accept(transaction.id, undefined, {
+ waitForResult: !shouldUseSmartTransaction,
+ });
+ if (shouldUseSmartTransaction) {
this.props.hideModal();
- } else {
- await ApprovalController.accept(transaction.id, undefined, {
- waitForResult: true,
- });
}
metrics.trackEvent(
@@ -935,7 +931,7 @@ const mapStateToProps = (state) => ({
providerType: selectProviderType(state),
providerRpcTarget: selectRpcUrl(state),
networkConfigurations: selectNetworkConfigurations(state),
- isSmartTransaction: getIsSmartTransaction(state),
+ shouldUseSmartTransaction: selectShouldUseSmartTransaction(state),
});
const mapDispatchToProps = (dispatch) => ({
diff --git a/app/components/Views/confirmations/Send/index.js b/app/components/Views/confirmations/Send/index.js
index 82064682b174..43c96be83ab5 100644
--- a/app/components/Views/confirmations/Send/index.js
+++ b/app/components/Views/confirmations/Send/index.js
@@ -63,8 +63,8 @@ import {
} from '../../../../selectors/preferencesController';
import { providerErrors } from '@metamask/rpc-errors';
import { withMetricsAwareness } from '../../../../components/hooks/useMetrics';
-import { getIsSmartTransaction } from '../../../../selectors/smartTransactionsController';
-import { STX_NO_HASH_ERROR } from '../../../../util/smart-transactions/smart-tx';
+import { selectShouldUseSmartTransaction } from '../../../../selectors/smartTransactionsController';
+import { STX_NO_HASH_ERROR } from '../../../../util/smart-transactions/smart-publish-hook';
const REVIEW = 'review';
const EDIT = 'edit';
@@ -158,9 +158,9 @@ class Send extends PureComponent {
*/
metrics: PropTypes.object,
/**
- * Boolean that represents whether the transaction is a smart transaction
+ * Boolean that indicates if smart transaction should be used
*/
- isSmartTransaction: PropTypes.bool,
+ shouldUseSmartTransaction: PropTypes.bool,
};
state = {
@@ -698,7 +698,7 @@ class Send extends PureComponent {
networkType,
transaction,
transaction: { selectedAsset, assetType },
- isSmartTransaction,
+ shouldUseSmartTransaction,
} = this.props;
return {
@@ -710,7 +710,7 @@ class Send extends PureComponent {
'ETH',
assetType,
...getBlockaidTransactionMetricsParams(transaction),
- is_smart_transaction: isSmartTransaction,
+ is_smart_transaction: shouldUseSmartTransaction,
};
};
@@ -787,7 +787,7 @@ const mapStateToProps = (state) => ({
selectedAddress: selectSelectedAddress(state),
dappTransactionModalVisible: state.modals.dappTransactionModalVisible,
tokenList: selectTokenList(state),
- isSmartTransaction: getIsSmartTransaction(state),
+ shouldUseSmartTransaction: selectShouldUseSmartTransaction(state),
});
const mapDispatchToProps = (dispatch) => ({
diff --git a/app/components/Views/confirmations/SendFlow/Confirm/index.js b/app/components/Views/confirmations/SendFlow/Confirm/index.js
index 0b4f21eb6f78..9330cce1afeb 100644
--- a/app/components/Views/confirmations/SendFlow/Confirm/index.js
+++ b/app/components/Views/confirmations/SendFlow/Confirm/index.js
@@ -119,8 +119,9 @@ import { withMetricsAwareness } from '../../../../../components/hooks/useMetrics
import { selectTransactionGasFeeEstimates } from '../../../../../selectors/confirmTransaction';
import { selectGasFeeControllerEstimateType } from '../../../../../selectors/gasFeeController';
import { updateTransaction } from '../../../../../util/transaction-controller';
-import { getIsSmartTransaction } from '../../../../../selectors/smartTransactionsController';
-import { STX_NO_HASH_ERROR } from '../../../../../util/smart-transactions/smart-tx';
+import { selectShouldUseSmartTransaction } from '../../../../../selectors/smartTransactionsController';
+import { STX_NO_HASH_ERROR } from '../../../../../util/smart-transactions/smart-publish-hook';
+import { getSmartTransactionMetricsProperties } from '../../../../../util/smart-transactions';
const EDIT = 'edit';
const EDIT_NONCE = 'edit_nonce';
@@ -243,9 +244,9 @@ class Confirm extends PureComponent {
*/
setTransactionId: PropTypes.func,
/**
- * Indicates if a transaction is going to be routed through smart tx
+ * Boolean that indicates if smart transaction should be used
*/
- isSmartTransaction: PropTypes.bool,
+ shouldUseSmartTransaction: PropTypes.bool,
};
state = {
@@ -287,26 +288,20 @@ class Confirm extends PureComponent {
getAnalyticsParams = (transactionMeta) => {
try {
- const { selectedAsset, gasEstimateType, chainId, isSmartTransaction } =
- this.props;
+ const {
+ selectedAsset,
+ gasEstimateType,
+ chainId,
+ shouldUseSmartTransaction,
+ } = this.props;
const { gasSelected, fromSelectedAddress } = this.state;
const { SmartTransactionsController } = Engine.context;
- let smartTransactionMetadata = {};
- if (transactionMeta) {
- const smartTransaction =
- SmartTransactionsController.getSmartTransactionByMinedTxHash(
- transactionMeta.transactionHash,
- );
-
- if (smartTransaction) {
- smartTransactionMetadata = {
- duplicated: smartTransaction.statusMetadata.duplicated,
- timedOut: smartTransaction.statusMetadata.timedOut,
- proxied: smartTransaction.statusMetadata.proxied,
- };
- }
- }
+ const smartTransactionMetricsProperties =
+ getSmartTransactionMetricsProperties(
+ SmartTransactionsController,
+ transactionMeta,
+ );
return {
active_currency: { value: selectedAsset?.symbol, anonymous: true },
@@ -321,8 +316,8 @@ class Confirm extends PureComponent {
? AppConstants.REQUEST_SOURCES.WC
: AppConstants.REQUEST_SOURCES.IN_APP_BROWSER,
- is_smart_transaction: isSmartTransaction,
- ...smartTransactionMetadata,
+ is_smart_transaction: shouldUseSmartTransaction,
+ ...smartTransactionMetricsProperties,
};
} catch (error) {
return {};
@@ -831,7 +826,7 @@ class Confirm extends PureComponent {
navigation,
resetTransaction,
gasEstimateType,
- isSmartTransaction,
+ shouldUseSmartTransaction,
} = this.props;
const {
@@ -897,7 +892,7 @@ class Confirm extends PureComponent {
await KeyringController.resetQRKeyringState();
- if (isSmartTransaction) {
+ if (shouldUseSmartTransaction) {
await ApprovalController.accept(transactionMeta.id, undefined, {
waitForResult: false,
});
@@ -930,7 +925,7 @@ class Confirm extends PureComponent {
stopGasPolling();
resetTransaction();
- if (!isSmartTransaction) {
+ if (!shouldUseSmartTransaction) {
// We popped it already earlier
navigation && navigation.dangerouslyGetParent()?.pop();
}
@@ -1211,7 +1206,7 @@ class Confirm extends PureComponent {
chainId,
gasEstimateType,
isNativeTokenBuySupported,
- isSmartTransaction,
+ shouldUseSmartTransaction,
} = this.props;
const { nonce } = this.props.transaction;
const {
@@ -1342,7 +1337,7 @@ class Confirm extends PureComponent {
updateGasState={this.updateGasState}
/>
)}
- {showCustomNonce && !isSmartTransaction && (
+ {showCustomNonce && !shouldUseSmartTransaction && (
this.toggleConfirmationModal(EDIT_NONCE)}
@@ -1446,7 +1441,7 @@ const mapStateToProps = (state) => ({
selectChainId(state),
getRampNetworks(state),
),
- isSmartTransaction: getIsSmartTransaction(state),
+ shouldUseSmartTransaction: selectShouldUseSmartTransaction(state),
});
const mapDispatchToProps = (dispatch) => ({
diff --git a/app/components/Views/confirmations/components/Approval/TemplateConfirmation/Templates/SmartTransactionStatus.ts b/app/components/Views/confirmations/components/Approval/TemplateConfirmation/Templates/SmartTransactionStatus.ts
index a81dcf6d6aa8..a4b68f9c70d9 100644
--- a/app/components/Views/confirmations/components/Approval/TemplateConfirmation/Templates/SmartTransactionStatus.ts
+++ b/app/components/Views/confirmations/components/Approval/TemplateConfirmation/Templates/SmartTransactionStatus.ts
@@ -1,8 +1,6 @@
import { ApprovalRequest } from '@metamask/approval-controller';
import { Actions } from '../TemplateConfirmation';
import { ConfirmationTemplateValues, ConfirmationTemplate } from '.';
-import Logger from '../../../../../../../util/Logger';
-import Engine from '../../../../../../../core/Engine';
function getValues(
pendingApproval: ApprovalRequest,
@@ -26,16 +24,9 @@ function getValues(
],
onConfirm: () => actions.onConfirm,
onCancel: () => {
+ // Need to stub out onCancel, otherwise the status modal will dismiss once the tx is complete
// This is called when the stx is done for some reason, ALSO called when user swipes down
// Cannot do onConfirm(), it will dismiss the status modal after tx complete, we want to keep it up after success
-
- try {
- // Remove the loading spinner on swipe down if tx is in progress
- // If swipe down after tx success an error is thrown b/c app/util/smart-transactions/smart-tx.ts ends the flow if tx success, so just catch
- Engine.context.ApprovalController.endFlow({ id: pendingApproval.id });
- } catch (e: any) {
- Logger.error(e, 'STX SmartTransactionStatus onCancel error');
- }
},
hideCancelButton: true,
hideSubmitButton: true,
diff --git a/app/components/Views/confirmations/components/ApproveTransactionReview/index.js b/app/components/Views/confirmations/components/ApproveTransactionReview/index.js
index 3cc8080e5812..2ab9c3469a93 100644
--- a/app/components/Views/confirmations/components/ApproveTransactionReview/index.js
+++ b/app/components/Views/confirmations/components/ApproveTransactionReview/index.js
@@ -97,7 +97,7 @@ import { ResultType } from '../BlockaidBanner/BlockaidBanner.types';
import TransactionBlockaidBanner from '../TransactionBlockaidBanner/TransactionBlockaidBanner';
import { regex } from '../../../../../util/regex';
import { withMetricsAwareness } from '../../../../../components/hooks/useMetrics';
-import { getIsSmartTransaction } from '../../../../../selectors/smartTransactionsController';
+import { selectShouldUseSmartTransaction } from '../../../../../selectors/smartTransactionsController';
const { ORIGIN_DEEPLINK, ORIGIN_QR_CODE } = AppConstants.DEEPLINKS;
const POLLING_INTERVAL_ESTIMATED_L1_FEE = 30000;
@@ -277,9 +277,9 @@ class ApproveTransactionReview extends PureComponent {
*/
metrics: PropTypes.object,
/**
- * Boolean that indicates if the transaction is a smart transaction
+ * Boolean that indicates if smart transaction should be used
*/
- isSmartTransaction: PropTypes.bool,
+ shouldUseSmartTransaction: PropTypes.bool,
};
state = {
@@ -517,8 +517,12 @@ class ApproveTransactionReview extends PureComponent {
getAnalyticsParams = () => {
try {
- const { chainId, transaction, onSetAnalyticsParams, isSmartTransaction } =
- this.props;
+ const {
+ chainId,
+ transaction,
+ onSetAnalyticsParams,
+ shouldUseSmartTransaction,
+ } = this.props;
const {
token: { tokenSymbol },
originalApproveAmount,
@@ -544,7 +548,7 @@ class ApproveTransactionReview extends PureComponent {
: this.originIsWalletConnect
? AppConstants.REQUEST_SOURCES.WC
: AppConstants.REQUEST_SOURCES.IN_APP_BROWSER,
- is_smart_transaction: isSmartTransaction,
+ is_smart_transaction: shouldUseSmartTransaction,
};
// Send analytics params to parent component so it's available when cancelling and confirming
onSetAnalyticsParams && onSetAnalyticsParams(params);
@@ -1281,7 +1285,7 @@ const mapStateToProps = (state) => ({
selectChainId(state),
getRampNetworks(state),
),
- isSmartTransaction: getIsSmartTransaction(state),
+ shouldUseSmartTransaction: selectShouldUseSmartTransaction(state),
});
const mapDispatchToProps = (dispatch) => ({
diff --git a/app/components/Views/confirmations/components/TransactionReview/TransactionReviewInformation/index.js b/app/components/Views/confirmations/components/TransactionReview/TransactionReviewInformation/index.js
index ff7d450c6d21..a7c565fb357e 100644
--- a/app/components/Views/confirmations/components/TransactionReview/TransactionReviewInformation/index.js
+++ b/app/components/Views/confirmations/components/TransactionReview/TransactionReviewInformation/index.js
@@ -62,7 +62,7 @@ import { isNetworkRampNativeTokenSupported } from '../../../../../../components/
import { getRampNetworks } from '../../../../../../reducers/fiatOrders';
import Routes from '../../../../../../constants/navigation/Routes';
import { withMetricsAwareness } from '../../../../../../components/hooks/useMetrics';
-import { getIsSmartTransaction } from '../../../../../../selectors/smartTransactionsController';
+import { selectShouldUseSmartTransaction } from '../../../../../../selectors/smartTransactionsController';
const createStyles = (colors) =>
StyleSheet.create({
@@ -238,9 +238,9 @@ class TransactionReviewInformation extends PureComponent {
*/
metrics: PropTypes.object,
/**
- * Boolean that indicates if the transaction is a smart transaction
+ * Boolean that indicates if smart transaction should be used
*/
- isSmartTransaction: PropTypes.bool,
+ shouldUseSmartTransaction: PropTypes.bool,
};
state = {
@@ -657,7 +657,7 @@ class TransactionReviewInformation extends PureComponent {
gasEstimateType,
gasSelected,
isNativeTokenBuySupported,
- isSmartTransaction,
+ shouldUseSmartTransaction,
} = this.props;
const { nonce } = this.props.transaction;
const colors = this.context.colors || mockTheme.colors;
@@ -686,7 +686,7 @@ class TransactionReviewInformation extends PureComponent {
warningMessage={strings('edit_gas_fee_eip1559.low_fee_warning')}
/>
)}
- {showCustomNonce && !isSmartTransaction && (
+ {showCustomNonce && !shouldUseSmartTransaction && (
)}
{!!amountError && (
@@ -752,7 +752,7 @@ const mapStateToProps = (state) => ({
selectChainId(state),
getRampNetworks(state),
),
- isSmartTransaction: getIsSmartTransaction(state),
+ shouldUseSmartTransaction: selectShouldUseSmartTransaction(state),
});
const mapDispatchToProps = (dispatch) => ({
diff --git a/app/components/Views/confirmations/components/TransactionReview/index.js b/app/components/Views/confirmations/components/TransactionReview/index.js
index fb19d421413e..d9166f01872d 100644
--- a/app/components/Views/confirmations/components/TransactionReview/index.js
+++ b/app/components/Views/confirmations/components/TransactionReview/index.js
@@ -57,7 +57,7 @@ import AppConstants from '../../../../../core/AppConstants';
import TransactionBlockaidBanner from '../TransactionBlockaidBanner/TransactionBlockaidBanner';
import { ResultType } from '../BlockaidBanner/BlockaidBanner.types';
import { withMetricsAwareness } from '../../../../../components/hooks/useMetrics';
-import { getIsSmartTransaction } from '../../../../../selectors/smartTransactionsController';
+import { selectShouldUseSmartTransaction } from '../../../../../selectors/smartTransactionsController';
const POLLING_INTERVAL_ESTIMATED_L1_FEE = 30000;
@@ -249,9 +249,9 @@ class TransactionReview extends PureComponent {
*/
metrics: PropTypes.object,
/**
- * Whether the transaction is a smart transaction
+ * Boolean that indicates if smart transaction should be used
*/
- isSmartTransaction: PropTypes.bool,
+ shouldUseSmartTransaction: PropTypes.bool,
};
state = {
@@ -297,7 +297,7 @@ class TransactionReview extends PureComponent {
chainId,
tokenList,
metrics,
- isSmartTransaction,
+ shouldUseSmartTransaction,
} = this.props;
let { showHexData } = this.props;
let assetAmount, conversionRate, fiatValue;
@@ -330,7 +330,7 @@ class TransactionReview extends PureComponent {
});
metrics.trackEvent(MetaMetricsEvents.TRANSACTIONS_CONFIRM_STARTED, {
- is_smart_transaction: isSmartTransaction,
+ is_smart_transaction: shouldUseSmartTransaction,
});
if (isMultiLayerFeeNetwork(chainId)) {
@@ -664,7 +664,7 @@ const mapStateToProps = (state) => ({
browser: state.browser,
primaryCurrency: state.settings.primaryCurrency,
tokenList: selectTokenList(state),
- isSmartTransaction: getIsSmartTransaction(state),
+ shouldUseSmartTransaction: selectShouldUseSmartTransaction(state),
});
TransactionReview.contextType = ThemeContext;
diff --git a/app/core/Engine.test.js b/app/core/Engine.test.js
index 70e386878a79..c801685c83d6 100644
--- a/app/core/Engine.test.js
+++ b/app/core/Engine.test.js
@@ -72,7 +72,7 @@ describe('Engine', () => {
approvalTxFees: undefined,
tradeTxFees: undefined,
},
- '0x5': {
+ '0xaa36a7': {
approvalTxFees: undefined,
tradeTxFees: undefined,
},
@@ -80,7 +80,7 @@ describe('Engine', () => {
liveness: true,
livenessByChainId: {
'0x1': true,
- '0x5': true,
+ '0xaa36a7': true,
},
smartTransactions: {
'0x1': [],
diff --git a/app/core/Engine.ts b/app/core/Engine.ts
index 21cbce98546b..540bcf71c636 100644
--- a/app/core/Engine.ts
+++ b/app/core/Engine.ts
@@ -192,10 +192,11 @@ import {
} from '../core/redux/slices/inpageProvider';
import SmartTransactionsController from '@metamask/smart-transactions-controller';
import { NETWORKS_CHAIN_ID } from '../../app/constants/network';
-import { getIsSmartTransaction } from '../selectors/smartTransactionsController';
-import { getSwapsChainFeatureFlags } from '../reducers/swaps';
+import { selectShouldUseSmartTransaction } from '../selectors/smartTransactionsController';
+import { selectSwapsChainFeatureFlags } from '../reducers/swaps';
import { SmartTransactionStatuses } from '@metamask/smart-transactions-controller/dist/types';
-import { submitSmartTransactionHook } from '../util/smart-transactions/smart-tx';
+import { submitSmartTransactionHook } from '../util/smart-transactions/smart-publish-hook';
+import { SmartTransactionsControllerState } from '@metamask/smart-transactions-controller/dist/SmartTransactionsController';
const NON_EMPTY = 'NON_EMPTY';
@@ -277,7 +278,7 @@ export interface EngineState {
TokenBalancesController: TokenBalancesState;
TokenRatesController: TokenRatesState;
TransactionController: TransactionState;
- SmartTransactionsController: any; // TODO look into improving this, smart tx cont. needs to export the SmartTransactionsControllerState type
+ SmartTransactionsController: SmartTransactionsControllerState;
SwapsController: SwapsState;
GasFeeController: GasFeeState;
TokensController: TokensState;
@@ -322,6 +323,7 @@ interface Controllers {
TokenRatesController: TokenRatesController;
TokensController: TokensController;
TransactionController: TransactionController;
+ SmartTransactionsController: SmartTransactionsController;
SignatureController: SignatureController;
///: BEGIN:ONLY_INCLUDE_IF(snaps)
SnapController: SnapController;
@@ -375,8 +377,8 @@ class Engine {
snapExecutionService: WebViewExecutionService;
///: END:ONLY_INCLUDE_IF
- txController: TransactionController;
- stxController: SmartTransactionsController;
+ transactionController: TransactionController;
+ smartTransactionsController: SmartTransactionsController;
/**
* Creates a CoreController instance
@@ -1033,22 +1035,27 @@ class Engine {
});
///: END:ONLY_INCLUDE_IF
- this.txController = new TransactionController({
+ this.transactionController = new TransactionController({
// @ts-expect-error at this point in time the provider will be defined by the `networkController.initializeProvider`
blockTracker: networkController.getProviderAndBlockTracker().blockTracker,
+ disableSendFlowHistory: true,
+ disableHistory: true,
getGasFeeEstimates: () => gasFeeController.fetchGasFeeEstimates(),
- //@ts-expect-error TransactionController needs to be updated to v13 for this error disappears
+ getCurrentNetworkEIP1559Compatibility:
+ networkController.getEIP1559Compatibility.bind(networkController),
getNetworkState: () => networkController.state,
getSelectedAddress: () => accountsController.getSelectedAccount().address,
incomingTransactions: {
- apiKey: process.env.MM_ETHERSCAN_KEY,
isEnabled: () => {
const currentHexChainId =
networkController.state.providerConfig.chainId;
+
+ const showIncomingTransactions =
+ preferencesController?.state?.showIncomingTransactions;
+
return Boolean(
- preferencesController?.state?.showIncomingTransactions?.[
- currentHexChainId
- ],
+ hasProperty(showIncomingTransactions, currentChainId) &&
+ showIncomingTransactions?.[currentHexChainId],
);
},
updateTransactions: true,
@@ -1065,7 +1072,6 @@ class Engine {
onNetworkStateChange: (listener) =>
this.controllerMessenger.subscribe(
AppConstants.NETWORK_STATE_CHANGE_EVENT,
- //@ts-expect-error TransactionController needs to be updated to v13 for this error disappears
listener,
),
// @ts-expect-error at this point in time the provider will be defined by the `networkController.initializeProvider`
@@ -1074,22 +1080,24 @@ class Engine {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
getExternalPendingTransactions: (address: string) =>
- this.stxController.getTransactions({
+ this.smartTransactionsController.getTransactions({
addressFrom: address,
status: SmartTransactionStatuses.PENDING,
}),
hooks: {
publish: (transactionMeta) => {
- const isSmartTransaction = getIsSmartTransaction(store.getState());
+ const shouldUseSmartTransaction = selectShouldUseSmartTransaction(
+ store.getState(),
+ );
return submitSmartTransactionHook({
transactionMeta,
- transactionController: this.txController,
- smartTransactionsController: this.stxController,
- isSmartTransaction,
+ transactionController: this.transactionController,
+ smartTransactionsController: this.smartTransactionsController,
+ shouldUseSmartTransaction,
approvalController,
- featureFlags: getSwapsChainFeatureFlags(store.getState()),
+ featureFlags: selectSwapsChainFeatureFlags(store.getState()),
});
},
},
@@ -1097,6 +1105,61 @@ class Engine {
const codefiTokenApiV2 = new CodefiTokenPricesServiceV2();
+ const smartTransactionsControllerTrackMetaMetricsEvent = (params: {
+ event: string;
+ category: string;
+ sensitiveProperties: any;
+ }) => {
+ const { event, category, ...restParams } = params;
+
+ MetaMetrics.getInstance().trackEvent(
+ {
+ category,
+ properties: {
+ name: event,
+ // action?: string;
+ },
+ },
+ restParams,
+ );
+ };
+ this.smartTransactionsController = new SmartTransactionsController(
+ {
+ confirmExternalTransaction:
+ this.transactionController.confirmExternalTransaction.bind(
+ this.transactionController,
+ ),
+ // @ts-expect-error this fine, STX controller has been downgraded to network controller v15
+ getNetworkClientById:
+ networkController.getNetworkClientById.bind(networkController),
+ getNonceLock: this.transactionController.getNonceLock.bind(
+ this.transactionController,
+ ),
+ // @ts-expect-error txController.getTransactions only uses txMeta.status and txMeta.hash, which v13 TxController has
+ getTransactions: this.transactionController.getTransactions.bind(
+ this.transactionController,
+ ),
+ onNetworkStateChange: (listener) =>
+ this.controllerMessenger.subscribe(
+ AppConstants.NETWORK_STATE_CHANGE_EVENT,
+ listener,
+ ),
+
+ provider: networkController.getProviderAndBlockTracker()
+ .provider as any,
+
+ trackMetaMetricsEvent: smartTransactionsControllerTrackMetaMetricsEvent,
+ },
+ {
+ supportedChainIds: [
+ NETWORKS_CHAIN_ID.MAINNET,
+ NETWORKS_CHAIN_ID.GOERLI,
+ NETWORKS_CHAIN_ID.SEPOLIA,
+ ],
+ },
+ initialState.SmartTransactionsController,
+ );
+
const controllers: Controllers[keyof Controllers][] = [
keyringController,
accountTrackerController,
@@ -1191,50 +1254,10 @@ class Engine {
tokenPricesService: codefiTokenApiV2,
interval: 30 * 60 * 1000,
}),
- new TransactionController({
- // @ts-expect-error at this point in time the provider will be defined by the `networkController.initializeProvider`
- blockTracker:
- networkController.getProviderAndBlockTracker().blockTracker,
- disableSendFlowHistory: true,
- disableHistory: true,
- getGasFeeEstimates: () => gasFeeController.fetchGasFeeEstimates(),
- getCurrentNetworkEIP1559Compatibility:
- networkController.getEIP1559Compatibility.bind(networkController),
- getNetworkState: () => networkController.state,
- getSelectedAddress: () =>
- accountsController.getSelectedAccount().address,
- incomingTransactions: {
- isEnabled: () => {
- const currentHexChainId =
- networkController.state.providerConfig.chainId;
-
- const showIncomingTransactions =
- preferencesController?.state?.showIncomingTransactions;
-
- return Boolean(
- hasProperty(showIncomingTransactions, currentChainId) &&
- showIncomingTransactions?.[currentHexChainId],
- );
- },
- updateTransactions: true,
- },
- // @ts-expect-error TODO: Resolve/patch mismatch between base-controller versions. Before: never, never. Now: string, string, which expects 3rd and 4th args to be informed for restrictedControllerMessengers
- messenger: this.controllerMessenger.getRestricted<
- 'TransactionController',
- 'ApprovalController:addRequest',
- never
- >({
- name: 'TransactionController',
- allowedActions: [`${approvalController.name}:addRequest`],
- }),
- onNetworkStateChange: (listener) =>
- this.controllerMessenger.subscribe(
- AppConstants.NETWORK_STATE_CHANGE_EVENT,
- listener,
- ),
- // @ts-expect-error at this point in time the provider will be defined by the `networkController.initializeProvider`
- provider: networkController.getProviderAndBlockTracker().provider,
- }),
+
+ this.transactionController,
+ this.smartTransactionsController,
+
new SwapsController(
{
// @ts-expect-error TODO: Resolve mismatch between gas fee and swaps controller types
diff --git a/app/reducers/swaps/index.js b/app/reducers/swaps/index.js
index 779f84e75622..762072acb0eb 100644
--- a/app/reducers/swaps/index.js
+++ b/app/reducers/swaps/index.js
@@ -75,16 +75,15 @@ export const swapsLivenessSelector = createSelector(
/**
* Returns if smart transactions are enabled in feature flags
*/
+const DEVICE_KEY = 'mobileActive';
export const swapsSmartTxFlagEnabled = createSelector(
swapsStateSelector,
(swapsState) => {
const globalFlags = swapsState.featureFlags;
- const deviceKey = 'mobileActive';
-
const isEnabled = Boolean(
globalFlags?.smart_transactions?.mobile_active &&
- globalFlags?.smartTransactions?.[deviceKey],
+ globalFlags?.smartTransactions?.[DEVICE_KEY],
);
return isEnabled;
@@ -94,7 +93,7 @@ export const swapsSmartTxFlagEnabled = createSelector(
/**
* Returns the swaps feature flags
*/
-export const getSwapsChainFeatureFlags = createSelector(
+export const selectSwapsChainFeatureFlags = createSelector(
swapsStateSelector,
chainIdSelector,
(swapsState, chainId) => swapsState[chainId].featureFlags,
diff --git a/app/reducers/swaps/swaps.test.ts b/app/reducers/swaps/swaps.test.ts
index faba4001e9f5..2ffec8be4110 100644
--- a/app/reducers/swaps/swaps.test.ts
+++ b/app/reducers/swaps/swaps.test.ts
@@ -10,7 +10,7 @@ import reducer, {
const emptyAction = { type: null };
-const defaultFeatureFlags = {
+const DEFAULT_FEATURE_FLAGS = {
ethereum: {
mobile_active: true,
extension_active: true,
@@ -65,7 +65,7 @@ describe('swaps reducer', () => {
const liveState = reducer(initalState, {
type: SWAPS_SET_LIVENESS,
payload: {
- featureFlags: defaultFeatureFlags,
+ featureFlags: DEFAULT_FEATURE_FLAGS,
chainId: '0x1',
},
});
@@ -76,7 +76,7 @@ describe('swaps reducer', () => {
Device.isAndroid = jest.fn().mockReturnValue(false);
const initalState = reducer(undefined, emptyAction);
- const featureFlags = cloneDeep(defaultFeatureFlags);
+ const featureFlags = cloneDeep(DEFAULT_FEATURE_FLAGS);
featureFlags.ethereum = {
mobile_active: false,
extension_active: true,
@@ -108,7 +108,7 @@ describe('swaps reducer', () => {
Device.isAndroid = jest.fn().mockReturnValue(true);
const initalState = reducer(undefined, emptyAction);
- const featureFlags = cloneDeep(defaultFeatureFlags);
+ const featureFlags = cloneDeep(DEFAULT_FEATURE_FLAGS);
featureFlags.ethereum = {
mobile_active: true,
extension_active: true,
@@ -140,7 +140,7 @@ describe('swaps reducer', () => {
Device.isAndroid = jest.fn().mockReturnValue(true);
const initalState = reducer(undefined, emptyAction);
- const featureFlags = cloneDeep(defaultFeatureFlags);
+ const featureFlags = cloneDeep(DEFAULT_FEATURE_FLAGS);
featureFlags.ethereum = {
mobile_active: false,
extension_active: true,
diff --git a/app/reducers/swaps/utils.ts b/app/reducers/swaps/utils.ts
index c0f7794b2690..3a3d7d1e002f 100644
--- a/app/reducers/swaps/utils.ts
+++ b/app/reducers/swaps/utils.ts
@@ -11,15 +11,22 @@ export const getChainFeatureFlags = (
return chainFeatureFlags;
};
-export const getFeatureFlagDeviceKey = () => {
+type FeatureFlagDeviceKey =
+ | 'mobileActiveIOS'
+ | 'mobileActiveAndroid'
+ | 'mobileActive';
+export const getFeatureFlagDeviceKey: () => FeatureFlagDeviceKey = () => {
const isIphone = Device.isIos();
const isAndroid = Device.isAndroid();
- const featureFlagDeviceKey = isIphone
- ? 'mobileActiveIOS'
- : isAndroid
- ? 'mobileActiveAndroid'
- : 'mobileActive';
+ let featureFlagDeviceKey: FeatureFlagDeviceKey;
+ if (isIphone) {
+ featureFlagDeviceKey = 'mobileActiveIOS';
+ } else if (isAndroid) {
+ featureFlagDeviceKey = 'mobileActiveAndroid';
+ } else {
+ featureFlagDeviceKey = 'mobileActive';
+ }
return featureFlagDeviceKey;
};
diff --git a/app/selectors/smartTransactionsController.test.ts b/app/selectors/smartTransactionsController.test.ts
index ff455d132710..a69c64febaa1 100644
--- a/app/selectors/smartTransactionsController.test.ts
+++ b/app/selectors/smartTransactionsController.test.ts
@@ -1,6 +1,6 @@
import {
- getIsSmartTransaction,
- getSmartTransactionsEnabled,
+ selectShouldUseSmartTransaction,
+ selectSmartTransactionsEnabled,
} from './smartTransactionsController';
import initialBackgroundState from '../util/test/initial-background-state.json';
import { isHardwareAccount } from '../util/address';
@@ -66,7 +66,7 @@ describe('SmartTransactionsController Selectors', () => {
const state = getDefaultState();
state.swaps['0x1'].smartTransactions = smartTransactions;
- const enabled = getSmartTransactionsEnabled(state);
+ const enabled = selectSmartTransactionsEnabled(state);
expect(enabled).toEqual(false);
},
);
@@ -74,20 +74,20 @@ describe('SmartTransactionsController Selectors', () => {
const state = getDefaultState();
state.engine.backgroundState.SmartTransactionsController.smartTransactionsState.liveness =
false;
- const enabled = getSmartTransactionsEnabled(state);
+ const enabled = selectSmartTransactionsEnabled(state);
expect(enabled).toEqual(false);
});
it('should return false if address is hardware account', () => {
(isHardwareAccount as jest.Mock).mockReturnValueOnce(true);
const state = getDefaultState();
- const enabled = getSmartTransactionsEnabled(state);
+ const enabled = selectSmartTransactionsEnabled(state);
expect(enabled).toEqual(false);
});
it('should return false if is mainnet and not the default RPC', () => {
const state = getDefaultState();
state.engine.backgroundState.NetworkController.providerConfig.rpcUrl =
'https://example.com';
- const enabled = getSmartTransactionsEnabled(state);
+ const enabled = selectSmartTransactionsEnabled(state);
expect(enabled).toEqual(false);
});
it('should return true if smart transactions are enabled', () => {
@@ -95,31 +95,31 @@ describe('SmartTransactionsController Selectors', () => {
state.swaps.featureFlags.smart_transactions.mobile_active = true;
state.swaps.featureFlags.smartTransactions.mobileActive = true;
- const enabled = getSmartTransactionsEnabled(state);
+ const enabled = selectSmartTransactionsEnabled(state);
expect(enabled).toEqual(true);
});
});
- describe('getIsSmartTransaction', () => {
+ describe('getShouldUseSmartTransaction', () => {
it('should return false if smart transactions are not opted into', () => {
const state = getDefaultState();
state.engine.backgroundState.PreferencesController.smartTransactionsOptInStatus =
false;
- const isSmartTransaction = getIsSmartTransaction(state);
- expect(isSmartTransaction).toEqual(false);
+ const shouldUseSmartTransaction = selectShouldUseSmartTransaction(state);
+ expect(shouldUseSmartTransaction).toEqual(false);
});
it('should return false if smart transactions are not enabled', () => {
const state = getDefaultState();
state.swaps['0x1'].smartTransactions = {};
- const isSmartTransaction = getIsSmartTransaction(state);
- expect(isSmartTransaction).toEqual(false);
+ const shouldUseSmartTransaction = selectShouldUseSmartTransaction(state);
+ expect(shouldUseSmartTransaction).toEqual(false);
});
it('should return true if smart transactions are enabled and opted into', () => {
const state = getDefaultState();
state.swaps.featureFlags.smart_transactions.mobile_active = true;
state.swaps.featureFlags.smartTransactions.mobileActive = true;
- const isSmartTransaction = getIsSmartTransaction(state);
- expect(isSmartTransaction).toEqual(true);
+ const shouldUseSmartTransaction = selectShouldUseSmartTransaction(state);
+ expect(shouldUseSmartTransaction).toEqual(true);
});
});
});
diff --git a/app/selectors/smartTransactionsController.ts b/app/selectors/smartTransactionsController.ts
index c2addebea46c..94e20c8e4d85 100644
--- a/app/selectors/smartTransactionsController.ts
+++ b/app/selectors/smartTransactionsController.ts
@@ -7,13 +7,17 @@ import { RootState } from '../reducers';
import { swapsSmartTxFlagEnabled } from '../reducers/swaps';
import { isHardwareAccount } from '../util/address';
import { selectChainId, selectProviderConfig } from './networkController';
+import {
+ SmartTransaction,
+ SmartTransactionStatuses,
+} from '@metamask/smart-transactions-controller/dist/types';
export const ALLOWED_SMART_TRANSACTIONS_CHAIN_IDS = [
NETWORKS_CHAIN_ID.MAINNET,
NETWORKS_CHAIN_ID.GOERLI,
NETWORKS_CHAIN_ID.SEPOLIA,
];
-export const getSmartTransactionsEnabled = (state: RootState) => {
+export const selectSmartTransactionsEnabled = (state: RootState) => {
const selectedAddress = selectSelectedAddress(state);
const addrIshardwareAccount = isHardwareAccount(selectedAddress);
const chainId = selectChainId(state);
@@ -43,10 +47,46 @@ export const getSmartTransactionsEnabled = (state: RootState) => {
smartTransactionsLiveness,
);
};
-export const getIsSmartTransaction = (state: RootState) => {
- const isSmartTransactionsEnabled = getSmartTransactionsEnabled(state);
+export const selectShouldUseSmartTransaction = (state: RootState) => {
+ const isSmartTransactionsEnabled = selectSmartTransactionsEnabled(state);
const smartTransactionsOptInStatus =
selectSmartTransactionsOptInStatus(state);
return isSmartTransactionsEnabled && smartTransactionsOptInStatus;
};
+
+export const selectPendingSmartTransactionsBySender = (state: RootState) => {
+ const selectedAddress = selectSelectedAddress(state);
+ const chainId = selectChainId(state);
+
+ const smartTransactions: SmartTransaction[] =
+ state.engine.backgroundState.SmartTransactionsController
+ ?.smartTransactionsState?.smartTransactions?.[chainId] || [];
+
+ const pendingSmartTransactions =
+ smartTransactions
+ ?.filter((stx) => {
+ const { txParams } = stx;
+ return (
+ txParams?.from.toLowerCase() === selectedAddress.toLowerCase() &&
+ ![
+ SmartTransactionStatuses.SUCCESS,
+ SmartTransactionStatuses.CANCELLED,
+ ].includes(stx.status as SmartTransactionStatuses)
+ );
+ })
+ .map((stx) => ({
+ ...stx,
+ // stx.uuid is one from sentinel API, not the same as tx.id which is generated client side
+ // Doesn't matter too much because we only care about the pending stx, confirmed txs are handled like normal
+ // However, this does make it impossible to read Swap data from TxController.swapsTransactions as that relies on client side tx.id
+ // To fix that we do transactionController.update({ swapsTransactions: newSwapsTransactions }) in app/util/smart-transactions/smart-tx.ts
+ id: stx.uuid,
+ status: stx.status?.startsWith(SmartTransactionStatuses.CANCELLED)
+ ? SmartTransactionStatuses.CANCELLED
+ : stx.status,
+ isSmartTransaction: true,
+ })) ?? [];
+
+ return pendingSmartTransactions;
+};
diff --git a/patches/@metamask+smart-transactions-controller+8.1.0.patch b/patches/@metamask+smart-transactions-controller+8.1.0.patch
deleted file mode 100644
index bfed016c7eae..000000000000
--- a/patches/@metamask+smart-transactions-controller+8.1.0.patch
+++ /dev/null
@@ -1,152 +0,0 @@
-diff --git a/node_modules/@metamask/smart-transactions-controller/dist/SmartTransactionsController.d.ts b/node_modules/@metamask/smart-transactions-controller/dist/SmartTransactionsController.d.ts
-index 8c1b820..589af61 100644
---- a/node_modules/@metamask/smart-transactions-controller/dist/SmartTransactionsController.d.ts
-+++ b/node_modules/@metamask/smart-transactions-controller/dist/SmartTransactionsController.d.ts
-@@ -76,11 +76,11 @@ export default class SmartTransactionsController extends StaticIntervalPollingCo
- getFees(tradeTx: UnsignedTransaction, approvalTx?: UnsignedTransaction, { networkClientId }?: {
- networkClientId?: NetworkClientId;
- }): Promise;
-- submitSignedTransactions({ transactionMeta, txParams, signedTransactions, signedCanceledTransactions, networkClientId, }: {
-+ submitSignedTransactions({ transactionMeta, transaction, signedTransactions, signedCanceledTransactions, networkClientId, }: {
- signedTransactions: SignedTransaction[];
- signedCanceledTransactions: SignedCanceledTransaction[];
- transactionMeta?: any;
-- txParams?: any;
-+ transaction?: any;
- networkClientId?: NetworkClientId;
- }): Promise;
- cancelSmartTransaction(uuid: string, { networkClientId, }?: {
-diff --git a/node_modules/@metamask/smart-transactions-controller/dist/SmartTransactionsController.js b/node_modules/@metamask/smart-transactions-controller/dist/SmartTransactionsController.js
-index 4bfa10a..473813f 100644
---- a/node_modules/@metamask/smart-transactions-controller/dist/SmartTransactionsController.js
-+++ b/node_modules/@metamask/smart-transactions-controller/dist/SmartTransactionsController.js
-@@ -289,7 +289,7 @@ class SmartTransactionsController extends polling_controller_1.StaticIntervalPol
- }
- // * After this successful call client must add a nonce representative to
- // * transaction controller external transactions list
-- async submitSignedTransactions({ transactionMeta, txParams, signedTransactions, signedCanceledTransactions, networkClientId, }) {
-+ async submitSignedTransactions({ transactionMeta, transaction, signedTransactions, signedCanceledTransactions, networkClientId, }) {
- var _a;
- const chainId = __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_getChainId).call(this, { networkClientId });
- const ethQuery = __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_getEthQuery).call(this, { networkClientId });
-@@ -304,23 +304,23 @@ class SmartTransactionsController extends polling_controller_1.StaticIntervalPol
- let preTxBalance;
- try {
- const preTxBalanceBN = await (0, controller_utils_1.query)(ethQuery, 'getBalance', [
-- txParams === null || txParams === void 0 ? void 0 : txParams.from,
-+ transaction === null || transaction === void 0 ? void 0 : transaction.from,
- ]);
- preTxBalance = new bignumber_js_1.BigNumber(preTxBalanceBN).toString(16);
- }
- catch (error) {
- console.error('provider error', error);
- }
-- const requiresNonce = !txParams.nonce;
-+ const requiresNonce = !transaction.nonce;
- let nonce;
- let nonceLock;
- let nonceDetails = {};
- if (requiresNonce) {
-- nonceLock = await this.getNonceLock(txParams === null || txParams === void 0 ? void 0 : txParams.from);
-+ nonceLock = await this.getNonceLock(transaction === null || transaction === void 0 ? void 0 : transaction.from);
- nonce = (0, bytes_1.hexlify)(nonceLock.nextNonce);
- nonceDetails = nonceLock.nonceDetails;
-- if (txParams) {
-- (_a = txParams.nonce) !== null && _a !== void 0 ? _a : (txParams.nonce = nonce);
-+ if (transaction) {
-+ (_a = transaction.nonce) !== null && _a !== void 0 ? _a : (transaction.nonce = nonce);
- }
- }
- const submitTransactionResponse = Object.assign(Object.assign({}, data), { txHash: (0, utils_1.getTxHash)(signedTransactions[0]) });
-@@ -331,9 +331,9 @@ class SmartTransactionsController extends polling_controller_1.StaticIntervalPol
- preTxBalance,
- status: types_1.SmartTransactionStatuses.PENDING,
- time,
-- txParams,
-+ transaction,
- uuid: submitTransactionResponse.uuid,
-- txHash: submitTransactionResponse.txHash,
-+ transactionHash: submitTransactionResponse.txHash,
- cancellable: true,
- type: (transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.type) || 'swap',
- }, { chainId, ethQuery });
-@@ -377,7 +377,7 @@ class SmartTransactionsController extends polling_controller_1.StaticIntervalPol
- const currentSmartTransactions = __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_getCurrentSmartTransactions).call(this);
- return currentSmartTransactions.filter((stx) => {
- var _a;
-- return stx.status === status && ((_a = stx.txParams) === null || _a === void 0 ? void 0 : _a.from) === addressFrom;
-+ return stx.status === status && ((_a = stx.transaction) === null || _a === void 0 ? void 0 : _a.from) === addressFrom;
- });
- }
- getSmartTransactionByMinedTxHash(txHash) {
-@@ -410,7 +410,7 @@ _SmartTransactionsController_instances = new WeakSet(), _SmartTransactionsContro
- // add smart transaction
- const cancelledNonceIndex = currentSmartTransactions === null || currentSmartTransactions === void 0 ? void 0 : currentSmartTransactions.findIndex((stx) => {
- var _a, _b, _c;
-- return ((_a = stx.txParams) === null || _a === void 0 ? void 0 : _a.nonce) === ((_b = smartTransaction.txParams) === null || _b === void 0 ? void 0 : _b.nonce) &&
-+ return ((_a = stx.transaction) === null || _a === void 0 ? void 0 : _a.nonce) === ((_b = smartTransaction.transaction) === null || _b === void 0 ? void 0 : _b.nonce) &&
- ((_c = stx.status) === null || _c === void 0 ? void 0 : _c.startsWith('cancelled'));
- });
- const snapshot = (0, cloneDeep_1.default)(smartTransaction);
-@@ -454,7 +454,7 @@ _SmartTransactionsController_instances = new WeakSet(), _SmartTransactionsContro
- const transactions = this.getRegularTransactions();
- const foundTransaction = transactions === null || transactions === void 0 ? void 0 : transactions.find((tx) => {
- var _a;
-- return ((_a = tx.hash) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === txHash.toLowerCase();
-+ return ((_a = tx.transactionHash) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === txHash.toLowerCase();
- });
- if (!foundTransaction) {
- return true;
-@@ -477,10 +477,10 @@ _SmartTransactionsController_instances = new WeakSet(), _SmartTransactionsContro
- if (transactionReceipt === null || transactionReceipt === void 0 ? void 0 : transactionReceipt.blockNumber) {
- const blockData = await (0, controller_utils_1.query)(ethQuery, 'getBlockByNumber', [transactionReceipt === null || transactionReceipt === void 0 ? void 0 : transactionReceipt.blockNumber, false]);
- const baseFeePerGas = blockData === null || blockData === void 0 ? void 0 : blockData.baseFeePerGas;
-- const updatedTxParams = Object.assign(Object.assign({}, smartTransaction.txParams), { maxFeePerGas,
-+ const updatedTxParams = Object.assign(Object.assign({}, smartTransaction.transaction), { maxFeePerGas,
- maxPriorityFeePerGas });
- // call confirmExternalTransaction
-- const originalTxMeta = Object.assign(Object.assign({}, smartTransaction), { id: smartTransaction.uuid, status: transaction_controller_1.TransactionStatus.confirmed, hash: txHash, txParams: updatedTxParams });
-+ const originalTxMeta = Object.assign(Object.assign({}, smartTransaction), { id: smartTransaction.uuid, status: transaction_controller_1.TransactionStatus.confirmed, transactionHash: txHash, transaction: updatedTxParams });
- // create txMeta snapshot for history
- const snapshot = (0, utils_1.snapshotFromTxMeta)(originalTxMeta);
- // recover previous tx state obj
-diff --git a/node_modules/@metamask/smart-transactions-controller/dist/SmartTransactionsController.js.map b/node_modules/@metamask/smart-transactions-controller/dist/SmartTransactionsController.js.map
-index c8c1920..3d8a598 100644
---- a/node_modules/@metamask/smart-transactions-controller/dist/SmartTransactionsController.js.map
-+++ b/node_modules/@metamask/smart-transactions-controller/dist/SmartTransactionsController.js.map
-@@ -1 +1 @@
--{"version":3,"file":"SmartTransactionsController.js","sourceRoot":"","sources":["../src/SmartTransactionsController.ts"],"names":[],"mappings":"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","sourcesContent":["// eslint-disable-next-line import/no-nodejs-modules\nimport { hexlify } from '@ethersproject/bytes';\nimport type { BaseConfig, BaseState } from '@metamask/base-controller';\nimport { query, safelyExecute } from '@metamask/controller-utils';\nimport type { Provider } from '@metamask/eth-query';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClientId,\n NetworkController,\n NetworkState,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingControllerV1 } from '@metamask/polling-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport { TransactionStatus } from '@metamask/transaction-controller';\nimport { BigNumber } from 'bignumber.js';\n// eslint-disable-next-line import/no-nodejs-modules\nimport EventEmitter from 'events';\nimport cloneDeep from 'lodash/cloneDeep';\n\nimport {\n CHAIN_IDS,\n MetaMetricsEventCategory,\n MetaMetricsEventName,\n} from './constants';\nimport type {\n Fees,\n Hex,\n IndividualTxFees,\n SignedCanceledTransaction,\n SignedTransaction,\n SmartTransaction,\n SmartTransactionsStatus,\n UnsignedTransaction,\n GetTransactionsOptions,\n} from './types';\nimport { APIType, SmartTransactionStatuses } from './types';\nimport {\n calculateStatus,\n generateHistoryEntry,\n getAPIRequestURL,\n getStxProcessingTime,\n handleFetch,\n incrementNonceInHex,\n isSmartTransactionCancellable,\n isSmartTransactionPending,\n replayHistory,\n snapshotFromTxMeta,\n getTxHash,\n} from './utils';\n\nconst SECOND = 1000;\nexport const DEFAULT_INTERVAL = SECOND * 5;\nconst ETH_QUERY_ERROR_MSG =\n '`ethQuery` is not defined on SmartTransactionsController';\n\nexport type SmartTransactionsControllerConfig = BaseConfig & {\n interval: number;\n clientId: string;\n chainId: Hex;\n supportedChainIds: string[];\n};\n\ntype FeeEstimates = {\n approvalTxFees: IndividualTxFees | undefined;\n tradeTxFees: IndividualTxFees | undefined;\n};\n\nexport type SmartTransactionsControllerState = BaseState & {\n smartTransactionsState: {\n smartTransactions: Record;\n userOptIn: boolean | undefined;\n userOptInV2: boolean | undefined;\n liveness: boolean | undefined;\n fees: FeeEstimates;\n feesByChainId: Record;\n livenessByChainId: Record;\n };\n};\n\nexport default class SmartTransactionsController extends StaticIntervalPollingControllerV1<\n SmartTransactionsControllerConfig,\n SmartTransactionsControllerState\n> {\n /**\n * Name of this controller used during composition\n */\n override name = 'SmartTransactionsController';\n\n public timeoutHandle?: NodeJS.Timeout;\n\n private readonly getNonceLock: any;\n\n private ethQuery: EthQuery | undefined;\n\n public confirmExternalTransaction: any;\n\n public getRegularTransactions: (\n options?: GetTransactionsOptions,\n ) => TransactionMeta[];\n\n private readonly trackMetaMetricsEvent: any;\n\n public eventEmitter: EventEmitter;\n\n private readonly getNetworkClientById: NetworkController['getNetworkClientById'];\n\n /* istanbul ignore next */\n private async fetch(request: string, options?: RequestInit) {\n const { clientId } = this.config;\n const fetchOptions = {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...(clientId && { 'X-Client-Id': clientId }),\n },\n };\n\n return handleFetch(request, fetchOptions);\n }\n\n constructor(\n {\n onNetworkStateChange,\n getNonceLock,\n provider,\n confirmExternalTransaction,\n getTransactions,\n trackMetaMetricsEvent,\n getNetworkClientById,\n }: {\n onNetworkStateChange: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n getNonceLock: any;\n provider: Provider;\n confirmExternalTransaction: any;\n getTransactions: (options?: GetTransactionsOptions) => TransactionMeta[];\n trackMetaMetricsEvent: any;\n getNetworkClientById: NetworkController['getNetworkClientById'];\n },\n config?: Partial,\n state?: Partial,\n ) {\n super(config, state);\n\n this.defaultConfig = {\n interval: DEFAULT_INTERVAL,\n chainId: CHAIN_IDS.ETHEREUM,\n clientId: 'default',\n supportedChainIds: [CHAIN_IDS.ETHEREUM, CHAIN_IDS.GOERLI],\n };\n\n this.defaultState = {\n smartTransactionsState: {\n smartTransactions: {},\n userOptIn: undefined,\n userOptInV2: undefined,\n fees: {\n approvalTxFees: undefined,\n tradeTxFees: undefined,\n },\n liveness: true,\n livenessByChainId: {\n [CHAIN_IDS.ETHEREUM]: true,\n [CHAIN_IDS.GOERLI]: true,\n },\n feesByChainId: {\n [CHAIN_IDS.ETHEREUM]: {\n approvalTxFees: undefined,\n tradeTxFees: undefined,\n },\n [CHAIN_IDS.GOERLI]: {\n approvalTxFees: undefined,\n tradeTxFees: undefined,\n },\n },\n },\n };\n\n this.initialize();\n this.setIntervalLength(this.config.interval);\n this.getNonceLock = getNonceLock;\n this.ethQuery = undefined;\n this.confirmExternalTransaction = confirmExternalTransaction;\n this.getRegularTransactions = getTransactions;\n this.trackMetaMetricsEvent = trackMetaMetricsEvent;\n this.getNetworkClientById = getNetworkClientById;\n\n this.initializeSmartTransactionsForChainId();\n\n onNetworkStateChange(({ providerConfig: newProvider }) => {\n const { chainId } = newProvider;\n this.configure({ chainId });\n this.initializeSmartTransactionsForChainId();\n this.checkPoll(this.state);\n this.ethQuery = new EthQuery(provider);\n });\n\n this.subscribe((currentState: any) => this.checkPoll(currentState));\n this.eventEmitter = new EventEmitter();\n }\n\n async _executePoll(networkClientId: string): Promise {\n // if this is going to be truly UI driven polling we shouldn't really reach here\n // with a networkClientId that is not supported, but for now I'll add a check in case\n // wondering if we should add some kind of predicate to the polling controller to check whether\n // we should poll or not\n const chainId = this.#getChainId({ networkClientId });\n if (!this.config.supportedChainIds.includes(chainId)) {\n return Promise.resolve();\n }\n return this.updateSmartTransactions({ networkClientId });\n }\n\n checkPoll(state: any) {\n const { smartTransactions } = state.smartTransactionsState;\n const currentSmartTransactions = smartTransactions[this.config.chainId];\n const pendingTransactions = currentSmartTransactions?.filter(\n isSmartTransactionPending,\n );\n if (!this.timeoutHandle && pendingTransactions?.length > 0) {\n this.poll();\n } else if (this.timeoutHandle && pendingTransactions?.length === 0) {\n this.stop();\n }\n }\n\n initializeSmartTransactionsForChainId() {\n if (this.config.supportedChainIds.includes(this.config.chainId)) {\n const { smartTransactionsState } = this.state;\n this.update({\n smartTransactionsState: {\n ...smartTransactionsState,\n smartTransactions: {\n ...smartTransactionsState.smartTransactions,\n [this.config.chainId]:\n smartTransactionsState.smartTransactions[this.config.chainId] ??\n [],\n },\n },\n });\n }\n }\n\n async poll(interval?: number): Promise {\n const { chainId, supportedChainIds } = this.config;\n interval && this.configure({ interval }, false, false);\n this.timeoutHandle && clearInterval(this.timeoutHandle);\n if (!supportedChainIds.includes(chainId)) {\n return;\n }\n await safelyExecute(async () => this.updateSmartTransactions());\n this.timeoutHandle = setInterval(() => {\n safelyExecute(async () => this.updateSmartTransactions());\n }, this.config.interval);\n }\n\n async stop() {\n this.timeoutHandle && clearInterval(this.timeoutHandle);\n this.timeoutHandle = undefined;\n }\n\n setOptInState(state: boolean | undefined): void {\n this.update({\n smartTransactionsState: {\n ...this.state.smartTransactionsState,\n userOptInV2: state,\n },\n });\n }\n\n trackStxStatusChange(\n smartTransaction: SmartTransaction,\n prevSmartTransaction?: SmartTransaction,\n ) {\n if (!prevSmartTransaction) {\n return; // Don't track the first STX, because it doesn't have all necessary params.\n }\n\n let updatedSmartTransaction = cloneDeep(smartTransaction);\n updatedSmartTransaction = {\n ...cloneDeep(prevSmartTransaction),\n ...updatedSmartTransaction,\n };\n\n if (\n !updatedSmartTransaction.swapMetaData ||\n (updatedSmartTransaction.status === prevSmartTransaction.status &&\n prevSmartTransaction.swapMetaData)\n ) {\n return; // If status hasn't changed, don't track it again.\n }\n\n const sensitiveProperties = {\n stx_status: updatedSmartTransaction.status,\n token_from_symbol: updatedSmartTransaction.sourceTokenSymbol,\n token_to_symbol: updatedSmartTransaction.destinationTokenSymbol,\n processing_time: getStxProcessingTime(updatedSmartTransaction.time),\n stx_enabled: true,\n current_stx_enabled: true,\n stx_user_opt_in: true,\n };\n\n this.trackMetaMetricsEvent({\n event: MetaMetricsEventName.StxStatusUpdated,\n category: MetaMetricsEventCategory.Transactions,\n sensitiveProperties,\n });\n }\n\n isNewSmartTransaction(smartTransactionUuid: string): boolean {\n const { chainId } = this.config;\n const { smartTransactionsState } = this.state;\n const { smartTransactions } = smartTransactionsState;\n const currentSmartTransactions = smartTransactions[chainId];\n const currentIndex = currentSmartTransactions?.findIndex(\n (stx) => stx.uuid === smartTransactionUuid,\n );\n return currentIndex === -1 || currentIndex === undefined;\n }\n\n updateSmartTransaction(\n smartTransaction: SmartTransaction,\n { networkClientId }: { networkClientId?: NetworkClientId } = {},\n ) {\n let {\n ethQuery,\n config: { chainId },\n } = this;\n if (networkClientId) {\n const networkClient = this.getNetworkClientById(networkClientId);\n chainId = networkClient.configuration.chainId;\n ethQuery = new EthQuery(networkClient.provider);\n }\n\n this.#updateSmartTransaction(smartTransaction, {\n chainId,\n ethQuery,\n });\n }\n\n async #updateSmartTransaction(\n smartTransaction: SmartTransaction,\n {\n chainId = this.config.chainId,\n ethQuery = this.ethQuery,\n }: {\n chainId: Hex;\n ethQuery: EthQuery | undefined;\n },\n ): Promise {\n const { smartTransactionsState } = this.state;\n const { smartTransactions } = smartTransactionsState;\n const currentSmartTransactions = smartTransactions[chainId] ?? [];\n const currentIndex = currentSmartTransactions?.findIndex(\n (stx) => stx.uuid === smartTransaction.uuid,\n );\n const isNewSmartTransaction = this.isNewSmartTransaction(\n smartTransaction.uuid,\n );\n if (this.ethQuery === undefined) {\n throw new Error(ETH_QUERY_ERROR_MSG);\n }\n\n this.trackStxStatusChange(\n smartTransaction,\n isNewSmartTransaction\n ? undefined\n : currentSmartTransactions[currentIndex],\n );\n\n if (isNewSmartTransaction) {\n // add smart transaction\n const cancelledNonceIndex = currentSmartTransactions?.findIndex(\n (stx: SmartTransaction) =>\n stx.txParams?.nonce === smartTransaction.txParams?.nonce &&\n stx.status?.startsWith('cancelled'),\n );\n const snapshot = cloneDeep(smartTransaction);\n const history = [snapshot];\n const historifiedSmartTransaction = { ...smartTransaction, history };\n const nextSmartTransactions =\n cancelledNonceIndex > -1\n ? currentSmartTransactions\n .slice(0, cancelledNonceIndex)\n .concat(currentSmartTransactions.slice(cancelledNonceIndex + 1))\n .concat(historifiedSmartTransaction)\n : currentSmartTransactions.concat(historifiedSmartTransaction);\n this.update({\n smartTransactionsState: {\n ...smartTransactionsState,\n smartTransactions: {\n ...smartTransactionsState.smartTransactions,\n [chainId]: nextSmartTransactions,\n },\n },\n });\n return;\n }\n\n if (\n (smartTransaction.status === SmartTransactionStatuses.SUCCESS ||\n smartTransaction.status === SmartTransactionStatuses.REVERTED) &&\n !smartTransaction.confirmed\n ) {\n // confirm smart transaction\n const currentSmartTransaction = currentSmartTransactions[currentIndex];\n const nextSmartTransaction = {\n ...currentSmartTransaction,\n ...smartTransaction,\n };\n await this.#confirmSmartTransaction(nextSmartTransaction, {\n chainId,\n ethQuery,\n });\n } else {\n this.update({\n smartTransactionsState: {\n ...smartTransactionsState,\n smartTransactions: {\n ...smartTransactionsState.smartTransactions,\n [chainId]: smartTransactionsState.smartTransactions[chainId].map(\n (item, index) => {\n return index === currentIndex\n ? { ...item, ...smartTransaction }\n : item;\n },\n ),\n },\n },\n });\n }\n\n this.eventEmitter.emit(\n `${smartTransaction.uuid}:smartTransaction`,\n smartTransaction,\n );\n }\n\n async updateSmartTransactions({\n networkClientId,\n }: {\n networkClientId?: NetworkClientId;\n } = {}): Promise {\n const { smartTransactions } = this.state.smartTransactionsState;\n const chainId = this.#getChainId({ networkClientId });\n const smartTransactionsForChainId = smartTransactions[chainId];\n\n const transactionsToUpdate: string[] = smartTransactionsForChainId\n .filter(isSmartTransactionPending)\n .map((smartTransaction) => smartTransaction.uuid);\n\n if (transactionsToUpdate.length > 0) {\n this.fetchSmartTransactionsStatus(transactionsToUpdate, {\n networkClientId,\n });\n }\n }\n\n #doesTransactionNeedConfirmation(txHash: string | undefined): boolean {\n if (!txHash) {\n return true;\n }\n const transactions = this.getRegularTransactions();\n const foundTransaction = transactions?.find((tx) => {\n return tx.hash?.toLowerCase() === txHash.toLowerCase();\n });\n if (!foundTransaction) {\n return true;\n }\n // If a found transaction is either confirmed or submitted, it doesn't need confirmation from the STX controller.\n // When it's in the submitted state, the TransactionController checks its status and confirms it,\n // so no need to confirm it again here.\n return ![TransactionStatus.confirmed, TransactionStatus.submitted].includes(\n foundTransaction.status,\n );\n }\n\n async #confirmSmartTransaction(\n smartTransaction: SmartTransaction,\n {\n chainId = this.config.chainId,\n ethQuery = this.ethQuery,\n }: {\n chainId: Hex;\n ethQuery: EthQuery | undefined;\n },\n ) {\n if (ethQuery === undefined) {\n throw new Error(ETH_QUERY_ERROR_MSG);\n }\n const txHash = smartTransaction.statusMetadata?.minedHash;\n try {\n const transactionReceipt: {\n maxFeePerGas?: string;\n maxPriorityFeePerGas?: string;\n blockNumber: string;\n } | null = await query(ethQuery, 'getTransactionReceipt', [txHash]);\n const transaction: {\n maxFeePerGas?: string;\n maxPriorityFeePerGas?: string;\n } | null = await query(ethQuery, 'getTransactionByHash', [txHash]);\n\n const maxFeePerGas = transaction?.maxFeePerGas;\n const maxPriorityFeePerGas = transaction?.maxPriorityFeePerGas;\n if (transactionReceipt?.blockNumber) {\n const blockData: { baseFeePerGas?: string } | null = await query(\n ethQuery,\n 'getBlockByNumber',\n [transactionReceipt?.blockNumber, false],\n );\n const baseFeePerGas = blockData?.baseFeePerGas;\n const updatedTxParams = {\n ...smartTransaction.txParams,\n maxFeePerGas,\n maxPriorityFeePerGas,\n };\n // call confirmExternalTransaction\n const originalTxMeta = {\n ...smartTransaction,\n id: smartTransaction.uuid,\n status: TransactionStatus.confirmed,\n hash: txHash,\n txParams: updatedTxParams,\n };\n // create txMeta snapshot for history\n const snapshot = snapshotFromTxMeta(originalTxMeta);\n // recover previous tx state obj\n const previousState = replayHistory(originalTxMeta.history);\n // generate history entry and add to history\n const entry = generateHistoryEntry(\n previousState,\n snapshot,\n 'txStateManager: setting status to confirmed',\n );\n const txMeta =\n entry.length > 0\n ? {\n ...originalTxMeta,\n history: originalTxMeta.history.concat(entry),\n }\n : originalTxMeta;\n\n if (this.#doesTransactionNeedConfirmation(txHash)) {\n this.confirmExternalTransaction(\n txMeta,\n transactionReceipt,\n baseFeePerGas,\n );\n }\n\n this.trackMetaMetricsEvent({\n event: MetaMetricsEventName.StxConfirmed,\n category: MetaMetricsEventCategory.Transactions,\n });\n\n this.#updateSmartTransaction(\n {\n ...smartTransaction,\n confirmed: true,\n },\n { chainId, ethQuery },\n );\n }\n } catch (error) {\n this.trackMetaMetricsEvent({\n event: MetaMetricsEventName.StxConfirmationFailed,\n category: MetaMetricsEventCategory.Transactions,\n });\n console.error('confirm error', error);\n }\n }\n\n // ! Ask backend API to accept list of uuids as params\n async fetchSmartTransactionsStatus(\n uuids: string[],\n { networkClientId }: { networkClientId?: NetworkClientId } = {},\n ): Promise> {\n const params = new URLSearchParams({\n uuids: uuids.join(','),\n });\n const chainId = this.#getChainId({ networkClientId });\n const ethQuery = this.#getEthQuery({ networkClientId });\n const url = `${getAPIRequestURL(\n APIType.BATCH_STATUS,\n chainId,\n )}?${params.toString()}`;\n\n const data = (await this.fetch(url)) as Record<\n string,\n SmartTransactionsStatus\n >;\n\n Object.entries(data).forEach(([uuid, stxStatus]) => {\n const smartTransaction = {\n statusMetadata: stxStatus,\n status: calculateStatus(stxStatus),\n cancellable: isSmartTransactionCancellable(stxStatus),\n uuid,\n };\n this.#updateSmartTransaction(smartTransaction, { chainId, ethQuery });\n });\n\n return data;\n }\n\n async addNonceToTransaction(\n transaction: UnsignedTransaction,\n ): Promise {\n const nonceLock = await this.getNonceLock(transaction.from);\n const nonce = nonceLock.nextNonce;\n nonceLock.releaseLock();\n return {\n ...transaction,\n nonce: `0x${nonce.toString(16)}`,\n };\n }\n\n clearFees(): Fees {\n const fees = {\n approvalTxFees: undefined,\n tradeTxFees: undefined,\n };\n this.update({\n smartTransactionsState: {\n ...this.state.smartTransactionsState,\n fees,\n },\n });\n return fees;\n }\n\n async getFees(\n tradeTx: UnsignedTransaction,\n approvalTx?: UnsignedTransaction,\n { networkClientId }: { networkClientId?: NetworkClientId } = {},\n ): Promise {\n const chainId = this.#getChainId({ networkClientId });\n const transactions = [];\n let unsignedTradeTransactionWithNonce;\n if (approvalTx) {\n const unsignedApprovalTransactionWithNonce =\n await this.addNonceToTransaction(approvalTx);\n transactions.push(unsignedApprovalTransactionWithNonce);\n unsignedTradeTransactionWithNonce = {\n ...tradeTx,\n // If there is an approval tx, the trade tx's nonce is increased by 1.\n nonce: incrementNonceInHex(unsignedApprovalTransactionWithNonce.nonce),\n };\n } else if (tradeTx.nonce) {\n unsignedTradeTransactionWithNonce = tradeTx;\n } else {\n unsignedTradeTransactionWithNonce = await this.addNonceToTransaction(\n tradeTx,\n );\n }\n transactions.push(unsignedTradeTransactionWithNonce);\n const data = await this.fetch(getAPIRequestURL(APIType.GET_FEES, chainId), {\n method: 'POST',\n body: JSON.stringify({\n txs: transactions,\n }),\n });\n let approvalTxFees;\n let tradeTxFees;\n if (approvalTx) {\n approvalTxFees = data?.txs[0];\n tradeTxFees = data?.txs[1];\n } else {\n tradeTxFees = data?.txs[0];\n }\n\n this.update({\n smartTransactionsState: {\n ...this.state.smartTransactionsState,\n ...(chainId === this.config.chainId && {\n fees: {\n approvalTxFees,\n tradeTxFees,\n },\n }),\n feesByChainId: {\n ...this.state.smartTransactionsState.feesByChainId,\n [chainId]: {\n approvalTxFees,\n tradeTxFees,\n },\n },\n },\n });\n\n return {\n approvalTxFees,\n tradeTxFees,\n };\n }\n\n // * After this successful call client must add a nonce representative to\n // * transaction controller external transactions list\n async submitSignedTransactions({\n transactionMeta,\n txParams,\n signedTransactions,\n signedCanceledTransactions,\n networkClientId,\n }: {\n signedTransactions: SignedTransaction[];\n signedCanceledTransactions: SignedCanceledTransaction[];\n transactionMeta?: any;\n txParams?: any;\n networkClientId?: NetworkClientId;\n }) {\n const chainId = this.#getChainId({ networkClientId });\n const ethQuery = this.#getEthQuery({ networkClientId });\n const data = await this.fetch(\n getAPIRequestURL(APIType.SUBMIT_TRANSACTIONS, chainId),\n {\n method: 'POST',\n body: JSON.stringify({\n rawTxs: signedTransactions,\n rawCancelTxs: signedCanceledTransactions,\n }),\n },\n );\n const time = Date.now();\n let preTxBalance;\n try {\n const preTxBalanceBN = await query(ethQuery, 'getBalance', [\n txParams?.from,\n ]);\n preTxBalance = new BigNumber(preTxBalanceBN).toString(16);\n } catch (error) {\n console.error('provider error', error);\n }\n\n const requiresNonce = !txParams.nonce;\n let nonce;\n let nonceLock;\n let nonceDetails = {};\n\n if (requiresNonce) {\n nonceLock = await this.getNonceLock(txParams?.from);\n nonce = hexlify(nonceLock.nextNonce);\n nonceDetails = nonceLock.nonceDetails;\n if (txParams) {\n txParams.nonce ??= nonce;\n }\n }\n const submitTransactionResponse = {\n ...data,\n txHash: getTxHash(signedTransactions[0]),\n };\n\n try {\n this.#updateSmartTransaction(\n {\n chainId,\n nonceDetails,\n preTxBalance,\n status: SmartTransactionStatuses.PENDING,\n time,\n txParams,\n uuid: submitTransactionResponse.uuid,\n txHash: submitTransactionResponse.txHash,\n cancellable: true,\n type: transactionMeta?.type || 'swap',\n },\n { chainId, ethQuery },\n );\n } finally {\n nonceLock?.releaseLock();\n }\n\n return submitTransactionResponse;\n }\n\n #getChainId({\n networkClientId,\n }: { networkClientId?: NetworkClientId } = {}): Hex {\n return networkClientId\n ? this.getNetworkClientById(networkClientId).configuration.chainId\n : this.config.chainId;\n }\n\n #getEthQuery({\n networkClientId,\n }: {\n networkClientId?: NetworkClientId;\n } = {}): EthQuery {\n if (networkClientId) {\n return new EthQuery(this.getNetworkClientById(networkClientId).provider);\n }\n\n if (this.ethQuery === undefined) {\n throw new Error(ETH_QUERY_ERROR_MSG);\n }\n\n return this.ethQuery;\n }\n\n // TODO: This should return if the cancellation was on chain or not (for nonce management)\n // After this successful call client must update nonce representative\n // in transaction controller external transactions list\n async cancelSmartTransaction(\n uuid: string,\n {\n networkClientId,\n }: {\n networkClientId?: NetworkClientId;\n } = {},\n ): Promise {\n const chainId = this.#getChainId({ networkClientId });\n await this.fetch(getAPIRequestURL(APIType.CANCEL, chainId), {\n method: 'POST',\n body: JSON.stringify({ uuid }),\n });\n }\n\n async fetchLiveness({\n networkClientId,\n }: {\n networkClientId?: NetworkClientId;\n } = {}): Promise {\n const chainId = this.#getChainId({ networkClientId });\n let liveness = false;\n try {\n const response = await this.fetch(\n getAPIRequestURL(APIType.LIVENESS, chainId),\n );\n liveness = Boolean(response.lastBlock);\n } catch (error) {\n console.log('\"fetchLiveness\" API call failed');\n }\n\n this.update({\n smartTransactionsState: {\n ...this.state.smartTransactionsState,\n ...(chainId === this.config.chainId && { liveness }),\n livenessByChainId: {\n ...this.state.smartTransactionsState.livenessByChainId,\n [chainId]: liveness,\n },\n },\n });\n\n return liveness;\n }\n\n async setStatusRefreshInterval(interval: number): Promise {\n if (interval !== this.config.interval) {\n this.configure({ interval }, false, false);\n }\n }\n\n #getCurrentSmartTransactions(): SmartTransaction[] {\n const { smartTransactions } = this.state.smartTransactionsState;\n const { chainId } = this.config;\n const currentSmartTransactions = smartTransactions?.[chainId];\n if (!currentSmartTransactions || currentSmartTransactions.length === 0) {\n return [];\n }\n return currentSmartTransactions;\n }\n\n getTransactions({\n addressFrom,\n status,\n }: {\n addressFrom: string;\n status: SmartTransactionStatuses;\n }): SmartTransaction[] {\n const currentSmartTransactions = this.#getCurrentSmartTransactions();\n return currentSmartTransactions.filter((stx) => {\n return stx.status === status && stx.txParams?.from === addressFrom;\n });\n }\n\n getSmartTransactionByMinedTxHash(\n txHash: string | undefined,\n ): SmartTransaction | undefined {\n if (!txHash) {\n return undefined;\n }\n const currentSmartTransactions = this.#getCurrentSmartTransactions();\n return currentSmartTransactions.find((smartTransaction) => {\n return (\n smartTransaction.statusMetadata?.minedHash?.toLowerCase() ===\n txHash.toLowerCase()\n );\n });\n }\n}\n"]}
-\ No newline at end of file
-+{"version":3,"file":"SmartTransactionsController.js","sourceRoot":"","sources":["../src/SmartTransactionsController.ts"],"names":[],"mappings":"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","sourcesContent":["// eslint-disable-next-line import/no-nodejs-modules\nimport { hexlify } from '@ethersproject/bytes';\nimport type { BaseConfig, BaseState } from '@metamask/base-controller';\nimport { query, safelyExecute } from '@metamask/controller-utils';\nimport type { Provider } from '@metamask/eth-query';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClientId,\n NetworkController,\n NetworkState,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingControllerV1 } from '@metamask/polling-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport { TransactionStatus } from '@metamask/transaction-controller';\nimport { BigNumber } from 'bignumber.js';\n// eslint-disable-next-line import/no-nodejs-modules\nimport EventEmitter from 'events';\nimport cloneDeep from 'lodash/cloneDeep';\n\nimport {\n CHAIN_IDS,\n MetaMetricsEventCategory,\n MetaMetricsEventName,\n} from './constants';\nimport type {\n Fees,\n Hex,\n IndividualTxFees,\n SignedCanceledTransaction,\n SignedTransaction,\n SmartTransaction,\n SmartTransactionsStatus,\n UnsignedTransaction,\n GetTransactionsOptions,\n} from './types';\nimport { APIType, SmartTransactionStatuses } from './types';\nimport {\n calculateStatus,\n generateHistoryEntry,\n getAPIRequestURL,\n getStxProcessingTime,\n handleFetch,\n incrementNonceInHex,\n isSmartTransactionCancellable,\n isSmartTransactionPending,\n replayHistory,\n snapshotFromTxMeta,\n getTxHash,\n} from './utils';\n\nconst SECOND = 1000;\nexport const DEFAULT_INTERVAL = SECOND * 5;\nconst ETH_QUERY_ERROR_MSG =\n '`ethQuery` is not defined on SmartTransactionsController';\n\nexport type SmartTransactionsControllerConfig = BaseConfig & {\n interval: number;\n clientId: string;\n chainId: Hex;\n supportedChainIds: string[];\n};\n\ntype FeeEstimates = {\n approvalTxFees: IndividualTxFees | undefined;\n tradeTxFees: IndividualTxFees | undefined;\n};\n\nexport type SmartTransactionsControllerState = BaseState & {\n smartTransactionsState: {\n smartTransactions: Record;\n userOptIn: boolean | undefined;\n userOptInV2: boolean | undefined;\n liveness: boolean | undefined;\n fees: FeeEstimates;\n feesByChainId: Record;\n livenessByChainId: Record;\n };\n};\n\nexport default class SmartTransactionsController extends StaticIntervalPollingControllerV1<\n SmartTransactionsControllerConfig,\n SmartTransactionsControllerState\n> {\n /**\n * Name of this controller used during composition\n */\n override name = 'SmartTransactionsController';\n\n public timeoutHandle?: NodeJS.Timeout;\n\n private readonly getNonceLock: any;\n\n private ethQuery: EthQuery | undefined;\n\n public confirmExternalTransaction: any;\n\n public getRegularTransactions: (\n options?: GetTransactionsOptions,\n ) => TransactionMeta[];\n\n private readonly trackMetaMetricsEvent: any;\n\n public eventEmitter: EventEmitter;\n\n private readonly getNetworkClientById: NetworkController['getNetworkClientById'];\n\n /* istanbul ignore next */\n private async fetch(request: string, options?: RequestInit) {\n const { clientId } = this.config;\n const fetchOptions = {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...(clientId && { 'X-Client-Id': clientId }),\n },\n };\n\n return handleFetch(request, fetchOptions);\n }\n\n constructor(\n {\n onNetworkStateChange,\n getNonceLock,\n provider,\n confirmExternalTransaction,\n getTransactions,\n trackMetaMetricsEvent,\n getNetworkClientById,\n }: {\n onNetworkStateChange: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n getNonceLock: any;\n provider: Provider;\n confirmExternalTransaction: any;\n getTransactions: (options?: GetTransactionsOptions) => TransactionMeta[];\n trackMetaMetricsEvent: any;\n getNetworkClientById: NetworkController['getNetworkClientById'];\n },\n config?: Partial,\n state?: Partial,\n ) {\n super(config, state);\n\n this.defaultConfig = {\n interval: DEFAULT_INTERVAL,\n chainId: CHAIN_IDS.ETHEREUM,\n clientId: 'default',\n supportedChainIds: [CHAIN_IDS.ETHEREUM, CHAIN_IDS.GOERLI],\n };\n\n this.defaultState = {\n smartTransactionsState: {\n smartTransactions: {},\n userOptIn: undefined,\n userOptInV2: undefined,\n fees: {\n approvalTxFees: undefined,\n tradeTxFees: undefined,\n },\n liveness: true,\n livenessByChainId: {\n [CHAIN_IDS.ETHEREUM]: true,\n [CHAIN_IDS.GOERLI]: true,\n },\n feesByChainId: {\n [CHAIN_IDS.ETHEREUM]: {\n approvalTxFees: undefined,\n tradeTxFees: undefined,\n },\n [CHAIN_IDS.GOERLI]: {\n approvalTxFees: undefined,\n tradeTxFees: undefined,\n },\n },\n },\n };\n\n this.initialize();\n this.setIntervalLength(this.config.interval);\n this.getNonceLock = getNonceLock;\n this.ethQuery = undefined;\n this.confirmExternalTransaction = confirmExternalTransaction;\n this.getRegularTransactions = getTransactions;\n this.trackMetaMetricsEvent = trackMetaMetricsEvent;\n this.getNetworkClientById = getNetworkClientById;\n\n this.initializeSmartTransactionsForChainId();\n\n onNetworkStateChange(({ providerConfig: newProvider }) => {\n const { chainId } = newProvider;\n this.configure({ chainId });\n this.initializeSmartTransactionsForChainId();\n this.checkPoll(this.state);\n this.ethQuery = new EthQuery(provider);\n });\n\n this.subscribe((currentState: any) => this.checkPoll(currentState));\n this.eventEmitter = new EventEmitter();\n }\n\n async _executePoll(networkClientId: string): Promise {\n // if this is going to be truly UI driven polling we shouldn't really reach here\n // with a networkClientId that is not supported, but for now I'll add a check in case\n // wondering if we should add some kind of predicate to the polling controller to check whether\n // we should poll or not\n const chainId = this.#getChainId({ networkClientId });\n if (!this.config.supportedChainIds.includes(chainId)) {\n return Promise.resolve();\n }\n return this.updateSmartTransactions({ networkClientId });\n }\n\n checkPoll(state: any) {\n const { smartTransactions } = state.smartTransactionsState;\n const currentSmartTransactions = smartTransactions[this.config.chainId];\n const pendingTransactions = currentSmartTransactions?.filter(\n isSmartTransactionPending,\n );\n if (!this.timeoutHandle && pendingTransactions?.length > 0) {\n this.poll();\n } else if (this.timeoutHandle && pendingTransactions?.length === 0) {\n this.stop();\n }\n }\n\n initializeSmartTransactionsForChainId() {\n if (this.config.supportedChainIds.includes(this.config.chainId)) {\n const { smartTransactionsState } = this.state;\n this.update({\n smartTransactionsState: {\n ...smartTransactionsState,\n smartTransactions: {\n ...smartTransactionsState.smartTransactions,\n [this.config.chainId]:\n smartTransactionsState.smartTransactions[this.config.chainId] ??\n [],\n },\n },\n });\n }\n }\n\n async poll(interval?: number): Promise {\n const { chainId, supportedChainIds } = this.config;\n interval && this.configure({ interval }, false, false);\n this.timeoutHandle && clearInterval(this.timeoutHandle);\n if (!supportedChainIds.includes(chainId)) {\n return;\n }\n await safelyExecute(async () => this.updateSmartTransactions());\n this.timeoutHandle = setInterval(() => {\n safelyExecute(async () => this.updateSmartTransactions());\n }, this.config.interval);\n }\n\n async stop() {\n this.timeoutHandle && clearInterval(this.timeoutHandle);\n this.timeoutHandle = undefined;\n }\n\n setOptInState(state: boolean | undefined): void {\n this.update({\n smartTransactionsState: {\n ...this.state.smartTransactionsState,\n userOptInV2: state,\n },\n });\n }\n\n trackStxStatusChange(\n smartTransaction: SmartTransaction,\n prevSmartTransaction?: SmartTransaction,\n ) {\n if (!prevSmartTransaction) {\n return; // Don't track the first STX, because it doesn't have all necessary params.\n }\n\n let updatedSmartTransaction = cloneDeep(smartTransaction);\n updatedSmartTransaction = {\n ...cloneDeep(prevSmartTransaction),\n ...updatedSmartTransaction,\n };\n\n if (\n !updatedSmartTransaction.swapMetaData ||\n (updatedSmartTransaction.status === prevSmartTransaction.status &&\n prevSmartTransaction.swapMetaData)\n ) {\n return; // If status hasn't changed, don't track it again.\n }\n\n const sensitiveProperties = {\n stx_status: updatedSmartTransaction.status,\n token_from_symbol: updatedSmartTransaction.sourceTokenSymbol,\n token_to_symbol: updatedSmartTransaction.destinationTokenSymbol,\n processing_time: getStxProcessingTime(updatedSmartTransaction.time),\n stx_enabled: true,\n current_stx_enabled: true,\n stx_user_opt_in: true,\n };\n\n this.trackMetaMetricsEvent({\n event: MetaMetricsEventName.StxStatusUpdated,\n category: MetaMetricsEventCategory.Transactions,\n sensitiveProperties,\n });\n }\n\n isNewSmartTransaction(smartTransactionUuid: string): boolean {\n const { chainId } = this.config;\n const { smartTransactionsState } = this.state;\n const { smartTransactions } = smartTransactionsState;\n const currentSmartTransactions = smartTransactions[chainId];\n const currentIndex = currentSmartTransactions?.findIndex(\n (stx) => stx.uuid === smartTransactionUuid,\n );\n return currentIndex === -1 || currentIndex === undefined;\n }\n\n updateSmartTransaction(\n smartTransaction: SmartTransaction,\n { networkClientId }: { networkClientId?: NetworkClientId } = {},\n ) {\n let {\n ethQuery,\n config: { chainId },\n } = this;\n if (networkClientId) {\n const networkClient = this.getNetworkClientById(networkClientId);\n chainId = networkClient.configuration.chainId;\n ethQuery = new EthQuery(networkClient.provider);\n }\n\n this.#updateSmartTransaction(smartTransaction, {\n chainId,\n ethQuery,\n });\n }\n\n async #updateSmartTransaction(\n smartTransaction: SmartTransaction,\n {\n chainId = this.config.chainId,\n ethQuery = this.ethQuery,\n }: {\n chainId: Hex;\n ethQuery: EthQuery | undefined;\n },\n ): Promise {\n const { smartTransactionsState } = this.state;\n const { smartTransactions } = smartTransactionsState;\n const currentSmartTransactions = smartTransactions[chainId] ?? [];\n const currentIndex = currentSmartTransactions?.findIndex(\n (stx) => stx.uuid === smartTransaction.uuid,\n );\n const isNewSmartTransaction = this.isNewSmartTransaction(\n smartTransaction.uuid,\n );\n if (this.ethQuery === undefined) {\n throw new Error(ETH_QUERY_ERROR_MSG);\n }\n\n this.trackStxStatusChange(\n smartTransaction,\n isNewSmartTransaction\n ? undefined\n : currentSmartTransactions[currentIndex],\n );\n\n if (isNewSmartTransaction) {\n // add smart transaction\n const cancelledNonceIndex = currentSmartTransactions?.findIndex(\n (stx: SmartTransaction) =>\n stx.transaction?.nonce === smartTransaction.transaction?.nonce &&\n stx.status?.startsWith('cancelled'),\n );\n const snapshot = cloneDeep(smartTransaction);\n const history = [snapshot];\n const historifiedSmartTransaction = { ...smartTransaction, history };\n const nextSmartTransactions =\n cancelledNonceIndex > -1\n ? currentSmartTransactions\n .slice(0, cancelledNonceIndex)\n .concat(currentSmartTransactions.slice(cancelledNonceIndex + 1))\n .concat(historifiedSmartTransaction)\n : currentSmartTransactions.concat(historifiedSmartTransaction);\n this.update({\n smartTransactionsState: {\n ...smartTransactionsState,\n smartTransactions: {\n ...smartTransactionsState.smartTransactions,\n [chainId]: nextSmartTransactions,\n },\n },\n });\n return;\n }\n\n if (\n (smartTransaction.status === SmartTransactionStatuses.SUCCESS ||\n smartTransaction.status === SmartTransactionStatuses.REVERTED) &&\n !smartTransaction.confirmed\n ) {\n // confirm smart transaction\n const currentSmartTransaction = currentSmartTransactions[currentIndex];\n const nextSmartTransaction = {\n ...currentSmartTransaction,\n ...smartTransaction,\n };\n await this.#confirmSmartTransaction(nextSmartTransaction, {\n chainId,\n ethQuery,\n });\n } else {\n this.update({\n smartTransactionsState: {\n ...smartTransactionsState,\n smartTransactions: {\n ...smartTransactionsState.smartTransactions,\n [chainId]: smartTransactionsState.smartTransactions[chainId].map(\n (item, index) => {\n return index === currentIndex\n ? { ...item, ...smartTransaction }\n : item;\n },\n ),\n },\n },\n });\n }\n\n this.eventEmitter.emit(\n `${smartTransaction.uuid}:smartTransaction`,\n smartTransaction,\n );\n }\n\n async updateSmartTransactions({\n networkClientId,\n }: {\n networkClientId?: NetworkClientId;\n } = {}): Promise {\n const { smartTransactions } = this.state.smartTransactionsState;\n const chainId = this.#getChainId({ networkClientId });\n const smartTransactionsForChainId = smartTransactions[chainId];\n\n const transactionsToUpdate: string[] = smartTransactionsForChainId\n .filter(isSmartTransactionPending)\n .map((smartTransaction) => smartTransaction.uuid);\n\n if (transactionsToUpdate.length > 0) {\n this.fetchSmartTransactionsStatus(transactionsToUpdate, {\n networkClientId,\n });\n }\n }\n\n #doesTransactionNeedConfirmation(txHash: string | undefined): boolean {\n if (!txHash) {\n return true;\n }\n const transactions = this.getRegularTransactions();\n const foundTransaction = transactions?.find((tx) => {\n return tx.transactionHash?.toLowerCase() === txHash.toLowerCase();\n });\n if (!foundTransaction) {\n return true;\n }\n // If a found transaction is either confirmed or submitted, it doesn't need confirmation from the STX controller.\n // When it's in the submitted state, the TransactionController checks its status and confirms it,\n // so no need to confirm it again here.\n return ![TransactionStatus.confirmed, TransactionStatus.submitted].includes(\n foundTransaction.status,\n );\n }\n\n async #confirmSmartTransaction(\n smartTransaction: SmartTransaction,\n {\n chainId = this.config.chainId,\n ethQuery = this.ethQuery,\n }: {\n chainId: Hex;\n ethQuery: EthQuery | undefined;\n },\n ) {\n if (ethQuery === undefined) {\n throw new Error(ETH_QUERY_ERROR_MSG);\n }\n const txHash = smartTransaction.statusMetadata?.minedHash;\n try {\n const transactionReceipt: {\n maxFeePerGas?: string;\n maxPriorityFeePerGas?: string;\n blockNumber: string;\n } | null = await query(ethQuery, 'getTransactionReceipt', [txHash]);\n const transaction: {\n maxFeePerGas?: string;\n maxPriorityFeePerGas?: string;\n } | null = await query(ethQuery, 'getTransactionByHash', [txHash]);\n\n const maxFeePerGas = transaction?.maxFeePerGas;\n const maxPriorityFeePerGas = transaction?.maxPriorityFeePerGas;\n if (transactionReceipt?.blockNumber) {\n const blockData: { baseFeePerGas?: string } | null = await query(\n ethQuery,\n 'getBlockByNumber',\n [transactionReceipt?.blockNumber, false],\n );\n const baseFeePerGas = blockData?.baseFeePerGas;\n const updatedTxParams = {\n ...smartTransaction.transaction,\n maxFeePerGas,\n maxPriorityFeePerGas,\n };\n // call confirmExternalTransaction\n const originalTxMeta = {\n ...smartTransaction,\n id: smartTransaction.uuid,\n status: TransactionStatus.confirmed,\n transactionHash: txHash,\n transaction: updatedTxParams,\n };\n // create txMeta snapshot for history\n const snapshot = snapshotFromTxMeta(originalTxMeta);\n // recover previous tx state obj\n const previousState = replayHistory(originalTxMeta.history);\n // generate history entry and add to history\n const entry = generateHistoryEntry(\n previousState,\n snapshot,\n 'txStateManager: setting status to confirmed',\n );\n const txMeta =\n entry.length > 0\n ? {\n ...originalTxMeta,\n history: originalTxMeta.history.concat(entry),\n }\n : originalTxMeta;\n\n if (this.#doesTransactionNeedConfirmation(txHash)) {\n this.confirmExternalTransaction(\n txMeta,\n transactionReceipt,\n baseFeePerGas,\n );\n }\n\n this.trackMetaMetricsEvent({\n event: MetaMetricsEventName.StxConfirmed,\n category: MetaMetricsEventCategory.Transactions,\n });\n\n this.#updateSmartTransaction(\n {\n ...smartTransaction,\n confirmed: true,\n },\n { chainId, ethQuery },\n );\n }\n } catch (error) {\n this.trackMetaMetricsEvent({\n event: MetaMetricsEventName.StxConfirmationFailed,\n category: MetaMetricsEventCategory.Transactions,\n });\n console.error('confirm error', error);\n }\n }\n\n // ! Ask backend API to accept list of uuids as params\n async fetchSmartTransactionsStatus(\n uuids: string[],\n { networkClientId }: { networkClientId?: NetworkClientId } = {},\n ): Promise> {\n const params = new URLSearchParams({\n uuids: uuids.join(','),\n });\n const chainId = this.#getChainId({ networkClientId });\n const ethQuery = this.#getEthQuery({ networkClientId });\n const url = `${getAPIRequestURL(\n APIType.BATCH_STATUS,\n chainId,\n )}?${params.toString()}`;\n\n const data = (await this.fetch(url)) as Record<\n string,\n SmartTransactionsStatus\n >;\n\n Object.entries(data).forEach(([uuid, stxStatus]) => {\n const smartTransaction = {\n statusMetadata: stxStatus,\n status: calculateStatus(stxStatus),\n cancellable: isSmartTransactionCancellable(stxStatus),\n uuid,\n };\n this.#updateSmartTransaction(smartTransaction, { chainId, ethQuery });\n });\n\n return data;\n }\n\n async addNonceToTransaction(\n transaction: UnsignedTransaction,\n ): Promise {\n const nonceLock = await this.getNonceLock(transaction.from);\n const nonce = nonceLock.nextNonce;\n nonceLock.releaseLock();\n return {\n ...transaction,\n nonce: `0x${nonce.toString(16)}`,\n };\n }\n\n clearFees(): Fees {\n const fees = {\n approvalTxFees: undefined,\n tradeTxFees: undefined,\n };\n this.update({\n smartTransactionsState: {\n ...this.state.smartTransactionsState,\n fees,\n },\n });\n return fees;\n }\n\n async getFees(\n tradeTx: UnsignedTransaction,\n approvalTx?: UnsignedTransaction,\n { networkClientId }: { networkClientId?: NetworkClientId } = {},\n ): Promise {\n const chainId = this.#getChainId({ networkClientId });\n const transactions = [];\n let unsignedTradeTransactionWithNonce;\n if (approvalTx) {\n const unsignedApprovalTransactionWithNonce =\n await this.addNonceToTransaction(approvalTx);\n transactions.push(unsignedApprovalTransactionWithNonce);\n unsignedTradeTransactionWithNonce = {\n ...tradeTx,\n // If there is an approval tx, the trade tx's nonce is increased by 1.\n nonce: incrementNonceInHex(unsignedApprovalTransactionWithNonce.nonce),\n };\n } else if (tradeTx.nonce) {\n unsignedTradeTransactionWithNonce = tradeTx;\n } else {\n unsignedTradeTransactionWithNonce = await this.addNonceToTransaction(\n tradeTx,\n );\n }\n transactions.push(unsignedTradeTransactionWithNonce);\n const data = await this.fetch(getAPIRequestURL(APIType.GET_FEES, chainId), {\n method: 'POST',\n body: JSON.stringify({\n txs: transactions,\n }),\n });\n let approvalTxFees;\n let tradeTxFees;\n if (approvalTx) {\n approvalTxFees = data?.txs[0];\n tradeTxFees = data?.txs[1];\n } else {\n tradeTxFees = data?.txs[0];\n }\n\n this.update({\n smartTransactionsState: {\n ...this.state.smartTransactionsState,\n ...(chainId === this.config.chainId && {\n fees: {\n approvalTxFees,\n tradeTxFees,\n },\n }),\n feesByChainId: {\n ...this.state.smartTransactionsState.feesByChainId,\n [chainId]: {\n approvalTxFees,\n tradeTxFees,\n },\n },\n },\n });\n\n return {\n approvalTxFees,\n tradeTxFees,\n };\n }\n\n // * After this successful call client must add a nonce representative to\n // * transaction controller external transactions list\n async submitSignedTransactions({\n transactionMeta,\n transaction,\n signedTransactions,\n signedCanceledTransactions,\n networkClientId,\n }: {\n signedTransactions: SignedTransaction[];\n signedCanceledTransactions: SignedCanceledTransaction[];\n transactionMeta?: any;\n transaction?: any;\n networkClientId?: NetworkClientId;\n }) {\n const chainId = this.#getChainId({ networkClientId });\n const ethQuery = this.#getEthQuery({ networkClientId });\n const data = await this.fetch(\n getAPIRequestURL(APIType.SUBMIT_TRANSACTIONS, chainId),\n {\n method: 'POST',\n body: JSON.stringify({\n rawTxs: signedTransactions,\n rawCancelTxs: signedCanceledTransactions,\n }),\n },\n );\n const time = Date.now();\n let preTxBalance;\n try {\n const preTxBalanceBN = await query(ethQuery, 'getBalance', [\n transaction?.from,\n ]);\n preTxBalance = new BigNumber(preTxBalanceBN).toString(16);\n } catch (error) {\n console.error('provider error', error);\n }\n\n const requiresNonce = !transaction.nonce;\n let nonce;\n let nonceLock;\n let nonceDetails = {};\n\n if (requiresNonce) {\n nonceLock = await this.getNonceLock(transaction?.from);\n nonce = hexlify(nonceLock.nextNonce);\n nonceDetails = nonceLock.nonceDetails;\n if (transaction) {\n transaction.nonce ??= nonce;\n }\n }\n const submitTransactionResponse = {\n ...data,\n txHash: getTxHash(signedTransactions[0]),\n };\n\n try {\n this.#updateSmartTransaction(\n {\n chainId,\n nonceDetails,\n preTxBalance,\n status: SmartTransactionStatuses.PENDING,\n time,\n transaction,\n uuid: submitTransactionResponse.uuid,\n transactionHash: submitTransactionResponse.txHash,\n cancellable: true,\n type: transactionMeta?.type || 'swap',\n },\n { chainId, ethQuery },\n );\n } finally {\n nonceLock?.releaseLock();\n }\n\n return submitTransactionResponse;\n }\n\n #getChainId({\n networkClientId,\n }: { networkClientId?: NetworkClientId } = {}): Hex {\n return networkClientId\n ? this.getNetworkClientById(networkClientId).configuration.chainId\n : this.config.chainId;\n }\n\n #getEthQuery({\n networkClientId,\n }: {\n networkClientId?: NetworkClientId;\n } = {}): EthQuery {\n if (networkClientId) {\n return new EthQuery(this.getNetworkClientById(networkClientId).provider);\n }\n\n if (this.ethQuery === undefined) {\n throw new Error(ETH_QUERY_ERROR_MSG);\n }\n\n return this.ethQuery;\n }\n\n // TODO: This should return if the cancellation was on chain or not (for nonce management)\n // After this successful call client must update nonce representative\n // in transaction controller external transactions list\n async cancelSmartTransaction(\n uuid: string,\n {\n networkClientId,\n }: {\n networkClientId?: NetworkClientId;\n } = {},\n ): Promise {\n const chainId = this.#getChainId({ networkClientId });\n await this.fetch(getAPIRequestURL(APIType.CANCEL, chainId), {\n method: 'POST',\n body: JSON.stringify({ uuid }),\n });\n }\n\n async fetchLiveness({\n networkClientId,\n }: {\n networkClientId?: NetworkClientId;\n } = {}): Promise {\n const chainId = this.#getChainId({ networkClientId });\n let liveness = false;\n try {\n const response = await this.fetch(\n getAPIRequestURL(APIType.LIVENESS, chainId),\n );\n liveness = Boolean(response.lastBlock);\n } catch (error) {\n console.log('\"fetchLiveness\" API call failed');\n }\n\n this.update({\n smartTransactionsState: {\n ...this.state.smartTransactionsState,\n ...(chainId === this.config.chainId && { liveness }),\n livenessByChainId: {\n ...this.state.smartTransactionsState.livenessByChainId,\n [chainId]: liveness,\n },\n },\n });\n\n return liveness;\n }\n\n async setStatusRefreshInterval(interval: number): Promise {\n if (interval !== this.config.interval) {\n this.configure({ interval }, false, false);\n }\n }\n\n #getCurrentSmartTransactions(): SmartTransaction[] {\n const { smartTransactions } = this.state.smartTransactionsState;\n const { chainId } = this.config;\n const currentSmartTransactions = smartTransactions?.[chainId];\n if (!currentSmartTransactions || currentSmartTransactions.length === 0) {\n return [];\n }\n return currentSmartTransactions;\n }\n\n getTransactions({\n addressFrom,\n status,\n }: {\n addressFrom: string;\n status: SmartTransactionStatuses;\n }): SmartTransaction[] {\n const currentSmartTransactions = this.#getCurrentSmartTransactions();\n return currentSmartTransactions.filter((stx) => {\n return stx.status === status && stx.transaction?.from === addressFrom;\n });\n }\n\n getSmartTransactionByMinedTxHash(\n txHash: string | undefined,\n ): SmartTransaction | undefined {\n if (!txHash) {\n return undefined;\n }\n const currentSmartTransactions = this.#getCurrentSmartTransactions();\n return currentSmartTransactions.find((smartTransaction) => {\n return (\n smartTransaction.statusMetadata?.minedHash?.toLowerCase() ===\n txHash.toLowerCase()\n );\n });\n }\n}\n"]}
-\ No newline at end of file
-diff --git a/node_modules/@metamask/smart-transactions-controller/dist/types.d.ts b/node_modules/@metamask/smart-transactions-controller/dist/types.d.ts
-index 977c983..c6493f7 100644
---- a/node_modules/@metamask/smart-transactions-controller/dist/types.d.ts
-+++ b/node_modules/@metamask/smart-transactions-controller/dist/types.d.ts
-@@ -61,7 +61,7 @@ export declare type SmartTransactionsStatus = {
- };
- export declare type SmartTransaction = {
- uuid: string;
-- txHash?: string;
-+ transactionHash?: string;
- chainId?: string;
- destinationTokenAddress?: string;
- destinationTokenDecimals?: string;
-@@ -77,7 +77,7 @@ export declare type SmartTransaction = {
- swapTokenValue?: string;
- time?: number;
- creationTime?: number;
-- txParams?: any;
-+ transaction?: any;
- type?: string;
- confirmed?: boolean;
- cancellable?: boolean;
-diff --git a/node_modules/@metamask/smart-transactions-controller/dist/types.js.map b/node_modules/@metamask/smart-transactions-controller/dist/types.js.map
-index 5be3df1..9965800 100644
---- a/node_modules/@metamask/smart-transactions-controller/dist/types.js.map
-+++ b/node_modules/@metamask/smart-transactions-controller/dist/types.js.map
-@@ -1 +1 @@
--{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAEA,UAAU;AACV,IAAY,OAOX;AAPD,WAAY,OAAO;IACjB,6CAAU,CAAA;IACV,qDAAc,CAAA;IACd,mEAAqB,CAAA;IACrB,yCAAQ,CAAA;IACR,qDAAc,CAAA;IACd,6CAAU,CAAA;AACZ,CAAC,EAPW,OAAO,GAAP,eAAO,KAAP,eAAO,QAOlB;AAED,wBAAwB;AACxB,IAAY,uBAMX;AAND,WAAY,uBAAuB;IACjC,kDAAuB,CAAA;IACvB,8CAAmB,CAAA;IACnB,kDAAuB,CAAA;IACvB,gDAAqB,CAAA;IACrB,8CAAmB,CAAA;AACrB,CAAC,EANW,uBAAuB,GAAvB,+BAAuB,KAAvB,+BAAuB,QAMlC;AAED,IAAY,kCAQX;AARD,WAAY,kCAAkC;IAC5C,mEAA6B,CAAA;IAC7B,6DAAuB,CAAA;IACvB,yEAAmC,CAAA;IACnC,qEAA+B,CAAA;IAC/B,uEAAiC,CAAA;IACjC,qEAA+B,CAAA;IAC/B,qFAA+C,CAAA;AACjD,CAAC,EARW,kCAAkC,GAAlC,0CAAkC,KAAlC,0CAAkC,QAQ7C;AAED,IAAY,wBAaX;AAbD,WAAY,wBAAwB;IAClC,+CAAmB,CAAA;IACnB,+CAAmB,CAAA;IACnB,iDAAqB,CAAA;IACrB,+CAAmB,CAAA;IACnB,mDAAuB,CAAA;IACvB,6EAAiD,CAAA;IACjD,uEAA2C,CAAA;IAC3C,mFAAuD,CAAA;IACvD,+EAAmD,CAAA;IACnD,iFAAqD,CAAA;IACrD,+FAAmE,CAAA;IACnE,iDAAqB,CAAA;AACvB,CAAC,EAbW,wBAAwB,GAAxB,gCAAwB,KAAxB,gCAAwB,QAanC;AAEY,QAAA,6BAA6B,GAAG;IAC3C,CAAC,kCAAkC,CAAC,YAAY,CAAC,EAC/C,wBAAwB,CAAC,sBAAsB;IACjD,CAAC,kCAAkC,CAAC,SAAS,CAAC,EAC5C,wBAAwB,CAAC,mBAAmB;IAC9C,CAAC,kCAAkC,CAAC,eAAe,CAAC,EAClD,wBAAwB,CAAC,yBAAyB;IACpD,CAAC,kCAAkC,CAAC,aAAa,CAAC,EAChD,wBAAwB,CAAC,uBAAuB;IAClD,CAAC,kCAAkC,CAAC,cAAc,CAAC,EACjD,wBAAwB,CAAC,wBAAwB;IACnD,CAAC,kCAAkC,CAAC,qBAAqB,CAAC,EACxD,wBAAwB,CAAC,+BAA+B;CAC3D,CAAC","sourcesContent":["import type { TransactionMeta } from '@metamask/transaction-controller';\n\n/** API */\nexport enum APIType {\n 'GET_FEES',\n 'ESTIMATE_GAS',\n 'SUBMIT_TRANSACTIONS',\n 'CANCEL',\n 'BATCH_STATUS',\n 'LIVENESS',\n}\n\n/** SmartTransactions */\nexport enum SmartTransactionMinedTx {\n NOT_MINED = 'not_mined',\n SUCCESS = 'success',\n CANCELLED = 'cancelled',\n REVERTED = 'reverted',\n UNKNOWN = 'unknown',\n}\n\nexport enum SmartTransactionCancellationReason {\n WOULD_REVERT = 'would_revert',\n TOO_CHEAP = 'too_cheap',\n DEADLINE_MISSED = 'deadline_missed',\n INVALID_NONCE = 'invalid_nonce',\n USER_CANCELLED = 'user_cancelled',\n NOT_CANCELLED = 'not_cancelled',\n PREVIOUS_TX_CANCELLED = 'previous_tx_cancelled',\n}\n\nexport enum SmartTransactionStatuses {\n PENDING = 'pending',\n SUCCESS = 'success',\n REVERTED = 'reverted',\n UNKNOWN = 'unknown',\n CANCELLED = 'cancelled',\n CANCELLED_WOULD_REVERT = 'cancelled_would_revert',\n CANCELLED_TOO_CHEAP = 'cancelled_too_cheap',\n CANCELLED_DEADLINE_MISSED = 'cancelled_deadline_missed',\n CANCELLED_INVALID_NONCE = 'cancelled_invalid_nonce',\n CANCELLED_USER_CANCELLED = 'cancelled_user_cancelled',\n CANCELLED_PREVIOUS_TX_CANCELLED = 'cancelled_previous_tx_cancelled',\n RESOLVED = 'resolved',\n}\n\nexport const cancellationReasonToStatusMap = {\n [SmartTransactionCancellationReason.WOULD_REVERT]:\n SmartTransactionStatuses.CANCELLED_WOULD_REVERT,\n [SmartTransactionCancellationReason.TOO_CHEAP]:\n SmartTransactionStatuses.CANCELLED_TOO_CHEAP,\n [SmartTransactionCancellationReason.DEADLINE_MISSED]:\n SmartTransactionStatuses.CANCELLED_DEADLINE_MISSED,\n [SmartTransactionCancellationReason.INVALID_NONCE]:\n SmartTransactionStatuses.CANCELLED_INVALID_NONCE,\n [SmartTransactionCancellationReason.USER_CANCELLED]:\n SmartTransactionStatuses.CANCELLED_USER_CANCELLED,\n [SmartTransactionCancellationReason.PREVIOUS_TX_CANCELLED]:\n SmartTransactionStatuses.CANCELLED_PREVIOUS_TX_CANCELLED,\n};\n\nexport type SmartTransactionsStatus = {\n error?: string;\n cancellationFeeWei: number;\n cancellationReason?: SmartTransactionCancellationReason;\n deadlineRatio: number;\n minedHash: string;\n minedTx: SmartTransactionMinedTx;\n isSettled: boolean;\n duplicated?: boolean;\n timedOut?: boolean;\n proxied?: boolean;\n};\n\nexport type SmartTransaction = {\n uuid: string;\n txHash?: string;\n chainId?: string;\n destinationTokenAddress?: string;\n destinationTokenDecimals?: string;\n destinationTokenSymbol?: string;\n history?: any;\n nonceDetails?: any;\n origin?: string;\n preTxBalance?: string;\n status?: string;\n statusMetadata?: SmartTransactionsStatus;\n sourceTokenSymbol?: string;\n swapMetaData?: any;\n swapTokenValue?: string;\n time?: number; // @deprecated We should use creationTime instead.\n creationTime?: number;\n txParams?: any;\n type?: string;\n confirmed?: boolean;\n cancellable?: boolean;\n};\n\nexport type Fee = {\n maxFeePerGas: number;\n maxPriorityFeePerGas: number;\n};\n\nexport type IndividualTxFees = {\n fees: Fee[];\n cancelFees: Fee[];\n feeEstimate: number;\n gasLimit: number;\n gasUsed: number;\n};\n\nexport type Fees = {\n approvalTxFees: IndividualTxFees | undefined;\n tradeTxFees: IndividualTxFees | undefined;\n};\n\n// TODO\nexport type UnsignedTransaction = any;\n\n// TODO\nexport type SignedTransaction = any;\n\n// TODO\nexport type SignedCanceledTransaction = any;\n\nexport type Hex = `0x${string}`;\n\nexport type GetTransactionsOptions = {\n searchCriteria?: any;\n initialList?: TransactionMeta[];\n filterToCurrentNetwork?: boolean;\n limit?: number;\n};\n"]}
-\ No newline at end of file
-+{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAEA,UAAU;AACV,IAAY,OAOX;AAPD,WAAY,OAAO;IACjB,6CAAU,CAAA;IACV,qDAAc,CAAA;IACd,mEAAqB,CAAA;IACrB,yCAAQ,CAAA;IACR,qDAAc,CAAA;IACd,6CAAU,CAAA;AACZ,CAAC,EAPW,OAAO,GAAP,eAAO,KAAP,eAAO,QAOlB;AAED,wBAAwB;AACxB,IAAY,uBAMX;AAND,WAAY,uBAAuB;IACjC,kDAAuB,CAAA;IACvB,8CAAmB,CAAA;IACnB,kDAAuB,CAAA;IACvB,gDAAqB,CAAA;IACrB,8CAAmB,CAAA;AACrB,CAAC,EANW,uBAAuB,GAAvB,+BAAuB,KAAvB,+BAAuB,QAMlC;AAED,IAAY,kCAQX;AARD,WAAY,kCAAkC;IAC5C,mEAA6B,CAAA;IAC7B,6DAAuB,CAAA;IACvB,yEAAmC,CAAA;IACnC,qEAA+B,CAAA;IAC/B,uEAAiC,CAAA;IACjC,qEAA+B,CAAA;IAC/B,qFAA+C,CAAA;AACjD,CAAC,EARW,kCAAkC,GAAlC,0CAAkC,KAAlC,0CAAkC,QAQ7C;AAED,IAAY,wBAaX;AAbD,WAAY,wBAAwB;IAClC,+CAAmB,CAAA;IACnB,+CAAmB,CAAA;IACnB,iDAAqB,CAAA;IACrB,+CAAmB,CAAA;IACnB,mDAAuB,CAAA;IACvB,6EAAiD,CAAA;IACjD,uEAA2C,CAAA;IAC3C,mFAAuD,CAAA;IACvD,+EAAmD,CAAA;IACnD,iFAAqD,CAAA;IACrD,+FAAmE,CAAA;IACnE,iDAAqB,CAAA;AACvB,CAAC,EAbW,wBAAwB,GAAxB,gCAAwB,KAAxB,gCAAwB,QAanC;AAEY,QAAA,6BAA6B,GAAG;IAC3C,CAAC,kCAAkC,CAAC,YAAY,CAAC,EAC/C,wBAAwB,CAAC,sBAAsB;IACjD,CAAC,kCAAkC,CAAC,SAAS,CAAC,EAC5C,wBAAwB,CAAC,mBAAmB;IAC9C,CAAC,kCAAkC,CAAC,eAAe,CAAC,EAClD,wBAAwB,CAAC,yBAAyB;IACpD,CAAC,kCAAkC,CAAC,aAAa,CAAC,EAChD,wBAAwB,CAAC,uBAAuB;IAClD,CAAC,kCAAkC,CAAC,cAAc,CAAC,EACjD,wBAAwB,CAAC,wBAAwB;IACnD,CAAC,kCAAkC,CAAC,qBAAqB,CAAC,EACxD,wBAAwB,CAAC,+BAA+B;CAC3D,CAAC","sourcesContent":["import type { TransactionMeta } from '@metamask/transaction-controller';\n\n/** API */\nexport enum APIType {\n 'GET_FEES',\n 'ESTIMATE_GAS',\n 'SUBMIT_TRANSACTIONS',\n 'CANCEL',\n 'BATCH_STATUS',\n 'LIVENESS',\n}\n\n/** SmartTransactions */\nexport enum SmartTransactionMinedTx {\n NOT_MINED = 'not_mined',\n SUCCESS = 'success',\n CANCELLED = 'cancelled',\n REVERTED = 'reverted',\n UNKNOWN = 'unknown',\n}\n\nexport enum SmartTransactionCancellationReason {\n WOULD_REVERT = 'would_revert',\n TOO_CHEAP = 'too_cheap',\n DEADLINE_MISSED = 'deadline_missed',\n INVALID_NONCE = 'invalid_nonce',\n USER_CANCELLED = 'user_cancelled',\n NOT_CANCELLED = 'not_cancelled',\n PREVIOUS_TX_CANCELLED = 'previous_tx_cancelled',\n}\n\nexport enum SmartTransactionStatuses {\n PENDING = 'pending',\n SUCCESS = 'success',\n REVERTED = 'reverted',\n UNKNOWN = 'unknown',\n CANCELLED = 'cancelled',\n CANCELLED_WOULD_REVERT = 'cancelled_would_revert',\n CANCELLED_TOO_CHEAP = 'cancelled_too_cheap',\n CANCELLED_DEADLINE_MISSED = 'cancelled_deadline_missed',\n CANCELLED_INVALID_NONCE = 'cancelled_invalid_nonce',\n CANCELLED_USER_CANCELLED = 'cancelled_user_cancelled',\n CANCELLED_PREVIOUS_TX_CANCELLED = 'cancelled_previous_tx_cancelled',\n RESOLVED = 'resolved',\n}\n\nexport const cancellationReasonToStatusMap = {\n [SmartTransactionCancellationReason.WOULD_REVERT]:\n SmartTransactionStatuses.CANCELLED_WOULD_REVERT,\n [SmartTransactionCancellationReason.TOO_CHEAP]:\n SmartTransactionStatuses.CANCELLED_TOO_CHEAP,\n [SmartTransactionCancellationReason.DEADLINE_MISSED]:\n SmartTransactionStatuses.CANCELLED_DEADLINE_MISSED,\n [SmartTransactionCancellationReason.INVALID_NONCE]:\n SmartTransactionStatuses.CANCELLED_INVALID_NONCE,\n [SmartTransactionCancellationReason.USER_CANCELLED]:\n SmartTransactionStatuses.CANCELLED_USER_CANCELLED,\n [SmartTransactionCancellationReason.PREVIOUS_TX_CANCELLED]:\n SmartTransactionStatuses.CANCELLED_PREVIOUS_TX_CANCELLED,\n};\n\nexport type SmartTransactionsStatus = {\n error?: string;\n cancellationFeeWei: number;\n cancellationReason?: SmartTransactionCancellationReason;\n deadlineRatio: number;\n minedHash: string;\n minedTx: SmartTransactionMinedTx;\n isSettled: boolean;\n duplicated?: boolean;\n timedOut?: boolean;\n proxied?: boolean;\n};\n\nexport type SmartTransaction = {\n uuid: string;\n transactionHash?: string;\n chainId?: string;\n destinationTokenAddress?: string;\n destinationTokenDecimals?: string;\n destinationTokenSymbol?: string;\n history?: any;\n nonceDetails?: any;\n origin?: string;\n preTxBalance?: string;\n status?: string;\n statusMetadata?: SmartTransactionsStatus;\n sourceTokenSymbol?: string;\n swapMetaData?: any;\n swapTokenValue?: string;\n time?: number; // @deprecated We should use creationTime instead.\n creationTime?: number;\n transaction?: any;\n type?: string;\n confirmed?: boolean;\n cancellable?: boolean;\n};\n\nexport type Fee = {\n maxFeePerGas: number;\n maxPriorityFeePerGas: number;\n};\n\nexport type IndividualTxFees = {\n fees: Fee[];\n cancelFees: Fee[];\n feeEstimate: number;\n gasLimit: number;\n gasUsed: number;\n};\n\nexport type Fees = {\n approvalTxFees: IndividualTxFees | undefined;\n tradeTxFees: IndividualTxFees | undefined;\n};\n\n// TODO\nexport type UnsignedTransaction = any;\n\n// TODO\nexport type SignedTransaction = any;\n\n// TODO\nexport type SignedCanceledTransaction = any;\n\nexport type Hex = `0x${string}`;\n\nexport type GetTransactionsOptions = {\n searchCriteria?: any;\n initialList?: TransactionMeta[];\n filterToCurrentNetwork?: boolean;\n limit?: number;\n};\n"]}
-\ No newline at end of file
diff --git a/patches/@metamask+swaps-controller+6.9.3.patch b/patches/@metamask+swaps-controller+6.9.3.patch
index 3001514cbc0f..11b97016349a 100644
--- a/patches/@metamask+swaps-controller+6.9.3.patch
+++ b/patches/@metamask+swaps-controller+6.9.3.patch
@@ -114,33 +114,46 @@ index 9d8a521..601fd18 100644
[exports.ETH_CHAIN_ID]: 'ethereum',
[exports.BSC_CHAIN_ID]: 'bsc',
diff --git a/node_modules/@metamask/swaps-controller/dist/swapsInterfaces.d.ts b/node_modules/@metamask/swaps-controller/dist/swapsInterfaces.d.ts
-index 43f7356..74a382b 100644
+index 43f7356..5416244 100644
--- a/node_modules/@metamask/swaps-controller/dist/swapsInterfaces.d.ts
+++ b/node_modules/@metamask/swaps-controller/dist/swapsInterfaces.d.ts
-@@ -19,14 +19,38 @@ export interface SwapsToken extends SwapsAsset {
+@@ -19,14 +19,51 @@ export interface SwapsToken extends SwapsAsset {
occurrences?: number;
iconUrl?: string;
}
+-export interface NetworkFeatureFlags {
+
- export interface NetworkFeatureFlags {
++export type NetworkFeatureFlags = {
mobile_active: boolean;
extension_active: boolean;
-- fallback_to_v1?: boolean;
-+ fallback_to_v1: boolean;
+ fallback_to_v1?: boolean;
+-}
++ };
+ export interface NetworksFeatureStatus {
+ [network: string]: NetworkFeatureFlags;
+ }
++
++export type NetworkFeatureFlagsAll = {
++ mobile_active: boolean;
++ extension_active: boolean;
++ fallback_to_v1?: boolean;
+ fallbackToV1: boolean;
+ mobileActive: boolean;
+ extensionActive: boolean;
+ mobileActiveIOS: boolean;
+ mobileActiveAndroid: boolean;
++
+ smartTransactions: {
-+ expectedDeadline: number;
-+ maxDeadline: number;
-+ returnTxHashAsap: boolean;
++ expectedDeadline: number;
++ maxDeadline: number;
++ returnTxHashAsap: boolean;
+ };
- }
- export interface NetworksFeatureStatus {
- [network: string]: NetworkFeatureFlags;
- }
++};
++
++export type NetworksFeatureStatusAll = {
++ [network: string]: NetworkFeatureFlagsAll;
++ };
++
+export interface GlobalFeatureFlags {
+ smart_transactions: {
+ mobile_active: boolean;
@@ -153,7 +166,8 @@ index 43f7356..74a382b 100644
+ mobileActiveAndroid: boolean;
+ };
+}
-+export declare type FeatureFlags = NetworksFeatureStatus & GlobalFeatureFlags;
++export type FeatureFlags = NetworksFeatureStatusAll & GlobalFeatureFlags;
++
/**
* Metadata needed to fetch quotes
*
diff --git a/yarn.lock b/yarn.lock
index 6e04968efdcb..8bc75fe94f07 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -29210,4 +29210,4 @@ zod@^3.22.4:
zxcvbn@4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/zxcvbn/-/zxcvbn-4.4.2.tgz#28ec17cf09743edcab056ddd8b1b06262cc73c30"
- integrity sha1-KOwXzwl0PtyrBW3dixsGJizHPDA=
\ No newline at end of file
+ integrity sha1-KOwXzwl0PtyrBW3dixsGJizHPDA=