Skip to content

feat: sync V2 ramps orders from User Storage#44367

Open
georgeweiler wants to merge 6 commits into
mainfrom
feat/ramps-order-syncing
Open

feat: sync V2 ramps orders from User Storage#44367
georgeweiler wants to merge 6 commits into
mainfrom
feat/ramps-order-syncing

Conversation

@georgeweiler

@georgeweiler georgeweiler commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Delegates User Storage + auth actions to the ramps messenger so RampsController.syncOrdersWithUserStorage() can run.
  • Exposes syncRampsOrdersWithUserStorage on the ramps background API.
  • Pulls remote V2 orders on unlock via useRampsOrderSyncing in MetamaskIdentityProvider (same gates as account/contact sync).
  • selectIsRampsSyncingEnabled defaults to true when absent from persisted state.
  • Adds Backup & Sync Buy & sell orders sub-toggle (BACKUPANDSYNC_FEATURES.rampsSyncing), matching mobile.
  • Synced orders land in RampsController.orders / existing hooks and selectors (no dedicated orders history UI in this PR).

Depends on

Works with

QA / debugging (separate branch)

Orders home-tab demo for manual verification lives on feat/ramps-orders-qa-tab (not included here). Use that branch to inspect synced orders and trigger manual sync during cross-client testing.

Cross-client flow

  1. Mobile creates V2 order with Backup & Sync + Buy & sell orders enabled.
  2. Extension unlock with same signed-in profile → useRampsOrderSyncing runs full sync.
  3. Order is available via useRampsOrders / selectRampsOrders.
  4. Disabling Buy & sell orders on either client blocks sync.

Local testing (until core packages are published)

Copy built packages from core feat/ramps-order-syncing into extension node_modules:

yarn workspace @metamask/profile-sync-controller run build
yarn workspace @metamask/ramps-controller run build

rm -rf node_modules/@metamask/profile-sync-controller/dist node_modules/@metamask/ramps-controller/dist
cp -R ../core/packages/profile-sync-controller/dist node_modules/@metamask/profile-sync-controller/dist
cp -R ../core/packages/ramps-controller/dist node_modules/@metamask/ramps-controller/dist

Then:

  1. Complete a V2 buy on mobile (with Backup & Sync on)
  2. Unlock extension with the same SRP / signed-in profile
  3. Inspect RampsController.orders (or use feat/ramps-orders-qa-tab Orders tab)

Test plan

  • Unit tests for messenger API, useRampsOrderSyncing, identity provider, selectors
  • Backup & Sync ramps toggle unit tests
  • Manual: mobile order → extension unlock pull (verified)
  • Bump @metamask/ramps-controller + @metamask/profile-sync-controller once core Allow running CircleCI locally #9474 is published

Note

Medium Risk
Touches authentication (sign-out/sign-in around migrate sync), User Storage, and cross-client order data; failures are mostly logged and retried, but wrong env/auth could block sync until retry.

Overview
Wires V2 ramps buy/sell order sync through User Storage: the ramps messenger delegates User Storage, auth, and feature-flag actions; the background API exposes syncRampsOrdersWithUserStorage; and useRampsOrderSyncing runs a full sync from MetamaskIdentityProvider when the same gates as account/contact sync pass (signed in, unlocked, Backup & Sync on, ramps sub-feature enabled).

Adds a Buy & sell orders Backup & Sync sub-toggle (i18n + UI), includes ramps in the “all sub-features off → disable main” cascade, and selectIsRampsSyncingEnabled defaults to true when missing from persisted state.

For wallets that ever connected to Portfolio, native goToBuy runs a one-shot silent migration: background Portfolio tab uploads local buy orders, then User Storage sync pulls into the extension; migration completion is stored only after sync succeeds. Provider auto-selection re-runs when synced completed orders arrive, with normalized provider ids so Portfolio /providers/... paths match the extension catalog.

Local dev: loadAuthenticationConfig uses Profile Sync DEV for development/testing builds so buy-widget JWTs and order-sync e2e align with staging Portfolio.

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

Wire RampsController order syncing so orders created on mobile can be
pulled into the extension on unlock, without adding ramps UI.

Co-authored-by: Cursor <cursoragent@cursor.com>
@georgeweiler
georgeweiler requested a review from a team as a code owner July 11, 2026 13:23
@github-actions

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 commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

✨ Files requiring CODEOWNER review ✨

🔑 @MetaMask/accounts-engineers (8 files, +404 -5)
  • 📁 ui/
    • 📁 components/
      • 📁 app/
        • 📁 identity/
          • 📁 backup-and-sync-features-toggles/
            • 📄 backup-and-sync-features-toggles.test.tsx +70 -4
            • 📄 backup-and-sync-features-toggles.tsx +19 -1
    • 📁 contexts/
      • 📁 identity/
        • 📄 index.test.tsx +40 -0
        • 📄 index.tsx +9 -0
    • 📁 hooks/
      • 📁 identity/
        • 📁 useRampsOrderSyncing/
          • 📄 useRampsOrderSyncing.test.tsx +167 -0
          • 📄 useRampsOrderSyncing.ts +67 -0
    • 📁 selectors/
      • 📁 identity/
        • 📄 backup-and-sync.test.ts +19 -0
        • 📄 backup-and-sync.ts +13 -0

👨‍🔧 @MetaMask/money-movement (9 files, +550 -16)
  • 📁 ui/
    • 📁 hooks/
      • 📁 ramps/
        • 📁 useRampsNavigation/
          • 📄 useRampsNavigation.test.tsx +28 -0
          • 📄 useRampsNavigation.ts +18 -12
        • 📁 utils/
          • 📄 determinePreferredProvider.test.ts +13 -0
          • 📄 determinePreferredProvider.ts +12 -2
          • 📄 portfolioBuyOrdersMigration.test.ts +142 -0
          • 📄 portfolioBuyOrdersMigration.ts +233 -0
          • 📄 portfolioConnection.test.ts +50 -0
          • 📄 portfolioConnection.ts +39 -0
          • 📄 useRampsProviders.ts +15 -2

@metamask-ci

metamask-ci Bot commented Jul 11, 2026

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

Baseline (latest main): 1716549 | Date: 6/29/2026 | Pipeline: 29154220417 | 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]
User Journey Benchmarks · Samples: 5 · mock API

⚠️ Missing data: chrome/webpack/userJourneyAssets, chrome/webpack/userJourneyTransactions

Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
importSrpHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
assetDetails
[Sentry log · main/release]
🟢 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]
Bundle sizes
  • background: 14.22 MiB
  • ui: 17.06 MiB
  • common: 0 Bytes
  • other: 998.07 KiB
  • contentScripts: 1.87 MiB
  • zip: 27.03 MiB
No matching bundle-size baseline was found in the history data, so diff values are omitted.

Match mobile by exposing a Buy & sell orders sub-toggle, and include
ramps syncing in the reverse-cascade that disables the main Backup &
Sync switch when every sub-feature is off.

Co-authored-by: Cursor <cursoragent@cursor.com>
@metamask-ci

metamask-ci Bot commented Jul 16, 2026

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

Baseline (latest main): 41ca3b9 | Date: 7/16/2026 | Pipeline: 29495402797 | 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]
User Journey Benchmarks · Samples: 5 · mock API

⚠️ Missing data: chrome/webpack/userJourneyAssets, chrome/webpack/userJourneyTransactions

Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
importSrpHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
assetDetails
[Sentry log · main/release]
🟢 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • dappPageLoad/pageLoadTime: +15%
Bundle sizes
  • background: 14.26 MiB
  • ui: 17.15 MiB
  • common: 0 Bytes
  • other: 998.07 KiB
  • contentScripts: 1.87 MiB
  • zip: 27.12 MiB
No matching bundle-size baseline was found in the history data, so diff values are omitted.

georgeweiler and others added 2 commits July 16, 2026 10:10
Required after merging main so RampsController can read
moneyHeadlessAllProviders for quote widening alongside order sync.

Co-authored-by: Cursor <cursoragent@cursor.com>
@metamask-ci

metamask-ci Bot commented Jul 16, 2026

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

Baseline (latest main): 2ba6714 | Date: 7/16/2026 | Pipeline: 29515209701 | 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]
User Journey Benchmarks · Samples: 5 · mock API

⚠️ Missing data: chrome/webpack/userJourneyAssets, chrome/webpack/userJourneyTransactions

Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
importSrpHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
assetDetails
[Sentry log · main/release]
🟢 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 539 Bytes (0%)
  • ui: 1.89 KiB (0.01%)
  • common: 0 Bytes (0%)
  • other: 0 Bytes (0%)
  • contentScripts: 14 Bytes (0%)
  • zip: 589 Bytes (0%)

georgeweiler and others added 2 commits July 21, 2026 05:44
Open a background Portfolio tab to upload Buy history, re-sign into DEV
Profile Sync, sync all HD entropy sources, and prefer the prior provider
(with /providers/ id normalize) instead of defaulting to Transak.

Co-authored-by: Cursor <cursoragent@cursor.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

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 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4182484. Configure here.

} catch (signOutError) {
console.error('performSignOut before migrate sync failed', signOutError);
}
await submitRequestToBackground('performSignIn');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Buy migration signs users out

High Severity

runPortfolioBuyOrdersMigration always calls performSignOut then performSignIn before syncing, though the comment targets stale tokens in local DEV Profile Sync. On production builds, a first native Buy can sign the profile out; if performSignIn fails, sync is skipped while the session may stay signed out until another sign-in path runs, disrupting Backup & Sync during Buy.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 4182484. Configure here.

// migrate+sync (previous bug: invalid token still marked done → permanent Transak).
if (syncSucceeded) {
await markPortfolioBuyOrdersMigrationCompleted();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Migration completes without Portfolio done

Medium Severity

When the background Portfolio tab never posts the migrate-done URL, waitForMigrateDone still resolves after the timeout, the tab is closed, and a successful User Storage sync marks migration complete. Portfolio localStorage orders may never upload, yet retries are permanently disabled.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 4182484. Configure here.

@metamask-ci

metamask-ci Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor
Builds ready [4182484]
⚡ Performance Benchmarks (Total: 🟢 13 pass · 🟡 8 warn · 🔴 0 fail)

Baseline (latest main): 6c0217c | Date: 7/21/2026 | Pipeline: 29854723021 | 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: +38%
  • loadNewAccount/total: +38%
  • loadNewAccount/inp: -26%
  • loadNewAccount/fcp: -49%
  • loadNewAccount/lcp: +1445%
  • confirmTx/longTaskCount: -100%
  • confirmTx/longTaskTotalDuration: -100%
  • confirmTx/longTaskMaxDuration: -100%
  • confirmTx/tbt: -100%
  • confirmTx/inp: -26%
  • confirmTx/fcp: -47%
  • confirmTx/lcp: +1190%

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

  • 🟡 loadNewAccount/LCP: p75 2.7s
Startup Benchmarks · Samples: 100
Benchmarkfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]
startupPowerUserHome
[Sentry log · main/release]
🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • startupStandardHome/domInteractive: -40%
  • startupStandardHome/backgroundConnect: -11%
  • startupStandardHome/firstReactRender: -12%
  • startupStandardHome/numNetworkReqs: -57%
  • startupStandardHome/fcp: -39%
  • startupPowerUserHome/uiStartup: +18%
  • startupPowerUserHome/load: +24%
  • startupPowerUserHome/domContentLoaded: +24%
  • startupPowerUserHome/domInteractive: +114%
  • startupPowerUserHome/backgroundConnect: +56%
  • startupPowerUserHome/loadScripts: +22%
  • startupPowerUserHome/setupStore: +21%
  • startupPowerUserHome/numNetworkReqs: +14%
  • startupPowerUserHome/fcp: +109%
  • startupPowerUserHome/lcp: +20%

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

  • 🟡 startupPowerUserHome/LCP: p75 3.9s
User Journey Benchmarks · Samples: 5 · mock API

⚠️ Missing data: chrome/webpack/userJourneyTransactions

Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
🟡 total
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]
swap
[Sentry log · main/release]
🟢 [CI log]

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

  • 🟡 assetDetails/FCP: p75 1.8s
  • 🟡 solanaAssetDetails/FCP: p75 1.9s
  • 🟡 importSrpHome/FCP: p75 2.0s
  • 🟡 sendTransactions/FCP: p75 2.0s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 1.05 KiB (0.01%)
  • ui: 3.77 KiB (0.02%)
  • common: 0 Bytes (0%)
  • other: 0 Bytes (0%)
  • contentScripts: 56 Bytes (0%)
  • zip: 1.08 KiB (0%)

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant