Skip to content

feat: enable hardware wallet error management for swaps.#39985

Merged
montelaidev merged 21 commits intomainfrom
feat/hardware-wallet-state-management-13
Feb 12, 2026
Merged

feat: enable hardware wallet error management for swaps.#39985
montelaidev merged 21 commits intomainfrom
feat/hardware-wallet-state-management-13

Conversation

@montelaidev
Copy link
Contributor

@montelaidev montelaidev commented Feb 11, 2026

Description

This is the 12th pr to enable the usage of hardware wallet error management for swaps. It manages the connection lifecycle, permission handling, error states, and provides a clean interface for UI components to interact with hardware wallets.

Open in GitHub Codespaces

Changelog

CHANGELOG entry: Enable hardware wallet error management for the swaps flow.

Related issues

Related to: https://consensyssoftware.atlassian.net/browse/MUL-1299?atlOrigin=eyJpIjoiZWZlYjE4M2NiOWVmNDk0N2I3MzA4MzMzZTg2M2U1YzYiLCJwIjoiaiJ9

Manual testing steps

  1. Go to swap page with a ledger account
  2. Disconnect ledger device
  3. Press connect
  4. See error.
  5. Unlock Wallet.
  6. See eth app not open
  7. Disable blind signing and see error after pressing connect
  8. At the end you will see the success modal and the account is ready.

Screenshots/Recordings

Before

After

Dapp interaction

Screen.Recording.2026-02-11.at.20.45.31.mov

Send

Screen.Recording.2026-02-11.at.10.00.29.AM.mov

Swap/Bridge

Screen.Recording.2026-02-11.at.10.01.58.AM.mov

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

Medium Risk
Touches core approval resolution/RPC error serialization and changes the bridge submission gating logic, which could affect transaction confirmation and error handling paths for hardware wallet users.

Overview
Adds hardware-wallet-aware approval resolution by normalizing resolvePendingApproval options, stripping non-ApprovalController fields, and converting hardware wallet SDK errors into serialized JsonRpcError internal errors (plus a new approveHardwareWalletTransaction helper exposed via controller actions).

Updates the Bridge/Swap CTA to gate submission on ensureDeviceReady, display a wallet-specific "Connect " label, and avoid state updates after unmount; bridge submission now detects user-rejection via structured hardware wallet RPC error data instead of string matching.

Wraps the app in HardwareWalletErrorProvider, adds the new connectHardwareDevice i18n string, and extends/adjusts unit tests and background action tests for the new hardware-wallet flows and background methods (getAppNameAndVersion, getLedgerPublicKey).

Written by Cursor Bugbot for commit 0c34fb4. This will update automatically on new commits. Configure here.

@montelaidev montelaidev requested a review from a team as a code owner February 11, 2026 13:24
@github-actions
Copy link
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.

@metamaskbot metamaskbot added the team-accounts-framework Accounts team label Feb 11, 2026
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 11, 2026

✨ Files requiring CODEOWNER review ✨

🔄 @MetaMask/swaps-engineers (6 files, +243 -22)
  • 📁 ui/
    • 📁 pages/
      • 📁 bridge/
        • 📁 hooks/
          • 📄 useSubmitBridgeTransaction.ts +7 -5
        • 📁 prepare/
          • 📄 bridge-cta-button.test.tsx +74 -0
          • 📄 bridge-cta-button.tsx +72 -17
          • 📄 bridge-transaction-settings-modal.test.tsx +29 -0
          • 📄 prepare-bridge-page.test.tsx +29 -0
          • 📄 index.test.tsx +32 -0

@montelaidev montelaidev force-pushed the feat/hardware-wallet-state-management-13 branch from d4bc609 to c96d2e3 Compare February 11, 2026 13:44
…ement-12' into feat/hardware-wallet-state-management-13
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 11, 2026

Builds ready [e2fd836]
UI Startup Metrics (1375 ± 99 ms)
PlatformBuildTypePageMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
ChromeBrowserifyStandard HomeuiStartup1375114116539914401547
load119298714429012561339
domContentLoaded118698014359112491330
domInteractive261699162371
firstPaint1446637168194250
backgroundConnect23722128313241264
firstReactRender16103441724
initialActions108114
loadScripts96375812259310301115
setupStore1263251520
numNetworkReqs231589201582
BrowserifyPower User HomeuiStartup------
load------
domContentLoaded------
domInteractive------
firstPaint------
backgroundConnect------
firstReactRender------
initialActions------
loadScripts------
setupStore------
numNetworkReqs------
WebpackStandard HomeuiStartup83168611711078691052
load714607102695760914
domContentLoaded709602101895756909
domInteractive2715152222378
firstPaint1056133649122201
backgroundConnect25174862734
firstReactRender16103951924
initialActions104112
loadScripts706600100994754907
setupStore1264361225
numNetworkReqs231595211582
WebpackPower User HomeuiStartup1314885323534013481985
load7376251449116747950
domContentLoaded7276201431115735941
domInteractive39181843236126
firstPaint1516742078195294
backgroundConnect17913174982168344
firstReactRender23173342529
initialActions102011
loadScripts7246181420113733933
setupStore1344161521
numNetworkReqs1354626142159203
FirefoxBrowserifyStandard HomeuiStartup15931360238317516361937
load13711180201714414361626
domContentLoaded13701180201014414321626
domInteractive72333275392161
firstPaint------
backgroundConnect5628190225887
firstReactRender1293831214
initialActions102012
loadScripts13451151192613914091595
setupStore166171211347
numNetworkReqs241399221786
BrowserifyPower User HomeuiStartup30092041852191331223898
load17421260654379617082436
domContentLoaded17411260654279617082436
domInteractive162371474170170412
firstPaint------
backgroundConnect42311012843135261054
firstReactRender221584122149
initialActions206122
loadScripts16981237650079316552410
setupStore14111743182138586
numNetworkReqs864118231106141
WebpackStandard HomeuiStartup------
load------
domContentLoaded------
domInteractive------
firstPaint------
backgroundConnect------
firstReactRender------
initialActions------
loadScripts------
setupStore------
numNetworkReqs------
WebpackPower User HomeuiStartup28491962906393229553620
load15961247705559916182052
domContentLoaded15961247705559916122052
domInteractive16232810158174527
firstPaint------
backgroundConnect47512560346575051104
firstReactRender23155562531
initialActions206123
loadScripts15431161702459415422007
setupStore1548777183166589
numNetworkReqs844017031100145
📊 Page Load Benchmark Results

Current Commit: e2fd836 | Date: 2/11/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.02s (±51ms) 🟡 | historical mean value: 1.04s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 714ms (±49ms) 🟢 | historical mean value: 724ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 75ms (±11ms) 🟢 | historical mean value: 78ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.02s 51ms 1000ms 1.30s 1.07s 1.30s
domContentLoaded 714ms 49ms 692ms 984ms 751ms 984ms
firstPaint 75ms 11ms 56ms 172ms 84ms 172ms
firstContentfulPaint 75ms 11ms 56ms 172ms 84ms 172ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms

Base automatically changed from feat/hardware-wallet-state-management-12 to main February 11, 2026 17:01
@montelaidev montelaidev requested review from a team as code owners February 11, 2026 17:01
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 11, 2026

