Skip to content

Conversation

@smilingkylan
Copy link
Contributor

@smilingkylan smilingkylan commented Nov 5, 2025

Part 2 of 4 to fix:
https://github.com/MetaMask/mobile-planning/issues/2343
https://consensyssoftware.atlassian.net/jira/polaris/projects/MWMR/ideas/view/8845676?selectedIssue=MWMR-10

Previous Part: #21869

Description

This PR adds LegacyLinkAdapter, a bidirectional adapter that bridges the new CoreUniversalLink format (from PR #XXXX) with the existing legacy deep link handlers. This is the second PR in Phase 1 of the deep link consolidation project.

Context

The current deep link system has routing logic fragmented across multiple files with nested switch-case statements. This adapter enables gradual migration to a unified routing system while maintaining 100% backward compatibility with existing handlers.

What Changed

  • Created LegacyLinkAdapter with bidirectional conversion methods:

    • toLegacyFormat() - Converts CoreUniversalLink to legacy urlObj + params format
    • fromLegacyFormat() - Creates CoreUniversalLink from legacy URL strings
    • extractActionParams() - Extracts action-specific paths and query parameters
    • toProtocolUrl() - Converts links between protocols (metamask://, https://, ethereum://, dapp://)
    • shouldUseNewSystem() - Feature flag system for gradual rollout (currently disabled for all actions)
    • wrapHandler() - Wraps legacy handlers to accept CoreUniversalLink
  • Added comprehensive test coverage (23 test cases):

    • Format conversion tests
    • Parameter handling (including SDK params)
    • Protocol conversions
    • Edge cases (null/undefined values, empty paths)

Why This Approach

  • Non-breaking: No changes to existing deep link handlers in this PR
  • Gradual migration: shouldUseNewSystem() allows action-by-action rollout
  • Type-safe: Full TypeScript coverage with proper type guards
  • Testable: All adapter methods are pure functions with comprehensive tests

Dependencies

None

How to Test

  • Only automated tests at this time since this functionality is not actually "enabled" in the app

Changelog

Added

  • Added LegacyLinkAdapter for bidirectional conversion between new CoreUniversalLink format and legacy deep link handlers
  • Added migration strategy with shouldUseNewSystem() feature flag for gradual rollout

Note

Introduce LegacyLinkAdapter for bidirectional conversion between new core links and legacy handlers, add protocol/path utilities and tests, and map ACTIONS.PERPS_MARKETS in the normalizer.

  • Deeplink Adapter:
    • Implement LegacyLinkAdapter with:
      • toLegacyFormat / fromLegacyFormat for bidirectional conversion between CoreUniversalLink and legacy urlObj + params.
      • wrapHandler to adapt legacy handlers to core links.
      • extractActionParams to derive action path/query params.
      • toProtocolUrl to convert links across metamask, https, ethereum, and dapp.
      • shouldUseNewSystem feature-flag list (currently empty).
  • Normalizer:
    • Add ACTIONS.PERPS_MARKETSperpsMarketsPath to ACTION_PATH_MAP in CoreLinkNormalizer.
  • Tests:
    • Add LegacyLinkAdapter.test.ts covering conversions, param handling (incl. SDK and custom params), protocol conversions, empty/edge cases, and handler wrapping.

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

@smilingkylan smilingkylan marked this pull request as ready for review November 5, 2025 18:08
@smilingkylan smilingkylan requested a review from a team as a code owner November 5, 2025 18:08
@github-actions
Copy link
Contributor

github-actions bot commented Nov 5, 2025

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-mobile-platform Mobile Platform team label Nov 5, 2025
@github-actions github-actions bot added the size-L label Nov 5, 2025
@smilingkylan smilingkylan added the No QA Needed Apply this label when your PR does not need any QA effort. label Nov 5, 2025
@smilingkylan smilingkylan changed the title feat: First draft of LegacyLinkAdapter between old and new 'core' links feat: Implement LegacyLinkAdapter between old and new 'core' links Nov 5, 2025
const actionParams: Record<string, string> = {};
if (actionPath.includes('?')) {
const [basePath, queryString] = actionPath.split('?');
actionPath = basePath;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a false positive. Anyone using multiple ? in a URL shall get no consideration 😁 follow standards or get left behind

@MetaMask MetaMask deleted a comment from cursor bot Nov 6, 2025
@MetaMask MetaMask deleted a comment from sonarqubecloud bot Nov 6, 2025
@smilingkylan smilingkylan added the no-changelog no-changelog Indicates no external facing user changes, therefore no changelog documentation needed label Nov 6, 2025
@metamaskbot metamaskbot added the INVALID-PR-TEMPLATE PR's body doesn't match template label Nov 6, 2025
[ACTIONS.ONBOARDING]: 'onboardingPath',
[ACTIONS.CREATE_ACCOUNT]: 'createAccountPath',
[ACTIONS.DEPOSIT]: 'depositCashPath',
};
Copy link

Choose a reason for hiding this comment

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

Bug: Incomplete action path mapping for PERPS_MARKETS

The actionPaths mapping is missing an entry for ACTIONS.PERPS_MARKETS. The CoreLinkParams interface includes a perpsMarketsPath field, and toProtocolUrl (line 276) deletes this field from query params, indicating it's a valid action-specific path. However, extractActionParams cannot properly extract the path for PERPS_MARKETS actions because the mapping is incomplete. The fix should add [ACTIONS.PERPS_MARKETS]: 'perpsMarketsPath' to the actionPaths object.

Fix in Cursor Fix in Web

[ACTIONS.ONBOARDING]: 'onboardingPath',
[ACTIONS.CREATE_ACCOUNT]: 'createAccountPath',
[ACTIONS.DEPOSIT]: 'depositCashPath',
[ACTIONS.PERPS_MARKETS]: 'perpsMarketsPath',
Copy link

Choose a reason for hiding this comment

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

Bug: Action Path Mapping: A Dead End

The ACTIONS.PERPS_MARKETS entry in ACTION_PATH_MAP is unreachable dead code. Since PERPS_MARKETS is included in the PERPS_ACTIONS array, the getActionSpecificParams method will always match it in the PERPS_ACTIONS.includes(action) branch and set perpsPath instead of perpsMarketsPath. The ACTION_PATH_MAP lookup only occurs in the else branch, which PERPS_MARKETS never reaches.

Fix in Cursor Fix in Web

@smilingkylan smilingkylan added the skip-e2e skip E2E test jobs label Nov 7, 2025
@smilingkylan smilingkylan removed the skip-e2e skip E2E test jobs label Nov 7, 2025
@sonarqubecloud
Copy link

sonarqubecloud bot commented Nov 7, 2025

@smilingkylan smilingkylan added this pull request to the merge queue Nov 7, 2025
Merged via the queue into main with commit 8b9607b Nov 7, 2025
123 checks passed
@smilingkylan smilingkylan deleted the kylan/feat/legacy-link-adapter branch November 7, 2025 20:26
@github-actions github-actions bot locked and limited conversation to collaborators Nov 7, 2025
@metamaskbot metamaskbot added the release-7.60.0 Issue or pull request that will be included in release 7.60.0 label Nov 7, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

INVALID-PR-TEMPLATE PR's body doesn't match template 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.60.0 Issue or pull request that will be included in release 7.60.0 size-L team-mobile-platform Mobile Platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants