Skip to content

feat: QrSyncController and integration to UI (new users flow)#32078

Draft
lwin-kyaw wants to merge 7 commits into
feat/qr-code-designfrom
feat/qr-sync-controller
Draft

feat: QrSyncController and integration to UI (new users flow)#32078
lwin-kyaw wants to merge 7 commits into
feat/qr-code-designfrom
feat/qr-sync-controller

Conversation

@lwin-kyaw

@lwin-kyaw lwin-kyaw commented Jun 19, 2026

Copy link
Copy Markdown

Summary

This PR adds QrSyncController and integration to the UI.

Each QR sync is one short-lived session: it starts when the user scans a QR code and ends when the sync completes, is cancelled, or hits an error.

User flow (simple)

  1. User opens Add Device to Wallet and scans the QR code on the browser extension.
  2. Mobile connects and shows a verification code for the user to enter in the extension.
  3. After the extension confirms the code, mobile continues the sync in the background.
  4. User sees Device added while waiting for account data from the extension.
  5. Mobile opens the import wallet step with data from the sync.
  6. Sync completes and the session closes.

If the user goes back during an active sync, mobile cancels and tells the extension.

UI ↔ Controller communication

flowchart TB
  subgraph UI["Add Device screens"]
    Main["Add Device screen"]
    OTP["OTP bottom sheet"]
    Linked["Device added screen"]
    Import["Import wallet screen"]
  end

  subgraph Controller["QrSync Controller"]
    Phase["phase"]
    OTPData["otp"]
    Error["error"]
    Review["review / import plan"]
  end

  Main -->|"User scans QR"| Controller
  Main -->|"User taps Back"| Controller
  OTP -->|"User closes sheet"| Main

  Controller -->|"selectors read state"| Main
  Controller -->|"show OTP sheet"| OTP
  Controller -->|"device-linked"| Linked
  Controller -->|"reviewing-import"| Import

  Controller <-->|"encrypted messages"| Ext["Browser extension"]
Loading

In plain terms:

  • UI → Controller: user actions (scan, back/cancel).
  • Controller → UI: current step (phase) and related data (code, errors).
  • Controller ↔ Extension: sync protocol over an encrypted connection.

The UI does not decide the step on its own. It reads the controller through selectors.

Controller phases

Phase What it means What the user sees
idle No active sync Instructions + Scan button
initializing Connecting after QR scan Loading
displaying-otp Code ready to show OTP bottom sheet
connected Extension verified the code Brief internal step
awaiting-sync-ready Waiting for account data from extension Device added (waiting)
reviewing-import Account data received Redirect to import wallet
completed Sync finished successfully Session closed
failed Something went wrong Error message (basic)

Sync flow (controller)

idle
  → initializing        (scan + connect)
  → displaying-otp      (OTP grant)
  → connected           (extension verified OTP)
  → awaiting-sync-ready (sync-offer sent)
  → reviewing-import    (sync-ready received)
  → completed           (sync-completed sent + session destroyed)

cancel / error → sync-cancel | sync-error → idle | failed + session destroyed

Main code changes

  • QrSyncPhases — named constants so UI and controller share the same step names.
  • QrSyncController — clear phase transitions, strict session lifetime, peer notification on cancel/error.
  • app/selectors/qrSyncController/ — UI reads controller state through selectors.
  • Add Device UI — removed local deviceAdded state and DeviceEventEmitter.
  • Protocol — added sync-cancel; sync-completed sent after valid sync-ready (extension not blocked on import).

Session rules

  • Session exists only between QR scan and terminal outcome.
  • No resume/reconnect: each scan starts fresh.
  • Back during active sync cancels and notifies the extension.
  • Dismissing the OTP sheet does not cancel.

Changelog

CHANGELOG entry:

Related issues

Fixes:

Manual testing steps

Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]

Screenshots/Recordings

Before

After

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production performance metrics

For performance guidelines and tooling, see the Performance Guide.

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.

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

CLA Signature Action:

Thank you for your submission, we really appreciate it. We ask that you read and sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just by adding a comment to this pull request with this exact sentence:

I have read the CLA Document and I hereby sign the CLA

By commenting with the above message you are agreeing to the terms of the CLA. Your account will be recorded as agreeing to our CLA so you don't need to sign it again for future contributions to this repository.

0 out of 1 committers have signed the CLA.
@lwin-kyaw

@socket-security

socket-security Bot commented Jun 19, 2026

Copy link
Copy Markdown

No dependency changes detected. Learn more about Socket for GitHub.

