Skip to content

fix(swaps): fix stale search results after network filter change cp-13.39.0 - #44194

Merged
SteP-n-s merged 2 commits into
mainfrom
fix/picker_network_switching
Jul 6, 2026
Merged

fix(swaps): fix stale search results after network filter change cp-13.39.0#44194
SteP-n-s merged 2 commits into
mainfrom
fix/picker_network_switching

Conversation

@SteP-n-s

@SteP-n-s SteP-n-s commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Description

When changing the network filter in the bridge asset picker with an active search query, token search stopped refetching after several network switches. The list stayed mounted (network management UX from #43453), but useTokenSearchResults only re-ran its fetch effect when searchQuery, stableMinimalAssetsString, or jwt changed - not when chainIds changed.

Once stableMinimalAssetsString stopped changing (e.g. no owned tokens matching the query on the selected networks), further network changes did not trigger new /getTokens/search requests, leaving stale results.

This PR adds chainIds to the refetch effect dependencies so search runs again whenever the network filter changes, without remounting the asset list or re-fetching popular/local tokens. A regression test covers the case where chainIds changes but stableMinimalAssetsString does not.

Changelog

CHANGELOG entry: Fixed bridge asset picker search not updating after changing the network filter while a search query is active.

Related issues

Fixes: #44145

Manual testing steps

  1. Go to this bridge screen
  2. Open the asset picker modal
  3. Type a search query
  4. Update networks until you stop seeing content being updated

Screenshots/Recordings

Before

After

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Note

Low Risk
Small React hook dependency fix in bridge UI search with targeted unit test coverage; no auth, payments, or persistence changes.

Overview
Fixes stale bridge asset picker search results when users change the network filter while a search query is still active.

useTokenSearchResults now includes chainIds in the effect that resets state and triggers the debounced /getTokens/search fetch. Previously that effect only depended on searchQuery, stableMinimalAssetsString, and jwt, so after several network switches—especially when owned assets no longer matched the query and stableMinimalAssetsString stopped changing—no new search ran and the list could show outdated tokens.

A unit test asserts that rerendering with a new chainIds set (same query, empty assetsToInclude) calls fetchTokensBySearchQuery again with the updated chains.

Reviewed by Cursor Bugbot for commit 176bc86. Bugbot is set up for automated code reviews on this repo. Configure here.

@SteP-n-s
SteP-n-s requested a review from a team as a code owner July 6, 2026 12:23
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamask-ci metamask-ci Bot added the team-swaps-and-bridge Swaps and Bridge team label Jul 6, 2026
@metamask-ci

metamask-ci Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

✨ Files requiring CODEOWNER review ✨

🔄 @MetaMask/swaps-engineers (2 files, +79 -1)
  • 📁 ui/
    • 📁 hooks/
      • 📁 bridge/
        • 📄 useTokenSearchResults.test.ts +78 -0
        • 📄 useTokenSearchResults.ts +1 -1

@SteP-n-s SteP-n-s changed the title fix(swaps): fix stale search results after network filter change fix(swaps): fix stale search results after network filter change cp-13.39.0 Jul 6, 2026
@github-actions github-actions Bot added the size-S label Jul 6, 2026
@metamask-ci

metamask-ci Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor
Builds ready [89acab3]
Deprecated Browserify fallback builds
⚡ Performance Benchmarks (Total: 🟢 16 pass · 🟡 9 warn · 🔴 0 fail)

Baseline (latest main): 1716549 | Date: 6/29/2026 | Pipeline: 28791245897 | Baseline logs

Interaction Benchmarks · Samples: 5
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
confirmTx
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • loadNewAccount/load_new_account: -20%
  • loadNewAccount/total: -20%
  • loadNewAccount/inp: -18%
  • bridgeUserActions/bridge_load_page: -33%
  • bridgeUserActions/bridge_load_asset_picker: -28%
  • bridgeUserActions/longTaskCount: -17%
  • bridgeUserActions/longTaskTotalDuration: -32%
  • bridgeUserActions/longTaskMaxDuration: -24%
  • bridgeUserActions/tbt: -57%
  • bridgeUserActions/inp: -14%
  • loadNewAccount/inp: -18%
  • loadNewAccount/lcp: +1057%
  • confirmTx/longTaskCount: -100%
  • confirmTx/longTaskTotalDuration: -100%
  • confirmTx/longTaskMaxDuration: -100%
  • confirmTx/tbt: -100%
  • confirmTx/lcp: +1031%
  • bridgeUserActions/bridge_load_page: +95%
  • bridgeUserActions/bridge_load_asset_picker: +29%
  • bridgeUserActions/longTaskCount: -100%
  • bridgeUserActions/longTaskTotalDuration: -100%
  • bridgeUserActions/longTaskMaxDuration: -100%
  • bridgeUserActions/tbt: -100%
  • bridgeUserActions/total: +13%
  • bridgeUserActions/inp: -22%
  • bridgeUserActions/fcp: -48%
  • bridgeUserActions/lcp: +1171%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 loadNewAccount/FCP: p75 1.8s
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
🟡 loadScripts
startupPowerUserHome
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • startupStandardHome/uiStartup: +13%
  • startupStandardHome/load: +13%
  • startupStandardHome/domContentLoaded: +13%
  • startupStandardHome/domInteractive: +74%
  • startupStandardHome/backgroundConnect: +13%
  • startupStandardHome/firstReactRender: +13%
  • startupStandardHome/loadScripts: +14%
  • startupStandardHome/setupStore: +23%
  • startupStandardHome/fcp: +70%
  • startupStandardHome/lcp: +14%
  • startupPowerUserHome/domInteractive: +26%
  • startupPowerUserHome/backgroundConnect: +56%
  • startupPowerUserHome/inp: -16%
  • startupPowerUserHome/fcp: +24%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🔴 startupPowerUserHome/INP: p75 536ms
  • 🟡 startupPowerUserHome/LCP: p75 3.7s
User Journey Benchmarks · Samples: 5 · mock API
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
🟡 total
assetDetails
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
importSrpHome
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • onboardingImportWallet/metricsToWalletReadyScreen: -17%
  • onboardingImportWallet/doneButtonToHomeScreen: -86%
  • onboardingImportWallet/openAccountMenuToAccountListLoaded: -97%
  • onboardingImportWallet/longTaskCount: -60%
  • onboardingImportWallet/longTaskTotalDuration: -87%
  • onboardingImportWallet/longTaskMaxDuration: -90%
  • onboardingImportWallet/tbt: -98%
  • onboardingImportWallet/total: -85%
  • onboardingNewWallet/createPwToRecoveryScreen: +16%
  • onboardingNewWallet/skipBackupToMetricsScreen: +17%
  • onboardingNewWallet/agreeButtonToOnboardingSuccess: +21%
  • onboardingNewWallet/doneButtonToAssetList: -10%
  • onboardingNewWallet/longTaskTotalDuration: -37%
  • onboardingNewWallet/longTaskMaxDuration: -15%
  • onboardingNewWallet/tbt: -33%
  • solanaAssetDetails/assetClickToPriceChart: -68%
  • solanaAssetDetails/total: -68%
  • solanaAssetDetails/inp: -17%
  • solanaAssetDetails/cls: +1620%
  • importSrpHome/homeAfterImportWithNewWallet: -24%
  • importSrpHome/longTaskCount: -19%
  • importSrpHome/longTaskTotalDuration: -25%
  • importSrpHome/longTaskMaxDuration: -22%
  • importSrpHome/tbt: -29%
  • importSrpHome/total: -15%
  • importSrpHome/inp: -36%
  • importSrpHome/lcp: -56%
  • importSrpHome/cls: -47%
  • sendTransactions/openSendPageFromHome: -23%
  • sendTransactions/selectTokenToSendFormLoaded: -47%
  • sendTransactions/reviewTransactionToConfirmationPage: +20%
  • sendTransactions/longTaskCount: -20%
  • sendTransactions/longTaskTotalDuration: -27%
  • sendTransactions/longTaskMaxDuration: -12%
  • sendTransactions/tbt: -62%
  • sendTransactions/total: +19%
  • sendTransactions/inp: -11%
  • sendTransactions/lcp: -14%
  • sendTransactions/cls: -40%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 assetDetails/FCP: p75 1.8s
  • 🟡 solanaAssetDetails/FCP: p75 1.9s
  • 🟡 importSrpHome/FCP: p75 1.8s
  • 🟡 sendTransactions/FCP: p75 2.3s
  • 🟡 sendTransactions/LCP: p75 2.5s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 71.38 KiB (0.65%)
  • ui: 42.33 KiB (0.24%)
  • common: 0 Bytes (0%)
  • other: 0 Bytes (0%)
  • contentScripts: 726 Bytes (0.04%)
  • zip: 33.16 KiB (0.12%)

@sonarqubecloud

sonarqubecloud Bot commented Jul 6, 2026

Copy link
Copy Markdown

@metamask-ci

metamask-ci Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor
Builds ready [176bc86]
Deprecated Browserify fallback builds
⚡ Performance Benchmarks (Total: 🟢 17 pass · 🟡 8 warn · 🔴 0 fail)

Baseline (latest main): 1716549 | Date: 6/29/2026 | Pipeline: 28816841046 | Baseline logs

Interaction Benchmarks · Samples: 5
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
confirmTx
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • loadNewAccount/load_new_account: -22%
  • loadNewAccount/total: -22%
  • bridgeUserActions/bridge_load_page: -11%
  • bridgeUserActions/longTaskCount: -17%
  • bridgeUserActions/longTaskTotalDuration: -21%
  • bridgeUserActions/longTaskMaxDuration: -12%
  • bridgeUserActions/tbt: -29%
  • loadNewAccount/load_new_account: +76%
  • loadNewAccount/total: +76%
  • loadNewAccount/inp: -26%
  • loadNewAccount/lcp: +1096%
  • confirmTx/confirm_tx: +10%
  • confirmTx/longTaskCount: -100%
  • confirmTx/longTaskTotalDuration: -100%
  • confirmTx/longTaskMaxDuration: -100%
  • confirmTx/tbt: -100%
  • confirmTx/total: +10%
  • confirmTx/fcp: -44%
  • confirmTx/lcp: +1096%
  • bridgeUserActions/bridge_load_page: +54%
  • bridgeUserActions/bridge_load_asset_picker: +78%
  • bridgeUserActions/longTaskCount: -100%
  • bridgeUserActions/longTaskTotalDuration: -100%
  • bridgeUserActions/longTaskMaxDuration: -100%
  • bridgeUserActions/tbt: -100%
  • bridgeUserActions/total: +13%
  • bridgeUserActions/inp: -14%
  • bridgeUserActions/fcp: -47%
  • bridgeUserActions/lcp: +1151%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 loadNewAccount/FCP: p75 1.9s
  • 🟡 loadNewAccount/FCP: p75 1.9s
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
startupPowerUserHome
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • startupStandardHome/numNetworkReqs: +50%
  • startupPowerUserHome/initialActions: +33%
  • startupStandardHome/firstReactRender: +13%
  • startupStandardHome/setupStore: +16%
  • startupStandardHome/fcp: +12%
  • startupPowerUserHome/backgroundConnect: +14%
  • startupPowerUserHome/inp: -27%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🔴 startupPowerUserHome/INP: p75 544ms
  • 🟡 startupPowerUserHome/LCP: p75 3.6s
User Journey Benchmarks · Samples: 5 · mock API
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
🟡 total
assetDetails
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
importSrpHome
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • onboardingImportWallet/srpButtonToSrpForm: +23%
  • onboardingImportWallet/doneButtonToHomeScreen: -86%
  • onboardingImportWallet/openAccountMenuToAccountListLoaded: -95%
  • onboardingImportWallet/longTaskCount: -80%
  • onboardingImportWallet/longTaskTotalDuration: -94%
  • onboardingImportWallet/longTaskMaxDuration: -92%
  • onboardingImportWallet/tbt: -100%
  • onboardingImportWallet/total: -85%
  • onboardingNewWallet/skipBackupToMetricsScreen: +16%
  • onboardingNewWallet/doneButtonToAssetList: -34%
  • onboardingNewWallet/longTaskCount: -50%
  • onboardingNewWallet/longTaskTotalDuration: -65%
  • onboardingNewWallet/longTaskMaxDuration: -38%
  • onboardingNewWallet/tbt: -80%
  • onboardingNewWallet/total: -27%
  • solanaAssetDetails/assetClickToPriceChart: -38%
  • solanaAssetDetails/total: -38%
  • solanaAssetDetails/cls: +1620%
  • importSrpHome/loginToHomeScreen: -16%
  • importSrpHome/openAccountMenuAfterLogin: -10%
  • importSrpHome/homeAfterImportWithNewWallet: -36%
  • importSrpHome/longTaskCount: -44%
  • importSrpHome/longTaskTotalDuration: -42%
  • importSrpHome/longTaskMaxDuration: -28%
  • importSrpHome/tbt: -39%
  • importSrpHome/total: -30%
  • importSrpHome/inp: -24%
  • importSrpHome/lcp: -54%
  • importSrpHome/cls: -47%
  • sendTransactions/openSendPageFromHome: -31%
  • sendTransactions/selectTokenToSendFormLoaded: -54%
  • sendTransactions/reviewTransactionToConfirmationPage: +27%
  • sendTransactions/longTaskCount: -20%
  • sendTransactions/longTaskTotalDuration: -12%
  • sendTransactions/tbt: +28%
  • sendTransactions/total: +26%
  • sendTransactions/inp: -19%
  • sendTransactions/fcp: -11%
  • sendTransactions/cls: -40%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 assetDetails/FCP: p75 1.9s
  • 🟡 solanaAssetDetails/FCP: p75 1.9s
  • 🟡 importSrpHome/FCP: p75 1.8s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 71.59 KiB (0.65%)
  • ui: 58.46 KiB (0.34%)
  • common: 0 Bytes (0%)
  • other: 0 Bytes (0%)
  • contentScripts: 940 Bytes (0.05%)
  • zip: 37.83 KiB (0.14%)

@SteP-n-s
SteP-n-s added this pull request to the merge queue Jul 6, 2026
Merged via the queue into main with commit 767bc86 Jul 6, 2026
205 of 207 checks passed
@SteP-n-s
SteP-n-s deleted the fix/picker_network_switching branch July 6, 2026 21:42
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 6, 2026
@metamaskbot metamaskbot added the release-13.40.0 Issue or pull request that will be included in release 13.40.0 label Jul 6, 2026
@MajorLift

MajorLift commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

🧪 Validation Run

Verdict: ✅ the regression test has power over the dependency fix — Claim: search refetches when the network filter changes, because chainIds was added to the effect's dependencies. head 767bc86afeb · 2026-08-02 · falsifying-test check

Note

Trial run of the MetaMask evidence skills
feedback welcome, on the finding or on whether this format is useful to a reviewer.
Not a review verdict; nothing here blocks the PR.

The fix is one entry in a dependency array at useTokenSearchResults.ts#L154. Removing chainIds from it and re-running in CI is what distinguishes a test that covers the regression from one that happens to pass alongside it.

Falsification probe — falsifying

Arm Mutation Result
A — baseline none Test Suites: 1 passed, 1 total Tests: 3 passed, 3 total
B — mutant ui/hooks/bridge/useTokenSearchResults.ts:154 replaced Test Suites: 1 failed, 1 total Tests: 1 failed, 2 passed, 3 total

The suite fails when the mechanism is removed and passes when restored, running the same 3 tests in both arms. The test has power.

Failing under mutation:

  • ● useTokenSearchResults › refetches search results when chainIds change with the same search query

Produced by falsify-probe.sh at 767bc86afeb22d8b6b9f9a9bc92b3f509c3bd76b · node v24.13.1 · yarn.lock 5a67f92c7ce42ac0 · 0 tracked changes. Run: https://github.com/MajorLift/metamask-skills/actions/runs/30751002114 — logs and artifacts attached there.

Follows from the arm above

  • Dropping chainIds fails 1 of 3 tests — the regression test added by this change is the one that fails.
  • The other 2 keep passing and all 3 run in both arms, so the module still loads; the failure is an assertion, not a broken import.

Open for review: the hook aborts in three places — abort('Asset balances changed'), abort('Search query changed'), and one on unmount. This arm covers the dependency array, not the staleness guarantee those aborts provide; whether a superseded response can still overwrite newer state is a separate question and a separate mutation.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-13.40.0 Issue or pull request that will be included in release 13.40.0 risk:medium size-S team-swaps-and-bridge Swaps and Bridge team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Switching networks in swap screen has no effect after typing token in search

5 participants