Builds ready [eb61081]
UI Startup Metrics (1363 ± 95 ms)
PlatformBuildTypePageMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
ChromeBrowserifyStandard HomeuiStartup1363118117939514211500
load116998115478912171298
domContentLoaded116297615268812131295
domInteractive2716110192382
firstPaint164661259166203242
backgroundConnect23621437222237263
firstReactRender15102231720
initialActions104113
loadScripts9417651285889971070
setupStore1262941419
numNetworkReqs221589201581
BrowserifyPower User HomeuiStartup1977142010612103718133598
load11691027198317711421628
domContentLoaded11531020195117011341601
domInteractive37191963432140
firstPaint1787044791241360
backgroundConnect4462837951792327908
firstReactRender23155172336
initialActions106112
loadScripts91678117001649001328
setupStore1674481835
numNetworkReqs1154726047140202
WebpackStandard HomeuiStartup82768711841048701059
load721606110796776881
domContentLoaded716601109995772874
domInteractive2716127202378
firstPaint1076136760115194
backgroundConnect24184452735
firstReactRender14102941724
initialActions104112
loadScripts713599109794770872
setupStore1162731216
numNetworkReqs231591201582
WebpackPower User HomeuiStartup1241885274527112981733
load71061012421266931034
domContentLoaded70160512351266821023
domInteractive37171753033110
firstPaint1406443977186273
backgroundConnect16113033143160261
firstReactRender21173432327
initialActions103111
loadScripts69860312241246801006
setupStore1243041319
numNetworkReqs1284526748153214
FirefoxBrowserifyStandard HomeuiStartup15541343205115415951907
load13461161185412513911586
domContentLoaded13451161184812513871586
domInteractive76323495492174
firstPaint------
backgroundConnect5426139205385
firstReactRender1291611213
initialActions102122
loadScripts13211137182512313641549
setupStore13667111240
numNetworkReqs2412105221788
BrowserifyPower User HomeuiStartup27672175429834129333356
load15761337256822216162067
domContentLoaded15751337256222216152067
domInteractive15336955157132480
firstPaint------
backgroundConnect301114934229358887
firstReactRender20158182128
initialActions217123
loadScripts15361319254020715821993
setupStore1349749179117634
numNetworkReqs73361573596137
WebpackStandard HomeuiStartup14891267213514715361787
load12891141154110113501506
domContentLoaded12881138154110213491506
domInteractive58272514082134
firstPaint------
backgroundConnect50241552652112
firstReactRender14114861419
initialActions102112
loadScripts1264112815119313281422
setupStore146163231135
numNetworkReqs221288171865
WebpackPower User HomeuiStartup26231967368037627853441
load15331258226925216242078
domContentLoaded15321250226525216242078
domInteractive13833605137123530
firstPaint------
backgroundConnect254481233213239760
firstReactRender2216135132329
initialActions203122
loadScripts14931231225223715712036
setupStore1578762201197605
numNetworkReqs69362253889135
📊 Page Load Benchmark Results

Current Commit: eb61081 | Date: 2/11/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.03s (±40ms) 🟡 | historical mean value: 1.05s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 714ms (±37ms) 🟢 | historical mean value: 733ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 75ms (±10ms) 🟢 | historical mean value: 80ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.03s 40ms 1.00s 1.31s 1.06s 1.31s
domContentLoaded 714ms 37ms 692ms 987ms 741ms 987ms
firstPaint 75ms 10ms 56ms 160ms 84ms 160ms
firstContentfulPaint 75ms 10ms 56ms 160ms 84ms 160ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 790 Bytes (0.02%)
  • ui: -184.32 KiB (-2.22%)
  • common: 185.41 KiB (1.7%)

@Gudahtt Gudahtt removed request for a team February 12, 2026 13:53
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

const keyringType = fromAccount?.metadata?.keyring?.type;
const detectedWalletType =
keyringTypeToHardwareWalletType(keyringType ?? '') ??
HardwareWalletType.Ledger;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unknown keyring type silently defaults to Ledger wallet

Medium Severity

When keyringTypeToHardwareWalletType returns null (unrecognized or missing keyring type), the fallback ?? HardwareWalletType.Ledger silently treats the account as a Ledger device. For non-Ledger hardware wallets with an unrecognized keyring type, this causes the wrong hardware wallet error flow to execute, potentially showing Ledger-specific error messages and connection steps to Trezor, Lattice, or QR wallet users.

Fix in Cursor Fix in Web

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 12, 2026

Builds ready [0c34fb4]
UI Startup Metrics (1398 ± 115 ms)
PlatformBuildTypePageMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
ChromeBrowserifyStandard HomeuiStartup13981184177311514731597
load12091013154010812831387
domContentLoaded1202985153410812741380
domInteractive2816100212387
firstPaint158651293137208299
backgroundConnect24322033916250270
firstReactRender17114451823
initialActions104112
loadScripts975768130210610461151
setupStore1262751520
numNetworkReqs221587201581
BrowserifyPower User HomeuiStartup17701374485034717772073
load11691055191616811441643
domContentLoaded11521049179115811291618
domInteractive3818215313595
firstPaint1776968599237343
backgroundConnect3532863090277337386
firstReactRender23155272539
initialActions107112
loadScripts90780315001518921348
setupStore1555471623
numNetworkReqs1154725447136220
WebpackStandard HomeuiStartup82368011001039001022
load71360798091757912
domContentLoaded70860397591750905
domInteractive251688172273
firstPaint1066028449128186
backgroundConnect26176183044
firstReactRender14102741823
initialActions102111
loadScripts70560197390747903
setupStore1162841117
numNetworkReqs231588201584
WebpackPower User HomeuiStartup1235874174517113231534
load71463011371107061001
domContentLoaded7056251121109695996
domInteractive37182713533110
firstPaint1316951181142266
backgroundConnect1578530635157246
firstReactRender22174132428
initialActions102011
loadScripts7026231110107693987
setupStore1244261320
numNetworkReqs1154628750141225
FirefoxBrowserifyStandard HomeuiStartup15471353225018415671911
load13351159202714513861601
domContentLoaded13341155202214513841597
domInteractive65332894585136
firstPaint------
backgroundConnect5728173225989
firstReactRender12102421313
initialActions103112
loadScripts13091137199914113601575
setupStore136173181330
numNetworkReqs231288201783
BrowserifyPower User HomeuiStartup27802249384735229013559
load15671302231523616152186
domContentLoaded15661302231423616152182
domInteractive13436693135118455
firstPaint------
backgroundConnect3111091065265296911
firstReactRender211568102028
initialActions217122
loadScripts15261238229123315492145
setupStore1818891240180742
numNetworkReqs68341473296125
WebpackStandard HomeuiStartup15871326215214516501866
load13741162174510714441568
domContentLoaded13731162174510714431567
domInteractive772821545113145
firstPaint------
backgroundConnect5022144205696
firstReactRender15115471424
initialActions104122
loadScripts13501149168910414211536
setupStore156157211141
numNetworkReqs231287191777
WebpackPower User HomeuiStartup28541938825189929663773
load16521256638972216872312
domContentLoaded16521255638972316872312
domInteractive13130790161108623
firstPaint------
backgroundConnect301871302241299871
firstReactRender22167582430
initialActions217123
loadScripts16101239636271616672128
setupStore1718793219192655
numNetworkReqs65341573393123
📊 Page Load Benchmark Results

Current Commit: 0c34fb4 | Date: 2/12/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.03s (±43ms) 🟡 | historical mean value: 1.04s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 717ms (±39ms) 🟢 | historical mean value: 728ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 76ms (±12ms) 🟢 | historical mean value: 79ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.03s 43ms 1.00s 1.35s 1.05s 1.35s
domContentLoaded 717ms 39ms 692ms 1.00s 734ms 1.00s
firstPaint 76ms 12ms 60ms 184ms 84ms 184ms
firstContentfulPaint 76ms 12ms 60ms 184ms 84ms 184ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 3.49 KiB (0.08%)
  • ui: -184.03 KiB (-2.22%)
  • common: 190.97 KiB (1.75%)

@montelaidev montelaidev added this pull request to the merge queue Feb 12, 2026
Merged via the queue into main with commit 38ad3ee Feb 12, 2026
176 checks passed
@montelaidev montelaidev deleted the feat/hardware-wallet-state-management-13 branch February 12, 2026 14:59
@github-actions github-actions bot locked and limited conversation to collaborators Feb 12, 2026
@metamaskbot metamaskbot added the release-13.19.0 Issue or pull request that will be included in release 13.19.0 label Feb 12, 2026
import { createSentryError } from '../../shared/modules/error';
import {
toHardwareWalletError,
// eslint-disable-next-line import/no-restricted-paths
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not ok.

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

Labels

release-13.19.0 Issue or pull request that will be included in release 13.19.0 size-L team-accounts-framework Accounts team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants