Skip to content

chore: Refactor OAuthHydration screen with unlockWallet#24572

Merged
Cal-L merged 68 commits intomainfrom
refactor/MCWP-241-seedless-hydration
Jan 23, 2026
Merged

chore: Refactor OAuthHydration screen with unlockWallet#24572
Cal-L merged 68 commits intomainfrom
refactor/MCWP-241-seedless-hydration

Conversation

@Cal-L
Copy link
Copy Markdown
Contributor

@Cal-L Cal-L commented Jan 15, 2026

Description

This is part of the effort to consolidate and refactor areas calling userEntryAuth or appTriggeredAuth. This PR refactors the OAuthHydration screen to replace appTriggeredAuth with unlockWallet.

Changelog

CHANGELOG entry:

Related issues

Fixes:

Manual testing steps

While using seedless onboarding and global password is outdated

  • On extension, change seedless password
  • On mobile, attempt login with old password
  • Should get navigated to OAuthRehydration
  • Upon correct password entry, navigates to wallet screen

While first onboarding with seedless onboarding on mobile, with existing account on extension

  • Seedless onboarding wallet should already be created on extension
  • On fresh mobile install, use seedless onboarding with the same account
  • Should get navigated to OAuthRehydration
  • Upon correct password entry, navigates to wallet screen

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

Modernizes authentication flows and centralizes logic via useAuthentication.

  • Replace Authentication.userEntryAuth/appTriggeredAuth with useAuthentication.unlockWallet in Login and OAuthRehydration
  • Update auth preference resolution to componentAuthenticationType; remove password requirement pre-checks and resetPassword side effects
  • Improve error handling: use containsErrorMessage, treat SeedlessOnboardingControllerError via navigation to REHYDRATE, handle biometric cancellations, vault corruption, passcode-not-set, and seedless-specific errors (incorrect password, too many attempts, password recently updated)
  • Initialize OAuthRehydration error state from isSeedlessPasswordOutdated and streamline loading/biometry flags
  • Adjust analytics/tracing calls and navigation (e.g., defer login attempts to rehydration flow)
  • Overhaul tests to mock useAuthentication, cover new seedless cases, offline handling, and error sanitization

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

Cal-L added 30 commits December 11, 2025 20:59
mockAlert.mockRestore();
});

it('navigates to rehydrate screen when seedless onboarding error is detected', async () => {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Add unit test for ensuring that Login will navigate to OAuthRehydration whenever it encounters seedless onboarding errors

const [rehydrationFailedAttempts, setRehydrationFailedAttempts] = useState(0);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(
isSeedlessPasswordOutdated
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Since isSeedlessPasswordOutdated is available, we can just set the error message by default

});

try {
const locked = !passwordRequirementsMet(password);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Since the purpose of this is to log in, we do not want to show users a password requirement error

op: TraceOperation.Login,
},
async () => {
await Authentication.userEntryAuth(password, authType);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Replace userEntryAuth with unlockWallet

endTrace({ name: TraceName.OnboardingExistingSocialLogin });
endTrace({ name: TraceName.OnboardingJourneyOverall });

await navigateToHome();
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

unlockWallet navigates to home automatically


const newGlobalPasswordLogin = useCallback(async () => {
try {
const locked = !passwordRequirementsMet(password);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Same comment on removing the password requirement message

op: TraceOperation.Login,
},
async () => {
await Authentication.userEntryAuth(password, authType);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Replace userEntryAuth with unlockWallet

}, [route.params?.onboardingTraceCtx]);

// Handle password outdated state
useEffect(() => {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Remove the need to auto clear credentials. We want to avoid clearing credentials by itself unless absolutely needed since this risks throwing the credential dependencies out of sync. If we need to clear credentials, it's safer to ensure that all necessary states are being reset together. In a happy path, by removing this reset, UX would remain the same and the credentials will eventually be reset by successfully unlocking the wallet.

cursor[bot]

This comment was marked as outdated.

@Cal-L
Copy link
Copy Markdown
Contributor Author

Cal-L commented Jan 23, 2026

Synced with CW (@ieow) on this flow and agreed on sending users to the OAuthRehydration screen when any seedless onboarding error is encountered. I also mentioned that we removed the reset password here

Copy link
Copy Markdown

@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.

// Arrange
(Authentication.userEntryAuth as jest.Mock).mockRejectedValue(
new Error('Error: Decrypt failed'),
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Test passes for wrong reason after validation removal

Low Severity

The test "prevents login when password is too short" now passes for the wrong reason. The PR removed the passwordRequirementsMet validation, so short passwords are now allowed to be submitted to unlockWallet. The test asserts mockReplace is not called, which is true - but only because the component no longer calls navigation.replace() directly (navigation is now handled by unlockWallet). Login actually proceeds with the short password; the test title is misleading and should be removed or updated to reflect the new behavior.

Fix in Cursor Fix in Web

@Cal-L Cal-L enabled auto-merge January 23, 2026 20:14
@github-actions
Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeAccounts
  • Risk Level: medium
  • AI Confidence: 75%
click to see 🤖 AI reasoning details

The changes modify the Login and OAuthRehydration views, which handle authentication flows. The key changes are:

  1. Login/index.tsx: Changed error detection for seedless onboarding errors from string matching (containsErrorMessage(loginError, SeedlessOnboardingControllerErrorMessage.IncorrectPassword)) to using instanceof SeedlessOnboardingControllerError. This is a more robust error handling approach.

  2. OAuthRehydration/index.tsx: Refactored to use the useAuthentication hook instead of directly calling Authentication.userEntryAuth() and Authentication.componentAuthenticationType(). Also removed password requirements validation before login attempt, and improved error message handling.

These are internal refactoring changes that don't modify UI elements or test IDs. The E2E tests that interact with the Login screen (change-password.spec.ts, auto-lock.spec.ts) use the SmokeAccounts tag. Running SmokeAccounts tests will verify that:

  • Password entry and login still work correctly
  • App locking and unlocking behavior is preserved
  • Account management after login works as expected

The risk is medium because while the changes are refactoring, they touch core authentication logic that could affect login behavior. The unit tests have been updated to cover the new behavior, but E2E validation of the login flow is prudent.

View GitHub Actions results

@sonarqubecloud
Copy link
Copy Markdown

@Cal-L Cal-L added this pull request to the merge queue Jan 23, 2026
Merged via the queue into main with commit 1717139 Jan 23, 2026
232 of 253 checks passed
@Cal-L Cal-L deleted the refactor/MCWP-241-seedless-hydration branch January 23, 2026 22:02
@github-project-automation github-project-automation bot moved this from Review finalised - Ready to be merged to Merged, Closed or Archived in PR review queue Jan 23, 2026
@github-actions github-actions bot locked and limited conversation to collaborators Jan 23, 2026
@github-actions github-actions bot removed the needs-dev-review PR needs reviews from other engineers (in order to receive required approvals) label Jan 23, 2026
@metamaskbot metamaskbot added the release-7.65.0 Issue or pull request that will be included in release 7.65.0 label Jan 23, 2026
@metamaskbot metamaskbot added release-7.64.0 Issue or pull request that will be included in release 7.64.0 and removed release-7.65.0 Issue or pull request that will be included in release 7.65.0 labels Feb 3, 2026
@metamaskbot
Copy link
Copy Markdown
Collaborator

Missing release label release-7.64.0 on PR. Adding release label release-7.64.0 on PR and removing other release labels(release-7.65.0), as PR was added to branch 7.64.0 when release was cut.

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

Labels

no changelog required No changelog entry is required for this change No QA Needed Apply this label when your PR does not need any QA effort. no-changelog no-changelog Indicates no external facing user changes, therefore no changelog documentation needed release-7.64.0 Issue or pull request that will be included in release 7.64.0 size-M team-mobile-platform Mobile Platform team

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

5 participants