Skip to content

feat: sync V2 ramps orders with Backup & Sync#33148

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

feat: sync V2 ramps orders with Backup & Sync#33148
georgeweiler wants to merge 3 commits into
mainfrom
feat/ramps-order-syncing

Conversation

@georgeweiler

@georgeweiler georgeweiler commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Delegates User Storage + auth actions to the ramps messenger so RampsController.syncOrdersWithUserStorage() can run.
  • Adds a Backup & Sync Buy & sell orders sub-toggle (BACKUPANDSYNC_FEATURES.rampsSyncing / isRampsSyncingEnabled).
  • Pulls remote V2 orders on unlock via useRampsOrderSyncing in useIdentityEffects; local addOrder / removeOrder push incrementally from core.
  • Fixes selector gate: selectIsRampsSyncingEnabled defaults to true when absent from persisted state (matches controller + core sync utils).
  • Aligns Ramp V2 call sites with updated @metamask/ramps-controller (removes normalizeProviderCode usage).

Depends on

Works with

  • MetaMask/metamask-extension#44367 — extension pulls orders written by mobile on unlock (same SRP / signed-in profile).
  • Extension QA tab (separate branch): feat/ramps-orders-qa-tab on metamask-extension for manual inspection during testing.

Cross-client flow

  1. User completes V2 buy on mobile → order stored locally and pushed to User Storage (when toggles on).
  2. User unlocks extension → useRampsOrderSyncing calls syncOrdersWithUserStorage → order appears in RampsController.orders.
  3. Disabling Buy & sell orders blocks sync on both clients.

Local testing (until core packages are published)

Built packages from core feat/ramps-order-syncing were copied into node_modules for local testing:

# from core (feat/ramps-order-syncing)
yarn workspace @metamask/profile-sync-controller run build
yarn workspace @metamask/ramps-controller run build

# copy into mobile
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 restart Metro and verify:

  1. Settings → Backup & Sync shows Buy & sell orders toggle
  2. Complete a V2 buy → order appears in RampsController.orders and is written to User Storage
  3. Unlock extension with same profile → order appears there

Test plan

  • useRampsOrderSyncing unit tests
  • Ramp provider-ID alignment tests (useTransakRouting, unifiedOrderProcessor)
  • Manual: mobile order → extension unlock pull (verified)
  • Bump @metamask/profile-sync-controller + @metamask/ramps-controller once core feat: add localizations for the browser tab #9474 is published

@georgeweiler georgeweiler requested review from a team as code owners July 10, 2026 20:50
@github-actions

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

GitHub can't find an account for George Weiler.
You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.

@mm-token-exchange-service mm-token-exchange-service Bot added team-money-movement issues related to Money Movement features INVALID-PR-TEMPLATE PR's body doesn't match template labels Jul 10, 2026
@mm-token-exchange-service

Copy link
Copy Markdown
Contributor

PR template — items to address before "Ready for review"

Warnings — informational, address before merging:

See docs/readme/ready-for-review.md for the full Definition of Ready for Review.

@github-actions github-actions Bot added size-M risk:low AI analysis: low risk labels Jul 10, 2026
George Weiler and others added 3 commits July 11, 2026 14:12
Wire RampsController order syncing into mobile: messenger delegation,
Backup & Sync sub-toggle, identity-effect pull on unlock, and fixtures
for isRampsSyncingEnabled. Depends on MetaMask/core#9474.

Co-authored-by: Cursor <cursoragent@cursor.com>
Align selectIsRampsSyncingEnabled with UserStorageController default state
so the Backup & Sync toggle and background sync gates stay consistent for
upgraded profiles that omit isRampsSyncingEnabled.

Co-authored-by: Cursor <cursoragent@cursor.com>
@metamask/ramps-controller no longer exports normalizeProviderCode; use raw
provider IDs from quotes and orders so V2 ramp flows compile against core
order-syncing packages.

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

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeAccounts, SmokeConfirmations, SmokeNetworkAbstractions, SmokeNetworkExpansion, SmokeSwap, SmokeStake, SmokeWalletPlatform, SmokeMoney, SmokePerps, SmokeMultiChainAPI, SmokePredictions, SmokeSeedlessOnboarding, SmokeBrowser, SmokeSnaps
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: high
  • AI Confidence: 100%
click to see 🤖 AI reasoning details

E2E Test Selection:
Hard rule (test-framework-infra-change): Test framework infrastructure changed: tests/framework/fixtures/FixtureBuilder.ts. Running all tests.

Performance Test Selection:
No performance-sensitive changes in this PR. The changes are focused on: (1) adding a new ramps order syncing feature flag and hook, (2) removing normalizeProviderCode from ramp flows, and (3) updating test fixtures. None of these changes affect app launch time, asset loading, account list rendering, login performance, or other performance-measured scenarios.

View GitHub Actions results

@github-actions github-actions Bot added risk:medium AI analysis: medium risk and removed risk:low AI analysis: low risk labels Jul 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Flaky unit test detection

Run history flaky detection

View recent run history

Historical failure rate is a hint, not proof — review each suggestion in context. See the flaky-test-detection skill for the full pattern reference and manual audit workflow.

Failures / runs sampled per window:

File 7d 15d 30d
app/components/UI/Ramp/hooks/useTransakRouting.test.ts 0/50 0/179 0/387

AI-detected flaky patterns

app/components/UI/Ramp/hooks/useTransakRouting.test.ts

  • J10 — jest.spyOn without restoreAllMocks()/mockRestore() (medium)
    • This test creates a jest.spyOn(global, 'URL') to simulate a parsing error but does not call mockRestore() or use jest.restoreAllMocks() afterward. Spies on global objects persist across tests (J10), which can alter behavior of any other test that uses the URL constructor, causing intermittent failures depending on test order. The beforeEach only does clearAllMocks() which does not restore original implementations.
    • Suggested fix in app/components/UI/Ramp/hooks/useTransakRouting.test.ts:
      -      const OriginalURL = global.URL;
      -      const urlSpy = jest
      -        .spyOn(global, 'URL')
      -        .mockImplementation((url: string | URL, base?: string | URL) => {
      -          const urlStr = typeof url === 'string' ? url : url.href;
      -          if (urlStr === parseThrowingUrl) {
      -            throw new TypeError('Invalid URL');
      -          }
      -          return new OriginalURL(url, base);
      -        });
      -
      -      const handler = await runApprovedFlowToCaptureCallback();
      -      expect(handler).not.toBeNull();
      -      if (!handler) return;
      -      await act(async () => {
      -        await handler({ url: parseThrowingUrl });
      -      });
      -      expect(mockLoggerError).toHaveBeenCalledWith(
      -        expect.stringContaining('Failed to parse redirect URL'),
      -        expect.any(TypeError),
      -      );
      -
      +      const OriginalURL = global.URL;
      +      const urlSpy = jest
      +        .spyOn(global, 'URL')
      +        .mockImplementation((url: string | URL, base?: string | URL) => {
      +          const urlStr = typeof url === 'string' ? url : url.href;
      +          if (urlStr === parseThrowingUrl) {
      +            throw new TypeError('Invalid URL');
      +          }
      +          return new OriginalURL(url, base);
      +        });
      +
      +      const handler = await runApprovedFlowToCaptureCallback();
      +      expect(handler).not.toBeNull();
      +      if (!handler) return;
      +      await act(async () => {
      +        await handler({ url: parseThrowingUrl });
      +      });
      +      expect(mockLoggerError).toHaveBeenCalledWith(
      +        expect.stringContaining('Failed to parse redirect URL'),
      +        expect.any(TypeError),
      +      );
      +
      +      urlSpy.mockRestore();

This check is informational only and does not block merging.

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

Labels

INVALID-PR-TEMPLATE PR's body doesn't match template risk:medium AI analysis: medium risk size-M team-money-movement issues related to Money Movement features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant