Skip to content

feat: new tx list filter #28180

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 47 commits into from
Mar 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
d593b53
feat: new multichain trx history
salimtb Feb 18, 2025
62adc30
fix: clean up
salimtb Feb 18, 2025
4ab957d
fix: test
salimtb Feb 20, 2025
ba23d47
fix: test
salimtb Feb 24, 2025
79b3f66
fix: update smart transaction package
salimtb Feb 25, 2025
b080284
fix: update patch
salimtb Feb 26, 2025
526d166
fix: fix css
salimtb Feb 26, 2025
d892e74
fix: filter testnet
salimtb Feb 27, 2025
58f23ef
fix: update smart transaction patch
salimtb Feb 27, 2025
d8028dd
fix: fix after merge
salimtb Feb 27, 2025
64c0d99
fix: clean up
salimtb Feb 27, 2025
0b4ef82
fix: fix unit tests
salimtb Mar 3, 2025
fd24df7
fix: fix unit tests
salimtb Mar 3, 2025
d61a14e
fix: fix lint
salimtb Mar 3, 2025
043a97f
fix: fix ci
salimtb Mar 3, 2025
4198582
fix: fix design review
salimtb Mar 3, 2025
808b0a5
Merge branch 'main' into salim/new-tx-list
salimtb Mar 3, 2025
480a6d0
fix: update patch
salimtb Mar 13, 2025
7165880
fix: fix PR feedback
salimtb Mar 13, 2025
eaf749c
fix: fix fetch
salimtb Mar 13, 2025
0b1cd33
fix: clean up
salimtb Mar 13, 2025
9d43560
Merge branch 'main' into salim/new-tx-list
salimtb Mar 14, 2025
0d73838
fix: fix after merge
salimtb Mar 14, 2025
d65c5b8
fix: fix after merge
salimtb Mar 14, 2025
523e7da
fix: fix unit test
salimtb Mar 14, 2025
31aa843
Merge branch 'main' into salim/new-tx-list
salimtb Mar 14, 2025
6efa9e2
Merge branch 'main' into salim/new-tx-list
salimtb Mar 14, 2025
4b29600
fix: use new smart trx version
salimtb Mar 17, 2025
a9a7531
Merge branch 'main' into salim/new-tx-list
salimtb Mar 18, 2025
e23a762
Merge branch 'main' into salim/new-tx-list
salimtb Mar 19, 2025
7fea867
fix: fix after conflicts
salimtb Mar 19, 2025
aecb7fd
fix: process the migration only if 1 infura rpc exists
salimtb Mar 19, 2025
7f271a7
fix: add unit tests
salimtb Mar 19, 2025
92068bd
Merge branch 'main' into salim/new-tx-list
salimtb Mar 19, 2025
d7dbc75
fix: fix linter
salimtb Mar 19, 2025
6169cd4
fix: fix linter
salimtb Mar 19, 2025
a6bf320
fix: refacto
salimtb Mar 19, 2025
cdc4593
fix: fix PR comments
salimtb Mar 19, 2025
31fb58f
fix: fix PR comments
salimtb Mar 19, 2025
1a699ad
fix: fix linter
salimtb Mar 19, 2025
73edfee
fix: fix linter
salimtb Mar 19, 2025
b8be212
fix: fix snapshot
salimtb Mar 19, 2025
3c3addf
fix: fix linter
salimtb Mar 19, 2025
e6218b1
Merge branch 'main' into salim/new-tx-list
salimtb Mar 19, 2025
8bbb211
fix: clean up
salimtb Mar 19, 2025
875a0fb
fix: clean up
salimtb Mar 19, 2025
eea3493
fix: fix the build
salimtb Mar 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 38 additions & 25 deletions app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -2414,12 +2414,7 @@ export default class MetamaskController extends EventEmitter {
}

triggerNetworkrequests() {
this.txController.stopIncomingTransactionPolling();

this.txController.startIncomingTransactionPolling([
this.#getGlobalChainId(),
]);

this.#restartSmartTransactionPoller();
this.tokenDetectionController.enable();
this.getInfuraFeatureFlags();
}
Expand Down Expand Up @@ -2781,20 +2776,9 @@ export default class MetamaskController extends EventEmitter {
'PreferencesController:stateChange',
previousValueComparator(async (prevState, currState) => {
const { currentLocale } = currState;
const chainId = this.#getGlobalChainId();
this.#restartSmartTransactionPoller();

await updateCurrentLocale(currentLocale);

if (currState.incomingTransactionsPreferences?.[chainId]) {
this.txController.stopIncomingTransactionPolling();

this.txController.startIncomingTransactionPolling([
this.#getGlobalChainId(),
]);
} else {
this.txController.stopIncomingTransactionPolling();
}

this.#checkTokenListPolling(currState, prevState);
}, this.preferencesController.state),
);
Expand Down Expand Up @@ -2949,15 +2933,22 @@ export default class MetamaskController extends EventEmitter {
this.controllerMessenger.subscribe(
'NetworkController:networkDidChange',
async () => {
await this.txController.stopIncomingTransactionPolling();
const filteredChainIds = this.#getAllAddedNetworks().filter(
(networkId) =>
this.preferencesController.state.incomingTransactionsPreferences[
networkId
],
);

await this.txController.updateIncomingTransactions([
this.#getGlobalChainId(),
]);
if (filteredChainIds.length > 0) {
await this.txController.stopIncomingTransactionPolling();

await this.txController.startIncomingTransactionPolling([
this.#getGlobalChainId(),
]);
await this.txController.updateIncomingTransactions(filteredChainIds);

await this.txController.startIncomingTransactionPolling(
filteredChainIds,
);
}
},
);

Expand Down Expand Up @@ -8156,6 +8147,28 @@ export default class MetamaskController extends EventEmitter {
return globalNetworkClient.configuration.chainId;
}

#getAllAddedNetworks() {
const networksConfig =
this.networkController.state.networkConfigurationsByChainId;
const chainIds = Object.keys(networksConfig);

return chainIds;
}

#restartSmartTransactionPoller() {
const filteredChainIds = this.#getAllAddedNetworks().filter(
(networkId) =>
this.preferencesController.state.incomingTransactionsPreferences[
networkId
],
);

if (filteredChainIds.length > 0) {
this.txController.stopIncomingTransactionPolling();
this.txController.startIncomingTransactionPolling(filteredChainIds);
}
}

/**
* @deprecated Avoid new references to the global network.
* Will be removed once multi-chain support is fully implemented.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@
"@metamask/scure-bip39": "^2.0.3",
"@metamask/selected-network-controller": "^19.0.0",
"@metamask/signature-controller": "^26.0.0",
"@metamask/smart-transactions-controller": "^16.1.0",
"@metamask/smart-transactions-controller": "^16.2.0",
"@metamask/snaps-controllers": "^11.0.0",
"@metamask/snaps-execution-environments": "^7.0.0",
"@metamask/snaps-rpc-methods": "^12.0.0",
Expand Down
2 changes: 1 addition & 1 deletion test/data/transaction-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@
"status": "confirmed",
"originalGasEstimate": "0x118e0",
"userEditedGasLimit": false,
"chainId": "0x5",
"chainId": "0x1",
"loadingDefaults": false,
"dappSuggestedGasFees": {
"maxPriorityFeePerGas": "0x3B9ACA00",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { MetaMetricsEventCategory } from '../../../../shared/constants/metametri
import { getURLHostName } from '../../../helpers/utils/util';
import { NETWORKS_ROUTE } from '../../../helpers/constants/routes';
import { COPY_OPTIONS } from '../../../../shared/constants/copy';
import { CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP } from '../../../../shared/constants/network';

export default class TransactionListItemDetails extends PureComponent {
static contextTypes = {
Expand All @@ -50,7 +51,6 @@ export default class TransactionListItemDetails extends PureComponent {
recipientAddress: PropTypes.string,
recipientName: PropTypes.string,
recipientMetadataName: PropTypes.string,
rpcPrefs: PropTypes.object,
senderAddress: PropTypes.string.isRequired,
tryReverseResolveAddress: PropTypes.func.isRequired,
senderNickname: PropTypes.string.isRequired,
Expand All @@ -60,6 +60,8 @@ export default class TransactionListItemDetails extends PureComponent {
showErrorBanner: PropTypes.bool,
history: PropTypes.object,
blockExplorerLinkText: PropTypes.object,
chainId: PropTypes.string,
networkConfiguration: PropTypes.object,
};

state = {
Expand All @@ -69,11 +71,22 @@ export default class TransactionListItemDetails extends PureComponent {
handleBlockExplorerClick = () => {
const {
transactionGroup: { primaryTransaction },
rpcPrefs,
networkConfiguration,
isCustomNetwork,
history,
onClose,
chainId,
} = this.props;
const blockExplorerUrl =
networkConfiguration?.[chainId]?.blockExplorerUrls[
networkConfiguration?.[chainId]?.defaultBlockExplorerUrlIndex
];

const rpcPrefs = {
blockExplorerUrl,
imageUrl: CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[chainId],
};

const blockExplorerLink = getBlockExplorerLink(
primaryTransaction,
rpcPrefs,
Expand Down Expand Up @@ -300,6 +313,7 @@ export default class TransactionListItemDetails extends PureComponent {
transaction={transaction}
primaryCurrency={primaryCurrency}
className="transaction-list-item-details__transaction-breakdown"
chainId={chainId}
/>
{transactionGroup.initialTransaction.type !==
TransactionType.incoming && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
getMetadataContractName,
getInternalAccounts,
} from '../../../selectors';
import { getNetworkConfigurationsByChainId } from '../../../../shared/modules/selectors/networks';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
import TransactionListItemDetails from './transaction-list-item-details.component';

Expand All @@ -39,10 +40,12 @@ const mapStateToProps = (state, ownProps) => {
};
const rpcPrefs = getRpcPrefsForCurrentProvider(state);

const networkConfiguration = getNetworkConfigurationsByChainId(state);
const isCustomNetwork = getIsCustomNetwork(state);

return {
rpcPrefs,
networkConfiguration,
recipientEns,
senderNickname: getNickName(senderAddress),
recipientNickname: recipientAddress ? getNickName(recipientAddress) : null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default function SmartTransactionListItem({
smartTransaction,
transactionGroup,
isEarliestNonce = false,
chainId,
}) {
const dispatch = useDispatch();
const [cancelSwapLinkClicked, setCancelSwapLinkClicked] = useState(false);
Expand Down Expand Up @@ -128,6 +129,7 @@ export default function SmartTransactionListItem({
shouldShowTooltip={false}
/>
)}
chainId={chainId}
/>
)}
</>
Expand All @@ -138,4 +140,5 @@ SmartTransactionListItem.propTypes = {
smartTransaction: PropTypes.object.isRequired,
isEarliestNonce: PropTypes.bool,
transactionGroup: PropTypes.object,
chainId: PropTypes.string,
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useHistory } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';

import {
CHAIN_IDS,
TransactionStatus,
TransactionType,
} from '@metamask/transaction-controller';
Expand Down Expand Up @@ -48,11 +49,7 @@ import {
TransactionModalContextProvider,
useTransactionModalContext,
} from '../../../contexts/transaction-modal';
import {
checkNetworkAndAccountSupports1559,
getCurrentNetwork,
getTestNetworkBackgroundColor,
} from '../../../selectors';
import { checkNetworkAndAccountSupports1559 } from '../../../selectors';
import { isLegacyTransaction } from '../../../helpers/utils/transactions.util';
import { formatDateWithYearContext } from '../../../helpers/utils/util';
import Button from '../../ui/button';
Expand All @@ -69,11 +66,16 @@ import {
FINAL_NON_CONFIRMED_STATUSES,
} from '../../../hooks/bridge/useBridgeTxHistoryData';
import BridgeActivityItemTxSegments from '../../../pages/bridge/transaction-details/bridge-activity-item-tx-segments';
import {
CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP,
NETWORK_TO_NAME_MAP,
} from '../../../../shared/constants/network';

function TransactionListItemInner({
transactionGroup,
setEditGasMode,
isEarliestNonce = false,
chainId,
}) {
const t = useI18nContext();
const history = useHistory();
Expand All @@ -84,7 +86,6 @@ function TransactionListItemInner({
const [showRetryEditGasPopover, setShowRetryEditGasPopover] = useState(false);
const { supportsEIP1559 } = useGasFeeContext();
const { openModal } = useTransactionModalContext();
const testNetworkBackgroundColor = useSelector(getTestNetworkBackgroundColor);
const isSmartTransaction = useSelector(getIsSmartTransaction);
const dispatch = useDispatch();

Expand All @@ -97,6 +98,17 @@ function TransactionListItemInner({
isEarliestNonce,
});

const getTestNetworkBackgroundColor = (networkId) => {
switch (true) {
case networkId === CHAIN_IDS.GOERLI:
return BackgroundColor.goerli;
case networkId === CHAIN_IDS.SEPOLIA:
return BackgroundColor.sepolia;
default:
return undefined;
}
};

const {
initialTransaction: { id },
primaryTransaction: { error, status },
Expand Down Expand Up @@ -247,7 +259,6 @@ function TransactionListItemInner({
retryTransaction,
cancelTransaction,
]);
const currentChain = useSelector(getCurrentNetwork);
const showCancelButton =
!hasCancelled && isPending && !isUnapproved && !isSubmitting && !isBridgeTx;

Expand All @@ -271,10 +282,10 @@ function TransactionListItemInner({
className="activity-tx__network-badge"
data-testid="activity-tx-network-badge"
size={AvatarNetworkSize.Xs}
name={currentChain?.nickname}
src={currentChain?.rpcPrefs?.imageUrl}
name={NETWORK_TO_NAME_MAP[chainId]}
src={CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[chainId]}
borderColor={BackgroundColor.backgroundDefault}
backgroundColor={testNetworkBackgroundColor}
backgroundColor={getTestNetworkBackgroundColor(chainId)}
/>
}
>
Expand Down Expand Up @@ -374,6 +385,7 @@ function TransactionListItemInner({
shouldShowTooltip={false}
/>
)}
chainId={chainId}
/>
)}
{!supportsEIP1559 && showRetryEditGasPopover && (
Expand All @@ -398,6 +410,7 @@ TransactionListItemInner.propTypes = {
transactionGroup: PropTypes.object.isRequired,
isEarliestNonce: PropTypes.bool,
setEditGasMode: PropTypes.func,
chainId: PropTypes.string,
};

const TransactionListItem = (props) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`TransactionList renders TransactionList component correctly 1`] = `
<div>
<div
class="mm-box transaction-list"
>
<div
class="mm-box mm-box--margin-right-2 mm-box--margin-left-2 mm-box--justify-content-flex-start"
>
<button
class="mm-box mm-text mm-button-base mm-button-base--size-sm mm-button-base--disabled mm-button-base--ellipsis asset-list-control-bar__button asset-list-control-bar__network_control mm-text--body-md-medium mm-text--ellipsis mm-box--margin-right-2 mm-box--padding-0 mm-box--padding-right-4 mm-box--padding-left-4 mm-box--display-inline-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-default mm-box--rounded-pill"
data-testid="sort-by-popover-toggle"
disabled=""
>
<span
class="mm-box mm-text mm-text--inherit mm-text--ellipsis mm-box--color-text-default"
>
Goerli
</span>
<span
class="mm-box mm-icon mm-icon--size-sm mm-box--margin-inline-start-1 mm-box--display-inline-block mm-box--color-inherit"
style="mask-image: url('./images/icons/arrow-down.svg');"
/>
</button>
</div>
<div
class="mm-box transaction-list__transactions"
>
<div
class="mm-box transaction-list__completed-transactions"
/>
</div>
</div>
</div>
`;

exports[`TransactionList renders TransactionList component with props hideNetworkFilter correctly 1`] = `
<div>
<div
class="mm-box transaction-list"
>
<div
class="mm-box transaction-list__transactions"
>
<div
class="mm-box transaction-list__completed-transactions"
/>
</div>
</div>
</div>
`;
Loading
Loading