👍 No dependency changes detected in pull request

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeAccounts, SmokeConfirmations, SmokeIdentity, SmokeNetworkAbstractions, SmokeNetworkExpansion, SmokeSwap, SmokeStake, SmokeWalletPlatform, SmokeMoney, SmokePerps, SmokeMultiChainAPI, SmokePredictions, SmokeSeedlessOnboarding, SmokeBrowser, SmokeSnaps
  • Selected Performance tags: @PerformanceAccountList, @PerformanceOnboarding, @PerformanceLogin, @PerformanceSwaps, @PerformanceLaunch, @PerformanceAssetLoading, @PerformancePredict, @PerformancePreps
  • Risk Level: high
  • AI Confidence: 100%
click to see 🤖 AI reasoning details

E2E Test Selection:
Hard rule (global-infrastructure-change): Global infrastructure changed: app/core/Engine/Engine.ts. Running all tests.

Performance Test Selection:
Fallback: AI analysis did not complete successfully. Running all performance tests.

View GitHub Actions results

@github-actions

Copy link
Copy Markdown
Contributor

⚡ Performance Test Results

ℹ️ Performance test results are currently non-blocking and will not block this PR.

3 tests failed · 20 tests · 1 device

📱 Devices tested (1)

Android: Google Pixel 8 Pro (v14.0)

❌ Failed Tests (3)

@Accounts-team

Test Platform Device Reason Recording
Import SRP with +50 accounts, SRP 1, SRP 2, SRP 3 Android Google Pixel 8 Pro (v14.0) Test error 📹 Watch

@metamask-mobile-platform

Test Platform Device Reason Recording
Cold Start after importing a wallet Android Google Pixel 8 Pro (v14.0) Test error 📹 Watch

@metamask-onboarding-team

Test Platform Device Reason Recording
Account creation after fresh install Android Google Pixel 8 Pro (v14.0) Test error 📹 Watch
✅ Passed Tests (17)
Test Platform Device Duration Team Recording
Aggregated Balance Loading Time, SRP 1 + SRP 2 + SRP 3 Android Google Pixel 8 Pro (v14.0) 8.38s @assets-dev-team 📹 Watch
Asset View, SRP 1 + SRP 2 + SRP 3 Android Google Pixel 8 Pro (v14.0) 1.49s @assets-dev-team 📹 Watch
Cross-chain swap flow - ETH to SOL - 50+ accounts, SRP 1 + SRP 2 + SRP 3 Android Google Pixel 8 Pro (v14.0) 4.69s @swap-bridge-dev-team 📹 Watch
Swap flow - ETH to LINK, SRP 1 + SRP 2 + SRP 3 Android Google Pixel 8 Pro (v14.0) 2.37s @swap-bridge-dev-team 📹 Watch
Cold Start: Measure ColdStart To Login Screen Android Google Pixel 8 Pro (v14.0) 2.94s @metamask-mobile-platform 📹 Watch
Measure Warm Start: Login To Wallet Screen Android Google Pixel 8 Pro (v14.0) 1.44s @metamask-mobile-platform 📹 Watch
Measure Warm Start: Warm Start to Login Screen Android Google Pixel 8 Pro (v14.0) 1.48s @metamask-mobile-platform 📹 Watch
Perps add funds Android Google Pixel 8 Pro (v14.0) 13.21s @mm-perps-engineering-team 📹 Watch
Predict Available Balance - Complete Flow Performance Android Google Pixel 8 Pro (v14.0) 1.11s @team-predict 📹 Watch
Predict Market Details - Complete Flow Performance Android Google Pixel 8 Pro (v14.0) 5.46s @team-predict 📹 Watch
Predict Deposit - Complete Flow Performance Android Google Pixel 8 Pro (v14.0) 300.01s @team-predict
Connect to Uniswap dapp, edit accounts, choose another account, and skip Solana popup Android Google Pixel 8 Pro (v14.0) 19.38s @metamask-mobile-platform 📹 Watch
Measure Cold Start To Onboarding Screen Android Google Pixel 8 Pro (v14.0) 2.73s @metamask-mobile-platform 📹 Watch
Onboarding Import SRP with +50 accounts, SRP 3 Android Google Pixel 8 Pro (v14.0) 0.00s @metamask-onboarding-team 📹 Watch
Perps open position and close it Android Google Pixel 8 Pro (v14.0) 18.92s @mm-perps-engineering-team 📹 Watch
Seedless Onboarding: Apple Login New User Android Google Pixel 8 Pro (v14.0) 8.95s @metamask-onboarding-team 📹 Watch
Seedless Onboarding: Google Login New User Android Google Pixel 8 Pro (v14.0) 10.35s @metamask-onboarding-team 📹 Watch

Branch: feat/qr-sync-controller · Build: Normal · Commit: abfa9cc · View full run

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant